【App inventor】手機加速度感測器,控制藍芽小車。

App inventor 手機加速度感測器,控制藍芽小車

上回已經成功做出用手機藍芽遙控小車,但是是以按鍵的方式來遙控,感覺還是有一點點點沒那麼直覺的操控,那還有甚麼方式可以來控制小車呢??

你說用像手機玩一些平衡球遊戲或賽車遊戲時,需要傾斜手機來控制畫面中的東西,那麼透過傾斜手機來控制藍芽小車呢??

哦哦哦,感覺就挺有趣的,讓我們來試做看看吧~

加速度感測器是甚麼?

原理

簡單來說,就是透過兩端固定電極片,中間有一個可動的電極,而他連接著彈簧,當物體運動時會有慣性,使中間電極片移動,導致兩端的電容值發生改變,再經由運算就可以知道物體的加速度及方向。

圖片來源:MEMS Accelerometer Gyroscope Magnetometer & Arduino

影片中約00:30~1:00的部分為說明加速度感測器

手機讀取加速度感測器

把這個小東西安裝在手機裡面,就可以偵測手機的方向及是否有晃動等等。

一般就是感測三軸的加速度(X、Y、Z軸)

圖片來源: IT閱讀

因為重力的關係,物體傾斜時會有分力,使我們感測到X軸方向的加速度,以及Z軸方向的加速度,進而推算傾斜程度。

圖片來源:如何運用加速度計提升傾角量測準確度

使用App inventor先試做讀取X、Y、Z軸的數值

手機三軸加速度顯示影片

從影片中可以看出,某個軸的加速度數值越大傾斜角度越大,之後我們就可以用加速度作為參數來控制我們的小車了。

控制架構

方向控制策略

這裡使用兩輪的差速來達成轉彎目的

所以我們的想法是要個別控制左輪與右輪的速度

因為手機只有用到前後傾跟左右傾,故只用X、Y兩軸而已。

X軸用來控制前後速度,傾斜越大速度越快,Y軸用來控制左右速差,藉此產生轉彎。

建立公式:

    RightSpeed=dX+dY; //右馬達速度
    LeftSpeed=dX-dY; //左馬達速度

以下為舉例:

我手機前傾X軸會是為負數,後傾則為正數。

套用公式後:左右馬達速度為-10會前進,10則會後退

手機向右傾的話,Y軸會是正數,左傾是負數。

套用公式後可發現,左圖右馬達為0因此不會轉動,左馬達為-10會正轉,因此產生向右轉彎的效果;右圖同理,得出左轉的效果。

上述是舉例說明而已,實際控制馬達輸出時,馬達速度範圍會在0~255,因此還會再做一些計算。

實際用手機加速度感測器遙控小車

履帶玩具車硬體部分可參考這篇: [教學]arduino藍芽遙控車,改造履帶玩具車。

如果沒有想做履帶車,也可以買現成的arduino基本底盤車,以前大學第一次玩巡跡車就是用這種小車,非常方便。

App inventor 程式

App介面,主要是顯示X軸跟Y軸的數值而已,記得要加入”加速度感測器”跟”計時器”

App積木程式:

App inventor 專案檔案(.aia):

https://drive.google.com/file/d/1eFZOSaLtcAjJToGp6hxIW8HpuMBXoWC2/view?usp=sharing

Arduino 程式

#include <SoftwareSerial.h>
#include <Wire.h>

//輸出到L298N的腳位
#define MT_L 3  //ENA
#define IN1 4
#define IN2 5

#define IN3 7
#define IN4 8
#define MT_R 9  //ENB

SoftwareSerial BT(10,11);
String XYValue;
int dX,dY;
int RightSpeed;
int LeftSpeed;


void setup() {
  BT.begin(9600); // 設定和 HC-06 通訊的速度 (預設 9600)
  BT.setTimeout(50); //設定每50ms結束一次讀取
  Serial.begin(9600); 
  pinMode(MT_L,OUTPUT);
  pinMode(IN1,OUTPUT);
  pinMode(IN2,OUTPUT);
  pinMode(IN3,OUTPUT);
  pinMode(IN4,OUTPUT);
  pinMode(MT_R,OUTPUT);

  
}

void loop() {
  while(BT.available()) {
    XYValue=BT.readString();
    ValueTransform();
    RightSpeed=(dX+dY)*2;
    LeftSpeed=(dX-dY)*2;
    char MR_DIR=Motor_R_DIR();   
    char ML_DIR=Motor_L_DIR();  
    analogWrite(MT_R,abs(RightSpeed));//輸出右馬達速度
    analogWrite(MT_L,abs(LeftSpeed)); //輸出左馬達速度
    Serial.print(LeftSpeed);
    Serial.print(',');
    Serial.print(ML_DIR);
    Serial.print(',');
    Serial.print(RightSpeed);
    Serial.print(',');
    Serial.println(MR_DIR);
    
  }
  
}

//將收到的字串處理成X、Y整數
void ValueTransform(){
  String X, Y;
  for(int i=0; i<XYValue.length(); i++){
    if(i<XYValue.indexOf(',')){
      X=X+XYValue[i];
    }
    else if(i>XYValue.indexOf(',')){
      Y=Y+XYValue[i];
    }
  }
    dX=X.toInt();
    dY=Y.toInt();
}

//以右馬達速度正或負來決定正反轉
char Motor_R_DIR()
{
  if(RightSpeed>0){
   digitalWrite(IN3,HIGH);
   digitalWrite(IN4,LOW);
   return 'B';
  }
  else if(RightSpeed<0){
   digitalWrite(IN3,LOW);
   digitalWrite(IN4,HIGH);
   return 'F';
  }
}

//以左馬達速度正或負來決定正反轉
char Motor_L_DIR()
{
  if(LeftSpeed>0){
   digitalWrite(IN1,LOW);
   digitalWrite(IN2,HIGH);
   return 'B';
  }  
  else if(LeftSpeed<0){
   digitalWrite(IN1,HIGH);
   digitalWrite(IN2,LOW);
   return 'F';
  }   
}

最後!! 如果你喜歡這篇文章,或是這篇文章對你有幫助的話,也歡迎分享出去給需要的人,訂閱免費電子報獲得最新資訊😄😄😄

發佈留言

發佈留言必須填寫的電子郵件地址不會公開。 必填欄位標示為 *