gada888 发表于 2022-6-14 23:08:57

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: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

zhouzhuofeng 发表于 2022-6-17 08:15
学习,为了创造力

多谢鼓励
页: [1]
查看完整版本: ESP-NOW控制的小车(深度手工打造)