| 【项目背景】 一直我都想自制一辆遥控车,自己打板制作遥控器,自制车身框架。这段时间正在试用Esp32-c6,手上还有一块Esp32-c3,两者都支持ESP-NOW通信。使用佳立创画板,焊接元器件,打造自己的遥控车。
 
 【佳立创画板】
 1.摇杆VRx接esp32-c3的0引脚(A0),VRy接esp32-c3的4引脚(A4),按键分别接esp32-c3的2、8、9、21引脚(编程引脚初始化时设置为上拉输入模式)
 
 
 2.车身电路esp32-c6与电机驱动,esp32-c6的4、5、23、22引脚用来向电机驱动输入控制信号。
 
 
 【组装】
 1.遥控器
 
 
 
 2.车
 
 
 
 
 
 
 【编写程序】
 使用Arduino IDE 编写。
 1.esp32-c3遥控器程序
 
 2.esp32-c6 车程序复制代码
#include <esp_now.h>
#include <WiFi.h>
#include <esp_wifi.h> // only for esp_wifi_set_channel()
// Global copy of slave
esp_now_peer_info_t slave;
#define CHANNEL 1
#define PRINTSCANRESULTS 0
#define DELETEBEFOREPAIR 0
// Init ESP Now with fallback
void InitESPNow() {
  WiFi.disconnect();
  if (esp_now_init() == ESP_OK) {
    Serial.println("ESPNow Init Success");
  }
  else {
    Serial.println("ESPNow Init Failed");
    // Retry InitESPNow, add a counte and then restart?
    // InitESPNow();
    // or Simply Restart
    ESP.restart();
  }
}
// Scan for slaves in AP mode
void ScanForSlave() {
  int16_t scanResults = WiFi.scanNetworks(false, false, false, 300, CHANNEL); // Scan only on one channel
  // reset on each scan
  bool slaveFound = 0;
  memset(&slave, 0, sizeof(slave));
  Serial.println("");
  if (scanResults == 0) {
    Serial.println("No WiFi devices in AP Mode found");
  } else {
    Serial.print("Found "); Serial.print(scanResults); Serial.println(" devices ");
    for (int i = 0; i < scanResults; ++i) {
      // Print SSID and RSSI for each device found
      String SSID = WiFi.SSID(i);
      int32_t RSSI = WiFi.RSSI(i);
      String BSSIDstr = WiFi.BSSIDstr(i);
      if (PRINTSCANRESULTS) {
        Serial.print(i + 1);
        Serial.print(": ");
        Serial.print(SSID);
        Serial.print(" (");
        Serial.print(RSSI);
        Serial.print(")");
        Serial.println("");
      }
      delay(10);
      // Check if the current device starts with `Slave`
      if (SSID.indexOf("Slave") == 0) {
        // SSID of interest
        Serial.println("Found a Slave.");
        Serial.print(i + 1); Serial.print(": "); Serial.print(SSID); Serial.print(" ["); Serial.print(BSSIDstr); Serial.print("]"); Serial.print(" ("); Serial.print(RSSI); Serial.print(")"); Serial.println("");
        // Get BSSID => Mac Address of the Slave
        int mac[6];
        if ( 6 == sscanf(BSSIDstr.c_str(), "%x:%x:%x:%x:%x:%x",  &mac[0], &mac[1], &mac[2], &mac[3], &mac[4], &mac[5] ) ) {
          for (int ii = 0; ii < 6; ++ii ) {
            slave.peer_addr[ii] = (uint8_t) mac[ii];
          }
        }
        slave.channel = CHANNEL; // pick a channel
        slave.encrypt = 0; // no encryption
        slaveFound = 1;
        // we are planning to have only one slave in this example;
        // Hence, break after we find one, to be a bit efficient
        break;
      }
    }
  }
  if (slaveFound) {
    Serial.println("Slave Found, processing..");
  } else {
    Serial.println("Slave Not Found, trying again.");
  }
  // clean up ram
  WiFi.scanDelete();
}
// Check if the slave is already paired with the master.
// If not, pair the slave with master
bool manageSlave() {
  if (slave.channel == CHANNEL) {
    if (DELETEBEFOREPAIR) {
      deletePeer();
    }
    Serial.print("Slave Status: ");
    // check if the peer exists
    bool exists = esp_now_is_peer_exist(slave.peer_addr);
    if ( exists) {
      // Slave already paired.
      Serial.println("Already Paired");
      return true;
    } else {
      // Slave not paired, attempt pair
      esp_err_t addStatus = esp_now_add_peer(&slave);
      if (addStatus == ESP_OK) {
        // Pair success
        Serial.println("Pair success");
        return true;
      } else if (addStatus == ESP_ERR_ESPNOW_NOT_INIT) {
        // How did we get so far!!
        Serial.println("ESPNOW Not Init");
        return false;
      } else if (addStatus == ESP_ERR_ESPNOW_ARG) {
        Serial.println("Invalid Argument");
        return false;
      } else if (addStatus == ESP_ERR_ESPNOW_FULL) {
        Serial.println("Peer list full");
        return false;
      } else if (addStatus == ESP_ERR_ESPNOW_NO_MEM) {
        Serial.println("Out of memory");
        return false;
      } else if (addStatus == ESP_ERR_ESPNOW_EXIST) {
        Serial.println("Peer Exists");
        return true;
      } else {
        Serial.println("Not sure what happened");
        return false;
      }
    }
  } else {
    // No slave found to process
    Serial.println("No Slave found to process");
    return false;
  }
}
void deletePeer() {
  esp_err_t delStatus = esp_now_del_peer(slave.peer_addr);
  Serial.print("Slave Delete Status: ");
  if (delStatus == ESP_OK) {
    // Delete success
    Serial.println("Success");
  } else if (delStatus == ESP_ERR_ESPNOW_NOT_INIT) {
    // How did we get so far!!
    Serial.println("ESPNOW Not Init");
  } else if (delStatus == ESP_ERR_ESPNOW_ARG) {
    Serial.println("Invalid Argument");
  } else if (delStatus == ESP_ERR_ESPNOW_NOT_FOUND) {
    Serial.println("Peer not found.");
  } else {
    Serial.println("Not sure what happened");
  }
}
// 发送结构体类型
typedef struct struct_message {
  char a;
  int b;
} struct_message;
// 创建一个结构体变量
struct_message data;
// send data
void sendData() {
  const uint8_t *peer_addr = slave.peer_addr;
  esp_err_t result = esp_now_send(peer_addr,(uint8_t *) &data, sizeof(data));
  Serial.print("Send Status: ");
  if (result == ESP_OK) {
    Serial.println("Success");
  } else if (result == ESP_ERR_ESPNOW_NOT_INIT) {
    // How did we get so far!!
    Serial.println("ESPNOW not Init.");
  } else if (result == ESP_ERR_ESPNOW_ARG) {
    Serial.println("Invalid Argument");
  } else if (result == ESP_ERR_ESPNOW_INTERNAL) {
    Serial.println("Internal Error");
  } else if (result == ESP_ERR_ESPNOW_NO_MEM) {
    Serial.println("ESP_ERR_ESPNOW_NO_MEM");
  } else if (result == ESP_ERR_ESPNOW_NOT_FOUND) {
    Serial.println("Peer not found.");
  } else {
    Serial.println("Not sure what happened");
  }
}
// callback when data is sent from Master to Slave
void OnDataSent(const uint8_t *mac_addr, esp_now_send_status_t status) {
  char macStr[18];
  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.print("Last Packet Sent to: "); Serial.println(macStr);
  Serial.print("Last Packet Send Status: "); Serial.println(status == ESP_NOW_SEND_SUCCESS ? "Delivery Success" : "Delivery Fail");
}
void setup() {
  Serial.begin(115200);
  //Set device in STA mode to begin with
  WiFi.mode(WIFI_STA);
  esp_wifi_set_channel(CHANNEL, WIFI_SECOND_CHAN_NONE);
  Serial.println("ESPNow/Basic/Master Example");
  // This is the mac address of the Master in Station Mode
  Serial.print("STA MAC: "); Serial.println(WiFi.macAddress());
  Serial.print("STA CHANNEL "); Serial.println(WiFi.channel());
  // Init ESPNow with a fallback logic
  InitESPNow();
  // Once ESPNow is successfully Init, we will register for Send CB to
  // get the status of Trasnmitted packet
  esp_now_register_send_cb(OnDataSent);
     pinMode(2,INPUT_PULLUP);  //配置按键所在端口为上拉输入模式 
     pinMode(8,INPUT_PULLUP);  //配置按键所在端口为上拉输入模式 
     pinMode(9,INPUT_PULLUP);  //配置按键所在端口为上拉输入模式 
     pinMode(21,INPUT_PULLUP);  //配置按键所在端口为上拉输入模式 
}
bool i=1;
int xValue;
int yValue; 
int bs=0;
void loop() {
  // In the loop we scan for slave
  if (i) {
   ScanForSlave();
  }
  // If Slave is found, it would be populate in `slave` variable
  // We will check if `slave` is defined and then we proceed further
  if (slave.channel == CHANNEL) { // check if slave channel is defined
    // `slave` is defined
    // Add slave as peer if it has not been added already
    bool isPaired = manageSlave();
    if (isPaired) {
      i=0;
      // pair success or already paired
      // Send data to device
      if(!digitalRead(9))  //如果按键按下,即GPIO9的端口状态为低电平 
      {
      data.a='y';
      data.b=4000;
      sendData();
      delay(500);
      }
          if(!digitalRead(8))  //如果按键按下,即GPIO9的端口状态为低电平 
      {
      data.a='y';
      data.b=500;
      sendData();
      delay(500);
      }
        if(!digitalRead(2))  //如果按键按下,即GPIO2的端口状态为低电平 
      {
      data.a='x';
      data.b=4000;
      sendData();
      delay(500);
      }
       if(!digitalRead(21))  //如果按键按下,即GPIO21的端口状态为低电平 
      {
      data.a='x';
      data.b=500;
      sendData();
      delay(500);
      }
      xValue = analogRead(4);//获取摇杆的x值,连接在主板A4接口
      yValue = analogRead(0);//获取摇杆的y值,连接在主板A0接口
      Serial.println(xValue);
      Serial.println(yValue);
      delay(100);
      if(xValue>4000 || xValue<500)
      {
        bs=1;
        data.a='x';
        data.b=xValue;
        sendData();
        Serial.println('x');
      }
      else{
        if(yValue>4000 || yValue<500)
        {  bs=1;
           data.a='y';
           data.b=yValue;
           sendData();
           Serial.println('y');
        }
        else{
          if(bs==1){
           bs=0;
           data.a='s';
           sendData();
          Serial.println('s');
          }
        }
      }
    } else {
      // slave pair failed
      Serial.println("Slave pair failed!");
    }
  }
  else {
    // No slave found to process
  }
  // wait for 3seconds to run the logic again
  
}
 【演示视频】复制代码
#include <esp_now.h>
#include <WiFi.h>
#define CHANNEL 1
//设置PWM参数
// Init ESP Now with fallback
void InitESPNow() {
  WiFi.disconnect();
  if (esp_now_init() == ESP_OK) {
    Serial.println("ESPNow Init Success");
  }
  else {
    Serial.println("ESPNow Init Failed");
    // Retry InitESPNow, add a counte and then restart?
    // InitESPNow();
    // or Simply Restart
    ESP.restart();
  }
}
// config AP SSID
void configDeviceAP() {
  const char *SSID = "Slave_1";
  bool result = WiFi.softAP(SSID, "Slave_1_Password", CHANNEL, 0);
  if (!result) {
    Serial.println("AP Config failed.");
  } else {
    Serial.println("AP Config Success. Broadcasting with AP: " + String(SSID));
    Serial.print("AP CHANNEL "); Serial.println(WiFi.channel());
  }
}
    const int IA1=4;
    const int IA2=5;
    const int IB1=23;
    const int IB2=22;
void setup() {
  Serial.begin(115200);
 
         pinMode(IA1, OUTPUT);
         pinMode(IA2, OUTPUT);
         pinMode(IB1, OUTPUT);
         pinMode(IB2, OUTPUT);
  Serial.println("ESPNow/Basic/Slave Example");
  //Set device in AP mode to begin with
  WiFi.mode(WIFI_AP);
  // configure device AP mode
  configDeviceAP();
  // This is the mac address of the Slave in AP Mode
  Serial.print("AP MAC: "); Serial.println(WiFi.softAPmacAddress());
  // Init ESPNow with a fallback logic
  InitESPNow();
  // Once ESPNow is successfully Init, we will register for recv CB to
  // get recv packer info.
  esp_now_register_recv_cb(OnDataRecv);
}
// 创建一个结构体接收数据
typedef struct struct_message {
    char a;
    int b;
} struct_message;
// 创建一个结构体变量
struct_message myData;
                        
// callback when data is recv from Master
void OnDataRecv(const esp_now_recv_info_t * info, const uint8_t *data, int data_len) {
  memcpy(&myData, data, sizeof(myData));
  char macStr[18];
  snprintf(macStr, sizeof(macStr), "%02x:%02x:%02x:%02x:%02x:%02x",
           info->src_addr[0], info->src_addr[1], info->src_addr[2], info->src_addr[3], info->src_addr[4], info->src_addr[5]);
  Serial.print("Last Packet Recv from: "); Serial.println(macStr);
  Serial.print("Last Packet Recv Data a: "); Serial.println(myData.a);
  Serial.print("Last Packet Recv Data b: "); Serial.println(myData.b);
  if(myData.a=='x')
  {   
    int v1=int(myData.b)-2400;
    if(v1>0)
      {
     
      MA2_Backward(); 
       MB1_Forward();
        
      }
      else{
        MA1_Forward();
      MB2_Backward(); 
      }
  }
  else{
    if(myData.a=='y')
    {
    int v1=int(myData.b)-2600;
    if(v1>0)
      {
      MA1_Forward();
      MB1_Forward();
        
      }
      else{
       MA2_Backward(); 
       MB2_Backward(); 
      }
    }
    else{
         if(myData.a=='s')
           {
            stop();
            
           } 
    }
  }
}
void MA1_Forward()
    {
         digitalWrite(IA1,HIGH);
         digitalWrite(IA2,LOW);
      }
    void MA2_Backward()
    {
        digitalWrite(IA2,HIGH);
         digitalWrite(IA1,LOW);
      }
    void MB1_Forward()
    {
         digitalWrite(IB2,HIGH);
         digitalWrite(IB1,LOW);
      }
    void MB2_Backward()
    {
        digitalWrite(IB1,HIGH);
         digitalWrite(IB2,LOW);
      }
    void stop()
    {
      digitalWrite(IA1,LOW);
      digitalWrite(IA2,LOW);
      digitalWrite(IB1,LOW);
      digitalWrite(IB2,LOW);
    }
void loop() {
  // Chill
}
 
 
 
 |