跟站长阿张折腾硬件之第三版本 esp32控+esp32接收端 (esp-now,Arduino IDE)
发布于
第三个版本,使用espnow模式(wifi broadcast)传输信号,使用esp32遥控端读取摇杆中的电位器信号,通过espnow 广播遥控信号。esp32接收端接收到信号包,转换成pwm控制信号,分别控制舵机和电调控制小车。
这个视频中有一部分讲代码中要调整的部分
https://www.bilibili.com/video/BV1pM411H7KS/?vd_source=5112aa86344ed83491a31bc47f2b5e76
接线方式
接线方式同 第二版本一致
https://www.xiwnn.com/article/a_64318283a086df73c41a3ff6.html
代码部分
发送端 (ESP32 摇杆端)
记得改一下这份代码中的接收端MAC地址,不然连接不上。先刷接收端,运行之后,在串口监视器中有打出。
// 参考自此文章 https://zhuanlan.zhihu.com/p/344109867
#include <WiFi.h>
#include <esp_now.h>
//Are we currently connected?
boolean connected = false;
// 设置遥控数据结构体
typedef struct rc_struct_message {
int ch1;
int ch2;
} rc_struct_message;
rc_struct_message rcData;
int LED_BUILTIN = 2;
bool ledShow = false;
int baseX = 0;
int baseY = 0;
// 100的间隙
int gap = 100;
// 接收设备的 MAC 地址,运行接收端的esp32后,从串口监视器中获得
uint8_t broadcastAddress[] = {0xE0, 0x5A, 0x1B, 0xA0, 0x04, 0xB4};
unsigned long timeNow = 0;
// 上一次发送数据的成功时间
unsigned long lastTickTime = millis();
// 数据发送回调函数
void OnDataSent(const uint8_t *mac_addr, esp_now_send_status_t status) {
if (status == ESP_NOW_SEND_SUCCESS) {
lastTickTime = millis();
}
// char macStr[18];
// Serial.print("Packet to: ");
// snprintf(macStr, sizeof(macStr), "%02x:%02x:%02x:%02x:%02x:%02x",
// mac_addr[0], mac_addr[1], mac_addr[2], mac_addr[3], mac_addr[4], mac_addr[5]);
// Serial.println(macStr);
// Serial.print("Send status: ");
// Serial.println(status == ESP_NOW_SEND_SUCCESS ? "Delivery Success" : "Delivery Fail");
// Serial.println();
}
void setup() {
Serial.begin(9600);
baseX = analogRead(35); // X 读取35针脚
baseY = analogRead(34); // Y 读取34针脚
WiFi.mode(WIFI_MODE_STA);
Serial.print("ESP32 RC TX MAC Address: ");
Serial.println(WiFi.macAddress());
if (esp_now_init() != ESP_OK) {
Serial.println("Error initializing ESP-NOW");
return;
}
// 设置发送数据回调函数
esp_now_register_send_cb(OnDataSent);
// 绑定数据接收端
esp_now_peer_info_t peerInfo;
memcpy(peerInfo.peer_addr, broadcastAddress, 6);
peerInfo.channel = 0;
peerInfo.encrypt = false;
// 检查设备是否配对成功
if (esp_now_add_peer(&peerInfo) != ESP_OK) {
Serial.println("Failed to add peer");
return;
}
pinMode(LED_BUILTIN, OUTPUT); // Initialize the LED_BUILTIN pin as an output
}
int MAX = 4096;
int vx = 0;
int vy = 0;
int sendMax = 1024;
int sendHaf = sendMax / 2;
// 输出到频道值 0 - 1024;
int ch1Value = 0;
int ch2Value = 0;
int ledLoopTick = -1;
void loop() {
timeNow = millis();
vx = analogRead(35);
vy = analogRead(34);
ch1Value = sendHaf;
ch2Value = sendHaf;
if (vx > baseX) {
if (vx > baseX + gap) {
ch1Value = int(float(vx - baseX - gap) / (MAX - baseX - gap) * sendHaf) + sendHaf;
}
} else {
if (vx < baseX - gap) {
ch1Value = int(float(vx) / float(baseX - gap) * sendHaf);
}
}
if (vy > baseY) {
if (vy > baseY + gap) {
ch2Value = int(float(vy - baseY - gap) / (MAX - baseY - gap) * sendHaf) + sendHaf;
}
} else {
if (vy < baseY - gap) {
ch2Value = int(float(vy) / float(baseY - gap) * sendHaf);
}
}
rcData.ch1 = ch1Value;
rcData.ch2 = ch2Value;
// 发送数据
esp_now_send(broadcastAddress, (uint8_t *) &rcData, sizeof(rcData));
if (timeNow - lastTickTime > 1000) {
// 没发送成功,进行闪烁
ledLoopTick += 1;
if (ledLoopTick >= 50) { // 闪太快看不清,隔50帧闪一次
ledLoopTick = 0;
}
if (ledLoopTick == 0) {
if (ledShow) {
digitalWrite(LED_BUILTIN, LOW);
ledShow = false;
} else {
digitalWrite(LED_BUILTIN, HIGH);
ledShow = true;
}
}
delay(10);
} else {
ledShow = true;
digitalWrite(LED_BUILTIN, HIGH);
}
delay(1); // 去掉
}
接收端(ESP32 车上端)
#include "WiFi.h"
#include <esp_now.h>
#include <stdio.h>
// 设置遥控数据结构体
typedef struct rc_struct_message {
int ch1;
int ch2;
} rc_struct_message;
rc_struct_message rcData;
/**
* 封装舵机的控制类
*/
class LedcServo {
public:
float freq = 50;
int resolution = 8;
float pwmBaseScale;
float pwmMin;
float pwmMax;
int channel;
int scale = 1;
void setup(float freq, int resolution, int channel);
/* 0 < scale <= 1 */
void setScale(float scale);
void attachPin(int pin);
void write(float value, float min, float max);
};
void LedcServo:: setup(float f, int r, int c) {
this->freq = f;
this->resolution = r;
this->pwmBaseScale = this->freq * pow(2, this->resolution) / 1000;
this->pwmMin = 1 * this->pwmBaseScale;
this->pwmMax = 2 * this->pwmBaseScale;
this->channel = c;
ledcSetup(this->channel, this->freq, this->resolution);
}
void LedcServo:: setScale(float s) {
if (s <= 0) throw "s 不能小于等于0";
if (s > 1) throw "s 不能大于1";
this->scale = s;
this->pwmMin = (1.5 - s) * this->pwmBaseScale;
this->pwmMax = (1.5 + s) * this->pwmBaseScale;
}
void LedcServo:: attachPin(int p) {
ledcAttachPin(p, this->channel);
}
void LedcServo:: write(float v, float min, float max) {
ledcWrite(this->channel, map(v, min, max, this->pwmMin, this->pwmMax));
// Serial.println(this->channel);
// Serial.println(v);
}
int sendMin = 0;
int sendMax = 1024;
int sendHaf = sendMax / 2;
int rxC1 = sendHaf;
int rxC2 = sendHaf;
int lastRxC1 = sendHaf;
int lastRxC2 = sendHaf;
LedcServo rxC1Servo;
LedcServo rxC1ServoHaf;
LedcServo rxC2Servo;
LedcServo rxC2ServoHaf;
unsigned long timeNow = 0;
unsigned long lastDataTickTime = 0;
int LED_BUILTIN = 2;
bool ledShow = false;
int ledLoopTick = -1;
// 数据接收回调函数
void OnDataRecv(const uint8_t * mac, const uint8_t *incomingData, int len) {
memcpy(&rcData, incomingData, sizeof(rcData));
rxC1 = rcData.ch1;
rxC2 = rcData.ch2;
lastDataTickTime = millis();
}
void setup() {
pinMode(LED_BUILTIN, OUTPUT); // Initialize the LED_BUILTIN pin as an output
digitalWrite(LED_BUILTIN, LOW);
rxC1Servo.setup(100, 10, 8);
rxC1Servo.attachPin(23); // 动力电机控制信号全强度,动力会很猛
rxC1Servo.setScale(1); // 全强度
rxC1Servo.write(0, -1, 1);
rxC1ServoHaf.setup(100, 10, 9);
rxC1ServoHaf.attachPin(22); // 动力电机控制信号一半强度,动力会可控一些
rxC1ServoHaf.setScale(0.3); // 半强度
rxC1ServoHaf.write(0, -1, 1);
rxC2Servo.setup(500, 10, 10);
rxC2Servo.attachPin(26); // 方向舵机信号全强度, 容易侧翻
rxC2Servo.setScale(0.7); // 半角度,顽皮龙D12的转向角最大到这个角度,继续调大,会让舵机在左右两边憋力,最后可能造成舵机齿轮扫坏。
// 其它类型的车辆
rxC2Servo.write(0, -1, 1);
rxC2ServoHaf.setup(500, 10, 11);
rxC2ServoHaf.attachPin(25); // 方向舵机信号一半强度,防止转弯过度
rxC2ServoHaf.setScale(0.3); // 小角度
rxC2ServoHaf.write(0, -1, 1);
Serial.begin(9600);
Serial.println();
Serial.print("Configuring access point...");
// 初始化 ESP-NOW
WiFi.mode(WIFI_STA);
Serial.print("ESP32 RC RX MAC Address: ");
Serial.println(WiFi.macAddress());
if (esp_now_init() != 0) {
Serial.println("Error initializing ESP-NOW");
return;
}
// 设置接收数据回调函数
esp_now_register_recv_cb(OnDataRecv);
}
void updateServo() {
if (lastRxC1 != rxC1) {
rxC1Servo.write(rxC1, sendMin, sendMax);
rxC1ServoHaf.write(rxC1, sendMin, sendMax);
lastRxC1 = rxC1;
}
if (lastRxC2 != rxC2) {
rxC2Servo.write(rxC2, sendMax, sendMin); // 反向
rxC2ServoHaf.write(rxC2, sendMax, sendMin); // 反向
lastRxC2 = rxC2;
}
}
void loop() {
timeNow = millis();
if (timeNow > lastDataTickTime && timeNow - lastDataTickTime > 1000) {
// 超过1秒未收到数据,自动归中,开始闪灯
rxC1 = sendHaf;
rxC2 = sendHaf;
ledLoopTick += 1;
if (ledLoopTick >= 50) { // 闪太快看不清,隔50帧闪一次
ledLoopTick = 0;
}
if (ledLoopTick == 0) {
if (ledShow) {
digitalWrite(LED_BUILTIN, LOW);
ledShow = false;
} else {
digitalWrite(LED_BUILTIN, HIGH);
ledShow = true;
}
}
delay(10);
} else {
// 有数据,就常亮
digitalWrite(LED_BUILTIN, HIGH);
ledShow = true;
}
updateServo();
}
或 匿名发表评论
找到 0 条评论