278浏览
查看: 278|回复: 1

[项目] Esp32-c6与Esp32-c3自制ESP-NOW 遥控车

[复制链接]
【项目背景】
一直我都想自制一辆遥控车,自己打板制作遥控器,自制车身框架。这段时间正在试用Esp32-c6,手上还有一块Esp32-c3,两者都支持ESP-NOW通信。使用佳立创画板,焊接元器件,打造自己的遥控车。
Esp32-c6与Esp32-c3自制ESP-NOW 遥控车图1

【佳立创画板】
1.摇杆VRx接esp32-c3的0引脚(A0),VRy接esp32-c3的4引脚(A4),按键分别接esp32-c3的2、8、9、21引脚(编程引脚初始化时设置为上拉输入模式)
Esp32-c6与Esp32-c3自制ESP-NOW 遥控车图4

Esp32-c6与Esp32-c3自制ESP-NOW 遥控车图5

2.车身电路esp32-c6与电机驱动,esp32-c6的4、5、23、22引脚用来向电机驱动输入控制信号。
Esp32-c6与Esp32-c3自制ESP-NOW 遥控车图6

Esp32-c6与Esp32-c3自制ESP-NOW 遥控车图7

【组装】
1.遥控器
Esp32-c6与Esp32-c3自制ESP-NOW 遥控车图8

Esp32-c6与Esp32-c3自制ESP-NOW 遥控车图9

Esp32-c6与Esp32-c3自制ESP-NOW 遥控车图10

2.车
Esp32-c6与Esp32-c3自制ESP-NOW 遥控车图2


Esp32-c6与Esp32-c3自制ESP-NOW 遥控车图3




【编写程序】
使用Arduino IDE 编写。
1.esp32-c3遥控器程序
  1. #include <esp_now.h>
  2. #include <WiFi.h>
  3. #include <esp_wifi.h> // only for esp_wifi_set_channel()
  4. // Global copy of slave
  5. esp_now_peer_info_t slave;
  6. #define CHANNEL 1
  7. #define PRINTSCANRESULTS 0
  8. #define DELETEBEFOREPAIR 0
  9. // Init ESP Now with fallback
  10. void InitESPNow() {
  11.   WiFi.disconnect();
  12.   if (esp_now_init() == ESP_OK) {
  13.     Serial.println("ESPNow Init Success");
  14.   }
  15.   else {
  16.     Serial.println("ESPNow Init Failed");
  17.     // Retry InitESPNow, add a counte and then restart?
  18.     // InitESPNow();
  19.     // or Simply Restart
  20.     ESP.restart();
  21.   }
  22. }
  23. // Scan for slaves in AP mode
  24. void ScanForSlave() {
  25.   int16_t scanResults = WiFi.scanNetworks(false, false, false, 300, CHANNEL); // Scan only on one channel
  26.   // reset on each scan
  27.   bool slaveFound = 0;
  28.   memset(&slave, 0, sizeof(slave));
  29.   Serial.println("");
  30.   if (scanResults == 0) {
  31.     Serial.println("No WiFi devices in AP Mode found");
  32.   } else {
  33.     Serial.print("Found "); Serial.print(scanResults); Serial.println(" devices ");
  34.     for (int i = 0; i < scanResults; ++i) {
  35.       // Print SSID and RSSI for each device found
  36.       String SSID = WiFi.SSID(i);
  37.       int32_t RSSI = WiFi.RSSI(i);
  38.       String BSSIDstr = WiFi.BSSIDstr(i);
  39.       if (PRINTSCANRESULTS) {
  40.         Serial.print(i + 1);
  41.         Serial.print(": ");
  42.         Serial.print(SSID);
  43.         Serial.print(" (");
  44.         Serial.print(RSSI);
  45.         Serial.print(")");
  46.         Serial.println("");
  47.       }
  48.       delay(10);
  49.       // Check if the current device starts with `Slave`
  50.       if (SSID.indexOf("Slave") == 0) {
  51.         // SSID of interest
  52.         Serial.println("Found a Slave.");
  53.         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("");
  54.         // Get BSSID => Mac Address of the Slave
  55.         int mac[6];
  56.         if ( 6 == sscanf(BSSIDstr.c_str(), "%x:%x:%x:%x:%x:%x",  &mac[0], &mac[1], &mac[2], &mac[3], &mac[4], &mac[5] ) ) {
  57.           for (int ii = 0; ii < 6; ++ii ) {
  58.             slave.peer_addr[ii] = (uint8_t) mac[ii];
  59.           }
  60.         }
  61.         slave.channel = CHANNEL; // pick a channel
  62.         slave.encrypt = 0; // no encryption
  63.         slaveFound = 1;
  64.         // we are planning to have only one slave in this example;
  65.         // Hence, break after we find one, to be a bit efficient
  66.         break;
  67.       }
  68.     }
  69.   }
  70.   if (slaveFound) {
  71.     Serial.println("Slave Found, processing..");
  72.   } else {
  73.     Serial.println("Slave Not Found, trying again.");
  74.   }
  75.   // clean up ram
  76.   WiFi.scanDelete();
  77. }
  78. // Check if the slave is already paired with the master.
  79. // If not, pair the slave with master
  80. bool manageSlave() {
  81.   if (slave.channel == CHANNEL) {
  82.     if (DELETEBEFOREPAIR) {
  83.       deletePeer();
  84.     }
  85.     Serial.print("Slave Status: ");
  86.     // check if the peer exists
  87.     bool exists = esp_now_is_peer_exist(slave.peer_addr);
  88.     if ( exists) {
  89.       // Slave already paired.
  90.       Serial.println("Already Paired");
  91.       return true;
  92.     } else {
  93.       // Slave not paired, attempt pair
  94.       esp_err_t addStatus = esp_now_add_peer(&slave);
  95.       if (addStatus == ESP_OK) {
  96.         // Pair success
  97.         Serial.println("Pair success");
  98.         return true;
  99.       } else if (addStatus == ESP_ERR_ESPNOW_NOT_INIT) {
  100.         // How did we get so far!!
  101.         Serial.println("ESPNOW Not Init");
  102.         return false;
  103.       } else if (addStatus == ESP_ERR_ESPNOW_ARG) {
  104.         Serial.println("Invalid Argument");
  105.         return false;
  106.       } else if (addStatus == ESP_ERR_ESPNOW_FULL) {
  107.         Serial.println("Peer list full");
  108.         return false;
  109.       } else if (addStatus == ESP_ERR_ESPNOW_NO_MEM) {
  110.         Serial.println("Out of memory");
  111.         return false;
  112.       } else if (addStatus == ESP_ERR_ESPNOW_EXIST) {
  113.         Serial.println("Peer Exists");
  114.         return true;
  115.       } else {
  116.         Serial.println("Not sure what happened");
  117.         return false;
  118.       }
  119.     }
  120.   } else {
  121.     // No slave found to process
  122.     Serial.println("No Slave found to process");
  123.     return false;
  124.   }
  125. }
  126. void deletePeer() {
  127.   esp_err_t delStatus = esp_now_del_peer(slave.peer_addr);
  128.   Serial.print("Slave Delete Status: ");
  129.   if (delStatus == ESP_OK) {
  130.     // Delete success
  131.     Serial.println("Success");
  132.   } else if (delStatus == ESP_ERR_ESPNOW_NOT_INIT) {
  133.     // How did we get so far!!
  134.     Serial.println("ESPNOW Not Init");
  135.   } else if (delStatus == ESP_ERR_ESPNOW_ARG) {
  136.     Serial.println("Invalid Argument");
  137.   } else if (delStatus == ESP_ERR_ESPNOW_NOT_FOUND) {
  138.     Serial.println("Peer not found.");
  139.   } else {
  140.     Serial.println("Not sure what happened");
  141.   }
  142. }
  143. // 发送结构体类型
  144. typedef struct struct_message {
  145.   char a;
  146.   int b;
  147. } struct_message;
  148. // 创建一个结构体变量
  149. struct_message data;
  150. // send data
  151. void sendData() {
  152.   const uint8_t *peer_addr = slave.peer_addr;
  153.   esp_err_t result = esp_now_send(peer_addr,(uint8_t *) &data, sizeof(data));
  154.   Serial.print("Send Status: ");
  155.   if (result == ESP_OK) {
  156.     Serial.println("Success");
  157.   } else if (result == ESP_ERR_ESPNOW_NOT_INIT) {
  158.     // How did we get so far!!
  159.     Serial.println("ESPNOW not Init.");
  160.   } else if (result == ESP_ERR_ESPNOW_ARG) {
  161.     Serial.println("Invalid Argument");
  162.   } else if (result == ESP_ERR_ESPNOW_INTERNAL) {
  163.     Serial.println("Internal Error");
  164.   } else if (result == ESP_ERR_ESPNOW_NO_MEM) {
  165.     Serial.println("ESP_ERR_ESPNOW_NO_MEM");
  166.   } else if (result == ESP_ERR_ESPNOW_NOT_FOUND) {
  167.     Serial.println("Peer not found.");
  168.   } else {
  169.     Serial.println("Not sure what happened");
  170.   }
  171. }
  172. // callback when data is sent from Master to Slave
  173. void OnDataSent(const uint8_t *mac_addr, esp_now_send_status_t status) {
  174.   char macStr[18];
  175.   snprintf(macStr, sizeof(macStr), "%02x:%02x:%02x:%02x:%02x:%02x",
  176.            mac_addr[0], mac_addr[1], mac_addr[2], mac_addr[3], mac_addr[4], mac_addr[5]);
  177.   Serial.print("Last Packet Sent to: "); Serial.println(macStr);
  178.   Serial.print("Last Packet Send Status: "); Serial.println(status == ESP_NOW_SEND_SUCCESS ? "Delivery Success" : "Delivery Fail");
  179. }
  180. void setup() {
  181.   Serial.begin(115200);
  182.   //Set device in STA mode to begin with
  183.   WiFi.mode(WIFI_STA);
  184.   esp_wifi_set_channel(CHANNEL, WIFI_SECOND_CHAN_NONE);
  185.   Serial.println("ESPNow/Basic/Master Example");
  186.   // This is the mac address of the Master in Station Mode
  187.   Serial.print("STA MAC: "); Serial.println(WiFi.macAddress());
  188.   Serial.print("STA CHANNEL "); Serial.println(WiFi.channel());
  189.   // Init ESPNow with a fallback logic
  190.   InitESPNow();
  191.   // Once ESPNow is successfully Init, we will register for Send CB to
  192.   // get the status of Trasnmitted packet
  193.   esp_now_register_send_cb(OnDataSent);
  194.      pinMode(2,INPUT_PULLUP);  //配置按键所在端口为上拉输入模式
  195.      pinMode(8,INPUT_PULLUP);  //配置按键所在端口为上拉输入模式
  196.      pinMode(9,INPUT_PULLUP);  //配置按键所在端口为上拉输入模式
  197.      pinMode(21,INPUT_PULLUP);  //配置按键所在端口为上拉输入模式
  198. }
  199. bool i=1;
  200. int xValue;
  201. int yValue;
  202. int bs=0;
  203. void loop() {
  204.   // In the loop we scan for slave
  205.   if (i) {
  206.    ScanForSlave();
  207.   }
  208.   // If Slave is found, it would be populate in `slave` variable
  209.   // We will check if `slave` is defined and then we proceed further
  210.   if (slave.channel == CHANNEL) { // check if slave channel is defined
  211.     // `slave` is defined
  212.     // Add slave as peer if it has not been added already
  213.     bool isPaired = manageSlave();
  214.     if (isPaired) {
  215.       i=0;
  216.       // pair success or already paired
  217.       // Send data to device
  218.       if(!digitalRead(9))  //如果按键按下,即GPIO9的端口状态为低电平
  219.       {
  220.       data.a='y';
  221.       data.b=4000;
  222.       sendData();
  223.       delay(500);
  224.       }
  225.           if(!digitalRead(8))  //如果按键按下,即GPIO9的端口状态为低电平
  226.       {
  227.       data.a='y';
  228.       data.b=500;
  229.       sendData();
  230.       delay(500);
  231.       }
  232.         if(!digitalRead(2))  //如果按键按下,即GPIO2的端口状态为低电平
  233.       {
  234.       data.a='x';
  235.       data.b=4000;
  236.       sendData();
  237.       delay(500);
  238.       }
  239.        if(!digitalRead(21))  //如果按键按下,即GPIO21的端口状态为低电平
  240.       {
  241.       data.a='x';
  242.       data.b=500;
  243.       sendData();
  244.       delay(500);
  245.       }
  246.       xValue = analogRead(4);//获取摇杆的x值,连接在主板A4接口
  247.       yValue = analogRead(0);//获取摇杆的y值,连接在主板A0接口
  248.       Serial.println(xValue);
  249.       Serial.println(yValue);
  250.       delay(100);
  251.       if(xValue>4000 || xValue<500)
  252.       {
  253.         bs=1;
  254.         data.a='x';
  255.         data.b=xValue;
  256.         sendData();
  257.         Serial.println('x');
  258.       }
  259.       else{
  260.         if(yValue>4000 || yValue<500)
  261.         {  bs=1;
  262.            data.a='y';
  263.            data.b=yValue;
  264.            sendData();
  265.            Serial.println('y');
  266.         }
  267.         else{
  268.           if(bs==1){
  269.            bs=0;
  270.            data.a='s';
  271.            sendData();
  272.           Serial.println('s');
  273.           }
  274.         }
  275.       }
  276.     } else {
  277.       // slave pair failed
  278.       Serial.println("Slave pair failed!");
  279.     }
  280.   }
  281.   else {
  282.     // No slave found to process
  283.   }
  284.   // wait for 3seconds to run the logic again
  285.   
  286. }
复制代码
2.esp32-c6 车程序
  1. #include <esp_now.h>
  2. #include <WiFi.h>
  3. #define CHANNEL 1
  4. //设置PWM参数
  5. // Init ESP Now with fallback
  6. void InitESPNow() {
  7.   WiFi.disconnect();
  8.   if (esp_now_init() == ESP_OK) {
  9.     Serial.println("ESPNow Init Success");
  10.   }
  11.   else {
  12.     Serial.println("ESPNow Init Failed");
  13.     // Retry InitESPNow, add a counte and then restart?
  14.     // InitESPNow();
  15.     // or Simply Restart
  16.     ESP.restart();
  17.   }
  18. }
  19. // config AP SSID
  20. void configDeviceAP() {
  21.   const char *SSID = "Slave_1";
  22.   bool result = WiFi.softAP(SSID, "Slave_1_Password", CHANNEL, 0);
  23.   if (!result) {
  24.     Serial.println("AP Config failed.");
  25.   } else {
  26.     Serial.println("AP Config Success. Broadcasting with AP: " + String(SSID));
  27.     Serial.print("AP CHANNEL "); Serial.println(WiFi.channel());
  28.   }
  29. }
  30.     const int IA1=4;
  31.     const int IA2=5;
  32.     const int IB1=23;
  33.     const int IB2=22;
  34. void setup() {
  35.   Serial.begin(115200);
  36.          pinMode(IA1, OUTPUT);
  37.          pinMode(IA2, OUTPUT);
  38.          pinMode(IB1, OUTPUT);
  39.          pinMode(IB2, OUTPUT);
  40.   Serial.println("ESPNow/Basic/Slave Example");
  41.   //Set device in AP mode to begin with
  42.   WiFi.mode(WIFI_AP);
  43.   // configure device AP mode
  44.   configDeviceAP();
  45.   // This is the mac address of the Slave in AP Mode
  46.   Serial.print("AP MAC: "); Serial.println(WiFi.softAPmacAddress());
  47.   // Init ESPNow with a fallback logic
  48.   InitESPNow();
  49.   // Once ESPNow is successfully Init, we will register for recv CB to
  50.   // get recv packer info.
  51.   esp_now_register_recv_cb(OnDataRecv);
  52. }
  53. // 创建一个结构体接收数据
  54. typedef struct struct_message {
  55.     char a;
  56.     int b;
  57. } struct_message;
  58. // 创建一个结构体变量
  59. struct_message myData;
  60.                         
  61. // callback when data is recv from Master
  62. void OnDataRecv(const esp_now_recv_info_t * info, const uint8_t *data, int data_len) {
  63.   memcpy(&myData, data, sizeof(myData));
  64.   char macStr[18];
  65.   snprintf(macStr, sizeof(macStr), "%02x:%02x:%02x:%02x:%02x:%02x",
  66.            info->src_addr[0], info->src_addr[1], info->src_addr[2], info->src_addr[3], info->src_addr[4], info->src_addr[5]);
  67.   Serial.print("Last Packet Recv from: "); Serial.println(macStr);
  68.   Serial.print("Last Packet Recv Data a: "); Serial.println(myData.a);
  69.   Serial.print("Last Packet Recv Data b: "); Serial.println(myData.b);
  70.   if(myData.a=='x')
  71.   {   
  72.     int v1=int(myData.b)-2400;
  73.     if(v1>0)
  74.       {
  75.      
  76.       MA2_Backward();
  77.        MB1_Forward();
  78.         
  79.       }
  80.       else{
  81.         MA1_Forward();
  82.       MB2_Backward();
  83.       }
  84.   }
  85.   else{
  86.     if(myData.a=='y')
  87.     {
  88.     int v1=int(myData.b)-2600;
  89.     if(v1>0)
  90.       {
  91.       MA1_Forward();
  92.       MB1_Forward();
  93.         
  94.       }
  95.       else{
  96.        MA2_Backward();
  97.        MB2_Backward();
  98.       }
  99.     }
  100.     else{
  101.          if(myData.a=='s')
  102.            {
  103.             stop();
  104.             
  105.            }
  106.     }
  107.   }
  108. }
  109. void MA1_Forward()
  110.     {
  111.          digitalWrite(IA1,HIGH);
  112.          digitalWrite(IA2,LOW);
  113.       }
  114.     void MA2_Backward()
  115.     {
  116.         digitalWrite(IA2,HIGH);
  117.          digitalWrite(IA1,LOW);
  118.       }
  119.     void MB1_Forward()
  120.     {
  121.          digitalWrite(IB2,HIGH);
  122.          digitalWrite(IB1,LOW);
  123.       }
  124.     void MB2_Backward()
  125.     {
  126.         digitalWrite(IB1,HIGH);
  127.          digitalWrite(IB2,LOW);
  128.       }
  129.     void stop()
  130.     {
  131.       digitalWrite(IA1,LOW);
  132.       digitalWrite(IA2,LOW);
  133.       digitalWrite(IB1,LOW);
  134.       digitalWrite(IB2,LOW);
  135.     }
  136. void loop() {
  137.   // Chill
  138. }
复制代码
【演示视频】


hnyzcj  版主

发表于 2024-3-31 12:07:28

哈哈哈哈,这个好玩
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

为本项目制作心愿单
购买心愿单
心愿单 编辑
[[wsData.name]]

硬件清单

  • [[d.name]]
btnicon
我也要做!
点击进入购买页面
上海智位机器人股份有限公司 沪ICP备09038501号-4

© 2013-2024 Comsenz Inc. Powered by Discuz! X3.4 Licensed

mail