延續上一篇

米免積木卡車改裝 <機構部份>

 

今天來看看 Arduino的程式碼

 

首先,所有程式碼如下:

#include <Servo.h>

const int dirServoCenter = 80;
const int dirServoGap = 40;

const int runServoStop = 111;
const int runServoGap = 80;

const int stepPin[4] = {4, 5, 6, 7};

Servo runServo;
Servo dirServo;

int stepRunFlag = 0;
int stepIndex = 0;
int delayCnt = 0;


void setup() {
  runServo.attach(8);
  dirServo.attach(9);
  
  runServo.write(runServoStop);
  dirServo.write(dirServoCenter);
  
  Serial.begin(9600);
  
  for(int i = 0; i < 4; i++)
  {
    pinMode(stepPin[i], OUTPUT);
    digitalWrite(stepPin[i], LOW);
  }
  
  stepRunFlag = 0;
  stepIndex = 0;
  delayCnt = 0;
}

void loop() {
  if(Serial.available())
  {
    char recvData = Serial.read();

    switch(recvData)
    {
      case 'F' : {
        runServo.write(runServoStop + runServoGap);
        break;}
      case 'B' : {
        runServo.write(runServoStop - runServoGap);
        break;}
      case 'S' : {
        runServo.write(runServoStop);
        break;}
      
      case 'R' : {
        dirServo.write(dirServoCenter - dirServoGap);
        break;}
      case 'L' : {
        dirServo.write(dirServoCenter + dirServoGap);
        break;}
      case 'C' : {
        dirServo.write(dirServoCenter);
        break;}
      
      case 'U' : {
        stepRunFlag = 1;
        break;}
      case 'D' : {
        stepRunFlag = 2;
        break;}
      case 'P' : {
        stepRunFlag = 0;
        break;}
    }
  }
  
  if(stepRunFlag > 0)
  {
    if(delayCnt >= 49)
    {
      delayCnt = 0;
      if(stepRunFlag == 1)
      {
        if(stepIndex >= 3) stepIndex = 0;
        else stepIndex ++;
      }
      else if(stepRunFlag == 2)
      {
        if(stepIndex <= 0) stepIndex = 3;
        else stepIndex --;
      }
      for(int i = 0; i < 4; i++)
      {
        if(i == stepIndex) digitalWrite(stepPin[i], HIGH);
        else digitalWrite(stepPin[i], LOW);
      }
    }
    else delayCnt ++;
  }
  else
  {
    for(int i = 0; i < 4; i++)
    {
      digitalWrite(stepPin[i], LOW);
    }
  }
}

 

接下來我們一一來看這些程式碼到底在做什麼吧!

 

2021B1

因為我們使用伺服馬達,所以要將這個函式庫給 include 進來,這樣就可以很方便的控制伺服馬達囉~

 

2021B2

這邊定義一些固定的數值,方便程式中使用,若需變更時也不必於程式中多處修改,或是漏到某些沒有改到。

dirServoCenter 這個是定義方向控制的伺服馬達,正中間(不偏左也不偏右)時的控制傳入數值,這個數值須依實際情況修改

dirServoGap 則是左轉或右轉時,方向伺服馬達轉動的角度大小(此數值不是指角度,而是一個 由0~255的數字代表 0度~180度)

runServoStop 為控制前進、後退的伺服,停止時的參數(此伺服為連續運轉的型式,這個數值亦須依實際狀況修改)

runServoGap 為控制前進、後退的速度,數值越大,速度越快

stepPin[4] = {4 , 5, 6, 7} 定義步進馬達的接腳

 

2021B3

建立兩個伺服,一個控制 前/後,另一個控制 左/右

 

2021B4

宣告一些變數,其作用在下方用到的時侯一併說明

 

2021B5

在這個 setup() 大括號裡的程式碼,會於單晶片啟動時(剛給電或重置時)執行一次

 

2021B6

設定伺服使用的腳位

 

2021B7

設定停止狀態的 前/後 伺服,及 左/右 伺服的參數值

 

2021B8

設定串列傳輸的鮑率,用於和藍芽模組通訊

 

2021B9

設定步進馬達使用的腳位,並將其設置為低電位(即沒有激磁,馬達為放鬆的狀態)

 

2021B10

將變數初始化為 0

 

2021B11

在這個  loop() 大括號裡的程式碼,會重覆不斷的執行

 

2021B12

先判斷藍芽模組是否有接收到資料,有的話再將資料接收下來,放在 recvData 這個變數裡

 

2021B13

看接收到的資料符合大括號裡的那一個 case,再做相對應的處理

這裡先判斷接收到的是否為字元 'F',代表接收到前進的指令,我們就將控制前/後的伺服參數更新為前進的數值

若為'B'則 代表後退,若為'S'代表停止,依指令更新參數

 

2021B14

延續上面的判斷,接收到的字元為 'R'代表右轉,'L'代表左轉,'C'代表直行,依指令更新控制左/右轉的伺服的參數

 

2021B15

再延續上面的判斷,接收到的字元為 'U'代表車斗上升,'D'代表車斗下降,'P'代表暫停動作,保持目前的狀態

這裡用到的變數 stepRunFlag 是存放目前車斗要做的動作的一個代碼,1代表上升,2代表下降,0代表不動作。這樣後面控制步進馬達動作的程式,即可依照這個代碼做相對應的動作

 

2021B16

這裡開始處理步進馬達的動作

首先判斷 stepRunFlag 是否大於 0 ,代表要轉動步進馬達帶動車斗,可能上升,也可能是下降

再來因為如果依序給步進馬達轉動的太快,很容易發生失步,所以這裡我們使用 delayCnt 這個變數來計數,loop每執行50次,才讓步進馬達走一步,這個 delayCnt 的數字越大,步進馬達轉動的越慢

接著我們使用 stepIndex 這個變數來存放目前步進馬達驅動的腳位代碼,當判斷 stepRunFlag 等於1時(上升),將 stepIndex 依 0->1->2->3->0->1->2->3->0->1 ...... 這樣的順序改變;當判斷stepRunFlag 等於2時(下降),將 stepIndex 依 0->3->2->1->0->3->2->1->0->3 ...... 這樣的順序改變

最後使用一個 for 迴圈,讓變數 i 為 0~3 ,當 i 等於 stepIndex 時,將對應的步進馬達腳位輸出 HIGH,其餘的設為 LOW,這樣就能使步進馬達正轉或反轉

 

2021B17

這個 else 是對應到上面的第一行 if(stepRunFlag > 0),即表示沒有要轉動步進馬達

這裡做的事是將步進馬達的四個腳位都設為LOW,此時步進馬達沒有溵磁,減少電流消耗

 

 

補充:

步進馬達的控制,也可以使用 Arduino 的函式庫,請參考 https://www.arduino.cc/en/reference/stepper

 

好了,以上所有的程式碼都講解了。至於手機端的APP如何創建呢?我們下一次談囉!

米免積木卡車改裝 <Android APP>

arrow
arrow
    創作者介紹
    創作者 肯特王 的頭像
    肯特王

    肯特王的簿

    肯特王 發表在 痞客邦 留言(0) 人氣()