2022-6-14 23:08:57 [显示全部楼层]
169浏览
查看: 169|回复: 4

[项目] ESP-NOW控制的小车(深度手工打造)

[复制链接]
本帖最后由 gada888 于 2022-6-15 07:28 编辑

做了个小车.小车底盘是手工深度打造,个人原创,就是利用了有机玻璃边角料.成品效果还不错,小车遥控通讯是用的ESP-NOW协议.ESP-NOW是乐心开发的无线控制协议,它用途可大了.它类似2.4G无线协议.它可以让你连接多个ESP模块进行通讯,并且不依赖WIFI网络.因此网络上可见很多创客用ESP-NOW做的有意思的项目.例如智能养花,防丢器等等.据说有网友把它的控制距离弄到了450M,我自己的实测是最大空旷距离100M.50M内稳定控制.这次带来的小车案例是首先找到了国外创客的小车项目.测试时候发现他的代码冗长复杂.要先用代码把模拟控制摇杆的信号转换成数字信号.然后驱动电机.這就造成初学者会很难在这个基础上修改.很容易脑子乱掉.所以我把他的代码做了深度简化.把最复杂的那段C++的struc命令代码传递模拟信号改成了直接传递数字信号.这样不仅简洁,而且便于我添加功能.
showcase.png


下面给点ESP-NOW的简介
ESP-NOW 可以让低功耗控制器直接控制所有智能照明设备而无需连接
路由器。这种方式具有低功耗和方便简易的特点。


ESP-NOW 是由乐鑫开发的另一款协议,可以使多个设备在没有或不使用 Wi-Fi 的情况下进行通信。这种协议类似常见于无线鼠标中的低功耗 2.4GHz 无线连接——设备在进行通信之前要进行配对。配对之后,设备之间的连接是持续的、点对点的,并且不需要握手协议。
=================先插一句题外话,为什么选用FireBeetle 2 ESP32-E IoT 开发板和FireBeetle 2:Gravity IO扩展板?
主要是因为连线方便.这个模块上面有清晰标注了ESP32的脚位,众所周知,ESP32的脚位最乱.你看标注都是标两套,通常大家不知道标注的脚位和代码里写的脚位怎么对应,

初学者也往往搞的晕头转向,这个扩展模块清晰的把数字和模拟信号脚列了出来

下面给两张图一看就明白了
2022-06-15_071643.png
2022-06-15_071631.png




下面老规矩,先上图


展示 (3).jpg
手工打造的遥控发射器,用按钮发送数字信号
展示 (1).jpg
深度手工打造的小车地盘,这里小车的电机驱动用的是两个大功率MOSFET模块
展示 (2).jpg
小车全家福

第二步
硬件清单


序号 元件名称 数量 链接
1 FireBeetle 2 ESP32-E IoT 2 https://www.dfrobot.com.cn/goods-3048.html
2 FireBeetle 2:Gravity IO扩展板 2 https://www.dfrobot.com.cn/goods-3293.html
3 3PI MiniQ N20电机支架 2 https://www.dfrobot.com.cn/goods-750.html
4 n20微型金属减速电机 2 https://www.dfrobot.com.cn/goods-1704.html
5 3PI miniQ 小车橡胶轮 2 https://www.dfrobot.com.cn/goods-749.html
6 锂电池3.7Vx2和7.4Vx13 https://www.dfrobot.com.cn/goods-434.html
https://www.dfrobot.com.cn/goods-534.html
7 按钮 4 https://www.dfrobot.com.cn/goods-78.html
8
9 mosfet模块 2 某宝买的
10 DC2.1 电源转接头 2 https://www.dfrobot.com.cn/goods-569.html
11 牛眼轮 万向轮 1 https://www.dfrobot.com.cn/goods-350.html

第三步
知识点


首先FireBeetle 2 ESP32-E IoT是在Arduino ide编程的.它的bootloader对应的是NodeMCU32-S

NodeMCU32-S.jpg
其次,编程时要先找到接收信号的ESP32模块的MAC地址.这个地址是要写进发送信号的ESP32模块的.就是我要发送信号的话,我要知道发送给谁,并且只发送给他.
MAC.png

把上面的代码在ESP32模块,就是用来接收信号的模块运行.然后会在COM里看到你的MAC地址.例如TX-NodeMCU-32S
接收端的MAC
A8:03:2A:EA:AB:40
你要把这个写入你的发送端ESP32里,注意写错将无法完成任务.
2022-06-14_225048.png

最后谈谈为什么用mosfet来做电机驱动.本来可以用电机驱动来完成任务的.可问题是很多电机驱动需要写analogwrite命令,可偏偏ESP32写analogwrite很麻烦,它没有arduino那样支持直接写analogwrite.然后有个简单的选项是用继电器来完成驱动电机的工作.可问题又来了.ESP32的脚位输出电流是最大40mA.而继电器触发需要的电流是大约70mA.最后发现只有mosfet能满足要求.mosfet的规格如下

ok-mosfet.jpg
mosfet 3.3V就能信号触发了.而且输出电压5V+.电流可以到15A.

===============
说句题外话,我最开始是连接的继电器.因为遥控类模块除了串口,你什么也看不见,出了问题你很难找bug.因此我先用relay来做了测试.relay上的灯可以很好的反应出遥控信号的接收情况.
relay wiring.jpg

================
接下来是这个案例的的ESP32发送端和接收端的连线图

Trans-wiring.jpg 发射端ESP32连线图

ReceiverWiring.jpg
接收端ESP32连线图

最后是代码部分

ok-espnow.png

  1. #include "WiFi.h"
  2. void setup()
  3. {
  4.   Serial.begin(115200);
  5.   WiFi.mode(WIFI_MODE_STA);
  6.   Serial.println(WiFi.macAddress());
  7. }
  8. void loop()
  9. {
  10. }
复制代码

查找MAC地址的代码

复制代码
  1. #include <esp_now.h>
  2. #include <WiFi.h>
  3. #define a_AXIS_PIN 12
  4. #define b_AXIS_PIN 4
  5. #define c_AXIS_PIN 16
  6. #define d_AXIS_PIN 17
  7. // REPLACE WITH YOUR RECEIVER MAC Address
  8. uint8_t receiverMacAddress[] = {0xA8,0x03,0x2A,0xEA,0xAB,0x40};  //A8:03:2A:EA:AB:40
  9. struct MessageData
  10. {
  11.   int aAxisValue;
  12.   int bAxisValue;
  13.   int cAxisValue;
  14.   int dAxisValue;
  15. };
  16. MessageData messageData;
  17. // callback when data is sent
  18. void OnDataSent(const uint8_t *mac_addr, esp_now_send_status_t status)
  19. {
  20.   Serial.print("\r\nLast Packet Send Status:\t ");
  21.   Serial.println(status);
  22.   Serial.println(status == ESP_NOW_SEND_SUCCESS ? "Message sent" : "Message failed");
  23. }
  24. void setup()
  25. {
  26.   
  27.   Serial.begin(115200);
  28.   WiFi.mode(WIFI_STA);
  29.   // Init ESP-NOW
  30.   if (esp_now_init() != ESP_OK)
  31.   {
  32.     Serial.println("Error initializing ESP-NOW");
  33.     return;
  34.   }
  35.   else
  36.   {
  37.     Serial.println("Succes: Initialized ESP-NOW");
  38.   }
  39.   esp_now_register_send_cb(OnDataSent);
  40.   
  41.   // Register peer
  42.   esp_now_peer_info_t peerInfo;
  43.   memcpy(peerInfo.peer_addr, receiverMacAddress, 6);
  44.   peerInfo.channel = 0;  
  45.   peerInfo.encrypt = false;
  46.   
  47.   // Add peer        
  48.   if (esp_now_add_peer(&peerInfo) != ESP_OK)
  49.   {
  50.     Serial.println("Failed to add peer");
  51.     return;
  52.   }
  53.   else
  54.   {
  55.     Serial.println("Succes: Added peer");
  56.   }  
  57. }
  58. void loop()
  59. {
  60.   messageData.aAxisValue = digitalRead(a_AXIS_PIN);
  61.   messageData.bAxisValue = digitalRead(b_AXIS_PIN);
  62.   messageData.cAxisValue = digitalRead(c_AXIS_PIN);
  63.   messageData.dAxisValue = digitalRead(d_AXIS_PIN);
  64.   delay(500);
  65.   
  66.   esp_err_t result = esp_now_send(receiverMacAddress, (uint8_t *) &messageData, sizeof(messageData));
  67.   if (result == ESP_OK)
  68.   {
  69.     Serial.println("Sent with success");
  70.   }
  71.   else
  72.   {
  73.     Serial.println("Error sending the data");
  74.   }   
  75. }
复制代码


这是发射端代码,记得改MAC地址.因为每个ESP32的MAC都不同.

  1. #include <esp_now.h>
  2. #include <WiFi.h>
  3. int DIR1 = 12;
  4. int DIR2 = 4;
  5. int LEFT_THRESHOLD = 0;
  6. int RIGHT_THRESHOLD = 0;
  7. int UP_THRESHOLD = 0;
  8. int DOWN_THRESHOLD = 0;
  9. //===========================
  10. typedef struct RxStruct
  11. {
  12.   int aAxisValue;//To store value of the a
  13.   int bAxisValue;// To store value of the b
  14.   int cAxisValue;//To store value of the c
  15.   int dAxisValue;// To store value of the d
  16. }RxStruct;
  17. RxStruct messageData;
  18. //===================
  19. // callback function that will be executed when data is received
  20. void OnDataRecv(const uint8_t * mac, const uint8_t *incomingData, int len)
  21. {
  22.   if (len == 0)
  23.   {
  24.     return;
  25.   }
  26.   memcpy(&messageData, incomingData, sizeof(messageData));
  27.   String inputData ;
  28.   inputData = inputData + "values " + messageData.aAxisValue + "  " + messageData.bAxisValue+ "  " + messageData.cAxisValue+ "  " + messageData.dAxisValue;
  29.   Serial.println(inputData);
  30. }
  31. //=========================
  32. void setup()
  33. {
  34. pinMode(DIR1, OUTPUT);
  35. pinMode(DIR2, OUTPUT);
  36.   Serial.begin(115200);
  37.   WiFi.mode(WIFI_STA);
  38.   // Init ESP-NOW
  39.   if (esp_now_init() != ESP_OK)
  40.   {
  41.     Serial.println("Error initializing ESP-NOW");
  42.     return;
  43.   }
  44.   esp_now_register_recv_cb(OnDataRecv);
  45. }
  46. //=============================
  47. void loop()
  48. {
  49.    if (messageData.aAxisValue > LEFT_THRESHOLD) {      //Move car Forward
  50.      Serial.println("Forward");
  51.     digitalWrite(DIR1, HIGH);
  52.     digitalWrite(DIR2, HIGH);
  53.    }
  54.     else if (messageData.bAxisValue > RIGHT_THRESHOLD){  //Move car STOP
  55.      Serial.println("Stop");
  56.     digitalWrite(DIR1, LOW);
  57.     digitalWrite(DIR2, LOW);
  58.    }
  59.   if (messageData.cAxisValue > UP_THRESHOLD){   //Move car LEFT
  60.     Serial.println("Left");
  61.     digitalWrite(DIR1, HIGH);
  62.     digitalWrite(DIR2, LOW);
  63.     }
  64.    else if (messageData.dAxisValue > DOWN_THRESHOLD){   //Move car RIGHT
  65.     Serial.println("Right");
  66.     digitalWrite(DIR1, LOW);
  67.     digitalWrite(DIR2, HIGH);
  68.   }
  69. }
复制代码
这是接收端的代码



telling0000  见习技师

发表于 2022-6-15 09:41:20

学习,为了创造力
回复

使用道具 举报

gada888  版主
 楼主|

发表于 2022-6-16 15:29:36

telling0000 发表于 2022-6-15 09:41
学习,为了创造力

多谢鼓励
回复

使用道具 举报

zhouzhuofeng  初级技师

发表于 2022-6-17 08:15:49

学习,为了创造力
回复

使用道具 举报

gada888  版主
 楼主|

发表于 2022-6-17 10:52:57


多谢鼓励
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

为本项目制作心愿单
购买心愿单
心愿单 编辑
[[wsData.name]]

硬件清单

  • [[d.name]]
btnicon
我也要做!
点击进入购买页面
上海智位机器人股份有限公司 沪ICP备09038501号-4

© 2013-2022 Comsenz Inc. Powered by Discuz! X3.4 Licensed

mail