本帖最后由 gada888 于 2022-6-15 07:28 编辑
做了个小车.小车底盘是手工深度打造,个人原创,就是利用了有机玻璃边角料.成品效果还不错,小车遥控通讯是用的ESP-NOW协议.ESP-NOW是乐心开发的无线控制协议,它用途可大了.它类似2.4G无线协议.它可以让你连接多个ESP模块进行通讯,并且不依赖WIFI网络.因此网络上可见很多创客用ESP-NOW做的有意思的项目.例如智能养花,防丢器等等.据说有网友把它的控制距离弄到了450M,我自己的实测是最大空旷距离100M.50M内稳定控制.这次带来的小车案例是首先找到了国外创客的小车项目.测试时候发现他的代码冗长复杂.要先用代码把模拟控制摇杆的信号转换成数字信号.然后驱动电机.這就造成初学者会很难在这个基础上修改.很容易脑子乱掉.所以我把他的代码做了深度简化.把最复杂的那段C++的struc命令代码传递模拟信号改成了直接传递数字信号.这样不仅简洁,而且便于我添加功能.
下面给点ESP-NOW的简介
ESP-NOW 可以让低功耗控制器直接控制所有智能照明设备而无需连接
路由器。这种方式具有低功耗和方便简易的特点。
ESP-NOW 是由乐鑫开发的另一款协议,可以使多个设备在没有或不使用 Wi-Fi 的情况下进行通信。这种协议类似常见于无线鼠标中的低功耗 2.4GHz 无线连接——设备在进行通信之前要进行配对。配对之后,设备之间的连接是持续的、点对点的,并且不需要握手协议。
=================先插一句题外话,为什么选用FireBeetle 2 ESP32-E IoT 开发板和FireBeetle 2:Gravity IO扩展板?
主要是因为连线方便.这个模块上面有清晰标注了ESP32的脚位,众所周知,ESP32的脚位最乱.你看标注都是标两套,通常大家不知道标注的脚位和代码里写的脚位怎么对应,
初学者也往往搞的晕头转向,这个扩展模块清晰的把数字和模拟信号脚列了出来
下面给两张图一看就明白了
下面老规矩,先上图
手工打造的遥控发射器,用按钮发送数字信号
深度手工打造的小车地盘,这里小车的电机驱动用的是两个大功率MOSFET模块
小车全家福
第二步
硬件清单
第三步
知识点
首先FireBeetle 2 ESP32-E IoT是在Arduino ide编程的.它的bootloader对应的是NodeMCU32-S
其次,编程时要先找到接收信号的ESP32模块的MAC地址.这个地址是要写进发送信号的ESP32模块的.就是我要发送信号的话,我要知道发送给谁,并且只发送给他.
把上面的代码在ESP32模块,就是用来接收信号的模块运行.然后会在COM里看到你的MAC地址.例如TX-NodeMCU-32S
接收端的MAC
A8:03:2A:EA:AB:40
你要把这个写入你的发送端ESP32里,注意写错将无法完成任务.
最后谈谈为什么用mosfet来做电机驱动.本来可以用电机驱动来完成任务的.可问题是很多电机驱动需要写analogwrite命令,可偏偏ESP32写analogwrite很麻烦,它没有arduino那样支持直接写analogwrite.然后有个简单的选项是用继电器来完成驱动电机的工作.可问题又来了.ESP32的脚位输出电流是最大40mA.而继电器触发需要的电流是大约70mA.最后发现只有mosfet能满足要求.mosfet的规格如下
mosfet 3.3V就能信号触发了.而且输出电压5V+.电流可以到15A.
===============
说句题外话,我最开始是连接的继电器.因为遥控类模块除了串口,你什么也看不见,出了问题你很难找bug.因此我先用relay来做了测试.relay上的灯可以很好的反应出遥控信号的接收情况.
================
接下来是这个案例的的ESP32发送端和接收端的连线图
发射端ESP32连线图
接收端ESP32连线图
最后是代码部分
- #include "WiFi.h"
-
- void setup()
- {
- Serial.begin(115200);
- WiFi.mode(WIFI_MODE_STA);
- Serial.println(WiFi.macAddress());
- }
-
- void loop()
- {
-
- }
复制代码
查找MAC地址的代码
复制代码
- #include <esp_now.h>
- #include <WiFi.h>
-
- #define a_AXIS_PIN 12
- #define b_AXIS_PIN 4
- #define c_AXIS_PIN 16
- #define d_AXIS_PIN 17
-
- // REPLACE WITH YOUR RECEIVER MAC Address
- uint8_t receiverMacAddress[] = {0xA8,0x03,0x2A,0xEA,0xAB,0x40}; //A8:03:2A:EA:AB:40
-
- struct MessageData
- {
- int aAxisValue;
- int bAxisValue;
- int cAxisValue;
- int dAxisValue;
- };
-
- MessageData messageData;
-
- // callback when data is sent
- void OnDataSent(const uint8_t *mac_addr, esp_now_send_status_t status)
- {
- Serial.print("\r\nLast Packet Send Status:\t ");
- Serial.println(status);
- Serial.println(status == ESP_NOW_SEND_SUCCESS ? "Message sent" : "Message failed");
- }
-
- void setup()
- {
-
- Serial.begin(115200);
- WiFi.mode(WIFI_STA);
-
- // Init ESP-NOW
- if (esp_now_init() != ESP_OK)
- {
- Serial.println("Error initializing ESP-NOW");
- return;
- }
- else
- {
- Serial.println("Succes: Initialized ESP-NOW");
- }
-
- esp_now_register_send_cb(OnDataSent);
-
- // Register peer
- esp_now_peer_info_t peerInfo;
- memcpy(peerInfo.peer_addr, receiverMacAddress, 6);
- peerInfo.channel = 0;
- peerInfo.encrypt = false;
-
- // Add peer
- if (esp_now_add_peer(&peerInfo) != ESP_OK)
- {
- Serial.println("Failed to add peer");
- return;
- }
- else
- {
- Serial.println("Succes: Added peer");
- }
- }
-
- void loop()
- {
- messageData.aAxisValue = digitalRead(a_AXIS_PIN);
- messageData.bAxisValue = digitalRead(b_AXIS_PIN);
- messageData.cAxisValue = digitalRead(c_AXIS_PIN);
- messageData.dAxisValue = digitalRead(d_AXIS_PIN);
- delay(500);
-
- esp_err_t result = esp_now_send(receiverMacAddress, (uint8_t *) &messageData, sizeof(messageData));
- if (result == ESP_OK)
- {
- Serial.println("Sent with success");
- }
- else
- {
- Serial.println("Error sending the data");
- }
- }
复制代码
这是发射端代码,记得改MAC地址.因为每个ESP32的MAC都不同.
- #include <esp_now.h>
- #include <WiFi.h>
-
- int DIR1 = 12;
- int DIR2 = 4;
-
- int LEFT_THRESHOLD = 0;
- int RIGHT_THRESHOLD = 0;
- int UP_THRESHOLD = 0;
- int DOWN_THRESHOLD = 0;
- //===========================
- typedef struct RxStruct
- {
- int aAxisValue;//To store value of the a
- int bAxisValue;// To store value of the b
- int cAxisValue;//To store value of the c
- int dAxisValue;// To store value of the d
- }RxStruct;
- RxStruct messageData;
- //===================
-
- // callback function that will be executed when data is received
- void OnDataRecv(const uint8_t * mac, const uint8_t *incomingData, int len)
- {
- if (len == 0)
- {
- return;
- }
- memcpy(&messageData, incomingData, sizeof(messageData));
- String inputData ;
- inputData = inputData + "values " + messageData.aAxisValue + " " + messageData.bAxisValue+ " " + messageData.cAxisValue+ " " + messageData.dAxisValue;
- Serial.println(inputData);
- }
-
- //=========================
- void setup()
- {
- pinMode(DIR1, OUTPUT);
- pinMode(DIR2, OUTPUT);
-
- Serial.begin(115200);
- WiFi.mode(WIFI_STA);
-
- // Init ESP-NOW
- if (esp_now_init() != ESP_OK)
- {
- Serial.println("Error initializing ESP-NOW");
- return;
- }
-
- esp_now_register_recv_cb(OnDataRecv);
- }
- //=============================
- void loop()
- {
- if (messageData.aAxisValue > LEFT_THRESHOLD) { //Move car Forward
- Serial.println("Forward");
- digitalWrite(DIR1, HIGH);
- digitalWrite(DIR2, HIGH);
- }
- else if (messageData.bAxisValue > RIGHT_THRESHOLD){ //Move car STOP
- Serial.println("Stop");
- digitalWrite(DIR1, LOW);
- digitalWrite(DIR2, LOW);
- }
- if (messageData.cAxisValue > UP_THRESHOLD){ //Move car LEFT
- Serial.println("Left");
- digitalWrite(DIR1, HIGH);
- digitalWrite(DIR2, LOW);
- }
- else if (messageData.dAxisValue > DOWN_THRESHOLD){ //Move car RIGHT
- Serial.println("Right");
- digitalWrite(DIR1, LOW);
- digitalWrite(DIR2, HIGH);
- }
- }
-
复制代码
这是接收端的代码
|