利用Nodemcu+Arduino nano+TB6612+点灯科技APP制作简易麦克纳姆轮Wi-Fi遥控小车
摘要
麥克納姆輪小車由于車輪本身的特殊結構,可以實現全向行駛,可玩性非常強。麥克納姆輪原理在這里不做展開,麥克納姆小車主要是通過控制四個輪胎的轉與不轉以及轉動的方向來實現多方向的運動,其中一種X型車輪分布車輪轉動方向與車體運動方向關系如下:
所需材料
1. Nodemcu模塊
2. Arduino nano 開發板
3. TB6612電機驅動模塊×2
4. 麥克納姆輪小車底盤
5. 點燈科技APP
6. 電烙鐵、導線、穩壓電源等
制作步驟
1. 將各模塊按如下圖所示進行連接
2.打開點燈科技APP,添加獨立設備,在添加的設備界面添加如圖所示的按鍵組件,數據鍵名與代碼內一致
3.分別在Nodemcu和Arduino nano中寫入以下代碼
Nodemcu
#define BLINKER_WIFI //選擇WIFI連接模式 #include <Blinker.h> #include <Wire.h>char auth[] = "***************"; //BlinkerAPP內獲取的設備密鑰 char ssid[] = "Your Wi-Fi Name"; //Wi-Fi名稱 char pswd[] = "Your Wi-Fi Password"; //Wi-Fi密碼 BlinkerButton Button1("1"); //新建按鍵對象 BlinkerButton Button2("2"); BlinkerButton Button3("3"); BlinkerButton Button4("4"); BlinkerButton Button5("5"); BlinkerButton Button6("6"); BlinkerButton Button7("7"); BlinkerButton Button8("8"); BlinkerButton Button9("9"); BlinkerButton Button0("0"); BlinkerButton Button11("11");void button1_callback(const String & state) //按鍵1所執行函數 {BLINKER_LOG("get button state: ", state);if (state == BLINKER_CMD_BUTTON_PRESSED) //按鍵按下{Wire.beginTransmission(1); //發送數據到設備號為1的從機Wire.write("f"); // 發送字符串Wire.endTransmission(); // 停止發送Button1.text("向前行駛");Button1.print();} else if(state == BLINKER_CMD_BUTTON_RELEASED)//按鍵釋放{Wire.beginTransmission(1); Wire.write("s"); Wire.endTransmission(); }Blinker.vibrate(); //手機震動 }void button2_callback(const String & state) {BLINKER_LOG("get button state: ", state);if (state == BLINKER_CMD_BUTTON_PRESSED) {Wire.beginTransmission(1); Wire.write("b"); Wire.endTransmission(); } else if(state == BLINKER_CMD_BUTTON_RELEASED){Wire.beginTransmission(1); Wire.write("s"); Wire.endTransmission(); }Blinker.vibrate(); }void button3_callback(const String & state) {BLINKER_LOG("get button state: ", state);if (state == BLINKER_CMD_BUTTON_PRESSED) {Wire.beginTransmission(1); Wire.write("l"); Wire.endTransmission(); } else if(state == BLINKER_CMD_BUTTON_RELEASED){Wire.beginTransmission(1); Wire.write("s"); Wire.endTransmission(); }Blinker.vibrate(); }void button4_callback(const String & state) {BLINKER_LOG("get button state: ", state);if (state == BLINKER_CMD_BUTTON_PRESSED) {Wire.beginTransmission(1);Wire.write("r"); Wire.endTransmission(); } else if(state == BLINKER_CMD_BUTTON_RELEASED){Wire.beginTransmission(1); Wire.write("s"); Wire.endTransmission(); }Blinker.vibrate(); }void button5_callback(const String & state) {BLINKER_LOG("get button state: ", state);if (state == BLINKER_CMD_BUTTON_PRESSED) {Wire.beginTransmission(1); Wire.write("t1"); Wire.endTransmission(); } else if(state == BLINKER_CMD_BUTTON_RELEASED){Wire.beginTransmission(1); Wire.write("s"); Wire.endTransmission(); }Blinker.vibrate(); }void button6_callback(const String & state) {BLINKER_LOG("get button state: ", state);if (state == BLINKER_CMD_BUTTON_PRESSED) {Wire.beginTransmission(1); Wire.write("t2"); Wire.endTransmission(); } else if(state == BLINKER_CMD_BUTTON_RELEASED){Wire.beginTransmission(1); Wire.write("s"); Wire.endTransmission(); }Blinker.vibrate(); }void button7_callback(const String & state) {BLINKER_LOG("get button state: ", state);if (state == BLINKER_CMD_BUTTON_PRESSED) {Wire.beginTransmission(1); Wire.write("lf"); Wire.endTransmission(); } else if(state == BLINKER_CMD_BUTTON_RELEASED){Wire.beginTransmission(1); Wire.write("s"); Wire.endTransmission(); }Blinker.vibrate(); }void button8_callback(const String & state) {BLINKER_LOG("get button state: ", state);if (state == BLINKER_CMD_BUTTON_PRESSED) {Wire.beginTransmission(1); Wire.write("rf"); Wire.endTransmission(); } else if(state == BLINKER_CMD_BUTTON_RELEASED){Wire.beginTransmission(1); Wire.write("s"); Wire.endTransmission(); }Blinker.vibrate(); }void button9_callback(const String & state) {BLINKER_LOG("get button state: ", state);if (state == BLINKER_CMD_BUTTON_PRESSED) {Wire.beginTransmission(1); Wire.write("lb"); Wire.endTransmission(); } else if(state == BLINKER_CMD_BUTTON_RELEASED){Wire.beginTransmission(1); Wire.write("s"); Wire.endTransmission(); }Blinker.vibrate(); }void button0_callback(const String & state) {BLINKER_LOG("get button state: ", state);if (state == BLINKER_CMD_BUTTON_PRESSED) {Wire.beginTransmission(1); Wire.write("rb"); Wire.endTransmission(); } else if(state == BLINKER_CMD_BUTTON_RELEASED){Wire.beginTransmission(1); Wire.write("s"); Wire.endTransmission(); }Blinker.vibrate(); }void button11_callback(const String & state) {BLINKER_LOG("get button state: ", state);if (state == BLINKER_CMD_BUTTON_TAP) {Wire.beginTransmission(1); Wire.write("s"); Wire.endTransmission(); } else if(state == BLINKER_CMD_BUTTON_PRESSED){Wire.beginTransmission(1); Wire.write("s"); Wire.endTransmission(); }Blinker.vibrate(); }void setup() {Wire.begin(D1,D2); //連接從機Serial.begin(115200); //初始化串口BLINKER_DEBUG.stream(Serial);Blinker.begin(auth, ssid, pswd);Button1.attach(button1_callback);Button2.attach(button2_callback);Button3.attach(button3_callback);Button4.attach(button4_callback);Button5.attach(button5_callback);Button6.attach(button6_callback);Button7.attach(button7_callback);Button8.attach(button8_callback);Button9.attach(button9_callback);Button0.attach(button0_callback);Button11.attach(button11_callback); }void loop() {Blinker.run();delay(100); }Arduino
#include <Wire.h>int PWM1=5;int PWM2=6;int PWM3=9;int PWM4=10; int M1A1=2;int M1A2=3; int M2A1=4;int M2A2=7; int M3A1=8;int M3A2=11; int M4A1=12;int M4A2=13;void setup() {Serial.begin(115200);Wire.begin(1); // 加入 i2c 總線,設置從機地址為1Wire.onReceive(receiveEvent); //注冊接收到主機字符的事件pinMode(PWM1,OUTPUT);pinMode(PWM2,OUTPUT);pinMode(PWM3,OUTPUT);pinMode(PWM4,OUTPUT);pinMode(M1A1,OUTPUT);pinMode(M1A2,OUTPUT);pinMode(M2A1,OUTPUT);pinMode(M2A2,OUTPUT);pinMode(M3A1,OUTPUT);pinMode(M3A2,OUTPUT);pinMode(M4A1,OUTPUT);pinMode(M4A2,OUTPUT); }void loop () {delay(200);}void receiveEvent(int a) // 當從機接收到主機字符,執行該事件 {String c;while( Wire.available()>0) {c += char(Wire.read()); // 作為字符接收字節}Serial.print(c); // 把字符打印到串口監視器中if(c=="s") {s();}if(c=="f") {f();}if(c=="b") {b();}if(c=="l") {l();}if(c=="r") {r();}if(c=="t1") {turn1();}if(c=="t2") {turn2();}if(c=="lf") {leftforth();}if(c=="rf") {rightforth();}if(c=="lb") {leftback();}if(c=="rb") {rightback();}}void PWM() //修改PWM數值可改變小車速度 0~255 {analogWrite(PWM1,200);analogWrite(PWM2,200);analogWrite(PWM3,200);analogWrite(PWM4,200); }void s() //小車停止 {digitalWrite(M1A1,LOW); //通過修改高低電頻來修改電機轉與不轉和轉向digitalWrite(M1A2,LOW);digitalWrite(M2A1,LOW);digitalWrite(M2A2,LOW);digitalWrite(M3A1,LOW);digitalWrite(M3A2,LOW);digitalWrite(M4A1,LOW);digitalWrite(M4A2,LOW); }void f() //向前行駛 {digitalWrite(M1A1,HIGH);digitalWrite(M1A2,LOW);digitalWrite(M2A1,HIGH);digitalWrite(M2A2,LOW);digitalWrite(M3A1,HIGH);digitalWrite(M3A2,LOW);digitalWrite(M4A1,HIGH);digitalWrite(M4A2,LOW);PWM(); }void b() //向后行駛 {digitalWrite(M1A1,LOW);digitalWrite(M1A2,HIGH);digitalWrite(M2A1,LOW);digitalWrite(M2A2,HIGH);digitalWrite(M3A1,LOW);digitalWrite(M3A2,HIGH);digitalWrite(M4A1,LOW);digitalWrite(M4A2,HIGH);PWM(); }void l() //向左平移 {digitalWrite(M1A1,LOW);digitalWrite(M1A2,HIGH);digitalWrite(M2A1,HIGH);digitalWrite(M2A2,LOW);digitalWrite(M3A1,HIGH);digitalWrite(M3A2,LOW);digitalWrite(M4A1,LOW);digitalWrite(M4A2,HIGH);PWM(); }void r() //向右平移 {digitalWrite(M1A1,HIGH);digitalWrite(M1A2,LOW);digitalWrite(M2A1,LOW);digitalWrite(M2A2,HIGH);digitalWrite(M3A1,LOW);digitalWrite(M3A2,HIGH);digitalWrite(M4A1,HIGH);digitalWrite(M4A2,LOW);PWM(); } void turn1() //順時針旋轉 {digitalWrite(M1A1,LOW);digitalWrite(M1A2,HIGH);digitalWrite(M2A1,HIGH);digitalWrite(M2A2,LOW);digitalWrite(M3A1,LOW);digitalWrite(M3A2,HIGH);digitalWrite(M4A1,HIGH);digitalWrite(M4A2,LOW);PWM(); }void turn2() //逆時針旋轉 {digitalWrite(M1A1,HIGH);digitalWrite(M1A2,LOW);digitalWrite(M2A1,LOW);digitalWrite(M2A2,HIGH);digitalWrite(M3A1,HIGH);digitalWrite(M3A2,LOW);digitalWrite(M4A1,LOW);digitalWrite(M4A2,HIGH);PWM(); }void leftforth() //向左前方行駛 {digitalWrite(M1A1,LOW);digitalWrite(M1A2,LOW);digitalWrite(M2A1,LOW);digitalWrite(M2A2,HIGH);digitalWrite(M3A1,LOW);digitalWrite(M3A2,HIGH);digitalWrite(M4A1,LOW);digitalWrite(M4A2,LOW);PWM(); }void rightforth() //向右前方行駛 {digitalWrite(M1A1,HIGH);digitalWrite(M1A2,LOW);digitalWrite(M2A1,LOW);digitalWrite(M2A2,LOW);digitalWrite(M3A1,LOW);digitalWrite(M3A2,LOW);digitalWrite(M4A1,HIGH);digitalWrite(M4A2,LOW);PWM(); } void leftback() //向左后方行駛 {digitalWrite(M1A1,LOW);digitalWrite(M1A2,HIGH);digitalWrite(M2A1,LOW);digitalWrite(M2A2,LOW);digitalWrite(M3A1,LOW);digitalWrite(M3A2,LOW);digitalWrite(M4A1,LOW);digitalWrite(M4A2,HIGH);PWM(); } void rightback() //向右后方行駛 {digitalWrite(M1A1,LOW);digitalWrite(M1A2,LOW);digitalWrite(M2A1,HIGH);digitalWrite(M2A2,LOW);digitalWrite(M3A1,HIGH);digitalWrite(M3A2,LOW);digitalWrite(M4A1,LOW);digitalWrite(M4A2,LOW);PWM(); }總結
本作品非常的簡單,利用ArduinoIDE進行編寫的代碼也非常通俗易懂。本人在這里只是提供了一種思路,結構、代碼等方面還有很多可以優化的地方,很多功能也有待開發。本作品利用了無線Wi-Fi去控制,優點是無需自己開發APP端,互聯網連接,沒有遙控距離的限制;但缺點也很明顯,由于接入的是互聯網而非局域網,所以在操控上有明顯的延遲。
(若各個車輪轉向錯誤可以嘗試更改兩電機線線序或者更改代碼中的高低電頻以修改電機轉向)
演示視頻:
【Nodemcu+arduino nano+點燈科技APP制作簡易Wi-Fi遙控麥克納姆輪小車-嗶哩嗶哩】https://b23.tv/kdcCtV
總結
以上是生活随笔為你收集整理的利用Nodemcu+Arduino nano+TB6612+点灯科技APP制作简易麦克纳姆轮Wi-Fi遥控小车的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 免费配音软件哪个好?快把这些软件收好
- 下一篇: Visual Studio 2022 中