Hello everyone !
Je vais Vigiboter mon train légo. Pour ce faire, j'utilise un ESP32.
J'ai donc repris le code d'exemple de @Mike118 que j'ai adapté :
#include <WiFi.h> #include <ESPmDNS.h> #include "esp32-hal-ledc.h" const char* ssid = "ssid"; const char* pass = "mdp"; // Set your Static IP address IPAddress local_IP(192, 168, 0, 61); // Set your Gateway IP address IPAddress gateway(192, 168, 0, 254); IPAddress subnet(255, 255, 255, 0); // Meta Type : typedef struct { union { struct { int16_t x; int16_t y; }; int16_t coordonnees[2]; uint8_t bytes[4]; }; } Point; typedef struct { 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 #define MAX_SPEED 1275 // max motor speed #define SPEED_RANGE 256 // // TTS #define TTSBUFFERSIZE 255 uint8_t ttsBuffer[TTSBUFFERSIZE]; uint8_t ttsCurseur = 0; // TX #define TXFRAMESIZE (NBPOSITIONS * 4 + 17) typedef struct { union { struct { uint8_t sync[4]; // 4 Point positions[NBPOSITIONS]; // NBPOSITIONS * 4 uint16_t val16[2]; // 2 * 2 uint8_t choixCameras; // 1 Vitesses vitesses; // 3 uint8_t interrupteurs; // 1 uint8_t val8[4]; // 4 }; uint8_t bytes[TXFRAMESIZE]; }; } TrameTx; // RX #define RXFRAMESIZE (NBPOSITIONS * 4 + 9) typedef struct { union { struct { // Sizes uint8_t sync[4]; // 4 Point positions[NBPOSITIONS]; // NBPOSITIONS * 4 uint8_t choixCameras; // 1 Vitesses vitesses; // 3 uint8_t interrupteurs; // 1 }; uint8_t bytes[RXFRAMESIZE]; }; } TrameRx; TrameTx trameTx; TrameRx trameRx; uint32_t lastTrameTimestamp = millis(); uint32_t lastSleepBeacon; WiFiServer server(7070); //ESP server port WiFiClient client; void setup() { Serial.begin(115200); ledcSetup(1, 50, 16); // channel 1, 50 Hz, 16-bit width ledcAttachPin(13, 1); // GPIO 13 assigned to channel 1 // We start by connecting to a WiFi network Serial.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 ledcWrite(1, 0); //stop the train } else { // put your main code here, to run repeatedly: // avoid abstacle, run speed ... int speed; // mixage pour obtenir les vitesses moteurs speed = (trameRx.vitesses.y * MAX_SPEED / SPEED_RANGE) - (trameRx.vitesses.z * MAX_SPEED / SPEED_RANGE); // Saturation des vitesse speed = min(max(speed, -MAX_SPEED), MAX_SPEED); ledcWrite(1, speed); } } bool readPiSerial() { uint8_t current; static uint8_t lastType = 0; static uint8_t n = 0; static uint8_t frame[RXFRAMESIZE]; static byte lastClientState = 0; if (client.connected()) { if (!lastClientState) { lastClientState = 1; Serial.println("New Client."); } while (client.available()) { current = client.read(); //Serial.write(current); //debug switch (n) { case 0: if (current == '$') n = 1; break; case 1: 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]); } else if (lastType == 'S') { for (uint8_t p = 0; p < RXFRAMESIZE; p++) trameRx.bytes[p] = frame[p]; } n = 0; return true; } //break; } } } else { //if current client is not actively connected anymore, disconnect and wait for new client if (lastClientState) { lastClientState = 0; // close the connection: client.stop(); Serial.println("Client Disconnected."); } client = server.available(); // listen for incoming clients } return false; } 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) { static uint8_t ttsCurseur = 0; if ( ttsCurseur < TTSBUFFERSIZE && ttsChar != '\n') { ttsBuffer[ttsCurseur] = ttsChar; ttsCurseur ++; } if ( ttsCurseur == TTSBUFFERSIZE || ttsChar == '\n') { displayTtsBuffer (ttsBuffer, ttsCurseur); ttsCurseur = 0; } }
Ca fonctionne parfaitement sauf que quand j'accélère sur Vigibot ca n'avance pas comme je veux vu que les math n'ont pas été faites.
Je parle de :
#define MAX_SPEED 1275 // max motor speed #define SPEED_RANGE 256 //
ou/et de :
ledcSetup(1, 50, 16); // channel 1, 50 Hz, 16-bit width
en sachant que vigibot envoi les consignes moteurs en 8 bit ..
Je n'ai pas encore le niveau pour améliorer comme je veux ce genre de réglage PWM Hertz etc..
Le calcul reste le meme que pour Zumo.
Merci de votre aide !
Pierre