搜尋程式碼

第29/31課:汽車-7 使用遙控器控制SunFounder智能車 | Robojax

第29/31課:汽車-7 使用遙控器控制SunFounder智能車 | Robojax

喺呢一課,我哋會將你嘅 SunFounder 智能車變成一部用紅外線(IR)遙控器控制嘅遙控車。唔使靠有線連接或者手機應用程式,你會學識點樣將標準紅外線遙控器上面嘅掣對應去控制架車嘅移動——前進、後退、轉彎,甚至斜行——仲可以即時調整速度。呢個項目係學完摩打控制同紅外線通訊基礎之後嘅完美下一步,因為佢將兩者結合成一個互動系統。

呢度嘅實際價值在於理解點樣為機械人平台建立一個穩健、易用嘅控制介面。你會學到嘅原理可以直接應用喺好多唔同類型嘅項目,例如:

  • 整一部用遙控嘅機械人做家居自動化任務,好似小型送貨機械人。
  • 為教育用機械人比賽整一部可編程車輛。
  • 為相機滑軌或者雲台機構開發自訂遙控器。
  • 為更大、更複雜嘅自動化系統製作原型用戶介面。

硬件同零件

呢個項目係建基於 SunFounder 3-in-1 Arduino 套件。要跟住做,你需要以下列出嘅零件。接線好直接,係由課程之前嘅課堂延伸落嚟。

  • SunFounder 3-in-1 Arduino 套件:包括智能車底盤、摩打驅動板同 Arduino 板。
  • 紅外線遙控器:套件跟嚟嘅標準遙控器。
  • 紅外線接收模組:用嚟解碼遙控器訊號嘅感應器。
  • LED 同 330 歐姆電阻:用嚟做視覺指示器,確認有掣被撳到。(影片 04:08 位置)
  • 跳線:用嚟喺麵包板上做必要嘅連接。

接線指南

car_9_lesson_29_wriing_for_IR

喺我哋深入探討程式碼之前,先確保硬件連接正確。紅外線接收器同摩打驅動器嘅接線同呢個系列之前嘅課堂一致。為咗令項目更加互動,我哋仲會將一個外置 LED 連接到第 13 腳,作為視覺回饋指示器。

以下係逐步接線指南:

  1. 紅外線接收器:紅外線接收器有三隻腳。正極腳連接到麵包板上嘅 5V 軌道。接地腳連接到 GND 軌道。訊號腳,即係最後嗰隻腳,連接到你 Arduino 板上嘅數位腳 11。(影片 05:29 位置)
  2. 外置 LED:將 330 歐姆電阻嘅一隻腳連接到 Arduino 上嘅數位腳 13。將電阻嘅另一隻腳連接到 LED 較長(陽極)嘅腳。LED 較短(陰極)嘅腳應該連接到麵包板上嘅 GND 軌道。(影片 04:08 位置)
  3. 摩打驅動器:摩打驅動器嘅四隻腳(A_1B、A_1A、B_1B、B_1A)分別連接到 Arduino 上嘅腳 5、6、9 同 10。呢個設定喺之前嘅課堂已經講過。(影片 06:44 位置)

如果想睇呢啲連接嘅視覺參考,請參閱下面嘅接線圖。

程式碼解釋

呢個項目嘅程式碼設計得好直觀。佢用 IRremote 函式庫嚟處理解碼紅外線訊號嘅複雜任務。等我哋拆解一啲你可以根據自己項目調整嘅用戶可設定部分。

喺程式碼最頂部,你會見到腳位定義。如果你將零件連接到同呢個例子唔同嘅腳位,呢啲就係你首先要檢查嘅嘢。

const int IR_RECEIVE_PIN = 12;  // 定義紅外線感應器嘅腳位號碼
const int A_1B = 5;
const int A_1A = 6;
const int B_1B = 9;
const int B_1A = 10;
  • IR_RECEIVE_PIN:呢個常數定義咗連接到你紅外線接收器訊號腳嘅數位腳。如果你將佢連接到另一個腳位,就要喺度改個號碼。
  • A_1BA_1AB_1BB_1A:呢啲常數對應你摩打驅動器上嘅四個控制腳。佢哋控制左邊同右邊摩打嘅速度同方向。

跟住,你會見到一個控制架車行為嘅關鍵變數。

int speed = 150;
  • speed:呢個變數設定架車嘅初始速度。數值可以由 0 到 255。喺呢個項目入面,你可以用遙控器上面嘅「+」同「-」掣嚟改變佢。程式碼仲包含邏輯,防止速度超過 255 或者跌到低過 0。(影片 09:22 位置)

遙控嘅核心邏輯喺 loop() 函數入面處理。當有掣被撳到,decodeKeyValue() 函數會將原始紅外線碼轉換成簡單嘅字串,好似「2」代表前進或者「+」代表加速。咁樣令跟住落嚟嘅 if 陳述式好易讀同修改。(影片 07:58 位置)

好似moveForward()turnRight()moveLeft()呢啲自訂函數就係控制摩打嘅地方。每個函數都會攞目前嘅speed做參數。例如,moveForward(speed)會以指定速度驅動兩個摩打向前。一個「轉彎」同一個「移動」嘅主要分別係,轉彎會令兩個轆向相反方向旋轉,令架車原地自轉,而移動就只會旋轉一個轆,令架車圍住靜止嗰個轆畫弧。(影片10:14)

現場項目示範

當程式碼上載好同架車開咗電之後,遙控器就成為你嘅主要操作介面。影片入面嘅示範突出咗幾個關鍵行為:

  • 速度控制:撳「+」掣會將速度增加50,而「-」掣就會減少。速度上限係255,下限係0,用嚟保護摩打。(影片11:56)
  • 瞬間移動:當你撳一個方向掣好似「2」(向前)或者「8」(向後),架車會移動一秒然後自動停低。呢個係程式碼入面內置嘅安全功能。(影片13:09)
  • 轉彎同操控:遙控器上面排成十字形嘅掣好似一個搖桿咁。撳「4」或者「6」會令架車原地向左或向右轉。撳斜角掣,好似「1」或者「3」,會執行「向左移」或者「向右移」,即係一個更急嘅轉彎,其中一個轆係靜止嘅。(影片16:42)

你可能會留意到架車唔係成日都行到好直嘅直線。呢個通常係因為摩打之間有少少差異,或者架車組裝嘅鬆緊度問題,呢啲係呢類套件常見同正常嘅特性。(影片15:14)

章節

  • [00:00] 智能車紅外線遙控簡介
  • [01:15] 先決條件同需要嘅先前課程
  • [01:56] 項目文件概覽
  • [02:29] 了解遙控器按鍵功能
  • [03:29] 紅外線接收器同LED接線步驟指南
  • [05:51] 開啟同載入項目程式碼
  • [07:41] 程式碼解釋:迴圈、按鍵解碼同動作
  • [09:22] 程式碼入面嘅速度限制同安全功能
  • [10:08] 摩打移動函數解釋
  • [11:49] 現場示範:測試速度控制同LED閃爍
  • [13:27] 現場示範:向前、向後同轉彎
  • [14:31] 完整架車通電同移動示範

圖片

Car 9 lesson 29 wiring for IR
Car 9 lesson 29 wiring for IR
896-Lesson 29/31: Car-7 Controlling SunFounder Smart Car using Remote Controller
語言: C++
/*
Lesson 29/31: Car-7 Controlling SunFounder Smart Car using Remote Controller
Get this code and watch video Download and resource page https://robojax.com/RJT612

*/
#include <IRremote.h>

const int IR_RECEIVE_PIN = 12;  // Define the pin number for the IR Sensor

const int A_1B = 5;
const int A_1A = 6;
const int B_1B = 9;
const int B_1A = 10;


int speed = 150;

void setup() {
  Serial.begin(9600);

  //motor
  pinMode(A_1B, OUTPUT);
  pinMode(A_1A, OUTPUT);
  pinMode(B_1B, OUTPUT);
  pinMode(B_1A, OUTPUT);

  //IR remote
  IrReceiver.begin(IR_RECEIVE_PIN, ENABLE_LED_FEEDBACK);  // Start the IR receiver // Start the receiver
  Serial.println("REMOTE CONTROL START");

}

void loop() {

  if (IrReceiver.decode()) {
    //    Serial.println(results.value,HEX);
    String key = decodeKeyValue(IrReceiver.decodedIRData.command);
    if (key != "ERROR") {
      Serial.println(key);

      if (key == "+") {
        speed += 50;
      } else if (key == "-") {
        speed -= 50;
      } else if (key == "2") {
        moveForward(speed);
        delay(1000);
      } else if (key == "1") {
        moveLeft(speed);
      } else if (key == "3") {
        moveRight(speed);
      } else if (key == "4") {
        turnLeft(speed);
      } else if (key == "6") {
        turnRight(speed);
      } else if (key == "7") {
        backLeft(speed);
      } else if (key == "9") {
        backRight(speed);
      } else if (key == "8") {
        moveBackward(speed);
        delay(1000);
      }

      if (speed >= 255) {
        speed = 255;
      }
      if (speed <= 0) {
        speed = 0;
      }
      delay(500);
      stopMove();
    }

    IrReceiver.resume();  // Enable receiving of the next value
  }
}

void moveForward(int speed) {
  analogWrite(A_1B, 0);
  analogWrite(A_1A, speed);
  analogWrite(B_1B, speed);
  analogWrite(B_1A, 0);
}

void moveBackward(int speed) {
  analogWrite(A_1B, speed);
  analogWrite(A_1A, 0);
  analogWrite(B_1B, 0);
  analogWrite(B_1A, speed);
}

void turnRight(int speed) {
  analogWrite(A_1B, speed);
  analogWrite(A_1A, 0);
  analogWrite(B_1B, speed);
  analogWrite(B_1A, 0);
}

void turnLeft(int speed) {
  analogWrite(A_1B, 0);
  analogWrite(A_1A, speed);
  analogWrite(B_1B, 0);
  analogWrite(B_1A, speed);
}

void moveLeft(int speed) {
  analogWrite(A_1B, 0);
  analogWrite(A_1A, speed);
  analogWrite(B_1B, 0);
  analogWrite(B_1A, 0);
}

void moveRight(int speed) {
  analogWrite(A_1B, 0);
  analogWrite(A_1A, 0);
  analogWrite(B_1B, speed);
  analogWrite(B_1A, 0);
}

void backLeft(int speed) {
  analogWrite(A_1B, speed);
  analogWrite(A_1A, 0);
  analogWrite(B_1B, 0);
  analogWrite(B_1A, 0);
}

void backRight(int speed) {
  analogWrite(A_1B, 0);
  analogWrite(A_1A, 0);
  analogWrite(B_1B, 0);
  analogWrite(B_1A, speed);
}

void stopMove() {
  analogWrite(A_1B, 0);
  analogWrite(A_1A, 0);
  analogWrite(B_1B, 0);
  analogWrite(B_1A, 0);
}


String decodeKeyValue(long result)
{
  switch(result){
    case 0x16:
      return "0";
    case 0xC:
      return "1"; 
    case 0x18:
      return "2"; 
    case 0x5E:
      return "3"; 
    case 0x8:
      return "4"; 
    case 0x1C:
      return "5"; 
    case 0x5A:
      return "6"; 
    case 0x42:
      return "7"; 
    case 0x52:
      return "8"; 
    case 0x4A:
      return "9"; 
    case 0x9:
      return "+"; 
    case 0x15:
      return "-"; 
    case 0x7:
      return "EQ"; 
    case 0xD:
      return "U/SD";
    case 0x19:
      return "CYCLE";         
    case 0x44:
      return "PLAY/PAUSE";   
    case 0x43:
      return "FORWARD";   
    case 0x40:
      return "BACKWARD";   
    case 0x45:
      return "POWER";   
    case 0x47:
      return "MUTE";   
    case 0x46:
      return "MODE";       
    case 0x0:
      return "ERROR";   
    default :
      return "ERROR";
    }
}

資源與參考資料

文件📁

Arduino 函式庫 (zip)