ESP-NOW控制的小车(深度手工打造)
本帖最后由 gada888 于 2022-6-15 07:28 编辑做了个小车.小车底盘是手工深度打造,个人原创,就是利用了有机玻璃边角料.成品效果还不错,小车遥控通讯是用的ESP-NOW协议.ESP-NOW是乐心开发的无线控制协议,它用途可大了.它类似2.4G无线协议.它可以让你连接多个ESP模块进行通讯,并且不依赖WIFI网络.因此网络上可见很多创客用ESP-NOW做的有意思的项目.例如智能养花,防丢器等等.据说有网友把它的控制距离弄到了450M,我自己的实测是最大空旷距离100M.50M内稳定控制.这次带来的小车案例是首先找到了国外创客的小车项目.测试时候发现他的代码冗长复杂.要先用代码把模拟控制摇杆的信号转换成数字信号.然后驱动电机.這就造成初学者会很难在这个基础上修改.很容易脑子乱掉.所以我把他的代码做了深度简化.把最复杂的那段C++的struc命令代码传递模拟信号改成了直接传递数字信号.这样不仅简洁,而且便于我添加功能.
https://www.bilibili.com/video/BV1KS4y1v7V4/
下面给点ESP-NOW的简介
ESP-NOW 可以让低功耗控制器直接控制所有智能照明设备而无需连接
路由器。这种方式具有低功耗和方便简易的特点。
ESP-NOW 是由乐鑫开发的另一款协议,可以使多个设备在没有或不使用 Wi-Fi 的情况下进行通信。这种协议类似常见于无线鼠标中的低功耗 2.4GHz 无线连接——设备在进行通信之前要进行配对。配对之后,设备之间的连接是持续的、点对点的,并且不需要握手协议。
=================先插一句题外话,为什么选用FireBeetle 2 ESP32-E IoT 开发板和FireBeetle 2:Gravity IO扩展板?
主要是因为连线方便.这个模块上面有清晰标注了ESP32的脚位,众所周知,ESP32的脚位最乱.你看标注都是标两套,通常大家不知道标注的脚位和代码里写的脚位怎么对应,
初学者也往往搞的晕头转向,这个扩展模块清晰的把数字和模拟信号脚列了出来
下面给两张图一看就明白了
下面老规矩,先上图
手工打造的遥控发射器,用按钮发送数字信号
深度手工打造的小车地盘,这里小车的电机驱动用的是两个大功率MOSFET模块
小车全家福
第二步
硬件清单
序号 元件名称 数量 链接
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
其次,编程时要先找到接收信号的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);
}
}
这是接收端的代码
学习,为了创造力 telling0000 发表于 2022-6-15 09:41
学习,为了创造力
多谢鼓励 学习,为了创造力
zhouzhuofeng 发表于 2022-6-17 08:15
学习,为了创造力
多谢鼓励
页:
[1]