1. 程式人生 > >Arduino的模數轉換(以Arduino讀取搖桿資訊為例)——人人都能玩硬體

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軸方向的模擬訊號而已。