iT邦幫忙

2022 iThome 鐵人賽

DAY 15
2
自我挑戰組

PixelBit 可以這樣玩!系列 第 15

(Day 15)FPV Car 第一人稱手機遙控車(Part 2)

  • 分享至 

  • xImage
  •  

這篇文章將會接續上一篇「FPV Car 第一人稱手機遙控車(Part 1)」。

教學原文參考:FPV Car 第一人稱手機遙控車

五、程式解析

1. 設定方式 Setup

在燒錄成程式之前需要先到 config.h 設定 Wi-Fi 連線的模式,預設 Pixel:Bit 會以 AP 模式的方式運作,也就是讓手機直接連進 Pixel:Bit 進行操作。這樣的好處是不管在室內或室外,即使沒有 Wi-Fi 網路也可以進行操作。

若環境中是有 Wi-Fi 網路的,也可以將 Pixel:Bit 設定為 Satation 模式,讓手機跟 Pixel:Bit 都同時連到場域中的熱點,如此一來也可以降低 Pixel:Bit的運算負荷。SSID 與 Password 也依照環境與喜好修改完成之後即可以進行燒錄。分別燒錄 ESP32 程式碼與 ATmega328 程式碼完成後,即可以將 UART 選擇開關切至「go」進行操作了!(如果還不清楚怎麼樣燒錄程式碼,可以參考前面的單元(二)教學

#define WIFI_AP_MODE        0
#define WIFI_STA_MODE       1

#define WIFI_MODE           WIFI_AP_MODE
#define WIFI_SSID           "PixelBit"
#define WIFI_PASS           "circuspi"

2. 產生二維碼 Generate QR Code

大家在使用物聯網開發板時,經常都會有一種困擾,就是不知道開發板現在的 Wi-Fi SSID、密碼與 IP 等資訊,時常都還需要連接序列埠到電腦監看,甚至在輸入密碼時可能因為手抖而不小心輸入錯誤,真的相當的惱人啊!

在 Pixel:Bit 上有一個 TFT 顯示器,我們可以很方便的把 Wi-Fi 網路資訊顯示在上面。而連線 Wi-Fi 的 QR code 格式為 WIFI:T:WPA;S:YourSSID;P:YourPass;;,詳細的說明如下表所示:

https://www.circuspi.com/wp-content/uploads/2022/05/PixelBit_08_table.jpg

舉例來說,我們只要將 WIFI:T:WPA;S:PixelBit;P:circuspi;; 這串文字轉換為 QR Code 顯示在 TFT 顯示器上,再使用手機掃描,手機就會自動地連入 Pixel:Bit 這組 Wi-Fi 網路,是不是相當方便呢?

產生可以快速連接 Wi-Fi 的QR Code

https://www.circuspi.com/wp-content/uploads/2022/05/PXL_20220428_091711652.jpg

在此範例中我們引用的函式庫是 github 上開發者 ricmoo 所編寫的 library,為了方便起見,我們直接內嵌在此範例的程式碼中。我們使用版本 3 的 QR Code,像素為 29×29,不同版本像素與訊息量皆有不同,例如版本 4 的像素為 33×33、版本 5 的像素為 37×37 等,完整資訊可以參閱 QR Code標準

3. 網頁伺服器 WEB Server

ESP32 的程式碼則是由國外的開發者 Rui Santos 旗下專案所修改而來的,如下圖所示。網頁伺服器的程式碼結構由原生範例 CameraWebServer 差異不大。在即時串流的部分使用 <IP>:81/stream 讀取影像資料,而各個對應按鈕則是用 Command Handler 的方式在各個按鈕被按下時,觸發 <IP>/action?go= HTTP GET 方法呼叫,並再 handler 中將對應的指令透過序列埠 Serial.print() 傳送給 ATmega328 執行動作。

if(!strcmp(variable, "forward")) {
  Serial.print(ESP32_CMD_FORWARD);
}
else if(!strcmp(variable, "left")) {
  Serial.print(ESP32_CMD_LEFT);
}
else if(!strcmp(variable, "right")) {
  Serial.print(ESP32_CMD_RIGHT);
}
else if(!strcmp(variable, "backward")) {
  Serial.print(ESP32_CMD_BACK);
}
else if(!strcmp(variable, "stop")) {
  Serial.print(ESP32_CMD_STOP);
}
else {
  res = -1;
}

4. 馬達控制 Motor Control

馬達控制將會透過 ATmega328p 經由邊緣連接器連到登月小車 MoonCar 上的馬達。從下方的 Pixel:Bit登月小車腳位對照圖可以看出,左輪的控制對應到 ATmega328p 的 2 跟 14 腳控制,而右輪的控制對應到 A1 與 13 腳控制,因此只要依照下表的方式控制這幾隻 pin 腳的電位,就能夠控制小車的動作姿態囉!

https://www.circuspi.com/wp-content/uploads/2022/05/PixelBit_08_table2-1.jpg

為了方便我們閱讀程式碼,先在 PixelBit_FPV_Car_328p\config.h 檔案中定義好 ATmega328 各個腳位的名稱,也避免後續忘記各個 pin 腳的功能。

如下程式所示,第 37~55 行先定義出 Pixel:Bit 邊緣連接器所對應 ATmega328 的 IO。第 57~62 行則延伸定義好左右輪的功能名稱,方便我們在做 IO 控制時使用。

#define MICRO_BIT_PIN_0     3
#define MICRO_BIT_PIN_1     A0
#define MICRO_BIT_PIN_2     A1
#define MICRO_BIT_PIN_3     A2
#define MICRO_BIT_PIN_4     A3
#define MICRO_BIT_PIN_5     4
#define MICRO_BIT_PIN_6     6
#define MICRO_BIT_PIN_7     7
#define MICRO_BIT_PIN_8     2
#define MICRO_BIT_PIN_9     8
#define MICRO_BIT_PIN_10    A7
#define MICRO_BIT_PIN_11    5
#define MICRO_BIT_PIN_12    9
#define MICRO_BIT_PIN_13    13
#define MICRO_BIT_PIN_14    12
#define MICRO_BIT_PIN_15    11
#define MICRO_BIT_PIN_16    10
#define MICRO_BIT_PIN_19    A5
#define MICRO_BIT_PIN_20    A4

#define APIN_BUTTON_A       MICRO_BIT_PIN_5
#define APIN_BUTTON_B       MICRO_BIT_PIN_11
#define APIN_WHEEL_R_A      MICRO_BIT_PIN_2
#define APIN_WHEEL_R_B      MICRO_BIT_PIN_13
#define APIN_WHEEL_L_A      MICRO_BIT_PIN_8
#define APIN_WHEEL_L_B      MICRO_BIT_PIN_14

此外我們也將每個小車的動作,例如前進、後退、左轉、右轉等,分別獨立寫成函式 function,後續在呼叫與閱讀上可以更為簡潔。完成各馬達的驅動函式後就接著要處理 ESP32 與 ATmeag328 之間 UART 溝通的程式,以利在使用者按下網頁上的按鈕時,可以立即做出對應的動作控制。

void m_forward(void) {
#if DEBUG
  Serial.println("forward");
#endif
  digitalWrite(APIN_WHEEL_R_A, HIGH);
  digitalWrite(APIN_WHEEL_R_B, LOW);
  digitalWrite(APIN_WHEEL_L_A, HIGH);
  digitalWrite(APIN_WHEEL_L_B, LOW);
}

void m_back(void) {
#if DEBUG
  Serial.println("back");
#endif
  
  digitalWrite(APIN_WHEEL_R_A, LOW);
  digitalWrite(APIN_WHEEL_R_B, HIGH);
  digitalWrite(APIN_WHEEL_L_A, LOW);
  digitalWrite(APIN_WHEEL_L_B, HIGH);
}

void m_left(void) {
#if DEBUG
  Serial.println("left");
#endif
  
  digitalWrite(APIN_WHEEL_R_A, HIGH);
  digitalWrite(APIN_WHEEL_R_B, LOW);
  digitalWrite(APIN_WHEEL_L_A, LOW);
  digitalWrite(APIN_WHEEL_L_B, LOW);
}

5. 串列埠溝通 UART Communication

ESP32 和 ATmega328 之間藉由序列埠 UART 相互連接,在此範例中,當我們操作網頁上的按鈕時,ESP32 就會收到事件觸發,並且將所要執行的動作(如前進、後退)傳送給 ATmega328,ATmega328 在收到對應的指令後,便會去執行相應的動作。

聰明如你應該不難想到,我們只要設計好前進、後退這些動作的對應的指令碼,在 ESP32 這一邊送出,ATmega328 這一邊接收並且判斷,即可完成這些功能了。沒有錯喔!概念即是如此而已,但我們在範例程式碼當中為了尋求程式碼的簡潔與擴充性,使用指令清單的程式技法來處理這個問題。

在 ATmega328 的程式碼第 86~95 行之間,可以看到這裡有個 CMD_T 結構的陣列,每個陣列中的成員就是一個指令以及要執行的指標函數,並且在最底部塞入一個 {NULL, 0, NULL} 代表已經沒有其他的指令要判斷了。

使用這種陣列的好處,就是我們只要調整這一個陣列的內容,就可以輕鬆的加入或刪除指令,不再需要更動到其他的程式敘述句,程式也可以看起來更加簡潔與容易閱讀喔!

// Command Handler
CMD_T cmd_list[] = {
  {ESP32_CMD_FORWARD, strlen(ESP32_CMD_FORWARD),  &m_forward},
  {ESP32_CMD_BACK,    strlen(ESP32_CMD_BACK),     &m_back},
  {ESP32_CMD_LEFT,    strlen(ESP32_CMD_LEFT),     &m_left},
  {ESP32_CMD_RIGHT,   strlen(ESP32_CMD_RIGHT),    &m_right},
  {ESP32_CMD_LSPIN,   strlen(ESP32_CMD_LSPIN),    &m_lspin},
  {ESP32_CMD_RSPIN,   strlen(ESP32_CMD_RSPIN),    &m_rspin},
  {ESP32_CMD_STOP,    strlen(ESP32_CMD_STOP),     &m_stop},
  {NULL, 0, NULL} //keep this elemnet in the end of list
};

六、小結

Pixel:Bit 有相容 micro:bit 的連接器,這樣的設計可以任意的搭配所有 micro:bit 擴充套件,同時結合自身的攝影鏡頭與 TFT 顯示螢幕等,打造更多的創意想像空間。

本篇教學示範 Pixel:Bit 搭配登月小車做出手機遙控車,各位夥伴們也可以額外增加在網頁控制的功能,例如:全彩 LED 控制、顏色感測器、蜂鳴器等。更多不同的可能性就讓各位玩家們自由發揮創意吧!

更多有趣系列教學文章


上一篇
(Day 14)FPV Car 第一人稱手機遙控車(Part 1)
下一篇
(Day 16)一起玩 Dino Game 小恐龍遊戲(Part 1)
系列文
PixelBit 可以這樣玩!30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言