Aller au contenu

Voiture télécommandée Arduino : prototype de véhicule à 3 roues

Voiture radiocommandée arduino fonctionnant sur accus lithium ion et émetteur récepteur nRF24 radio, pilotage L298N des moteurs électriques, modèle à 3 roues

Histoire de vous montrer une application concrète de l’émetteur/récepteur radio nRF24, je vous partage ici un prototype de voiture télécommandée arduino, à 3 roues. Bien sûr, ce véhicule n’aura pas pour but d’être performant, car il s’agit là d’un projet purement didactique (vous permettant donc d’apprendre l’électronique pas à pas, de manière simple, ludique, et pratique).

Comme d’habitude, je vous mettrai la liste de tous les composants utilisés ici, ainsi que les plans, schémas, et programme arduino en libre téléchargement, en fin d’article (aussi bien pour la partie électronique, que pour le châssis en impression 3d). Ainsi, vous pourrez reproduire cette voiture RC arduino, si le cœur vous en dit ! Par contre, gardez bien à l’esprit qu’il s’agit ici d’un prototype de voiture radiocommandée : il y a donc beaucoup de choses qui pourraient être améliorées ! Le but restant l’apprentissage de l’électronique avant tout ici, encore une fois 😉

Bonjour, et bienvenue sur le site Passion Electronique !

Au sujet de cette réalisation : ce projet de voiture télécommandée arduino a deux objectifs. Le 1er est de vous inspirer à créer vous-même vos propres projets, à partir d’un exemple concret de réalisation. Et le 2ème est de vous montrer comment mettre en œuvre des émetteurs récepteurs sans fil 2,4 GHz en pratique, notamment au niveau du code arduino. Bien sûr, libre à vous de reprendre tout ou partie de ce projet à votre guise, et selon vos besoins !

Intro : ce projet de « voiture télécommandée arduino »

En fait, l’idée d’une réalisation de voiture radiocommandée arduino fait suite à vos nombreux messages perso, et commentaires au niveau de l’article tutorial sur le nRF24. Et comme vous le souhaitiez, voici un exemple simple, pratique, et fonctionnel, de communication radio en 2,4 GHz !

Par ailleurs, ce projet me permettra de vous montrer également une mise en pratique concrète du driver de moteurs L298N, au sein d’un projet particulier. Ainsi, vous pourrez voir comment piloter des moteurs à courant continu en PWM, via un Arduino, en toute simplicité.

Enfin, comme j’avais précédemment réalisé une petite alimentation sans fil à base d’accus li-ion 18650, ce sera aussi l’occasion d’en montrer un exemple d’utilisation pratique !

Au final, comme vous l’aurez compris, cette voiture RC arduino comprendra :

  • 1 x coupleur d’accus lithium-ion 18650, pour alimenter la partie puissance, ainsi que la partie commande
  • 1 x module L298N, pour le pilotage des moteurs
  • 1 x module NRF24L01+, pour la partie radio
  • Et un arduino, pour orchestrer tout cela !

Bien évidemment, comme vous vous en doutez, il faudra un émetteur radio séparé, pour piloter cette voiture arduino. Pour cela, je me servirai tout simplement de la télécommande radio (à simple joystick), que j’avais réalisé il y a quelques temps. Ainsi, la boucle sera bouclée 😉

Du reste, comme je vous disais au début, ce projet n’a pas pour but d’être meilleur (ou moins cher) que ce que l’on trouve ailleurs, dans le commerce. Non, le but de ce projet est simplement de vous montrer une façon de mettre en œuvre plusieurs modules arduino, afin de créer un ensemble communiquant, et abouti. Et ceci, afin de vous permettre d’apprendre l’électronique de chez vous, tout simplement ! C’est pourquoi cet article se veut plus éducatif, avant toute autre chose !

Bon… trêve de blabla, et commençons par voir le schéma fonctionnel de cette voiture radiocommandée arduino, pour commencer !

Schéma fonctionnel de cette voiture radiocommandée arduino

Le schéma fonctionnel suivant, résume bloc par bloc tout ce que cette voiture télécommandée arduino va faire en « interne », vis-à-vis de l’extérieur. Enfin… de manière simplifiée !

Schéma fonctionnel voiture rc arduino, avec batterie li-ion, module nRF24, arduino nano, et driver de moteurs électriques L298N, avec signaux de contrôle

Comme vous pouvez le constater, on retrouve 6 blocs principaux, à savoir :

  • Le bloc d’alimentation, qui a pour rôle de fournir de l’énergie aux moteurs, ainsi qu’à la platine arduino
  • Le bloc de réception radio, qui a pour mission de capter tous les messages radios émanant de l’émetteur radio
  • Le bloc de conversion de niveaux, qui a pour but de transmettre des informations à l’Arduino, au sujet des accus li-ion 18650 (après abaissement des tensions mesurées)
  • Le bloc de gestion/pilotage, c’est-à-dire l’arduino en lui-même, qui a pour rôles de :
    • surveiller le niveau des accus (afin d’éviter toute décharge trop importante de ces derniers)
    • piloter les moteurs électrique (au travers du module L298N)
    • et afficher des signaux lumineux au besoin (en cas de batterie faible, ou de signal radio perdu)
  • Le bloc de commande de puissance des moteurs, basé sur le L298N, et permettant de piloter directement les moteurs, en fonction des consignes fournies par l’arduino
  • Et le bloc d’alertes, qui est simplement constitué de 2 leds (1 rouge pour signaler des accus possiblement trop déchargés, et 1 orange, pour indiquer la perte de signal radio)

Une parenthèse, concernant ce schéma fonctionnel : si je l’ai fait, c’est simplement pour préparer l’étape suivante. D’ailleurs, comme vous pourrez le vérifier, chaque bloc que nous avons vu ici se retrouvera sur le schéma électronique final. Ainsi, ce n’est pas travailler pour rien que de faire un tel travail préparatoire ! Au contraire, je dirais que c’est presque indispensable, lorsqu’on cherche à structurer son travail, pour être plus efficace 😉

Schéma électronique de la platine de commande

Comme évoqué juste avant, le schéma électronique de cette voiture RC arduino découle du schéma fonctionnel vu précédemment. Mais avant d’entrer dans le détail de ce schéma à proprement parler, il y a 2 choses qu’il faut bien comprendre :

  • Premièrement, le bloc d’accus assurant l’alimentation de commande et de puissance est un élément à part entière (et comme évoqué un peu plus haut, il a déjà été détaillé, dans un précédent article)
  • Deuxièmement, le module L298N assurant le pilotage de puissance des moteurs est également un élément à part entière

Du coup, le schéma présenté ici ne sera en fait que celui de la « platine de commande », intégrant un Arduino Nano et son transmetteur radio nRF24L01+. Cette platine s’alimentera à partir du bloc d’accus li-ion, et commandera le module L298N au besoin. D’ailleurs, voici le schéma complet de cette platine de commande arduino, avec toutes les interconnexions vers l’extérieur :

Schéma électronique voiture radiocommandée arduino avec alimentation sur accus 18650, récepteur radio nRF24L01 et commande moteur par L298N pilotage

Comme vous pouvez le constater, on retrouve bien les 6 blocs du schéma fonctionnel, de cette voiture radiocommandée arduino. Ceux-ci sont, pour rappel :

  • La partie alim : qui récupère la tension fournie par le pack d’accus li-ion 18650, via un connecteur XT30. Avec, au passage, un interrupteur marche/arrêt pour isoler l’arduino du reste du montage, ainsi qu’une diode de protection contre les inversions de polarité (modèle schottky 1N5817)
  • La partie commande : qui est tout simplement constituée d’un Arduino Nano
  • La partie signalisation lumineuse : qui est assurée par 2 leds colorées, une rouge et une orange (respectivement pour indiquer l’éventuelle faiblesse des batteries, et la perte éventuelle du signal radio)
  • La partie pilotage des moteurs : qui se résume à un connecteur à 6 fils, à destination du module L298N
  • La partie surveillance de niveaux d’accus : qui comprend 3 résistances permettant de compléter le système « pont diviseur de tension », initié au niveau du pack d’accus (sera détaillé plus loin)
  • Et la partie réception radio : qui est simplement constituée d’un module nRF24L01+ (avec antenne intégrée)

Pour ainsi dire, il n’y a vraiment rien de compliqué dans ce schéma. Il y a très peu de composants utilisés, comme vous pouvez le voir. Toutefois, il y a 2 subtilités à bien comprendre, là aussi :

  • La 1ère : les deux LED seront allumées lorsque les sorties de l’arduino seront à l’état bas (0V), et éteintes lorsque les sorties seront à l’état haut (c’est-à-dire quand elles seront à +5V)
  • La 2nde : les 3 résistances 10k mises à la masse au niveau du « bloc de surveillance de niveaux d’accus » font suite à 3 résistances 22k mises en série sur ces lignes, au niveau du bloc d’accus (non visibles, sur ce schéma) ; cela peut donc paraître bizarre, mais ces 6 résistances (les 3 ici et les 3 sur l’alim li-ion) forment bien 3 ponts diviseurs de tension, qui permettent d’abaisser la tension des accus, afin que celles-ci puissent être mesurées par l’arduino (pour être dans les limites de la plage de lecture du convertisseur analogique-digital de l’Arduino, plus précisément)

Du reste, comme vous l’aurez compris, toute la « logique de commande » se passe au niveau logiciel. Ce qui permet d’avoir une partie matérielle assez épurée. D’ailleurs, en parlant de la partie logicielle, voyons à présent comment celle-ci s’articule !

Diagramme fonctionnel (processus logiciel)

Le code de programmation arduino de cette voiture radiocommandée va suivre un process bien particulier, comme visible juste après. En effet, il faudra que le programme :

  • surveille en permanence le niveau des accus
  • vérifie s’il y a ou non des commandes radio reçues
  • et pilote les moteurs en conséquence (en envoyant les commandes appropriées, au module L298N)

C’est pourquoi l’ensemble de ces fonctionnalités sera intégré dans une boucle perpétuelle, à répétition cyclique. Le reste tout autour, n’est au final qu’accessoire. D’ailleurs, en parlant de ce diagramme fonctionnel, le voici :

Logigramme code de programmation voiture télécommandée arduino via ondes radio, avec système de gestion batterie lithium ion et nRF24

En fait, en « temps normal », tout se passe au niveau de la « colonne centrale ». Sinon :

  • si la batterie devient trop faible, alors on bascule sur la colonne de droite, pour mettre la voiture au repos, et arrêter le programme
  • et si le signal radio de l’émetteur est « perdu », alors on bascule sur la colonne de gauche, pour mettre temporairement les moteurs à l’arrêt (c’est en fait une sécurité pour que le véhicule ne continue pas sur sa lancée, en cas de défaillance de l’émetteur)

Cela étant dit, vous verrez que le programme est, à peu de choses près, calqué sur ce diagramme fonctionnel. D’ailleurs, voyons-le dès à présent, sans plus attendre !

Programme arduino (code)

Concernant le programme arduino de cette petite voiture télécommandée, vous verrez que cela suit à peu de choses près le diagramme fonctionnel précédent. D’ailleurs, le voici :

/*
   ______               _                  _///  _           _                   _
  /   _  \             (_)                |  __\| |         | |                 (_)
  |  [_|  |__  ___  ___ _  ___  _ __      | |__ | | ___  ___| |_ _ __ ___  _ __  _  ___  _   _  ___
  |   ___/ _ \| __|| __| |/ _ \| '_ \_____|  __|| |/ _ \/  _|  _| '__/   \| '_ \| |/   \| | | |/ _ \
  |  |  | ( ) |__ ||__ | | ( ) | | | |____| |__ | |  __/| (_| |_| | | (_) | | | | | (_) | |_| |  __/
  \__|   \__,_|___||___|_|\___/|_| [_|    \____/|_|\___|\____\__\_|  \___/|_| |_|_|\__  |\__,_|\___|
                                                                                      | |
                                                                                      \_|
  Fichier:      prgVoiture3rouesRC
  
  Description:  Programme de bord de l'Arduino Nano, faisant tourner le projet de "Voiture Radiocommandée à 3 roues"
                (exemple de mise en oeuvre des modules émetteur/récepteur NRF24L01+)

                
  Auteur:       Jérôme, Passion-Électronique (https://passionelectronique.fr/)
  Création :    29.11.2021

  Librairie utilisée : https://github.com/nRF24/RF24
  
*/

//***************//
// Bibliothèques //
//***************//
#include <SPI.h>
#include <RF24.h>


//**************************************************//
// Définition des entrées/sorties de l'Arduino Nano //
//**************************************************//
#define borneENA_L298N    9       // On associe la borne "ENA" du L298N à la pin D9 de l'arduino
#define borneIN1_L298N    8       // On associe la borne "IN1" du L298N à la pin D8 de l'arduino
#define borneIN2_L298N    7       // On associe la borne "IN2" du L298N à la pin D7 de l'arduino
#define borneIN3_L298N    5       // On associe la borne "IN3" du L298N à la pin D5 de l'arduino
#define borneIN4_L298N    4       // On associe la borne "IN4" du L298N à la pin D4 de l'arduino
#define borneENB_L298N    3       // On associe la borne "ENB" du L298N à la pin D3 de l'arduino

#define pinCE_RF24       10       // On associe la broche "CE" du NRF24L01 à la pin D10 de l'arduino
#define pinCSN_RF24       2       // On associe la broche "CSN" du NRF24L01 à la pin D2 de l'arduino

#define pinVA_PACK_ACCUS_18650    A0    // [Entrée] Pour mesure de tension "nominale 11,1V" du pack d'accus li-ion 18650
#define pinVB_PACK_ACCUS_18650    A1    // [Entrée] Pour mesure de tension "nominale  7,4V" du pack d'accus li-ion 18650
#define pinVC_PACK_ACCUS_18650    A2    // [Entrée] Pour mesure de tension "nominale  3,7V" du pack d'accus li-ion 18650

#define tensionMinimaleAccu       3     // On définit que la tension minimale de chaque accu 18650 qui alimente se projet, ne doit pas être en dessous de 3V

#define pinLed_BatterieFaible     A3    // [Sortie] Raccordé à la LED rouge présente sur le PCB (batterie faible), s'allumant quand la sortie est mise à 0
#define pinLed_SignalRadioPerdu   A4    // [Sortie] Raccordé à la LED orange présente sur le PCB (signal radio perdu), s'allumant quand la sortie est mise à 0


//*****************************************************//
// Définition de paramètres généraux pour ce programme //
//*****************************************************//
#define tunnelDeCommunication             "REA01"   // Déclaration d'un "nom de tunnel" (5 caractères) => doit être strictement identique à l'émetteur
#define valeurResistanceDiviseur_serie      22000   // Résistance 1/2 du pont diviseur de tension créé pour mesurer la tension de chaque accu 18650 (côté pack accus)
#define valeurResistanceDiviseur_pullDown   10000   // Résistance 2/2 du pont diviseur de tension créé pour mesurer la tension de chaque accu 18650 (côté de ce montage)
#define tensionReferenceAdcArduino              5   // Tension de référence de l'ADC de l'Arduino Nano (par défaut à 5 volts)
#define vitesseMinimale                        55   // Rapport cylique minimal des signaux PWM, pour faire tourner les moteur au minimum de leur vitesse (en pratique, on évitera de trop approcher de la valeur 0)
#define vitesseMaximale                       255   // Rapport cylique maximal des signaux PWM, pour faire tourner les moteur au maximum de leur vitesse


//************************//
// Variables du programme //
//************************//
const byte adresse[6] = tunnelDeCommunication;      // Mise au format "byte array" du nom du tunnel

int valBrocheVA;            // Variable 16 bits où sera stockée la lecture 10 bits (0..1023) de l'ADC en VA
int valBrocheVB;            // Variable 16 bits où sera stockée la lecture 10 bits (0..1023) de l'ADC en VB
int valBrocheVC;            // Variable 16 bits où sera stockée la lecture 10 bits (0..1023) de l'ADC en VC

float valTensionVA;         // Variable de calcul qui donnera la "vraie" valeur de tension de VA, après correction inverse du pont diviseur résistif (11,1V au nominal)
float valTensionVB;         // Variable de calcul qui donnera la "vraie" valeur de tension de VB, après correction inverse du pont diviseur résistif ( 7,4V au nominal)
float valTensionVC;         // Variable de calcul qui donnera la "vraie" valeur de tension de VC, après correction inverse du pont diviseur résistif ( 3,7V au nominal)

float tensionAccu1;         // Variable de calcul qui contiendra la tension de l'accu li-ion n°1
float tensionAccu2;         // Variable de calcul qui contiendra la tension de l'accu li-ion n°2
float tensionAccu3;         // Variable de calcul qui contiendra la tension de l'accu li-ion n°3

unsigned long heureDernierSignalRecu = 0;   // Variable qui contiendra "l'heure" du dernier signal reçu, en provenance de l'émetteur (nota : ce n'est pas réellement l'heure, mais un "compteur de millisecondes écoulées", interne à l'arduino)
boolean bSignalRadioPerdu = false;          // Variable qui mémorisera le fait que le signal radio de l'émetteur n'est plus reçu ici, si c'est le cas

RF24 radio(pinCE_RF24, pinCSN_RF24);                // Instanciation du NRF24L01


//************************************************************//
// Format des données à recevoir, par ondes radio (structure) //
//************************************************************//
struct DonneesArecevoir {
  int valAvancerReculer;    // int (2 octets), transportant une valeur comprise entre -255 et +255  (-255 signifie ici reculer à vitesse maximale, et +255, avancer à vitesse maximale)
  int valDroiteGauche;      // int (2 octets), transportant une valeur comprise entre -255 et +255  (-255 signifie ici tourner à gauche pleinement, et +255, signifie tourner pleinement à droite)
};
DonneesArecevoir donnees;


//*******//
// SETUP //
//*******//
void setup() {

  // Configuration des pins de l'Arduino Nano à destination du module L298N, en sorties
  pinMode(borneENA_L298N, OUTPUT);
  pinMode(borneIN1_L298N, OUTPUT);
  pinMode(borneIN2_L298N, OUTPUT);
  pinMode(borneIN3_L298N, OUTPUT);
  pinMode(borneIN4_L298N, OUTPUT);
  pinMode(borneENB_L298N, OUTPUT);
  
  // Configuration des pins de l'Arduino en destination des LEDs, en sorties également
  pinMode(pinLed_BatterieFaible, OUTPUT);       // Sortie LED rouge "Batterie faible"
  pinMode(pinLed_SignalRadioPerdu, OUTPUT);     // Sortie LED orange "Signal radio perdu"
  
  // Allumage/extinction des LEDS au démarrage, pour "autotest"
  autotestLedsAuDemarrage();
  arretMoteurs();
  
  // Démarrage du module NRF24L01+, avec paramétrages de base
  radio.begin();                        // Initialisation du module nRF24
  radio.openReadingPipe(0, adresse);    // Ouverture du tunnel en "LECTURE" (avec le "nom" qu'on lui a donné)
  radio.setPALevel(RF24_PA_MIN);        // Sélection d'un niveau "MINIMAL" d'émission, pour communiquer (car pas besoin ici d'une forte puissance, pour ce projet)
  radio.startListening();               // Activation du mode "écoute" pour le nRF24 (signifiant qu'on va recevoir des données, et non en émettre, ici)

}

//**************************//
// Boucle principale : LOOP //
//**************************//
void loop() {

  mesurerTensionsAccus();    // Stocke le résultat dans les variables : tensionAccu1, tensionAccu2, et tensionAccu3

  // Test : vérification de la tension de chaque accu, par rapport à la valeur minimale qu'on a définit plus haut
  if(tensionAccu1 < tensionMinimaleAccu || tensionAccu2 < tensionMinimaleAccu || tensionAccu3 < tensionMinimaleAccu) {
    // Si un des accus a une tension trop basse, alors "on arrête tout"
    stopperProgramme();
  }
  else {
    // Si les tensions d'accus sont bonnes, alors on continue le programme
    if(donneesRecues()) {
      heureDernierSignalRecu = millis();                  // Mise à jour de "l'heure" du dernier signal reçu
      digitalWrite(pinLed_SignalRadioPerdu, HIGH);        // Extinction de la LED "signal radio perdu", si allumée
      envoiConsignesAuxMoteurs();
    } else {
      // Si aucune donnée radio n'est reçue, alors on regarde si ça fait plus de 2 secondes (soit 2000 millisecondes)
      if((millis() - heureDernierSignalRecu) > 2000) {
        // Cela fait plus de 2 seconde qu'aucun signal radio n'a été reçu
        digitalWrite(pinLed_SignalRadioPerdu, LOW);       // Allumage de la LED "signal radio perdu"
        arretMoteurs();                                   // Arrêt des moteurs, car aucune donnée reçue (émetteur coupé ? trop éloigné ?)
      }
    }
  }
}



//**************************************//
// Fonction : autotestLedsAuDemarrage() //
//**************************************//
void autotestLedsAuDemarrage() {

  // Allumage puis extinction des LEDs rouge et orange (activent à l'état bas), et ce, deux fois de suite
  for(byte i = 0 ; i < 3 ; i++) {
    digitalWrite(pinLed_BatterieFaible, LOW);
    digitalWrite(pinLed_SignalRadioPerdu, LOW);
    delay(20);
    digitalWrite(pinLed_BatterieFaible, HIGH);
    digitalWrite(pinLed_SignalRadioPerdu, HIGH);
    delay(200);    
  }
}

//***********************************//
// Fonction : mesurerTensionsAccus() //
//***********************************//
void mesurerTensionsAccus() {

  // Lecture des entrées analogiques
  valBrocheVA = analogRead(pinVA_PACK_ACCUS_18650);       // Valeur comprise entre 0 et 1023 (avec 1023 correspondant à +5V)
  valBrocheVB = analogRead(pinVB_PACK_ACCUS_18650);       // Valeur comprise entre 0 et 1023 (avec 1023 correspondant à +5V)
  valBrocheVC = analogRead(pinVC_PACK_ACCUS_18650);       // Valeur comprise entre 0 et 1023 (avec 1023 correspondant à +5V)

  // Calcul des tensions réelles, correspondantes à ces entrées (avec calculs inverses, dûs aux ponts diviseurs de tension)
  // Les valeurs obtenues seront, au nominal, de : 11,1V pour VA / 7,4V pour VB / 3,7V pour VC
  valTensionVA = (float)valBrocheVA * (valeurResistanceDiviseur_serie + valeurResistanceDiviseur_pullDown) / valeurResistanceDiviseur_pullDown * tensionReferenceAdcArduino / 1023;
  valTensionVB = (float)valBrocheVB * (valeurResistanceDiviseur_serie + valeurResistanceDiviseur_pullDown) / valeurResistanceDiviseur_pullDown * tensionReferenceAdcArduino / 1023;
  valTensionVC = (float)valBrocheVC * (valeurResistanceDiviseur_serie + valeurResistanceDiviseur_pullDown) / valeurResistanceDiviseur_pullDown * tensionReferenceAdcArduino / 1023;

  // Calcul des tensions individuelles de chaque accu lithium ion
  tensionAccu1 = valTensionVA - valTensionVB;             // 11,1 - 7,4 = 3,7V au nominal
  tensionAccu2 = valTensionVB - valTensionVC;             //  7,4 - 3,7 = 3,7V au nominal
  tensionAccu3 = valTensionVC;                            //  3,7 - 0,0 = 3,7V au nominal
}

//*******************************//
// Fonction : stopperProgramme() //
//*******************************//
void stopperProgramme() {

    digitalWrite(pinLed_BatterieFaible, LOW);         // On allume la LED rouge ("batterie faible")
    digitalWrite(pinLed_SignalRadioPerdu, HIGH);      // On éteint la LED orange ("signal radio perdu"), si allumée
    arretMoteurs();                                   // On met les moteurs au repos
    radio.powerDown();                                // Mise en sommeil du module récepteur nRF24
    while(1) {}                                       // Boucle sans fin ("arrêt du programme")
}

//****************************//
// Fonction : donneesRecues() //
//****************************//
boolean donneesRecues() {

  // On regarde si des données sont en attente de lecture
  if (radio.available()) {
    // Si oui, on les lit, et on retourne "VRAI"
    radio.read(&donnees, sizeof(donnees)); 
    return true;    
  } else {
    // Sinon, on retourne "FAUX"
    return false; 
  }
}

//***************************//
// Fonction : arretMoteurs() //
//***************************//
void arretMoteurs() {

  // Stoppe les signaux PWM de commande
  analogWrite(borneENA_L298N, 0);
  analogWrite(borneENB_L298N, 0);

  // Mise à l'état bas des autres sorties (non indispensable)
  digitalWrite(borneIN1_L298N, LOW);
  digitalWrite(borneIN2_L298N, LOW);
  digitalWrite(borneIN3_L298N, LOW);
  digitalWrite(borneIN4_L298N, LOW);
}

//***************************************//
// Fonction : envoiConsignesAuxMoteurs() //
//***************************************//
void envoiConsignesAuxMoteurs() {
  
  // Analyse des données, et définition de valeurs qui vont nous servir
  byte vitesse = map(abs(donnees.valAvancerReculer), 0, 255, vitesseMinimale, vitesseMaximale);
  boolean bMarcheAvant = donnees.valAvancerReculer > 0 ? true : false;
  boolean bMarcheArriere = donnees.valAvancerReculer < 0 ? true : false;
  boolean bAuPointMort = donnees.valAvancerReculer == 0 ? true : false;

  float coefficienAngleVolant = (1 - abs(donnees.valDroiteGauche) / 255 * 0.7);
  boolean bTournerAdroite = donnees.valDroiteGauche > 0 ? true : false;
  boolean bTournerAgauche = donnees.valDroiteGauche < 0 ? true : false;


  // Cas "MARCHE AVANT"
  if (bMarcheAvant) {
    // Indication de sens des ponts en H, des L298N
    digitalWrite(borneIN1_L298N, HIGH);       // L'entrée IN1 doit être au niveau haut
    digitalWrite(borneIN2_L298N, LOW);        // L'entrée IN2 doit être au niveau bas
    digitalWrite(borneIN3_L298N, HIGH);       // L'entrée IN3 doit être au niveau haut
    digitalWrite(borneIN4_L298N, LOW);        // L'entrée IN4 doit être au niveau bas

    // Vitesse du moteur de droite (suivant consigne, sauf si besoin de tourner à droite ; là, il faudra le ralentir)
    if(bTournerAdroite) {
      analogWrite(borneENA_L298N, vitesse * coefficienAngleVolant);
    } else {
      analogWrite(borneENA_L298N, vitesse);
    }

    // Vitesse du moteur de gauche (suivant consigne, sauf si besoin de tourner à gauche ; là, il faudra le ralentir)
    if(bTournerAgauche) {
      analogWrite(borneENB_L298N, vitesse * coefficienAngleVolant);
    } else {
      analogWrite(borneENB_L298N, vitesse);
    }
  }
  
  // Cas "MARCHE ARRIERE"
  if (bMarcheArriere) {
    // Indication de sens des ponts en H, des L298N
    digitalWrite(borneIN1_L298N, LOW);        // L'entrée IN1 doit être au niveau bas
    digitalWrite(borneIN2_L298N, HIGH);       // L'entrée IN2 doit être au niveau haut
    digitalWrite(borneIN3_L298N, LOW);        // L'entrée IN3 doit être au niveau bas
    digitalWrite(borneIN4_L298N, HIGH);       // L'entrée IN4 doit être au niveau haut

      // Vitesse du moteur de droite (suivant consigne, sauf si besoin de tourner à droite ; là, il faudra le ralentir)
    if(bTournerAdroite) {
      analogWrite(borneENA_L298N, vitesse * coefficienAngleVolant);
    } else {
      analogWrite(borneENA_L298N, vitesse);
    }

    // Vitesse du moteur de gauche (suivant consigne, sauf si besoin de tourner à gauche ; là, il faudra le ralentir)
    if(bTournerAgauche) {
      analogWrite(borneENB_L298N, vitesse * coefficienAngleVolant);
    } else {
      analogWrite(borneENB_L298N, vitesse);
    }
  }

  // Cas "AU POINT MORT"
  if (bAuPointMort) {
    arretMoteurs();
  }
}

Comme vous avez pu le constater, un maximum de commentaires a été mis au niveau du code de programmation. Ainsi, chaque étape est décrite au possible, pour faciliter la compréhension de l’ensemble.

Mais même s’il n’y a rien de bien compliqué ici, il y a néanmoins 4 points qui vous sembleront peut-être difficile à appréhender au début, en première lecture. Il s’agit de :

  • la détection de perte de signal radio, faisant intervenir la fonction « millis() » (dont la valeur est systématiquement comparée à celle stockée lors du précédent passage dans la boucle loop, afin de voir si pas plus de 2 secondes se sont écoulées, depuis la dernière réception radio). Nota : en cas de perte de signal effectif, les moteurs seront coupés ; c’est une sécurité qui permet de stopper le véhicule, si jamais l’émetteur venait à être hors de portée, ou s’il ne pouvait plus émettre, à cause de batteries trop faibles, par exemple.
  • la conversion de niveaux de signaux, issus des accus li-ion. En fait, au niveau matériel, les tensions de chaque point de mesure du pack d’accus (les 3,7 volts, 7,4 volts, et 11,1 volts, nominales) sont ramenées à des valeurs comprises entre 0 et 5V, afin que l’arduino puisse les lire. Et donc, au niveau logiciel, il faut faire les calculs inverses, pour retrouver ces tensions, afin de pouvoir en déduire la tension de chaque accus, individuellement.
  • la gestion des vitesses de rotation moteurs, afin que les signaux PWM ne démarrent pas à 0 (les moteurs ayant besoin d’une tension minimale pour « démarrer », d’où le « mapping »)
  • ainsi que la gestion des modulations de vitesse, en fonction de l’angle de braquage (en effet, pour tourner à droite, on ralentit la vitesse du moteur droit tout en maintenant le moteur gauche à son régime nominal, et vice-versa quand on tourne à gauche).

En cas de difficultés de compréhension, n’hésitez pas à prendre votre temps, tout en analysant bien tout ça « bloc par bloc ». Ainsi, les choses vous paraitront bien moins complexes 😉

Fabrication du prototype de cette voiture RC arduino

Concernant la fabrication de cette voiture télécommandée arduino, cela se passe en plusieurs parties. Car il y a :

  • 1 x châssis, imprimé en 3D (avec le fichier STL téléchargeable en fin d’article, si vous souhaitez le reproduire à l’identique)
  • 1 x alim lithium-ion de 12V environ (c’est en fait le coupleur d’accus li-ion 3S, que j’avais réalisé il y a quelques temps)
  • 1 x module L298N (comme on en trouve couramment, dans le commerce)
  • Et 1 x platine arduino, que je vais détailler ci-après

En dehors de ça, il n’y a que du câblage, à proprement parler ! (c’est à dire : des connecteurs M/F XT30, des fils de raccordement pour la partie puissance, et des fils dupont pour les signaux de commande). Au passage, si vous souhaitez plus de détails sur tous les composants et accessoires utilisés ici, vous en trouverez la liste détaillée un peu plus bas, en fin d’article.

Platine de commande Arduino

Concernant la platine Arduino de cette voiture radiocommandée, voici son circuit imprimé (PCB), vu de face :

Circuit imprimé PCB de la voiture RC arduino, projet électronique avec Arduino Nano, module radio nRF24L01+, et pilotage de moteurs électriques L298N

Il n’y a que peu de composants à souder, mais attention, car il y a 5 résistances CMS implantées sur le circuit imprimé (par soucis de gain de place au niveau du PCB, en fait). Je vous recommande d’ailleurs de souder ces petits composants en premier, afin de ne pas être gêné par la suite. À noter que l’Arduino Nano et le nRF24L01+ figurant sur cette carte sont montés sur support ; mais, bien entendu, rien ne vous empêche de les souder directement, si le coeur vous en dit 😉

Voilà pour cette plaquette !

Du reste, pour soutenir les moteurs électriques ainsi que toutes les cartes électroniques, il faudra un support bien adapté. Ici, je vous propose un châssis rudimentaire, mais fonctionnel, réalisé en PLA, en impression 3d ! Bien sûr, libre à vous de faire de même, ou de prendre un tout autre support (planche de bois, …).

Cela étant dit, voici les étapes d’assemblages de cette voiture télécommandée arduino, avec le châssis spécialement conçu pour faire les essais, de mon côté !

Châssis en impression 3D

Pour commencer, voici le châssis que j’ai réalisé. Il est en fait constitué en un seul bloc, dont voici la vue de dessus, et de dessous :

Châssis imprimé 3d pour voiture rc arduino, vu de dessus, avec trous de fixation pour vis traversantes et inserts métalliques
Châssis de voiture rc arduino, vu de dessous, avec supports pour moteurs et roue pivotante

Vous noterez la présence de trous de fixation pour les cartes électroniques, ainsi que pour les moteurs et la roue centrale.

Entretoises de rehaussement

Afin de rehausser les 3 cartes électroniques qui vont prendre place sur ce châssis, des entretoises M3 de 10mm de haut ont été mises en œuvre. Ainsi, cela donne :

Entretoises de réhaussage sur châssis de voiture télécommandée arduino, pour support de cartes électroniques futures, vis nylon M3
Insert métallique encastré dans PLA de châssis voiture radiocommandée arduino, soudage par fonte et serrage en refroidissant
Autres entretoises nylon noir pour support de plaquettes PCB, pour projet de voiture rc arduino

À noter qu’il y a ici, de gauche à droite :

  • 10 x entretoises femelle/femelle M3 longueur 10 mm (nylon, noir)
  • 10 x vis M3 longueur 6 mm (nylon, noir), qui viennent se visser sous ces entretoises, par-dessous le châssis
  • 2 x inserts métalliques M3 (diamètre de vissage), OD 4,2 mm (diamètre extérieur), et longueur 6 mm
  • 2 x entretoises mâle/femelle M3 longueur 10 mm (nylon, noir), qui se visseront sur les inserts

Au passage, la pose des inserts métalliques s’est faite à chaud. C’est à dire que je les ai chauffé avec la panne de mon fer à souder, pour les faire pénétrer au travers de la matière PLA du châssis. Ainsi, cette « soudure » permet de bloquer efficacement les inserts dans le châssis, une fois refroidi !

Roue centrale (3ème roue), et supports de moteurs

Ensuite vient le tour de la troisième roue (qui sert d’équilibrage, à la voiture). Celle-ci se place au centre, sur la partie droite du châssis. Elle est fixée par 4 vis métalliques noires (en M4 x 10 mm).

Par ailleurs, les 2 équerres-support de moteur prennent également place sur le châssis, mais à gauche. Chacune de ces équerres est maintenue par 4 vis métalliques M3,5 x 10 mm (vis à « pas large », ici).

Voici ce que cela donne, en images :

Fixation roue avant sur châssis de voiture télécommandée arduino, roue pivotante à 360° et d'équilibrage du véhicule, avec fixation par vis noires
Equerres support de moteurs électriques, avec vis de fixation auto taraudeuses M3,5 longueur 10 mm
Supports de moteurs de propulsion du véhicule, avec roue avant mise en place, via vis de couloir noire

Nota : ces équerres de fixation étaient fournies avec les moteurs que j’ai achetés (cf. référence, en fin d’article, si vous souhaitez avoir les mêmes).

Moteurs électriques (avec réducteur de vitesse à engrenages)

On continue avec la fixation des 2 moteurs électriques, qui propulseront cette voiture RC arduino. Ceux-ci viennent se poser à même leurs équerres respectives.

Moteurs électriques 12V 77 RPM pour projet de voiture télécommandée arduino, modèles avec engrenage réducteur intégré
Vue de dessous du châssis du prototype de voiture radiocommandée arduino, avec moteurs électriques doubles, et roue de guidage avant

Là encore, rien de bien compliqué, car ces moteurs sont simplement tenus par deux vis chacun.

Roues motrices, de cette voiture

Vient ensuite la fixation des 2 roues motrices, sur l’axe des moteurs fixés précédemment. Là aussi, toute la visserie ainsi que les accessoires étaient fournis avec le moteur.

Roues bleues pour voiture télécommandée arduino, montées sur moteur électriques 12 volts de 77 tours par minute, fixés sur châssis imprimé 3d en PLA
Châssis de voiture télécommandée arduino vu en dessous, avec moteurs électriques de propulsion 12 volts, et 3ème roue de guidage et d'équilibrage
Châssis support pour voiture radiocommandée arduino, posé sur ses 3 roues, avec supports de fixation pouvant accueillir les cartes électroniques
Vue arrière du châssis voiture RC arduino, avec moteurs électriques 77 tr/min rpm, permettant de propulser le véhicule, avec roue de guidage central

J’en ai profité pour vous prendre des photos d’un peu tous les côtés, histoire que vous arriviez à bien vous représenter les choses ! Du reste, on en a fini avec cette partie « mécanique ». On arrive enfin à la partie électronique 😉

Cartes électroniques

Il ne reste plus qu’à poser et visser les 3 cartes électroniques (pack d’accus, module L298N, et platine Arduino), sur les entretoises posées en tout début (avec vis nylon M3 pour bloquer le tout).

Pack d'accus 18650 sur châssis voiture télécommandée arduino, modèle 3S avec protection par fusible, et avec voltmètre intégré pour tension batterie
Module L298N monté sur voiture RC arduino, pour commande des moteurs de puissance électriques en 12 volts, depuis pack lithium ion 18650
Platine arduino pour prototype de véhicule piloté par radiofréquence, avec alim sur batterie lithium ion 18650 et pilotage de puissance L298N pour les moteurs

Cela donne déjà plus de vie à notre véhicule ! En fait, à présent, il ne manque plus que les câbles de raccordement, pour finaliser cette voiture radiocommandée arduino !

Câblage des moteurs

Chaque moteur est relié à la carte de puissance L298N, via 2 fils chacun. Pour ma part, j’ai utilisé du fil de section 1 mm² environ (de couleurs jaune et vert, ici sur les photos).

Vue arrière véhicule radiocommandé arduino, avec alimentation batterie li-ion 18650, et pilotage via module driver L298N pour propulsion électrique
Soudage fils sur moteurs 77 RMP de 12V, pour projet de véhicule radiocommandé arduino, avec pilotage de puissance via module L298N avec ponts en H
Raccordement fils moteurs électriques autour châssis prototype de voiture RC arduino, câblage vers driver à ponts en H modèle L298N, sur circuit imprimé

Au passage, faites bien attention à ne pas vous mélanger les pinceaux, au niveau des fils de chaque moteur. Du reste, quant à la polarité, celle-ci n’a pas vraiment d’importance, puisque ces moteurs sont appelés à fonctionner dans les deux sens. Bien entendu, si toutefois l’un ne tourne pas dans le même sens que l’autre, il faudra alors inverser le branchement d’un des deux, pour que tout se passe bien 😉

Câbles d’alimentation (partie puissance)

Côté alimentation, il n’y a que 2 câbles XT30 à mettre en place :

  • Entre le pack d’accus 18650 et le module L298N (pour l’alimentation des moteurs)
  • Et entre le pack d’accus 18650 et la platine Arduino (pour l’alimentation de la partie commande)
Branchement alimentation de puissance arduino et L268N, depuis coupleur d'accus 18650 en 3S, fournissant environ 12 volts à cette voiture RC diy

Bien évidemment, pour ce genre de raccordement, vous pouvez fort bien utiliser des câbles mâle/femelle « tout prêt », afin de ne pas vous embêter ! Pour ma part, j’ai préféré me les fabriquer moi-même, afin qu’ils ne soient pas trop long (pour limiter les pertes en ligne).

Câbles de pilotage (partie commande)

Enfin, les derniers câbles à mettre en place sont :

  • 6 fils dupont mâle/femelle, de longueur 20 cm, entre le module L298N et la carte Arduino (pour le pilotage PWM des moteurs)
  • Et 3 fils dupont mâle/mâle 20 cm, entre le pack d’accus et la platine Arduino (pour la surveillance du niveau des accus)
Câblage des liaisons entre Arduino Nano et platine L298N, sur broches ENA et ENB, ainsi que IN1, IN2, IN3, et IN4, pour commande PWM des moteurs électriques
Raccordement fils dupont entre Arduino Nano et circuit PCB du L298N, ainsi que connectiques de surveillance de l'état du niveau des batteries li-ion

Nota : on pourrait certainement faire un câblage plus propre, et plus soigné, mais sinon, ça marche du tonnerre 😉

Vue d’ensemble de la voiture RC arduino

Une fois tous ces câblages effectués, on obtient cela (avec les accus li-ion mis en place, sur la photo de droite) :

Voiture télécommandée arduino câblée sur châssis imprimé 3d, montage prototype de véhicule radiocommandé DIY, pour apprendre l'électronique
Voiture radiocommandée arduino sur 3 roues, avec alim lithium ion 18650, puissance moteur au L298N, et partie commande par un Arduino Nano et nRF24

À noter que tant que l’Arduino n’est pas programmé, et que la vérification de tous les raccordements et soudures n’a pas été faite, il ne faut pas mettre le fusible de « mise en service », au niveau du pack d’accus lithium-ion. Ceci tant que toutes les vérifications nécessaires, et indispensables au bon fonctionnement, n’ont pas été faites, afin d’éviter toute mésaventure !

Essais, remarques, et améliorations possibles

Une fois les vérifications d’usage effectuées, on peut mettre en place les accus et leur fusible de protection, et mettre l’interrupteur de la platine arduino en position « ON ». Ainsi fait, les petites LEDS rouges (celle située sur le module L298N, et celle intégrée directement sur l’Arduino Nano) doivent s’allumer en rouge.

Mise en service de la voiture

À ce stade, si la télécommande est allumée, le voyant orange de la platine arduino devrait être éteint. Sinon, cela indiquerait qu’il y a un problème de transmission radio, entre la radiocommande et cette voiture.

À noter que si jamais la tension d’un accu venait à être inférieure à 3 volts, alors la led rouge s’allumerait (celle-ci se trouve juste à côté de la led orange). Ceci vous indiquerait que le niveau d’une ou plusieurs batteries n’est pas suffisant, et qu’il faut donc les recharger.

Au passage, si on appuie sur l’interrupteur à poussoir du bloc d’accus 18650, la tension du pack d’accus li-ion s’affiche, comme visible ci-dessous :

Projet DIY de voiture arduino téléguidée par onde radio 2,4 GHz, via module nRF24L01+, alimenté via batterie d'accus 18650, et fonctionnant avec module L298N
Fabriquer une voiture RC arduino avec moteurs électriques pilotés par L298N, télécommande radio nRF24, et pilotage en PWM via radiocommande électronique

Donc si je résume l’allumage des voyants, dans le cas où tout est fonctionnel :

  • Le voltmètre du pack d’accus lithium ion affiche la tension de la batterie
  • La petite LED rouge du L298N doit être allumée (« sous tension »)
  • La petite LED rouge intégrée à l’Arduino Nano doit être allumée (« sous tension »)
  • La grosse LED orange de la platine arduino doit être éteinte (« signal radio reçu, de manière continue »)
  • Et la grosse LED rouge sur la platine arduino doit également être éteinte (si « pas de batterie faible »)

Essais et remarques

Concernant les essais, tout a parfaitement bien fonctionné ! À part deux petits soucis, … pas méchants, mais pénibles quand même !

Pour commencer, j’ai constaté qu’une roue tournait plus vite que l’autre. En effet, celle de droite tournait plus vite que celle de gauche ! Et clairement, il n’y avait aucune raison à cela ! En fait, après vérifications, je me suis rendu compte que, bien que les moteurs que j’ai reçu avaient bien les mêmes caractéristiques, ceux-ci n’étaient pas de même marque. Du coup, il y avait une légère différence de vitesse de rotation, à tension égale. Ainsi : au lieu d’aller en ligne droite, mon véhicule tournait légèrement vers la gauche ! Bien sûr, j’aurais pu compenser cela dans la programmation. Mais comme il s’agissait là d’un problème d’usage de moteurs non identiques, et non d’un dysfonctionnement matériel, il n’était pas nécessaire de s’en préoccuper plus que ça (car cela ne devrait pas se produire, si vous utilisez deux moteurs strictement identiques).

Par ailleurs, j’ai constaté un autre souci : la vitesse max des moteurs était trop lente, à mon goût. J’étais parti sur des modèles 12V de 77 tours par minute (77 RPM). Mais cela est beaucoup trop lent, au final, selon moi. Qui plus est, la chute de tension induite par le L298N étant d’environ 1,5 volts, la tension arrivant aux moteurs est plutôt de l’ordre de 11 volts, plutôt que 12,6 (quand les accus sont « chargés à bloc »). Du coup, la vitesse de rotation des moteurs est « ralentie ». C’est pourquoi, je pense qu’il aurait mieux valu partir sur des 170 RPM (tr/min), pour plus de « dynamique », au niveau de cette voiture radiocommandée arduino 😉

Améliorations possibles

Au final, les améliorations qu’il serait intéressant de faire sur ce prototype, sont :

  • Le remplacement des moteurs 77 RPM par des modèles faisant par exemple 170 RPM (plus ou moins)
  • L’intégration d’un facteur de correction différentiel, dans le cas où un moteur tournerait un poil moins vite que l’autre (après tout, cela peut être très utile, en cas de légère dérive à droite ou à gauche !)

Sinon, une dernière remarque, qui n’a rien à voir avec ce prototype : l’émetteur que j’ai utilisé ici, bien que parfaitement fonctionnel, n’était pas si pratique que ça. En effet, celui-ci étant équipé d’un « joystick type PS2 », pour les contrôles haut/bas/droite/gauche, ce n’est pas aussi fin que ceux présent sur une « vraie » radiocommande RC ! Du coup, il faudrait que j’en fasse une version améliorée, en ce sens ! Enfin, … dès que j’aurais du temps de libre 😉

Liens utiles et téléchargements

Pour ceux qui voudraient savoir quels composants et accessoires j’ai utilisé ici, ou ceux qui voudraient simplement reproduire ce projet, voici toutes les sources de cette voiture télécommandée arduino :

Concernant les composants et accessoires utilisés au niveau du châssis :

Et enfin, concernant les composants électroniques de la platine Arduino, en elle-même :

Voiture RC arduino : conclusion !

Voilà ! Nous avons fait le tour de ce prototype de voiture télécommandée arduino ! Bien sûr, comme évoqué en intro, ce projet n’avait qu’un but « éducatif ». C’est pourquoi, bien que parfaitement fonctionnel, il nécessiterait bon nombre d’améliorations 😉

Du coup, n’hésitez pas à vous inspirer de ce prototype, sans forcément chercher à le reproduire tel quel ! Du reste, j’espère que vous aurez pu découvrir ou apprendre bon nombre de nouvelles choses ici, si vous débutez, ou que cela puisse vous inspirer, pour faire vos propres réalisations !

À bientôt !
Jérôme.

En complément de cette voiture RC arduino : une télécommande radio RC arduino (avec joystick)

Ce contenu vous plaît ? Alors abonnez-vous à la Newsletter pour ne rien louper !

(*) Mis à jour le 11/12/2021

4 commentaires sur “Voiture télécommandée Arduino : prototype de véhicule à 3 roues”

  1. Bravo..!! pour ce travail décortiqué et bien documenté, cela prend du temps à réaliser, avec beaucoup de passions.
    Je suis tes projets avec beaucoup d’intérêt et merci pour toutes ces infos qui m’aide à réaliser mes montages.

Laisser un commentaire

Votre adresse e-mail ne sera pas publiée.

Symbole danger point d'exclamation site PSE, triangle jaune avec contour noir, texte noir alerte au milieu Afin de filtrer au maximum les messages de type "spam" ou "inappropriés", chaque commentaire est soumis à modération, et validé manuellement. Du coup, il se peut que certains commentaires ne soient pas publiés, ou sinon, avec un peu de retard.