跟站长阿张折腾硬件之第二版本 esp32控+esp32接收端 (UDP协议,Arduino IDE)

跟站长阿张折腾硬件之第二版本 esp32控+esp32接收端  (UDP协议,Arduino IDE)
发布于
# 站长阿张折腾硬件

第二个版本,使用esp32创建一个wifi热点,使用另一个esp32(遥控端)连接esp32(接收端)的wifi热点,esp32遥控端读取摇杆中的电位器信号,通过UDP发送给esp32接收端监听的UDP端口。esp32接收端接收到udp包,转换成pwm控制信号,分别控制舵机和电调控制小车。

跟站长阿张折腾硬件之第二版本 esp32控+esp32接收端  (UDP协议,Arduino IDE)

记得关注我

跟站长阿张折腾硬件之第二版本 esp32控+esp32接收端  (UDP协议,Arduino IDE)

接线方式

遥控,发送端

esp32连接摇杆

● esp32 D35 连接 摇杆 VRX

● esp32 D34 连接 摇杆 VRY

● esp32 3V3 连接 摇杆 +5V

● esp32 GND(3v3隔壁的GND针脚) 连接 摇杆 GND

esp32连接电源

● esp32 VIN 连接 电压负极 3.7V的1S 或者 5V的正极

● esp32 GND(VIN隔壁的GND针脚) 连接 电源负极

车子端,接收端

电调连接电源(以物料单中的有刷电调为例)(此处可参考第一版本视频中的接法)

● 两黑两红的外侧黑线 接 2S电池(7.4v)的负极

● 两黑两红的外侧红线 接 2S电池(7.4v)的正极

电调连接电机(以物料单中的有刷电调为例)(此处可参考第一版本视频中的接法)

● 中间的窄JST接口黑线 接 电机红线

● 中间的窄JST接口红线 接 电机 黑线

(如果行驶方向相反,可以把这两根线交换连接)

esp32 连接电调

● esp32 VIN 连接 电调三pin排线的红线

● esp32 GND(VIN旁) 连接 电调三pin线的黑线

● 电调3pin线的白线(信号线) 连接 esp32的 D22(半功率)或者D23(满功率)

esp32 连接转向舵机

● 转向舵机3pin线的红色线 连接 esp32的 3V3

● 转向舵机3pin线的棕色线 连接 esp32的 GND(3V3旁)

● 转向舵机3pin线的黄色线 连接 esp32的 D25(半角度) 或者 D26(满角度)

代码部分

发送端 (ESP32)

#include <WiFi.h>
#include <WiFiUdp.h>

// WiFi network name and password:
const char * networkName = "xiaocheche";
const char * networkPswd = "xiaoxiaoche";

const char * udpAddress = "192.168.4.1";
const int udpPort = 8888;

//Are we currently connected?
boolean connected = false;

//The udp library class
WiFiUDP udp;

int LED_BUILTIN = 2;
bool ledShow = false;

int baseX = 0;
int baseY = 0;

// 100的间隙
int gap = 100;

void setup() {
  Serial.begin(9600);
  baseX = analogRead(35);  // X 读取35针脚
  baseY = analogRead(34);  // Y 读取34针脚

  //Connect to the WiFi network
  connectToWiFi(networkName, networkPswd);
  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 sendx = 0;
int sendy = 0;

int ledLoopTick = -1;

// unsigned long time1 = millis();
// unsigned long lastTickTime = millis();

// the loop function runs over and over again forever
void loop() {
  // time1 = millis();
  // Serial.printf("tlast: %d \n", time1 - lastTickTime);
  // lastTickTime = time1;

  vx = analogRead(35);
  vy = analogRead(34);

  sendx = sendHaf;
  sendy = sendHaf;

  if (vx > baseX) {
    if (vx > baseX + gap) {
      sendx = int(float(vx - baseX - gap) / (MAX - baseX - gap) * sendHaf) + sendHaf;
    }
  } else {
    if (vx < baseX - gap) {
      sendx = int(float(vx) / float(baseX - gap) * sendHaf);
    }
  }

  if (vy > baseY) {
    if (vy > baseY + gap) {
      sendy = int(float(vy - baseY - gap) / (MAX - baseY - gap) * sendHaf) + sendHaf;
    }
  } else {
    if (vy < baseY - gap) {
      sendy = int(float(vy) / float(baseY - gap) * sendHaf);
    }
  }

  if(connected){
    udp.beginPacket(udpAddress,udpPort);
    // Serial.printf("\t vx: %d \t vy: %d \t sy: %d \t sy: %d \n", vx, vy, sendx, sendy);
    udp.printf("c1:%d,c2:%d", sendx, sendy);
    udp.endPacket();

    ledLoopTick += 1;
    if (ledLoopTick >= 50) {
      ledLoopTick = 0;
    }
    if (ledLoopTick == 0) { // 闪太快看不清,隔50帧闪一次
      if (ledShow) {
        digitalWrite(LED_BUILTIN, LOW);
        ledShow = false;
      } else {
        digitalWrite(LED_BUILTIN, HIGH);
        ledShow = true;
      }
    }
  } else {
    ledShow = true;
    digitalWrite(LED_BUILTIN, HIGH);
  }

  delay(1); // 去掉
}



void connectToWiFi(const char * ssid, const char * pwd){
  Serial.println("Connecting to WiFi network: " + String(ssid));

  // delete old config
  WiFi.disconnect(true);
  //register event handler
  WiFi.onEvent(WiFiEvent);
  
  //Initiate connection
  WiFi.begin(ssid, pwd);

  Serial.println("Waiting for WIFI connection...");
}


//wifi event handler
void WiFiEvent(WiFiEvent_t event){
  switch(event) {
    case SYSTEM_EVENT_STA_GOT_IP:
      //When connected set 
      Serial.print("WiFi connected! IP address: ");
      Serial.println(WiFi.localIP());  
      //initializes the UDP state
      //This initializes the transfer buffer
      udp.begin(WiFi.localIP(),udpPort);
      connected = true;
      break;
    case SYSTEM_EVENT_STA_DISCONNECTED:
      Serial.println("WiFi lost connection");
      connected = false;
      break;
    default: break;
  }
}

接收端 (ESP32)

#include "WiFi.h"
#include "AsyncUDP.h"
#include <stdio.h>

#ifndef APSSID
#define APSSID "xiaocheche"     // 接收机,自动创建热点,wifi 名称
#define APPSK "xiaoxiaoche"     // wifi密码
#endif
const char *ssid = APSSID;
const char *password = APPSK;
unsigned int localPort = 8888;  // local port to listen on

/**
 * 封装舵机的控制类
 */
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);
}


AsyncUDP udp;

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 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...");
  /* You can remove the password parameter if you want the AP to be open. */
  WiFi.softAP(ssid, password);
  IPAddress myIP = WiFi.softAPIP();
  Serial.print("AP IP address: ");
  Serial.println(myIP);
  if(udp.listen(localPort)) {
    Serial.print("UDP Listening on IP: ");
    Serial.println(WiFi.localIP());
    udp.onPacket([](AsyncUDPPacket packet) {
      char* str = (char*)packet.data();
      str[packet.length()] = 0;
      sscanf(str, "c1:%d,c2:%d", &rxC1, &rxC2);
      lastDataTickTime = millis();

      // Serial.println(str);

      ledLoopTick += 1;
      if (ledLoopTick >= 50) {
        ledLoopTick = 0;
      }
      if (ledLoopTick == 0) { // 闪太快看不清,隔50帧闪一次
        if (ledShow) {
          digitalWrite(LED_BUILTIN, LOW);
          ledShow = false;
        } else {
          digitalWrite(LED_BUILTIN, HIGH);
          ledShow = true;
        }
      }

      // Serial.print("UDP Packet Type: ");
      // Serial.print(packet.isBroadcast()?"Broadcast":packet.isMulticast()?"Multicast":"Unicast");
      // Serial.print(", From: ");
      // Serial.print(packet.remoteIP());
      // Serial.print(":");
      // Serial.print(packet.remotePort());
      // Serial.print(", To: ");
      // Serial.print(packet.localIP());
      // Serial.print(":");
      // Serial.print(packet.localPort());
      // Serial.print(", Length: ");
      // Serial.print(packet.length());
      // Serial.print(", Data: ");
      // Serial.write(packet.data(), packet.length());
      // Serial.println();
      // //reply to the client
      // packet.printf("Got %u bytes of data", packet.length());
    });
  }

}


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;
    // 点亮灯
    digitalWrite(LED_BUILTIN, HIGH);
    ledShow = true;
    // Serial.println("xxxxxxxxxxxxxxxxxxx");
  }
  updateServo();
}
评论