Netduino 程式設計教學 國立豐原高中 郭再興
Netduino微控制器實驗板 Netduino基於微軟的 .NET Micro Framework發展的控制板,它的概念與Arduino非常類似,也是走開放原始碼(open source)的路線,腳位與Arduino相容,價格也差不多 硬體規格 Atmel 32-bit microcontroller Speed: 48MHz, ARM7 Code Storage: 128 KB RAM: 60 KB It combines 20 GPIOs with SPI, I2C, 2 UARTs (1 RTS/CTS), 4 PWM and 6 ADC channels
程式發展環境 Visual Studio C# express 支援事件驅動程式設計 支援多緒(multi-threading) 開放硬體架構(open source) 搭配.NET Micro Framework 4.1.0 程式發展環境 Visual Studio C# express 支援事件驅動程式設計 支援多緒(multi-threading) 支援強大除錯功能 在線除錯 (in-circuit debugging)、設定中斷點、單步執行、變數檢視
程式發展環境 Microsoft Visual C# Express 2010 Microsoft .NET Micro Framework v4.1 SDK Netduino SDK v4.1 32-bit Windows 64-bit Windows
第一個程式 啟動 Visual Studio 2010 檔案->新增->專案 -> Visual C# -> Micro Framework -> Netduino Application 輸入名稱、位置、方案名稱 右側方案總管,Double-click program.cs 接上 Netduino 的USB連接線,自動抓到驅動程式
點選專案 -> 專案屬性->.NET Micro Framework 設定Transport=>USB Device=>Netduino
F5 (run) 編譯->佈署->執行程式 編輯區輸入程式 F5 (run) 編譯->佈署->執行程式 public static void Main() { // 宣告建立一個輸出埠 led 控制物件 OutputPort led = new OutputPort(Pins.ONBOARD_LED, false); while (true) led.Write(true); //點亮LED Thread.Sleep(250); //等候 250ms led.Write(false); //熄滅LED } public static void Main() { // 宣告建立一個輸出埠 led 控制物件 OutputPort led = new OutputPort(Pins.ONBOARD_LED, false); while (true) led.Write(true); //點亮LED Thread.Sleep(250); //等候 250ms led.Write(false); //熄滅LED }
試著修改程式,讓藍色LED能夠快速閃爍、慢速閃爍、或是連續快閃5次接著再慢閃2次 當傳輸結束後,等約2~3秒,連接的小藍燈會閃爍
程式可分兩區塊 using區塊 (類似標頭檔區) namespace區塊 (主程式區) 程式是從 void Main( ) 開始撰寫起
除錯練習 程式繼續執行(F5) 滑鼠移到變數上面 程式中斷 (Ctrl+Alt+Break) 滑鼠右鍵加入監看式 停止偵錯 (Shift+F5) 重新啟動(Ctrl+Shift+F5) 單步執行(F11) 進入函式 單步執行(F10) 不進入函式 離開函式 (Shift+F11) 滑鼠移到變數上面 滑鼠右鍵加入監看式 建立中斷點
14個通用輸出入埠(Digital I/O) d0~d13 6個類比輸入 (Analog in) a0~a5 內建LED 內建按鈕
外接LED閃爍實驗 此程式會將內建藍光色LED,還有外接於pin11的紅色LED,交互閃爍 public static void Main() { // 宣告建立輸出埠 led, L11 控制物件 OutputPort led = new OutputPort(Pins.ONBOARD_LED, false); OutputPort L11 = new OutputPort(Pins.GPIO_PIN_D11, false); int va = 0, vb=100; while (true) led.Write(true); //點亮LED L11.Write(false); //熄滅L11 Thread.Sleep(250); //等候 250ms va++; led.Write(false); //熄滅LED L11.Write(true); //點亮L11 vb--; }
按鈕控制LED閃爍 進階題目 按下按鈕紅燈亮,放開按鈕改成藍燈亮。 按下按鈕讓LED閃爍5次後就熄滅。 public static void Main() { // 宣告建立輸出埠 led, L11 控制物件 OutputPort led = new OutputPort(Pins.ONBOARD_LED, false); OutputPort L11 = new OutputPort(Pins.GPIO_PIN_D11, false); InputPort button = new nputPort(Pins.ONBOARD_SW1, false, Port.ResistorMode.Disabled); while (true) if (button.Read()) led.Write(true); //點亮LED L11.Write(false); //熄滅L11 Thread.Sleep(250); //等候 250ms led.Write(false); //熄滅LED L11.Write(true); //點亮L11 } else led.Write(false); //熄滅LED 進階題目 按下按鈕紅燈亮,放開按鈕改成藍燈亮。 按下按鈕讓LED閃爍5次後就熄滅。
基本電路概念 電路實驗->麵包板
此電路是將兩個LED的正極分別連接到控制板的pin13、pin12接腳,另外將兩個LED負極並接一起連到控制板的GND
兩個LED交互閃爍 public static void Main() { // 宣告建立輸出埠 L13, L12 控制物件 OutputPort L13 = new OutputPort(Pins.GPIO_PIN_D13, false); OutputPort L12 = new OutputPort(Pins.GPIO_PIN_D12, false); while (true) L13.Write(true); //點亮LED L12.Write(false); //熄滅L11 Thread.Sleep(250); //等候 250ms L13.Write(false); //熄滅LED L12.Write(true); //點亮L11 }
紅綠燈實驗 時間點 要做的事情 0 秒 點亮綠燈 熄滅黃燈 熄滅紅燈 延時等候 0.8秒 0.8 秒 熄滅綠燈 點亮黃燈 延時等候 0.2秒 1.0秒 點亮紅燈 延時等候 1秒 2.0秒 <<重複上述工作>>
public static void Main() { // 宣告建立輸出埠 L13, L12 控制物件 OutputPort LED_G = new OutputPort(Pins.GPIO_PIN_D13, false); OutputPort LED_Y = new OutputPort(Pins.GPIO_PIN_D12, false); OutputPort LED_R = new OutputPort(Pins.GPIO_PIN_D11, false); while (true) LED_G.Write(true); //點亮綠燈 LED_Y.Write(false); //熄黃燈 LED_R.Write(false); //熄紅燈 Thread.Sleep(800); //等候 800ms LED_G.Write(false); //熄綠燈 LED_Y.Write(true); //點亮黃燈 Thread.Sleep(200); //等候 200ms LED_R.Write(true); //點亮紅燈 Thread.Sleep(1000); //等候 1000ms }
雙紅綠燈
雙紅綠燈實驗
public static void Main() { // 宣告建立輸出埠 OutputPort LED_G1 = new OutputPort(Pins.GPIO_PIN_D13, false); OutputPort LED_Y1 = new OutputPort(Pins.GPIO_PIN_D12, false); OutputPort LED_R1 = new OutputPort(Pins.GPIO_PIN_D11, false); OutputPort LED_G2 = new OutputPort(Pins.GPIO_PIN_D10, false); OutputPort LED_Y2 = new OutputPort(Pins.GPIO_PIN_D9, false); OutputPort LED_R2 = new OutputPort(Pins.GPIO_PIN_D8, false); while (true) //--- 步驟1 ----------------- LED_G1.Write(true); //點亮綠燈1 LED_Y1.Write(false); //熄黃燈1 LED_R1.Write(false); //熄紅燈1 LED_G2.Write(false); //熄綠燈2 LED_Y2.Write(false); //熄黃燈2 LED_R2.Write(true); //點亮紅燈2 Thread.Sleep(800); //等候 800ms //--- 步驟2 ----------------- LED_G1.Write(false); //熄綠燈1 LED_Y1.Write(true); //點亮黃燈1 Thread.Sleep(200); //等候 200ms //--- 步驟3 ----------------- LED_G1.Write(false); //熄綠燈1 LED_Y1.Write(false); //熄黃燈1 LED_R1.Write(true); //點亮紅燈1 LED_G2.Write(true); //點亮綠燈2 LED_Y2.Write(false); //熄黃燈2 LED_R2.Write(false); //熄紅燈2 Thread.Sleep(800); //等候 800ms //--- 步驟4 ----------------- LED_G2.Write(false); //熄綠燈2 LED_Y2.Write(true); //點亮黃燈2 Thread.Sleep(200); //等候 200ms }
PWM脈衝寬度調變
Netduino有提供PWM輸出功能,我們可以使用數值(0~100)控制輸出埠產生(0~3.3V)的電壓,接上LED就可以看見光度的變化。 例如下列程式宣告D6接腳做為PWM輸出,並且設定D6的duty cycle為37%,所以D6就會輸出約1.2V的電壓 10KHz clock
value 測得電壓 0V 4 0.13V 37 1.20V 87 2.83V 100 3.26V
逐漸點亮的LED public static void Main() { //設定 pin6 做為PWM輸出 PWM PWM_R = new PWM(Pins.GPIO_PIN_D6); uint value = 0; //控制變數初值設定 while (true) //無窮迴圈 value += 1; //遞增控制變數值 if (value >= 100) value = 0; //檢查 PWM_R.SetDutyCycle(value); //輸出值 0~100 Thread.Sleep(20); }
可變電阻 具有兩個固定接點與一個滑動接點,可由滑動而改變滑動端與兩個固定端間電阻值 若是將可變電阻兩端接腳連接GND以及3.3V,並測量中間接腳電壓,當旋鈕轉動時就會看到電壓隨之變化 Netduino內建6個類比數位轉換的輸入埠(A0~A5),如果將待測電壓(0~3.3V)接到A0接腳,Netduino會轉換成0~1023的數值
電子調光器 轉動可變電阻導致A點電壓改變(0~3.3V) 經過A0接腳轉換成0~1023數值 線性轉換成0~99的數值 輸出給D6產生PWM輸出0~3.3V 驅動LED產生不同的亮度
public static void Main() { // 宣告輸入埠 AnalogInput ADInput = new AnalogInput(Pins.GPIO_PIN_A0); //宣告PWM輸出埠 PWM LED_R = new PWM(Pins.GPIO_PIN_D6); //宣告變數 int in_value, out_value; while (true) //無窮迴圈 // A0 取得 0~3.3V 轉換成值 0~1023 in_value = ADInput.Read(); out_value = in_value * 100 / 1024; // 輸出 0~99 LED_R.SetDutyCycle((uint)out_value); //產生PWM輸出 Thread.Sleep(100); //每個0.1秒 }
音效控制實驗 聲音產生的原理 聲音是音頻振動的效果,音頻的範圍是20Hz到200kHz,人耳可辨識的範圍約是200Hz到20kHz
各種音調的頻率表 Do Re Mi Fa So La Si 低音 頻率(Hz) 262 294 330 349 392 440 494 0.003817 0.003401 0.00303 0.002865 0.002551 0.002273 0.002024 半週期(us) 1908 1701 1515 1433 1276 1136 1012 中音 523 587 659 698 784 880 988 0.001912 0.001704 0.001517 0.001433 0.001276 0.001136 0.001012 956 852 759 716 638 568 506 高音 1046 1175 1318 1397 1568 1760 1976 0.000956 0.000851 0.000759 0.000716 0.000638 0.000568 0.000506 478 426 379 358 319 284 253
喇叭如何發出聲音 發出特定音調(例如低音 Do 頻率是262Hz),只要利用程式控制連接喇叭的輸出電壓不斷的0、1 變化(也就是0V、3.3V變化),若變化的頻率與低音Do相同,就可以聽到了
例如下列程式片段可以控制第9號輸出腳位,產生周期為1000us=1ms=0. 001秒的方波 (相當於頻率為1 / 0 例如下列程式片段可以控制第9號輸出腳位,產生周期為1000us=1ms=0.001秒的方波 (相當於頻率為1 / 0.001=1000Hz),約等於中音Si。 PWM speaker = new PWM(Pins.GPIO_PIN_D9); speaker.SetPulse(1000,500); // (全週期, 半週期)
急促的嗶、嗶聲 和緩的嗶、嗶聲 public static void Main() public static void Main() { //宣告 D9 為 PWM 控制輸出埠 PWM speaker = new PWM(Pins.GPIO_PIN_D9); while (true) speaker.SetPulse(1000, 500); //發出1KHz的音頻 Thread.Sleep(100); //持續 100ms //產生斷音效果 speaker.SetPulse(1000, 0); //靜音 Thread.Sleep(50); //持續 50ms } public static void Main() { //宣告 D9 為 PWM 控制輸出埠 PWM speaker = new PWM(Pins.GPIO_PIN_D9); while (true) speaker.SetPulse(1000, 500); //發出1KHz的音頻 Thread.Sleep(400); //持續 400ms //產生斷音效果 speaker.SetPulse(1000, 0); //靜音 Thread.Sleep(100); //持續 100ms }
發出由高而低的音頻 public static void Main() { //宣告 D9 為 PWM 控制輸出埠 PWM speaker = new PWM(Pins.GPIO_PIN_D9); uint value = 200; //半週期波長 (us) while (true) value += 100; //半週期遞增=>頻率遞減=>聲音由高而低 if (value >= 2000) value = 200; //調整半週期 speaker.SetPulse(value*2, value); //發出不同的音頻 Thread.Sleep(100); //持續 100ms //產生斷音效果 speaker.SetPulse(1000, 0); //靜音 Thread.Sleep(50); //持續 10ms }
讓喇叭發聲,由高而低,再由低而高,就可以達到警笛的效果 警笛聲 讓喇叭發聲,由高而低,再由低而高,就可以達到警笛的效果 public static void Main() { //宣告 D9 為 PWM 控制輸出埠 PWM speaker = new PWM(Pins.GPIO_PIN_D9); uint value = 200; //半週期波長 (us) while (true) for (value = 300; value <= 800; value += 10) { //半週期遞增=>頻率遞減=>聲音由高而低 speaker.SetPulse(value * 2, value); //發出不同的音頻 Thread.Sleep(20); //持續 100ms } for (value = 800; value >= 400; value -= 10) { //半週期遞減=>頻率遞增=>聲音由低而高
伺服馬達控制實驗
藉由操控高電位的長度(工作週期duty cycle),可讓伺服器知道該讓擺臂轉到哪個角度 控制伺服馬達 大部分伺服器接收的訊號為20ms的週期脈波 藉由操控高電位的長度(工作週期duty cycle),可讓伺服器知道該讓擺臂轉到哪個角度 當 duty cycle=1.0ms (1000us) ,擺臂位置位於-45度 當duty cycle=1.5ms(1500us)時,擺臂位置位於0度。 static PWM servo = new PWM(Pins.GPIO_PIN_D9); servo.SetPulse(20000, 1500); // (全週期, 工作週期)
程式執行後會看到伺服馬達來回在 -45度~0~+45度之間轉動 public static void Main() { //宣告 D9 為 PWM 控制輸出埠 PWM servo1 = new PWM(Pins.GPIO_PIN_D9); while (true) //無窮迴圈 //全週期 20ms, 工作週期 0.5ms, 約45度 ↗ servo1.SetPulse((uint)20000, 500); Thread.Sleep(1000); //暫停程式1秒,等候旋轉到位 //全週期 20ms, 工作週期 1.5ms, 約0度 ↑ servo1.SetPulse((uint)20000, 1500); //全週期 20ms, 工作週期 2.5ms, 約-45度 ↖ servo1.SetPulse((uint)20000, 2500); }
超音波測距
由控制板送出Start Pulse 至少2us (建議5us),過一會兒感測器會送回echo time pulse(最小115 μs至最大 18.5 ms),時間的長短代表距離遠近
距離轉換 在平地乾燥空氣中,音速每秒鐘約前進343公尺 每一個 tick等於0.1ms = 100us 計算公式 //宣告輸出入接腳 TristatePort PingPin = new TristatePort(Pins.GPIO_PIN_D7, false, false, ResistorModes.Disabled); PingPin.Active = true; // 設定為輸出模式 PingPin.Write(true); // 輸出3.3V 產生一個脈衝 PingPin.Write(false); // 輸出0V PingPin.Active = false; // 設定為輸入模式 while (PingPin.Read() == false) ; // 等候輸入脈波的正緣 long t1 = System.DateTime.Now.Ticks; // 取得超音波發射起始時間 while (PingPin.Read() == true) ; // 等候輸入脈波的負緣 long t2 = System.DateTime.Now.Ticks; // 取得超音波反射回來的時間 PingPin.Dispose(); return (int)((t2 - t1) * 343 / 20000); // 將時間差轉換為距離公厘
六足機器蜘蛛 影片 組裝
控制伺服器動作,即可達到模仿蜘蛛效果
謝謝指教 問題與討論