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;
最后测试成功了。
2025-12-28T08:45:05.png

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);
}

发表评论