Styles Atelier

Quel style préfères-tu ?Which style do you prefer?

Même contenu, quatre ambiances. Essaie-les avant de voter.Same content, four looks. Try them before voting.

Donner mon avis sur TallyShare my preference on Tally ↗

Tally s’ouvre dans un nouvel onglet. Aucun nom ni email demandé.Tally opens in a new tab. No name or email requested.

Ce sondage recueille des avis indicatifs : les votes répétés sont possibles et les réponses ne représentent pas tous les visiteurs.This survey collects informal feedback: repeat votes are possible, and responses do not represent all visitors.

← Retour aux projetsBack to projects
RobotiqueRobotics

Robot mobile télécommandé via ESP-NOWESP-NOW Remote-Controlled Robot

TechnologiesTechnologies (6)
ESP32ESP-NOWC++DRV8833PWMLi-Ion

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.

Démonstration du projetProject demonstration
Le robot — ESP32, driver DRV8833, batteries Li-Ion 18650The robot — ESP32, DRV8833 driver, Li-Ion 18650 batteries

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.

Démonstration du robot télécommandéRemote-controlled robot demo
#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);
}