Arduino的模數轉換(以Arduino讀取搖桿資訊為例)——人人都能玩硬體
本文主要解決一下幾個問題:
1 微控制器中的資訊是如何表達的
2 什麼是模數轉換
3 Arduino如何做模數轉換
4 實操 —— Arduino讀取搖桿資訊
微控制器中的資訊是如何表達的
我們都知道,計算機實際上只是幾塊電路板。那麼計算機是如何在這些晶片和電子元件上做計算的呢?或許你知道計算機只識別0和1,而且你或許還知道高電平表示1,低電平表示0。
什麼是模數轉換
計算機中,我們可以簡單的理解這些0和1組成的訊號是數字訊號(這是很不嚴謹且不算正確的說法,這裡為了便於理解,我們先這麼說了,有興趣的可以自己瞭解詳細定義),與數字訊號相對的是模擬訊號,我們常常也需要收發模擬訊號,比如播放音樂,使用話筒,隨意調整光線亮度(隨意調整,也就是任何亮度,而不是分段的那種),稱重,測量壓力,測量電壓或者電流或者電阻。這是比較直觀的,此外還有一些可能你不太瞭解的,比如熱釋電紅外感測器(他通常用來做人體檢測感測器) ,火焰感測器,紅外測距,磁場感測器等等。還有遊戲手柄上的搖桿。
在這些場合下,我們就需要對資訊做個數模轉換或這模數轉換,所謂數模轉換就是將數字訊號變模擬訊號,模數轉換就是模擬訊號變數字訊號。
Arduino如何做模數轉換
對於Arduino UNO,有6個專門用於AD轉換的引腳(A0-A5),任何感測器,輸出的模擬訊號無非是電壓訊號或者電流訊號,其中,電壓訊號各類感測器模組中更常見,arduino可以將電壓訊號轉換為用10bit表示的數值。量程是0-5V,也就是說最大值是2^10-1=1023,最小值是0
先了解一個函式
int analogRead ( uint8_t ) :這是arduino的一個模數轉換函式,括號裡可以填模擬訊號輸入口,這裡我們用的Arduino UNO ,我們就可以填0-5分別對應Arduino UNO的A0-A5口(他們就在微控制器上,和其他針腳排在一起,位置很明顯)。他的返回值就是模擬訊號轉換的數字值,這個數值佔10bit,也就是說模數轉換的最大值是1023(二的十次方減一)代表5V,最小值是0代表0V,需要注意的是你的Arduino的模數轉換可能並不靈敏,不準確,後面我會寫使用I2C通訊介面的AD晶片ADXL345,它結合Arduino可以提供更精確,更靈敏模數轉換。如果還是不理解,沒關係,你再看看下面的程式碼,或許能理解了。
我們再來了解搖桿的工作原理
搖桿實際上是兩個電位器和一個微動按鈕,所謂電位器你可以理解為圓形的滑動電阻,所謂微動按鈕就是普通的按鈕,但是它不能保持按下狀態,也就是說,按下去以後,手一鬆開,他就自自動彈起了。實操 —— Arduino讀取搖桿資訊
在正式上手之前我們需要了解了兩個點(analogRead函式,搖桿基本原理)/************************************************************************** Copyright:FUNCO_小風 Author: FUNCO_小風 Date:2017-04-10 Description:從串列埠A0 A1 GPIO12 口讀入搖桿資料並通過串列埠輸出 **************************************************************************/ /* 定義串列埠傳送編碼 */ #define CAR_ADVANCE '1' #define CAR_BACK '2' #define CAR_LEFT '3' #define CAR_RIGHT '4' #define CAR_STOP '0' /************************************************* Function: void get_rocker(int *buff) Description: 獲取搖桿按鈕狀態(12針) x軸資料(A0針) y軸資料(A1) 並存儲於 Calls: digitalRead() analogRead() Table Accessed: // 被訪問的表(此項僅對於牽扯到<a href="http://lib.csdn.net/base/mysql" class='replace_word' title="MySQL知識庫" target='_blank' style='color:#df3434; font-weight:bold;'>資料庫</a>操作的程式) Table Updated: // 被修改的表(此項僅對於牽扯到資料庫操作的程式) Input: buff 整型指標,獲取一個指向3*sizeof(int)大小的儲存空間 Output: buff[0] 搖桿是否被按下 1-按鈕未按下 0-按鈕被按下 buff[1] 儲存y軸資料 max=2^10-1=1023 min=0 buff[2] 儲存x軸資料 max=2^10-1=1023 min=0 Return: void Others: void *************************************************/ void get_rocker(int *buff) { buff[0]=digitalRead(12); buff[1]=analogRead(); buff[2]=analogRead(0); } void setup() { Serial.begin(115200); pinMode(12,INPUT); digitalWrite(12,HIGH);//上拉 } void loop() { int rocker_data[3]; //用於臨時儲存搖桿x軸y軸以及switch狀態 get_rocker(rocker_data); //傳遞儲存搖桿狀態的陣列首地址 //判斷搖桿y軸狀態 >這裡定義>600表示正推 <300表示反推 if(rocker_data[1]>600){ Serial.println(CAR_LEFT); }else if(rocker_data[1]<300) { Serial.println(CAR_RIGHT); } //判斷搖桿x軸狀態 >這裡定義>600表示正推 <300表示反推 if(rocker_data[2]>600){ Serial.println(CAR_BACK); }else if(rocker_data[2]<300) { Serial.println(CAR_ADVANCE); } //判斷搖桿按鈕狀態 當按鈕被按下,讀取值為0 則經過邏輯非'!'運算取非,值變為真(0為假),則串列埠輸出資料 if(!rocker_data[0]){ Serial.println(CAR_STOP); } //一般玩家手指反應時間長於100ms,因此定義延時100ms //建議定義延時是為了避免串列埠傳送保持忙碌,給接收端處理資料時間 //具體延時時間視情況而定 delay(100); }
實物如下
執行結果如下
在上面程式碼中,可以注意到,我讀數取的是範圍值,而不是具體值,比如當搖桿的Y軸讀數>600我便當搖桿正推,是因為我發現Arduino的模數轉換並不靈敏,不準確,後面我會推薦一款使用I2C通訊介面的AD晶片ADXL345,它結合Arduino可以提供更精確,更靈敏模數轉換。
這裡順帶一提,搖桿的使用不要太死腦筋,怎樣算左怎樣算右,怎樣算前怎樣算後,完全看你的程式碼怎麼定義,搖桿只能提供X軸和Y軸方向的模擬訊號而已。