1.发现问题
使用qcoder或者chatgpt编写espnow相互通信的程序都不能正常工作,显示错误:E (1134) ESPNOW: Peer interface is invalid
2.问题关键
仔细研究了esp关于wifi方面的文档,并且仔细理解了下peer interface is invalid这句话到底是哪里出错了,后来推测是不是esp-now需要指定ifidx这个参数,
wifi_interface_t ifidx:说明如下
Wi-Fi interface that peer uses to send/receive ESPNOW data
程序中是没有指定这个参数的,所以参考文档,指定了这个参数,在 peer information里面加了一句:
peerInfo.ifidx = WIFI_IF_STA;
最后测试成功了。
3.发送端代码
#include <Arduino.h>
#include <esp_now.h>
#include <WiFi.h>
#define LED_PIN 2 // D2引脚定义
#define JOY_X_PIN 32 // Joystick X轴连接到GPIO32
#define JOY_Y_PIN 33 // Joystick Y轴连接到GPIO33
#define JOY_SW_PIN 27 // Joystick按钮连接到GPIO27
#define JOY_CENTER 1855 // Joystick中心值
#define DEAD_ZONE 40 // 死区范围,正负40以内视为0
// 结构体:用于发送Joystick数据
typedef struct {
int xValue;
int yValue;
int buttonState;
} joystick_data_t;
// 目标ESP32的MAC地址(接收端)- 需要替换为实际的接收端MAC地址
uint8_t receiver_mac[] = {0x58, 0xBF, 0x25, 0x16, 0xCA, 0xB8};
// 函数:应用死区处理
int applyDeadZone(int value) {
if (value >= -DEAD_ZONE && value <= DEAD_ZONE) {
return 0; // 在死区内返回0
} else {
return value; // 超出死区则返回原始值
}
}
// 发送回调函数
void OnDataSent(const uint8_t *mac_addr, esp_now_send_status_t status) {
Serial.print("数据发送 ");
Serial.println(status == ESP_NOW_SEND_SUCCESS ? "成功" : "失败");
}
void setup() {
// 初始化串口通信
Serial.begin(115200);
delay(1000);
// 将D2引脚设置为输出模式
pinMode(LED_PIN, OUTPUT);
// 将Joystick按钮引脚设置为输入模式,启用内部上拉电阻
pinMode(JOY_SW_PIN, INPUT_PULLUP);
Serial.print("当前ESP32的MAC地址: ");
Serial.println(WiFi.macAddress());
Serial.print("目标ESP32的MAC地址: ");
char macStr[18];
sprintf(macStr, "%02X:%02X:%02X:%02X:%02X:%02X", receiver_mac[0], receiver_mac[1], receiver_mac[2], receiver_mac[3], receiver_mac[4], receiver_mac[5]);
Serial.println(macStr);
// 初始化WiFi(必需,但不连接到任何网络)
WiFi.mode(WIFI_STA);
// 初始化ESP-NOW
if (esp_now_init() != ESP_OK) {
Serial.println("ESP-NOW初始化失败");
return;
}
Serial.println("ESP-NOW初始化成功");
// 注册发送回调函数
esp_now_register_send_cb(OnDataSent);
Serial.println("发送回调函数注册成功");
// 添加接收端作为对等设备
esp_now_peer_info_t peerInfo;
memcpy(peerInfo.peer_addr, receiver_mac, 6);
peerInfo.channel = 0;
peerInfo.encrypt = false;
peerInfo.ifidx = WIFI_IF_STA;
if (esp_now_add_peer(&peerInfo) != ESP_OK) {
Serial.println("添加对等设备失败");
return;
}
Serial.println("对等设备添加成功");
Serial.println("ESP32 Joystick ESP-NOW发送端启动");
Serial.println("X轴和Y轴范围: -2048 到 +2047, 按钮: 0(按下)/1(未按下)");
Serial.println("中间位置为0,向上/向右为正值,向下/向左为负值");
Serial.println("死区设置: 正负50以内视为0");
}
void loop() {
// 读取Joystick的X轴和Y轴值
int rawX = analogRead(JOY_X_PIN);
int rawY = analogRead(JOY_Y_PIN);
int buttonState = digitalRead(JOY_SW_PIN);
// 将原始值转换为以0为中心的值
int xValue = rawX - JOY_CENTER;
int yValue = rawY - JOY_CENTER;
// 应用死区处理
xValue = applyDeadZone(xValue);
yValue = applyDeadZone(yValue);
// 创建数据包
joystick_data_t joystickData;
joystickData.xValue = xValue;
joystickData.yValue = yValue;
joystickData.buttonState = buttonState;
// 发送数据到接收端
esp_err_t result = esp_now_send(receiver_mac, (uint8_t *) &joystickData, sizeof(joystickData));
// 串口输出数据
Serial.print("发送 - X: ");
Serial.print(xValue);
Serial.print(" | Y: ");
Serial.print(yValue);
Serial.print(" | Button: ");
Serial.print(buttonState);
Serial.print(" | 结果: ");
Serial.println(result == ESP_OK ? "成功" : "失败");
delay(30); // 发送频率控制
}4.接收端代码
// 摇杆遥控麦克纳姆轮小车
// Joystick-controlled Mecanum wheel car
#include <Arduino.h>
#include <esp_now.h>
#include <WiFi.h>
#define LED_PIN 2 // D2引脚定义
// 发送端ESP32的MAC地址(需要替换为实际的发送端MAC地址)
uint8_t sender_mac[] = {0x94, 0xB5, 0x55, 0x31, 0x9C, 0x28};
// 结构体:用于接收Joystick数据
typedef struct {
int xValue;
int yValue;
int buttonState;
} joystick_data_t;
// 接收回调函数
void OnDataRecv(const uint8_t *mac, const uint8_t *incomingData, int len) {
// 将接收到的数据转换为joystick_data_t结构体
joystick_data_t receivedData;
memcpy(&receivedData, incomingData, sizeof(receivedData));
// 串口输出接收到的数据
Serial.print("接收 - X: ");
Serial.print(receivedData.xValue);
Serial.print(" | Y: ");
Serial.print(receivedData.yValue);
Serial.print(" | Button: ");
Serial.println(receivedData.buttonState);
// 可以在这里添加对接收到的数据的处理
// 例如:根据摇杆位置控制LED、电机等
}
void setup() {
// 初始化串口通信
Serial.begin(115200);
delay(1000);
// 将D2引脚设置为输出模式
pinMode(LED_PIN, OUTPUT);
Serial.print("接收端MAC地址: ");
Serial.println(WiFi.macAddress());
Serial.print("发送端MAC地址: ");
char macStr[18];
sprintf(macStr, "%02X:%02X:%02X:%02X:%02X:%02X", sender_mac[0], sender_mac[1], sender_mac[2], sender_mac[3], sender_mac[4], sender_mac[5]);
Serial.println(macStr);
// 初始化WiFi(必需,但不连接到任何网络)
WiFi.mode(WIFI_STA);
// 初始化ESP-NOW
if (esp_now_init() != ESP_OK) {
Serial.println("ESP-NOW初始化失败");
return;
}
Serial.println("ESP-NOW初始化成功");
// 注册接收回调函数
esp_now_register_recv_cb(OnDataRecv);
Serial.println("接收回调函数注册成功");
// 添加发送端作为对等设备(可选,用于双向通信)
esp_now_peer_info_t peerInfo;
memcpy(peerInfo.peer_addr, sender_mac, 6);
peerInfo.channel = 0;
peerInfo.encrypt = false;
peerInfo.ifidx = WIFI_IF_STA;
if (esp_now_add_peer(&peerInfo) == ESP_OK) {
Serial.println("发送端对等设备添加成功");
} else {
Serial.println("发送端对等设备添加失败(可选,不影响接收)");
}
Serial.println("ESP32 ESP-NOW接收端启动");
Serial.println("等待接收Joystick数据...");
}
void loop() {
// 接收数据通过回调函数处理,这里可以做其他任务
delay(1000);
}