Robot mobile télécommandé via ESP-NOWESP-NOW Remote-Controlled Robot
TechnologiesTechnologies (6)
Véhicule robotique à 2 roues piloté par une manette personnalisée via le protocole ESP-NOW — communication directe P2P entre deux ESP32, sans Wi-Fi ni Bluetooth.2-wheel robotic vehicle controlled by a custom joystick via ESP-NOW — direct P2P communication between two ESP32s, no Wi-Fi or Bluetooth needed.
Lire la présentation complèteRead the full introduction
Véhicule robotique à 2 roues piloté par une manette personnalisée via le protocole ESP-NOW — communication directe P2P entre deux ESP32, sans Wi-Fi ni Bluetooth.2-wheel robotic vehicle controlled by a custom joystick via ESP-NOW — direct P2P communication between two ESP32s, no Wi-Fi or Bluetooth needed.
Concept
L'idée était de créer un véhicule rapide et réactif en utilisant deux ESP32 qui communiquent en direct via le protocole ESP-NOW, sans avoir besoin de Wi-Fi ou de Bluetooth. Ce protocole Peer-to-Peer garantit une portée élevée et une latence quasi nulle, idéale pour le pilotage en temps réel.
Matériel
Le robot utilise deux moteurs DC avec réducteur (type "jaune TT", rapport 1:48), pilotés par un driver DRV8833 (double pont en H) — plus compact que le L298N classique, avec moins de chauffe. L'alimentation est assurée par 3 batteries Li-Ion 18650 en série (11,1V) abaissées à 5V par un régulateur L7805CV pour l'électronique.
La manette est un ESP32 avec un joystick analogique 2 axes + bouton (turbo).
Pilotage différentiel (type tank)
Le robot n'a pas de roues directrices — il tourne en créant une différence de vitesse entre les deux roues :
Vitesse moteur gauche = Avancement + Rotation
Vitesse moteur droit = Avancement - Rotation
Sécurités intégrées
Zone morte logicielle pour éviter le drift au repos, atténuation de la direction (60%) pour des virages plus fluides, PWM à 30 kHz (inaudible), et failsafe automatique : si la connexion est perdue plus d'1 seconde, le robot s'arrête immédiatement.
Évolutions prévues
Remplacer le régulateur linéaire L7805CV (qui chauffe) par un régulateur à découpage (Buck Converter) pour améliorer le rendement et l'autonomie.
Concept
The goal was to build a fast, responsive vehicle using two ESP32s communicating directly via ESP-NOW — no Wi-Fi or Bluetooth required. This Peer-to-Peer protocol ensures high range and near-zero latency, ideal for real-time control.
Hardware
The robot uses two DC motors with gearbox (1:48 "yellow TT" type), driven by a DRV8833 module (dual H-bridge) — more compact than the classic L298N, with better thermal efficiency. Power comes from 3x Li-Ion 18650 cells in series (11.1V), stepped down to 5V by an L7805CV regulator for the electronics.
The controller is an ESP32 with a 2-axis analog joystick and push button (turbo).
Differential drive (tank mode)
No steering wheels — the robot turns by creating a speed difference between the two motors:
Left motor speed = Throttle + Steering
Right motor speed = Throttle - Steering
Built-in safety features
Software deadzone to prevent drift at rest, steering attenuation (60%) for smoother turns, 30 kHz PWM (silent to human ears), and automatic failsafe: if the connection is lost for more than 1 second, the robot cuts power immediately.
Planned improvements
Replace the linear L7805CV regulator (which overheats) with a switching Buck Converter for better efficiency and battery life.
#include <esp_now.h>
#include <WiFi.h>
// --- PINS JOYSTICK ---
const int VRX_PIN = 34;
const int VRY_PIN = 35;
const int SW_PIN = 32;
// --- ADRESSE MAC DU ROBOT ---
uint8_t broadcastAddress[] = {0x4C, 0xC3, 0x82, 0xDB, 0x0F, 0xC0};
typedef struct struct_message {
int x;
int y;
bool switchPressed;
} struct_message;
struct_message myData;
esp_now_peer_info_t peerInfo;
void OnDataSent(const uint8_t *mac_addr, esp_now_send_status_t status) {}
void setup() {
Serial.begin(115200);
pinMode(VRX_PIN, INPUT);
pinMode(VRY_PIN, INPUT);
pinMode(SW_PIN, INPUT_PULLUP);
WiFi.mode(WIFI_STA);
if (esp_now_init() != ESP_OK) return;
esp_now_register_send_cb(OnDataSent);
memcpy(peerInfo.peer_addr, broadcastAddress, 6);
peerInfo.channel = 0;
peerInfo.encrypt = false;
esp_now_add_peer(&peerInfo);
}
void loop() {
myData.x = map(analogRead(VRX_PIN), 0, 4095, 255, -255);
myData.y = map(analogRead(VRY_PIN), 0, 4095, -255, 255);
if (abs(myData.x) < 30) myData.x = 0;
if (abs(myData.y) < 30) myData.y = 0;
myData.switchPressed = (digitalRead(SW_PIN) == LOW);
esp_now_send(broadcastAddress, (uint8_t *) &myData, sizeof(myData));
delay(20);
}#include <esp_now.h>
#include <WiFi.h>
// --- PINS MOTEURS ---
const int IN1 = 13, IN2 = 12, IN3 = 14, IN4 = 27;
const int freq = 30000, resolution = 8;
const int ch_IN1 = 0, ch_IN2 = 1, ch_IN3 = 2, ch_IN4 = 3;
typedef struct struct_message {
int x, y;
bool switchPressed;
} struct_message;
struct_message myData;
unsigned long lastRecvTime = 0;
void driveMotor(int ch_A, int ch_B, int speed) {
if (speed > 0) { ledcWrite(ch_A, speed); ledcWrite(ch_B, 0); }
else if (speed < 0) { ledcWrite(ch_A, 0); ledcWrite(ch_B, -speed); }
else { ledcWrite(ch_A, 0); ledcWrite(ch_B, 0); }
}
void OnDataRecv(const uint8_t *mac, const uint8_t *incomingData, int len) {
memcpy(&myData, incomingData, sizeof(myData));
lastRecvTime = millis();
int throttle = myData.y, steering = myData.x;
if (abs(throttle) < 30) throttle = 0;
if (abs(steering) < 30) steering = 0;
if (steering != 0) steering = steering * 0.6;
int L = constrain(throttle + steering, -255, 255);
int R = constrain(throttle - steering, -255, 255);
driveMotor(ch_IN1, ch_IN2, L);
driveMotor(ch_IN3, ch_IN4, R);
}
void setup() {
ledcSetup(ch_IN1, freq, resolution); ledcAttachPin(IN1, ch_IN1);
ledcSetup(ch_IN2, freq, resolution); ledcAttachPin(IN2, ch_IN2);
ledcSetup(ch_IN3, freq, resolution); ledcAttachPin(IN3, ch_IN3);
ledcSetup(ch_IN4, freq, resolution); ledcAttachPin(IN4, ch_IN4);
driveMotor(ch_IN1, ch_IN2, 0);
driveMotor(ch_IN3, ch_IN4, 0);
WiFi.mode(WIFI_STA);
if (esp_now_init() != ESP_OK) return;
esp_now_register_recv_cb(OnDataRecv);
}
void loop() {
if (millis() - lastRecvTime > 1000) {
driveMotor(ch_IN1, ch_IN2, 0);
driveMotor(ch_IN3, ch_IN4, 0);
}
delay(10);
}