Arduino - contrôle de voiture via le Web

Ce tutoriel vous explique comment contrôler une voiture robotisée sans fil à l'aide d'un Arduino depuis un navigateur web sur votre smartphone ou PC via WiFi. La gestion du contrôle se fait à travers une interface utilisateur web graphique qui utilise la technologie WebSocket, permettant une opération fluide et dynamique de la voiture.

Arduino contrôle une voiture robot via le Web.

Préparation du matériel

1×Arduino UNO R4 WiFi
1×USB Cable Type-C
1×2WD RC Car
1×L298N Motor Driver Module
1×IR Remote Controller Kit
1×CR2025 Battery (for IR Remote controller)
1×1.5V AA Battery (for Arduino and Car)
1×Jumper Wires
1×Breadboard
1×(Recommended) Screw Terminal Block Shield for Arduino Uno
1×(Optional) Transparent Acrylic Enclosure For Arduino Uno

Or you can buy the following sensor kits:

1×DIYables Sensor Kit (30 sensors/displays)
1×DIYables Sensor Kit (18 sensors/displays)
Divulgation : Certains des liens fournis dans cette section sont des liens affiliés Amazon. Nous pouvons recevoir une commission pour tout achat effectué via ces liens, sans coût supplémentaire pour vous. Nous vous remercions de votre soutien.

À propos de la voiture RC 2WD et WebSocket

Maintenant, pourquoi choisir WebSocket ? Voici les raisons :

  • Sans WebSocket, vous devriez recharger la page chaque fois que vous souhaitez changer la direction de la voiture. Ce n'est pas efficace !
  • Avec WebSocket, une connexion spéciale est établie entre la page web et l'Arduino. Cela vous permet d'envoyer des commandes à l'Arduino en arrière-plan, sans avoir besoin de recharger la page. Le résultat ? La voiture robot répond de manière fluide et instantanée. Assez impressionnant, n'est-ce pas ?

En résumé, WebSocket facilite la commande en temps réel et fluide du robot.

Nous avons des tutoriels spécifiques sur les voitures RC 2WD et WebSocket. Chaque tutoriel contient des informations détaillées et des instructions étape par étape sur le brochage du matériel, le principe de fonctionnement, la connexion des câbles à l'Arduino, le code Arduino... Pour en savoir plus sur ces sujets, consultez les liens suivants :

Comment ça marche

Le code Arduino configure à la fois un serveur Web et un serveur WebSocket. Voici comment il fonctionne :

  • Lorsque vous tapez l'adresse IP de l'Arduino dans un navigateur web, cela envoie une demande pour la page web (Interface Utilisateur) depuis l'Arduino.
  • Le serveur web de l’Arduino répond en livrant le contenu de la page web (HTML, CSS, JavaScript).
  • Votre navigateur web affiche ensuite cette page web.
  • À l'intérieur de la page web, le code JavaScript initie une connexion WebSocket avec le serveur WebSocket sur l'Arduino.
  • Une fois cette connexion WebSocket active, toute pression ou relâchement de bouton sur la page web amène le code JavaScript à envoyer discrètement des commandes à l'Arduino via cette connexion.
  • Le serveur WebSocket sur l'Arduino reçoit ces commandes et dirige la voiture robot en conséquence.

Ci-dessous se trouve un tableau montrant la liste des commandes que la page web envoie à l'Arduino en fonction des actions de l'utilisateur :

User's Action Button Command Car Action
PRESS UP 1 MOVE FORWARD
PRESS DOWN 2 MOVE BACKWARD
PRESS LEFT 4 TURN LEFT
PRESS RIGHT 8 TURN RIGHT
PRESS STOP 0 STOP
RELEASE UP 0 STOP
RELEASE DOWN 0 STOP
RELEASE LEFT 0 STOP
RELEASE RIGHT 0 STOP
RELEASE STOP 0 STOP

Schéma de câblage entre une voiture RC 2WD et un Arduino

Schéma de câblage de la voiture RC Arduino 2WD

This image is created using Fritzing. Click to enlarge image

Normalement, vous auriez besoin de deux sources d'alimentation distinctes :

  • Un pour le moteur.
  • Un autre pour la carte Arduino et le module L298N (qui sert de contrôleur de moteur).

Cependant, vous pouvez simplifier cette installation en utilisant une seule source d'alimentation – quatre piles de 1,5V pour faire un total de 6V. Voici comment procéder :

  • Connectez les batteries au module L298N comme indiqué.
  • Retirez les deux cavaliers des broches ENA et ENB vers les 5 volts sur le module L298N.
  • Insérez un cavalier étiqueté 5VEN (indiqué par un cercle jaune sur le schéma).
  • Connectez la broche 12V sur le module L298N à la broche Vin sur l'Arduino. Cette connexion alimentera l'Arduino directement depuis les batteries.

La voiture RC 2WD comprend un interrupteur marche/arrêt, vous offrant la possibilité de connecter la batterie via l'interrupteur. Cette configuration vous permet d'allumer et d'éteindre la voiture selon vos besoins. Si vous préférez une configuration plus simple, vous pouvez choisir de contourner complètement l'interrupteur.

Code Arduino

Le contenu de la page web (HTML, CSS, JavaScript) est stocké séparément dans un fichier index.h. Nous aurons donc deux fichiers de code sur Arduino IDE :

  • Un fichier .ino qui contient du code Arduino, créant un serveur web et un serveur WebSocket, et contrôle une voiture.
  • Un fichier .h, qui contient le contenu de la page web.

Étapes rapides

  • Si c'est la première fois que vous utilisez Arduino Uno R4, consultez comment configurer l'environnement pour Arduino Uno R4 sur Arduino IDE.
  • Réalisez le câblage comme sur l'image ci-dessus.
  • Connectez la carte Arduino à votre PC via un câble micro USB.
  • Ouvrez Arduino IDE sur votre PC.
  • Sélectionnez la bonne carte Arduino (Arduino Uno R4 WiFi) et le port COM.
  • Ouvrez le Gestionnaire de bibliothèques en cliquant sur l'icône Gestionnaire de bibliothèques dans la barre de navigation gauche de l'Arduino IDE.
  • Recherchez "mWebSockets", puis trouvez les mWebSockets créés par Dawid Kurek.
  • Cliquez sur le bouton Install pour installer la bibliothèque mWebSockets.
Bibliothèque mWebSockets Arduino
  • Sur l'IDE Arduino, créez une nouvelle esquisse, nommez-la, par exemple, ArduinoGetStarted.com.ino
  • Copiez le code ci-dessous et ouvrez-le avec l'IDE Arduino
/* * Ce code Arduino a été développé par newbiely.fr * Ce code Arduino est mis à disposition du public sans aucune restriction. * Pour des instructions complètes et des schémas de câblage, veuillez visiter: * https://newbiely.fr/tutorials/arduino/arduino-controls-car-via-web */ #include <WiFiS3.h> #include <WebSocketServer.h> #include "index.h" #define CMD_STOP 0 #define CMD_FORWARD 1 #define CMD_BACKWARD 2 #define CMD_LEFT 4 #define CMD_RIGHT 8 #define ENA_PIN 7 // The Arduino pin connected to the ENA pin L298N #define IN1_PIN 6 // The Arduino pin connected to the IN1 pin L298N #define IN2_PIN 5 // The Arduino pin connected to the IN2 pin L298N #define IN3_PIN 4 // The Arduino pin connected to the IN3 pin L298N #define IN4_PIN 3 // The Arduino pin connected to the IN4 pin L298N #define ENB_PIN 2 // The Arduino pin connected to the ENB pin L298N const char *ssid = "YOUR_WIFI_SSID"; // CHANGE IT const char *password = "YOUR_WIFI_PASSWORD"; // CHANGE IT using namespace net; WebSocketServer webSocket(81); WiFiServer server(80); int status = WL_IDLE_STATUS; void setup() { Serial.begin(9600); pinMode(ENA_PIN, OUTPUT); pinMode(IN1_PIN, OUTPUT); pinMode(IN2_PIN, OUTPUT); pinMode(IN3_PIN, OUTPUT); pinMode(IN4_PIN, OUTPUT); pinMode(ENB_PIN, OUTPUT); digitalWrite(ENA_PIN, HIGH); // set full speed digitalWrite(ENB_PIN, HIGH); // set full speed //Initialize serial and wait for port to open: Serial.begin(9600); String fv = WiFi.firmwareVersion(); if (fv < WIFI_FIRMWARE_LATEST_VERSION) Serial.println("Please upgrade the firmware"); // attempt to connect to WiFi network: while (status != WL_CONNECTED) { Serial.print("Attempting to connect to SSID: "); Serial.println(password); // Connect to WPA/WPA2 network. Change this line if using open or WEP network: status = WiFi.begin(ssid, password); // wait 4 seconds for connection: delay(4000); } // print your board's IP address: Serial.print("IP Address: "); Serial.println(WiFi.localIP()); server.begin(); webSocket.onConnection([](WebSocket &ws) { const auto protocol = ws.getProtocol(); if (protocol) { Serial.print(F("Client protocol: ")); Serial.println(protocol); } ws.onMessage([](WebSocket &ws, const WebSocket::DataType dataType, const char *message, uint16_t length) { String cmd_str = String((char *)message); int command = cmd_str.toInt(); Serial.print("command: "); Serial.println(command); switch (dataType) { case WebSocket::DataType::TEXT: switch (command) { case CMD_STOP: Serial.println("Stop"); CAR_stop(); break; case CMD_FORWARD: Serial.println("Move Forward"); CAR_moveForward(); break; case CMD_BACKWARD: Serial.println("Move Backward"); CAR_moveBackward(); break; case CMD_LEFT: Serial.println("Turn Left"); CAR_turnLeft(); break; case CMD_RIGHT: Serial.println("Turn Right"); CAR_turnRight(); break; default: Serial.println("Unknown command"); } break; case WebSocket::DataType::BINARY: Serial.println(F("Received binary data")); break; } }); ws.onClose([](WebSocket &, const WebSocket::CloseCode, const char *, uint16_t) { Serial.println(F("Disconnected")); }); Serial.print(F("New WebSocket Connnection from client: ")); Serial.println(ws.getRemoteIP()); }); webSocket.begin(); } void loop() { webSocket.listen(); // listen for incoming clients WiFiClient client = server.available(); if (client) { // read the HTTP request header line by line while (client.connected()) { if (client.available()) { String HTTP_header = client.readStringUntil('\n'); // read the header line of HTTP request if (HTTP_header.equals("\r")) // the end of HTTP request break; Serial.print("<< "); Serial.println(HTTP_header); // print HTTP request to Serial Monitor } } // send the HTTP response header client.println("HTTP/1.1 200 OK"); client.println("Content-Type: text/html"); client.println("Connection: close"); // the connection will be closed after completion of the response client.println(); // the separator between HTTP header and body String html = String(HTML_CONTENT); client.println(html); client.flush(); // give the web browser time to receive the data delay(100); // close the connection: client.stop(); } } void CAR_moveForward() { digitalWrite(IN1_PIN, HIGH); digitalWrite(IN2_PIN, LOW); digitalWrite(IN3_PIN, HIGH); digitalWrite(IN4_PIN, LOW); } void CAR_moveBackward() { digitalWrite(IN1_PIN, LOW); digitalWrite(IN2_PIN, HIGH); digitalWrite(IN3_PIN, LOW); digitalWrite(IN4_PIN, HIGH); } void CAR_turnLeft() { digitalWrite(IN1_PIN, HIGH); digitalWrite(IN2_PIN, LOW); digitalWrite(IN3_PIN, LOW); digitalWrite(IN4_PIN, LOW); } void CAR_turnRight() { digitalWrite(IN1_PIN, LOW); digitalWrite(IN2_PIN, LOW); digitalWrite(IN3_PIN, HIGH); digitalWrite(IN4_PIN, LOW); } void CAR_stop() { digitalWrite(IN1_PIN, LOW); digitalWrite(IN2_PIN, LOW); digitalWrite(IN3_PIN, LOW); digitalWrite(IN4_PIN, LOW); }
  • Modifiez les informations WiFi (SSID et mot de passe) dans le code pour correspondre à vos propres identifiants de réseau.
  • Créez le fichier index.h dans l'IDE Arduino en :
    • Cliquant soit sur le bouton juste en dessous de l'icône du moniteur série et choisissez Nouvel Onglet, soit utilisez les touches Ctrl+Maj+N.
    L'IDE Arduino 2 ajoute un fichier
    • Donnez le nom du fichier index.h et cliquez sur le bouton OK
    L'IDE Arduino 2 ajoute le fichier index.h
    • Copiez le code ci-dessous et collez-le dans le fichier index.h.
    /* * Ce code Arduino a été développé par newbiely.fr * Ce code Arduino est mis à disposition du public sans aucune restriction. * Pour des instructions complètes et des schémas de câblage, veuillez visiter: * https://newbiely.fr/tutorials/arduino/arduino-controls-car-via-web */ const char *HTML_CONTENT = R"=====( <!DOCTYPE html> <html> <head> <title>Arduino Control Car via Web</title> <meta name="viewport" content="width=device-width, initial-scale=0.7, maximum-scale=1, user-scalable=no"> <style type="text/css"> body { text-align: center; font-size: 24px;} button { text-align: center; font-size: 24px;} #container { margin-right: auto; margin-left: auto; width: 400px; height: 400px; position: relative; margin-bottom: 10px; } div[class^='button'] { position: absolute; } .button_up, .button_down { width:214px; height:104px;} .button_left, .button_right { width:104px; height:214px;} .button_stop { width:178px; height:178px;} .button_up { background: url('https://esp32io.com/images/tutorial/up_inactive.png') no-repeat; background-size: contain; left: 200px; top: 0px; transform: translateX(-50%); } .button_down { background: url('https://esp32io.com/images/tutorial/down_inactive.png') no-repeat; background-size: contain; left:200px; bottom: 0px; transform: translateX(-50%); } .button_right { background: url('https://esp32io.com/images/tutorial/right_inactive.png') no-repeat; background-size: contain; right: 0px; top: 200px; transform: translateY(-50%); } .button_left { background: url('https://esp32io.com/images/tutorial/left_inactive.png') no-repeat; background-size: contain; left:0px; top: 200px; transform: translateY(-50%); } .button_stop { background: url('https://esp32io.com/images/tutorial/stop_inactive.png') no-repeat; background-size: contain; left:200px; top: 200px; transform: translate(-50%, -50%); } </style> <script> var CMD_STOP = 0; var CMD_FORWARD = 1; var CMD_BACKWARD = 2; var CMD_LEFT = 4; var CMD_RIGHT = 8; var img_name_lookup = { [CMD_STOP]: "stop", [CMD_FORWARD]: "up", [CMD_BACKWARD]: "down", [CMD_LEFT]: "left", [CMD_RIGHT]: "right" } var ws = null; function init() { var container = document.querySelector("#container"); container.addEventListener("touchstart", mouse_down); container.addEventListener("touchend", mouse_up); container.addEventListener("touchcancel", mouse_up); container.addEventListener("mousedown", mouse_down); container.addEventListener("mouseup", mouse_up); container.addEventListener("mouseout", mouse_up); } function ws_onmessage(e_msg) { e_msg = e_msg || window.event; // MessageEvent //alert("msg : " + e_msg.data); } function ws_onopen() { document.getElementById("ws_state").innerHTML = "OPEN"; document.getElementById("wc_conn").innerHTML = "Disconnect"; } function ws_onclose() { document.getElementById("ws_state").innerHTML = "CLOSED"; document.getElementById("wc_conn").innerHTML = "Connect"; console.log("socket was closed"); ws.onopen = null; ws.onclose = null; ws.onmessage = null; ws = null; } function wc_onclick() { if(ws == null) { ws = new WebSocket("ws://" + window.location.host + ":81"); document.getElementById("ws_state").innerHTML = "CONNECTING"; ws.onopen = ws_onopen; ws.onclose = ws_onclose; ws.onmessage = ws_onmessage; } else ws.close(); } function mouse_down(event) { if (event.target !== event.currentTarget) { var id = event.target.id; send_command(id); event.target.style.backgroundImage = "url('https://esp32io.com/images/tutorial/" + img_name_lookup[id] + "_active.png')"; } event.stopPropagation(); event.preventDefault(); } function mouse_up(event) { if (event.target !== event.currentTarget) { var id = event.target.id; send_command(CMD_STOP); event.target.style.backgroundImage = "url('https://esp32io.com/images/tutorial/" + img_name_lookup[id] + "_inactive.png')"; } event.stopPropagation(); event.preventDefault(); } function send_command(cmd) { if(ws != null) if(ws.readyState == 1) ws.send(cmd + "\r\n"); } window.onload = init; </script> </head> <body> <h2>Arduino - RC Car via Web</h2> <div id="container"> <div id="0" class="button_stop"></div> <div id="1" class="button_up"></div> <div id="2" class="button_down"></div> <div id="8" class="button_right"></div> <div id="4" class="button_left"></div> </div> <p> WebSocket : <span id="ws_state" style="color:blue">closed</span><br> </p> <button id="wc_conn" type="button" onclick="wc_onclick();">Connect</button> <br> <br> <div class="sponsor">Sponsored by <a href="https://amazon.com/diyables">DIYables</a></div> </body> </html> )=====";
    • Maintenant, vous avez le code dans deux fichiers : ArduinoGetStarted.com.ino et index.h
    • Cliquez sur le bouton Upload de l'IDE Arduino pour téléverser le code sur Arduino

    Vous verrez une erreur comme ci-dessous :

    In file included from c:\Users\YOU_ACCOUNT\Documents\Arduino\libraries\mWebSockets\src/utility.h:3:0, from c:\Users\YOU_ACCOUNT\Documents\Arduino\libraries\mWebSockets\src/WebSocket.h:5, from c:\Users\YOU_ACCOUNT\Documents\Arduino\libraries\mWebSockets\src/WebSocketServer.h:5, from C:\Users\YOU_ACCOUNT\Documents\Arduino\ArduinoGetStarted.com\ArduinoGetStarted.com.ino:2: C:\Users\YOU_ACCOUNT\Documents\Arduino\libraries\mWebSockets\src/platform.h:54:12: fatal error: Ethernet.h: No such file or directory # include <Ethernet.h> ^~~~~~~~~~~~ compilation terminated. exit status 1

    Pour corriger cette erreur :

    • Accédez au répertoire C:\Users\VOTRE_COMPTE\Documents\Arduino\libraries\mWebSockets\src/.
    • Trouvez le fichier config.h et ouvrez-le avec un éditeur de texte.
    • Regardez la ligne 26, vous la verrez comme ci-dessous :
    #define NETWORK_CONTROLLER ETHERNET_CONTROLLER_W5X00
    • Modifiez cette ligne par celle ci-dessous et enregistrez-la :
    #define NETWORK_CONTROLLER NETWORK_CONTROLLER_WIFI
    • Cliquez sur le bouton Upload sur l'IDE Arduino pour téléverser le code vers Arduino.
    • Ouvrez le moniteur série
    • Consultez le résultat sur le moniteur série.
    COM6
    Send
    Connecting to WiFi... Connected to WiFi Arduino Web Server's IP address IP address: 192.168.0.2
    Autoscroll Show timestamp
    Clear output
    9600 baud  
    Newline  
    • Prenez note de l'adresse IP affichée et saisissez cette adresse dans la barre d'adresse d'un navigateur web sur votre smartphone ou PC.
    • Vous verrez la page web comme ci-dessous :
    Arduino contrôle la voiture via le navigateur web
    • Cliquez sur le bouton CONNECT pour connecter la page web à Arduino via WebSocket.
    • Vous pouvez maintenant contrôler la voiture pour tourner à gauche/droite, avancer/reculer via l'interface web.

    Pour économiser la mémoire de l'Arduino, les images des boutons de contrôle ne sont PAS stockées sur l'Arduino. Au lieu de cela, elles sont stockées sur Internet, donc, votre téléphone ou PC doit être connecté à Internet pour charger les images pour la page de contrôle web.

    ※ NOTE THAT:

    • Si vous modifiez le contenu HTML dans le index.h et ne touchez à rien dans le fichier ArduinoGetStarted.com.ino, lorsque vous compilez et téléchargez le code sur Arduino, l'IDE Arduino ne mettra pas à jour le contenu HTML.
    • Pour que l'IDE Arduino mette à jour le contenu HTML dans ce cas, apportez une modification dans le fichier ArduinoGetStarted.com.ino (par exemple, ajouter une ligne vide, ajouter un commentaire....)

    Explication du code ligne par ligne

    Le code Arduino ci-dessus contient des explications ligne par ligne. Veuillez lire les commentaires dans le code !

※ OUR MESSAGES

  • Please feel free to share the link of this tutorial. However, Please do not use our content on any other websites. We invested a lot of effort and time to create the content, please respect our work!