This code allows control of ESP32 robots or gadgets over WLAN using vigibot.
A raspberry is still required for the camera and needs to be on the same network. the serial data usually sent and received to an Arduino over UART ( https://www.robot-ma...cation-example/ ), is being sent over WLAN instead, allowing control of small robots or gadgets.
usage example: a pi with a camera watches an arena where multiple small ESP32 robots can be driven, the ESP32 bots do not have an on-board camera.
second usage example: open or close a door or toy controlled fron an ESP32.
1) insert your network info and upload the following sketch to your ESP32 from the arduino IDE using an usb cable.
Spoiler
/*
Author: firened
File: vigibot_ESP32_slave.ino
Version:
V1.0 10.2020
Description:
Vigibot Pi to ESP32 over WLAN, based on the Arduino Uart example by Mike118.
check the robot-maker post for up to date setup instructions.
pinout GPIO:
*/#include<WiFi.h>#include<ESPmDNS.h>constchar* ssid ="your_ssid";constchar*pass="your_pass";// Set your Static IP addressIPAddress local_IP(192,168,1,61);// Set your Gateway IP addressIPAddress gateway(192,168,1,1);IPAddress subnet(255,255,255,0);// Meta Type :typedefstruct{union{struct{int16_t x;int16_t y;};int16_t coordonnees[2];uint8_t bytes[4];};}Point;typedefstruct{union{struct{int8_t x;int8_t y;int8_t z;};uint8_t bytes[3];};}Vitesses;// CONFIG//#define PISERIAL Serial#define NBPOSITIONS 2#define FAILSAFE 250// ms// TTS#define TTSBUFFERSIZE 255uint8_t ttsBuffer[TTSBUFFERSIZE];uint8_t ttsCurseur =0;// TX#define TXFRAMESIZE (NBPOSITIONS *4+17)typedefstruct{union{struct{uint8_t sync[4];// 4Point positions[NBPOSITIONS];// NBPOSITIONS * 4uint16_t val16[2];// 2 * 2uint8_t choixCameras;// 1Vitesses vitesses;// 3uint8_t interrupteurs;// 1uint8_t val8[4];// 4};uint8_t bytes[TXFRAMESIZE];};}TrameTx;// RX#define RXFRAMESIZE (NBPOSITIONS *4+9)typedefstruct{union{struct{// Sizesuint8_t sync[4];// 4Point positions[NBPOSITIONS];// NBPOSITIONS * 4 uint8_t choixCameras; // 1Vitesses vitesses;// 3uint8_t interrupteurs;// 1};uint8_t bytes[RXFRAMESIZE];};}TrameRx;TrameTx trameTx;TrameRx trameRx;uint32_t lastTrameTimestamp = millis();uint32_t lastSleepBeacon;WiFiServer server(7070);//ESP server portWiFiClient client;void setup(){Serial.begin(115200);// We start by connecting to a WiFi networkSerial.print("Connecting to ");Serial.println(ssid);WiFi.mode(WIFI_STA);WiFi.config(local_IP, gateway, subnet);WiFi.setHostname("Vigibot_ESP_0");WiFi.begin(ssid,pass);while(WiFi.waitForConnectResult()!= WL_CONNECTED){Serial.println("Connection Failed! Rebooting..."); delay(5000);
ESP.restart();}
server.begin();Serial.println("WiFi connected.");Serial.println("IP address: ");Serial.println(WiFi.localIP());// add all your init here}void loop(){while(WiFi.waitForConnectResult()!= WL_CONNECTED){Serial.println("WLAN Connection Failed! reconnecting...");WiFi.mode(WIFI_STA);WiFi.begin(ssid,pass);
delay(10000);}if(readPiSerial()){// each time we receive a full trame run repeatedly:// use values inside trameRx to tell your robot how to move ...// trameRx.vitesses.x , trameRx.vitesses.y, trameRx.vitesses.z// trameRx.positions[i].x trameRx.positions[i].y etc....
writePiSerial();
lastTrameTimestamp = millis();}if( millis()- lastTrameTimestamp > FAILSAFE ){if((millis()- lastSleepBeacon >10000)){// every 10 seconds
writePiSerial();// Beacon to say that the robot is alive
lastSleepBeacon = millis();}// Stop the robot in case the robot lost connection with the Pi}else{// put your main code here, to run repeatedly:// avoid abstacle, run speed ...}}bool readPiSerial(){uint8_t current;staticuint8_t lastType =0;staticuint8_t n =0;staticuint8_t frame[RXFRAMESIZE];staticbyte lastClientState =0;if(client.connected()){if(!lastClientState){
lastClientState =1;Serial.println("New Client.");}while(client.available()){
current = client.read();//Serial.write(current); //debugswitch(n){case0:if(current =='$')
n =1;break;case1:if(current !='T'&& lastType =='T')
writeTtsBuffer('\n');if(current =='S'|| current =='T'){
lastType = current;
n =2;}else
n =0;break;default:
frame[n++]= current;if(n == RXFRAMESIZE){if(lastType =='T'){for(uint8_t i =4; i < RXFRAMESIZE; i++)// Do not send the 4 sync data in tts
writeTtsBuffer(frame[i]);}elseif(lastType =='S'){for(uint8_t p =0; p < RXFRAMESIZE; p++)
trameRx.bytes[p]= frame[p];}
n =0;returntrue;}//break;}}}else{//if current client is not actively connected anymore, disconnect and wait for new clientif(lastClientState){
lastClientState =0;// close the connection:
client.stop();Serial.println("Client Disconnected.");}
client = server.available();// listen for incoming clients}returnfalse;}void writePiSerial(){// Header, do not modify
trameTx.sync[0]='$';
trameTx.sync[1]='R';
trameTx.sync[2]=' ';
trameTx.sync[3]=' ';// modify the feedback according your need. By default we copy the trameRx content ...for(uint8_t i =0; i < NBPOSITIONS; i++){
trameTx.positions[i].x = trameRx.positions[i].x;
trameTx.positions[i].y = trameRx.positions[i].y;}
trameTx.val16[0]=0;// Voltage (will be updated by Raspberry pi)
trameTx.val16[1]=0;// Percent (will be updated by Raspberry pi)
trameTx.choixCameras = trameRx.choixCameras;
trameTx.vitesses.x = trameRx.vitesses.x;
trameTx.vitesses.y = trameRx.vitesses.y;
trameTx.vitesses.z = trameRx.vitesses.z;
trameTx.interrupteurs = trameRx.interrupteurs;
trameTx.val8[0]=0;// CPU load (will be updated by Raspberry pi)
trameTx.val8[1]=0;// Soc temp (will be updated by Raspberry pi)
trameTx.val8[2]=0;// link (will be updated by Raspberry pi)
trameTx.val8[3]=0;// RSSI (will be updated by Raspberry pi)for(uint8_t i =0; i < TXFRAMESIZE; i++)
client.write(trameTx.bytes[i]);}void displayTtsBuffer (uint8_t* ttsBuffer,uint8_t bufferSize){// you can modify this function to display text on a screen depending on your hardware...for(uint8_t i =0; i < bufferSize; i++){Serial.write(ttsBuffer[i]);}Serial.println("");}void writeTtsBuffer(uint8_t ttsChar){staticuint8_t ttsCurseur =0;if( ttsCurseur < TTSBUFFERSIZE && ttsChar !='\n'){
ttsBuffer[ttsCurseur]= ttsChar;
ttsCurseur ++;}if( ttsCurseur == TTSBUFFERSIZE || ttsChar =='\n'){
displayTtsBuffer (ttsBuffer, ttsCurseur);
ttsCurseur =0;}}
2) open the serial monitor to confirm a successful WLAN connection.
3) the pi needs to create a virtual serial point that's being forwarded over WLAN to the ESP32. install socat on your raspberry:
sudo apt install socat
4) create a new script:
sudo nano /usr/local/socat-esp.sh
5) paste the following code and replace your ESP's IP: