Arduino範例講解(五)

與電腦通訊

到目前為止,我們僅使用USB連接將新程序碼上傳到Arduino。我們也可以使用該連接從電腦接收數據以及​​向電腦發送數據。

一些如Leonardo之類的Arduino開發板都有一個微控制器來完全處理USB通信,但是大多數開發板還有第二個或較小的微控制器,專門用於通信。在Arduino Uno上,這是USB連接器和TX-RX LED之間的黑色小方塊。該晶片與主微控制器之間的通信通過序列連接完成,然後第二個晶片告訴電腦”嘿,我是一個序列埠口”,然後將序列數據從主晶片轉換為USB格式,然後將來自電腦的消息轉換為主微控制器的序列訊息。

序列表示bits依次發送通過同一根導線,而並列埠是在分開的導線上同時發送8 bit或更多bit(例如,某些較舊電腦背面的大型並行打印機埠口)。

Arduino使用兩條序列線:一條是從Arduino到USB晶片的傳輸線(TX),另一條是從USB晶片到Arduino的線,即接收線(RX)。這些字母寫在引腳0和1的旁邊。這意味著當您與電腦連接時,這些引腳正在使用中,因此你不能將它們用於LED或按鈕等。如果再次停止通信,則你可以將它們用作普通的I / O引腳。
如果要使用序列通信將Arduino連接到另一設備,則還必須使用這兩個引腳。

將輸入訊息送到電腦

寫出範例serialButton,編譯然後上傳。
麵包板配置與Arduino範例講解(四)的範例相同。
然後打開序列埠監控視窗:”工具”>”序列埠監控視窗”,點擊右上角的放大鏡或按CTRL + SHFT + M。確保啟用了自動捲動,並且baud(鮑率)設為9600。

您會看到很多。現在按下連接到引腳3的按鈕,您將看到0,這是引腳的預設輸入值。

現在打開序列繪圖家:”工具”>”序列繪圖家”或CTRL + SHFT + L。這會將值繪製到圖形中。

讓我們看一下代碼:

在setup()中,我們加了一行新命令:Serial.begin(9600)。這僅僅是開始通信,而9600是鮑率,即每秒的脈衝數,因此是序列連接的速度。9600是預設值。如果將此值設置為其他值,則還必須在序列埠監控視窗中進行更改。否則,將不同步,並且會回傳給你非常奇怪的角色。Serial.begin(…)的相反是Serial.end()。在使用序列埠連接後,當您必須再次將引腳1和0用作普通I / O時,可以使用此功能,但是實際上並不建議這樣做。

在loop()中,您將看到相同的Serial關鍵字,這一次與println(…)函數一起使用。這只是打印出括號之間指定的值,然後是換行(ln)。
(請注意,這不只是將其轉換為二進位以通過序列發送,而是將其轉換為ASCII,然後通過序列埠發送,以便電腦可以印出來。如果要經由二進位發送二進位byte序列,請使用Serial.write(…)函數。)

執行換行功能,您還可以將Serial.print(…) n(換行符號)或 r(歸位符號一起使用,代表一行結束,而不是ln。

Serial.print(digitalRead(3)); 
Serial.print(' n');

單引號表示它是一個字元。

另一個特殊字元是 t(tab),讓我們用它來列印兩個開關的輸入。下面是範例serial2Buttons。上傳然後打開序列埠監控視窗來查看結果。

Arduino參考:序列

發送命令到Arduino

通信也可以通過其他方式進行:讓我們編寫一個程序來控制電腦的LED。

這是範例serialLEDs。編碼完後上傳後,打開序列埠監控視窗,然後嘗試送出0到3之間的值。再送出4了解它如何工作?
讓我們檢查一下代碼:

除了一個命令外,設定看起來應該很熟悉:這是一個while-loop,只要中括號之間的條件為(你可以將其與for loop比較,差別是沒有第一個和最後一個參數,只有條件),就重複while循環。這裏明確地使用了大括號{}來表明它是一個loop,你也可以只使用分號代替:while(!Serial);
序列當序列埠通訊處於啟動狀態時(例如,打開序列埠監控視窗器時)返回true。這裏加一個反相運算子(!),判斷在通訊開關不啟動時,回傳true。因此,當通信還沒啟動時,while loop會繼續重複讀取,等待它啟動為止。然後,我們知道可以使用println(…)函數發送數據。如果我們沒有使用while loop等待,將僅失掉第一個發送的數據。之後程序還是會嘗試將數據送到電腦,但是就無法監聽序列輸入的內容。

在loop用法中,還有另一個方法:if-statement,這有可能是電腦科學中最重要的方法。它確切地執行了其名稱所隱含的含義:只要當滿足特定條件時,它才執行一段代碼。否則,括號之間的代碼將被忽略。

現在,我將花一點時間來解釋Arduino如何接收序列埠訊息:
如前所述,序列發送bit一個byte接一個byte地發送。例如,試著發出訊息”test”被分成1個byte。一個字元的大小為一個byte,因此當你通過序列埠發送它時,它看起來像是 ‘t’ ‘e’ ‘s’ ‘t’。當Arduino收到這些字節時,它將把它們存在緩衝區中(只是一小塊記憶體臨時儲存它)。它一個byte一個byte的接收它,因此緩衝區看起來像這樣的””(空)”t”,”te”,”tes”,”test”。
當緩衝區為空時,Serial.available()函數將返回0,如果緩衝區中接收到數據,它將返回緩衝區中的bytes,因此在這種情況下為4。如果調用Serial.read()函數,它將從緩衝區中讀取第一個字節(’t’),將其從緩衝區中刪除,然後移動緩衝區,因此它現在包含”est”和Serial.available( )返回3。如果再次調用Serial.read(),它將返回”e”,並且緩衝區將為”st”。你可以繼續讀下去,直到Serial.available()等於0為止。(如果您想知道第一個字節而又不刪除它,可以使用Serial.peek()函數。)

因此,第一個if(Serial.available> 0)將檢查緩衝區中是否有任何數據。如果是這樣,它將讀取第一個byte,並將其存在變數serialValue中。然後檢查剛剛讀取的值是否為’0’。請注意單引號,它表示字元0(ASCII:’0’= 48),而不是值0,因為序列埠監控視窗將其作為字串發送。如果值為’0’,它將關閉兩個LED。如果該值不是’0’,則在’ else‘部分將執行:接著檢查值是否為’1’,如果是,它將點亮第一個LED並關掉第二個LED。如果不是’1’,將檢查它是否為’2’,如果是,將打開第二個LED,然後關閉第一個LED。如果不是’2’,將檢查是否為’3’,如果是,它將同時打開兩個LED,否則,它將執行else末節中的代碼,並列印您應輸入的值。

如果解釋不夠清楚,您可以檢查圖像中的流程圖。

注意,使用雙等號來檢查兩個值是否相同。如果您將使用單個等號(if(serialValue =’0’)),它將不會進行任何檢查,只會將變數’0’指定給變數serialValue。這是一個非常常見的錯誤。

其他測試值的運算子是<(小於)>(大於)<=(小於或等於)> =(大於或等於)!=(不等於)。
在if語句中,您還可以使用邏輯運算子(boolean運算子)來檢查多個條件:&&(and),|| (or)

一些例子:

5> 3→true
5 <3→false 3> 3→false
3> = 3→true
5!= 3→true
3 == 3→true

檢查值x是否在1到100之間:

(1 <= x)&&(x <= 100)

另一種編寫方式(不推薦,僅作為示範)

!((x <1)||(x> 100))

您可以嘗試弄清楚它是如何工作的,然後檢查下圖中的真值表。

注意:就像在數學中一樣,中括號用於指示運算順序,例如,在右圖表最右一個表達式中 !((x<1)||(x>100)) ,將首先判斷’x <1’,然後是’x> 100’,然後是’||’,最後是’!’ 。

Arduino參考:While

Arduino參考:If(和比較運算子)

Arduino參考:Else

Arduino參考:boolean運算子

_

摘要

  • 大多數Arduino都有第二個用於USB通信的晶片。該晶片使用序列埠連接與主微控制器通信。
  • 序列是指一個bit接一個bit地發送。有一條傳輸線和一條接收線(分別是TX和RX)。
  • 你可以使用序列埠監控視窗(CTRL + SHFT + M)和序列埠繪圖表(CTRL + SHFT + L)來顯示Arduino正在發送的數據,並將數據發送到Arduino。
  • Serial.begin(baud); 開始與電腦的序列埠通信。預設鮑率是9600。
  • Serial.end() ; 結束序列埠通信。
  • Serial.print(text); 將字串列印到電腦,可以在序列埠監控視窗/繪圖表中讀取。注意數字被轉換為ASCII:例如Serial.print(0); 將發送一個48的序列值(0字元的ASCII碼)。
  • Serial.println(text); 與print相同,但是會在訊息後加上換行。
  • ‘ n’是換行字元,’ r’是歸位符,’ t’是tab字元(用於縮進)
  • Serial.write(byte); 通過序列埠發送raw byte。例如,Serial.write(48); 將在序列埠監控視窗中列印一個0字元。
  • while(condition){…}稱為while loop。只要中括號之間的條件為true,大括號之間的代碼就會重複執行。
  • 當序列埠通訊處於啟動狀態時(例如,打開序列埠監控視窗時),序列埠返回true。
  • while(!Serial) ; 只要序列埠通訊未啟動,將重複”不執行任何操作”(”等待”之意)。
  • 如果條件為true,if(condition){if-code} else {else-code}將執行if-code,如果條件為false,則將執行else-code。
  • Arduino接收到的序列數據先暫存在緩衝區中,直到您讀取它或緩衝區溢出為止,它一直保持在那裡。
  • Serial.available(); 傳回緩衝區中可用的字節數。
  • Serial.read(); 傳回緩衝區中的第一個字節,然後將其刪除。
  • Serial.peek(); 傳回緩衝區中的第一個字節,而不刪除它。
  • 在你的條件下,可以使用以下測試運算子:==(等於),<(小於),>(大於),<=(小於或等於),> =(大於或等於), !=(不等於)。
  • 而且,您也可以使用邏輯&&(和)和|| (或)運算子。

補充:Switch

在最後一個範例中,我們使用了許多if … else語句。儘管這是最快的方法,但閱讀起來並不容易。如果要將變數與某些給定值進行比較,可以使用switch

我們用serialLEDsSwitch範例來說明。

如您所見,該開關以’switch’關鍵字開頭,後接著中括號之間檢查變數。在大括號之間,定義了我們的案例。他們使用語法’ case value:’,如果給定變數等於此’case’中的值,則使用該要執行的代碼。在特定於案例的代碼之後,” break ;” 關鍵字用於退出”case”條件。
請注意,您輸入的值不能是變數。如果要比較2個變數,則必須使用if語句。如果該變數與其他情況下的任何值都不匹配,則執行
“ default:”下的代碼。default也可以省略。

Arduino參考:SwitchCase

發佈留言