想做一个智能小车,同时小车上带有视频模块,想在室外玩,没有WIFI 覆盖的情况想
想法:
ESP32,是用于 视频传输的,
esp8266 是用来操控小车的,
操控是一个手机,通过微信小程序 来操控,同时在微信小程序上显示视频。
那么我的思路是:ESP8266 做WIFI主机, esp32 连接 esp8266的wifi , 手机 也连接 ESP8266 的wifi。
这样 手机就可以 同时操作2块芯片了。
esp8266 作为 WIFI 主机,我可以设置一个静态的ip主地址,但是 esp32 的ip 地址我就不知道了。
解决办法: esp32 在连接wifi后,通过 UDP 把自己的 ip地址发送给esp8266,在esp8266上缓存起来, 微信小程序 通过 UDP ,去esp8266上查询 esp32 的 ip地址。
先实现 esp8266 的代码
#include <WiFiUdp.h>
#include <ESP8266WiFi.h>
#include <Servo.h>
#include <stdlib.h>
WiFiUDP Udp;
unsigned int UDPPort = 8888; //wifi端口
// 定义ESP32 缓存IP
char caminfo[255];
//检查相机是否在线超时时间
int cam_timeout = 30000;
char packetBuffer[255]; //buffer to hold incoming packet
//l298n 驱动器连接
#define d1 D1
#define d2 D2
#define d3 D3
#define d4 D4
#define BASE 10
#define DIGIT_ASCII_START '0'
//wifi udp 数据传输初始化
void wifiUdpInit() {
Udp.begin(UDPPort);
}
//udp数据循环获取数据
void wifiUdpGetMsg() {
//控制cam 超时时间
if (cam_timeout > 100000) {
cam_timeout = 100000;
} else if (cam_timeout <= 1) {
//已经超时了
strcpy(caminfo, "");
} else {
cam_timeout--;
}
Serial.println(cam_timeout);
int packetSize = Udp.parsePacket();
if (packetSize) {
Serial.print("Received packet of size ");
Serial.println(packetSize);
Serial.print("From ");
IPAddress remoteIp = Udp.remoteIP();
Serial.print(remoteIp);
Serial.print(", port ");
Serial.println(Udp.remotePort());
// read the packet into packetBufffer
int len = Udp.read(packetBuffer, 255);
if (len > 0) {
packetBuffer[len] = 0;
}
Serial.print("Contents:");
Serial.println(packetBuffer);
char pre[] = "";
left(pre, packetBuffer, strcspn(packetBuffer, ":"));
Serial.print("pre:");
Serial.println(pre);
Serial.println(cam_timeout);
if (0 == strcmp(pre, "cam")) {
Serial.print("save camer ip:");
//保存信息
strcpy(caminfo,packetBuffer);
Serial.println(caminfo);
cam_timeout += 10000;
Serial.print("cam_timeout:"); Serial.println(cam_timeout);
returnUdpMsg("cam success");
return;
} else if (0 == strcmp(pre, "query-cam")) {
//查询 cam 的信息,就返回ip
returnUdpMsg(caminfo);
return;
}
// send a reply, to the IP address and port that sent us the packet we received
returnUdpMsg("success");
}
}
void returnUdpMsg(char *msg) {
Udp.beginPacket(Udp.remoteIP(), Udp.remotePort());
Udp.write(msg);
Udp.endPacket();
}
/*从字符串的右边截取n个字符*/
char * right(char *dst, char *src, int n)
{
char *p = src;
char *q = dst;
int len = strlen(src);
if (n > len) n = len;
p += (len - n); /*从右边第n个字符开始,到0结束,很巧啊*/
while (*(q++) = *(p++));
return dst;
}
/*从字符串的左边截取n个字符*/
char * left(char *dst, char *src, int n)
{
char *p = src;
char *q = dst;
int len = strlen(src);
if (n > len) n = len;
while (n--) *(q++) = *(p++);
*(q++) = '\0'; /*有必要吗?很有必要*/
return dst;
}
void charListToStr(const char* pChar, const int charLen, int* varName) {
int offset;
int baseCurrent = 1;
int result = 0;
for (offset = charLen - 1; offset >= 0; offset--) {
result += (*(pChar + offset) - DIGIT_ASCII_START) * baseCurrent;
baseCurrent *= BASE;
}
*varName = result;
}
void wifiInit() {
WiFi.mode(WIFI_AP); //设置Wi-Fi为AP模式
IPAddress softLocal(192, 168, 1, 1); //设置内网WIFI IP地址
IPAddress softGateway(192, 168, 1, 1); //设置网关
IPAddress softSubnet(255, 255, 255, 0);
WiFi.softAPConfig(softLocal, softGateway, softSubnet);
String apName = ("ESP8266-cat-car" ); // 2 设置WIFI名称
const char *softAPName = apName.c_str();
WiFi.softAP(softAPName, "87654321"); // 3创建wifi 名称 +密码 adminadmin
IPAddress myIP = WiFi.softAPIP(); // 4输出创建的WIFI IP地址
Serial.println("");
Serial.print("AP直链模式 网关IP: ");
Serial.println(myIP);
Serial.print("AP SSID: "); // 5输出WIFI 名称
Serial.println(apName);
Serial.print("AP 密码: "); // 5输出WIFI 名称
Serial.println("12345678"); // 5输出WIFI 名称
}
void setup() {
Serial.begin(115200);
wifiInit();//wifi 初始化
wifiUdpInit();//udp初始化
pinMode(d1, OUTPUT);
pinMode(d2, OUTPUT);
pinMode(d3, OUTPUT);
pinMode(d4, OUTPUT);
digitalWrite(d1, LOW);
digitalWrite(d2, LOW);
digitalWrite(d3, LOW);
digitalWrite(d4, LOW);
}
void loop() {
wifiUdpGetMsg();//循环获取数据
}
ESP32的 代码
#include "esp_camera.h"
#include <WiFi.h>
#include "WiFiUdp.h"
#define CAMERA_MODEL_AI_THINKER
#include "camera_pins.h"
WiFiUDP Udp;
const char* ssid = "ESP8266-cat-car";
const char* password = "87654321";
//const char* ssid = "16L-YiDong";
//const char* password = "9622596225";
void startCameraServer();
void setup() {
Serial.begin(115200);
Serial.setDebugOutput(true);
Serial.println();
camera_config_t config;
config.ledc_channel = LEDC_CHANNEL_0;
config.ledc_timer = LEDC_TIMER_0;
config.pin_d0 = Y2_GPIO_NUM;
config.pin_d1 = Y3_GPIO_NUM;
config.pin_d2 = Y4_GPIO_NUM;
config.pin_d3 = Y5_GPIO_NUM;
config.pin_d4 = Y6_GPIO_NUM;
config.pin_d5 = Y7_GPIO_NUM;
config.pin_d6 = Y8_GPIO_NUM;
config.pin_d7 = Y9_GPIO_NUM;
config.pin_xclk = XCLK_GPIO_NUM;
config.pin_pclk = PCLK_GPIO_NUM;
config.pin_vsync = VSYNC_GPIO_NUM;
config.pin_href = HREF_GPIO_NUM;
config.pin_sscb_sda = SIOD_GPIO_NUM;
config.pin_sscb_scl = SIOC_GPIO_NUM;
config.pin_pwdn = PWDN_GPIO_NUM;
config.pin_reset = RESET_GPIO_NUM;
config.xclk_freq_hz = 20000000;
config.pixel_format = PIXFORMAT_JPEG;
//init with high specs to pre-allocate larger buffers
if(psramFound()){
config.frame_size = FRAMESIZE_UXGA;
config.jpeg_quality = 10;
config.fb_count = 2;
} else {
config.frame_size = FRAMESIZE_SVGA;
config.jpeg_quality = 12;
config.fb_count = 1;
}
#if defined(CAMERA_MODEL_ESP_EYE)
pinMode(13, INPUT_PULLUP);
pinMode(14, INPUT_PULLUP);
#endif
// camera init
esp_err_t err = esp_camera_init(&config);
if (err != ESP_OK) {
Serial.printf("Camera init failed with error 0x%x", err);
return;
}
sensor_t * s = esp_camera_sensor_get();
//initial sensors are flipped vertically and colors are a bit saturated
if (s->id.PID == OV3660_PID) {
s->set_vflip(s, 1);//flip it back
s->set_brightness(s, 1);//up the blightness just a bit
s->set_saturation(s, -2);//lower the saturation
}
//drop down frame size for higher initial frame rate
s->set_framesize(s, FRAMESIZE_QVGA);
#if defined(CAMERA_MODEL_M5STACK_WIDE)
s->set_vflip(s, 1);
s->set_hmirror(s, 1);
#endif
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
}
Serial.println("");
Serial.println("WiFi connected");
startCameraServer();
Serial.print("Camera Ready! Use 'http://");
Serial.print(WiFi.localIP());
Serial.println("' to connect");
Serial.println(WiFi.gatewayIP());
//Udp.begin(8888);
}
//核销代码,每2秒发送一次自己的IP地址
void sendLocalIp(){
Serial.println("sendLocalIp");
int r = Udp.beginPacket(WiFi.gatewayIP(), 8888);
if(r < 1){
return;
}
char buf[] = "cam:";
char loadIp[20];
strcpy(loadIp,WiFi.localIP().toString().c_str());
strcat(buf,loadIp);
int bufsize = strlen(buf);
Serial.println(buf);
Udp.write((const uint8_t*)buf,bufsize); //复制数据到发送缓存
Udp.endPacket();
}
void loop() {
// put your main code here, to run repeatedly:
delay(2000);
sendLocalIp();
}