Véhicule robot avec contrôle de bylynk et d'odométrie

Bienvenue dans un nouveau blog de notre série sur les Robot Cars. Cette fois, il s'agit de déterminer la distance parcourue en utilisant le nombre de tours des roues. Ce processus s'appelle l'odométrie. Ce terme vient du grec et signifie mesure de la distance.

Bases géométriques

Pour la conduite en ligne droite, c'est assez simple. Si les deux roues tournent à la même vitesse, la distance parcourue après un tour est égale à la circonférence de la roue, c'est-à-dire au diamètre d 

Les révolutions peuvent être déterminées à l'aide d'un disque à fente et d'un capteur photoélectrique à fourche. Si le disque à fentes a n fentes, on obtient n impulsions par tour. Pour déterminer la distance entre deux impulsions, il faut diviser la circonférence par les impulsions par tour. On obtient le facteur de distance.

La détermination de l'angle de rotation est également simple pour un véhicule à deux roues si l'on suppose que les deux roues tournent en sens inverse à la même vitesse. Dans ce cas, les deux roues décrivent un cercle autour du point de vue immuable avec comme diamètre la distance entre les roues a. Afin de faire tourner le véhicule sur 360 degrés, une distance de 

peuvent être couverts. Pour un angle α, cela se traduit par une distance de

Les deux roues parcourent la même distance, mais dans des directions opposées. Pour obtenir le nombre d'impulsions, il faut diviser par le facteur de distance.

La réciprocité donne le facteur d'angle en degré/impulsion.

géométrie

Hardware requis

Contrairement à la première partie, nous avons besoin du module ESP32 dans ce cas, car des entrées supplémentaires pour les barrières lumineuses de la fourche sont nécessaires. Il est également préférable d'utiliser le châssis issu de l'imprimante 3D, car cela facilite grandement le montage des barrières lumineuses de la fourche.

Numéro

Composant

Note

1

2 moteurs avec roues


1

Boule de roulement comme roue de roulette


6

Vis M3 x 30 avec écrou


2

Vis M3 x 12 avec écrou


1

Châssis de l'imprimante 3D


1

Support du bloc d'alimentation de l'imprimante 3D


1

D1 Board Nodemcu ESP8266MOD-12F


1

Set de barrières lumineuses à fourche avec disques à fente


2

Vis d'étain 2.2 x 6,5 mm



Pour utiliser le blindage du pilote de moteur avec les contrôleurs ESP, de petites modifications sont nécessaires, car les contrôleurs ESP fonctionnent avec une tension d'alimentation de 3,3 V.

De la broche D7, une résistance de 10kOhm doit être connectée à GND. Ceci est nécessaire car la broche D7 sur le blindage est connectée à 5V via une résistance pullup de 10KOhm.

Bouclier moteur de moteurLes connexions A0 à A5, ainsi que les connexions d'alimentation correspondantes, doivent être équipées de têtes de broche. Afin d'utiliser ces connexions pour les capteurs, la tension d'alimentation doit également être connectée à 3,3V au lieu de 5V. Pour ce faire, il suffit de couper le fil de connexion aux broches du côté inférieur. Ensuite, vous pouvez connecter les broches à la broche 3.3V. Les connexions pour la tension d'alimentation doivent également être renseignées.

Les sorties M2 et M4 sont utilisées pour connecter les deux moteurs. Les connexions du moteur sont raccordées aux bornes à vis correspondantes sur le capot du moteur. Si le véhicule doit être alimenté par la prise USB du microcontrôleur, le cavalier (cercle rouge) doit être retiré et l'entrée M+ connectée à la connexion 5V du microcontrôleur (représentée en vert).

Moteurs au bouclier conducteur

Pour la mesure de la vitesse de rotation, une rondelle fendue est placée à l'extrémité intérieure de chaque axe du moteur et les barrières lumineuses fourchues sont chacune vissées au support prévu à cet effet avec une vis autotaraudeuse..

Tranches de fente

Connectez maintenant VCC, GND et D0 via un câble tripolaire aux connecteurs A2 et A3 de la plaque moteur.  Vcc avec +5V, GND avec Gnd et D0 avec A2 ou A3.

Motorshield

Le motorshield est ensuite simplement branché sur la carte du microcontrôleur. D'autres mesures de câblage ne sont pas nécessaires.
Pour le montage mécanique des cartes, le châssis de l'imprimante 3D comporte des trous correspondants, auxquels la carte de microcontrôleur peut être vissée à l'aide d'entretoises. Avec le kit, vous devrez peut-être percer des trous appropriés.

Software

Le logiciel Blynk, disponible gratuitement, doit être utilisé pour la commande à distance du véhicule. Blynk est un projet Kickstarter qui permet de contrôler des microcontrôleurs le plus simplement possible avec un smartphone. L'élément essentiel est l'application, qui permet de créer une application via une sorte de kit de construction. Toutes les informations concernant cette application sont stockées dans le serveur Blynk. Chaque demande reçoit un numéro d'identification unique. Du côté du microcontrôleur, une bibliothèque assure que le microcontrôleur communique avec le serveur Blynk et que l'application sur le smartphone peut directement lire ou contrôler les broches du microcontrôleur. Cela ne nécessite aucune programmation supplémentaire sur le microcontrôleur. La seule condition est que le microcontrôleur ait accès au serveur Blynk. Cependant, comme aucune broche du microcontrôleur ne peut être contrôlée directement pour la commande à distance du véhicule, une certaine programmation sera finalement nécessaire.

Mais il faut d'abord installer l'application Blynk sur le smartphone. Après l'installation et le démarrage de l'application, l'écran de connexion apparaît. Pour utiliser Blynk, vous avez besoin d'un compte pour le serveur Blynk. Tout ce dont vous avez besoin est une adresse électronique et un mot de passe de votre choix.

Après avoir créé un compte, un message sur l'énergie apparaît. Pour créer un projet Blynk, vous avez besoin d'une certaine quantité d'énergie pour chaque élément de l'écran. Avec un nouveau compte, vous recevez automatiquement 2000 points d'énergie pour travailler. Si vous avez besoin de plus de points d'énergie pour un projet, vous pouvez en acheter.

Après cette fenêtre de message, l'écran de démarrage apparaît. Ici, le projet Robocar peut maintenant être chargé via le code QR suivant.

Vous voyez maintenant la fenêtre du projet. Si vous cliquez sur le symbole de l'écrou, les paramètres du projet s'ouvriront. Dans les paramètres du projet, vous trouverez le lien "Email all". Si vous cliquez dessus, vous recevrez un courriel contenant la clé dont votre microcontrôleur Sketch a besoin pour communiquer avec le serveur Blynk. Utilisez l'icône en forme de triangle en haut à droite de la fenêtre du projet pour démarrer l'application.

CLYNC App

Vous trouverez de plus amples informations sur Blynk sur Internet ou dans le livre Smarthome. Le livre décrit également comment installer votre propre serveur Blynk privé sur un Raspberry Pi.

Le contrôle se fait en réglant la distance et l'angle souhaités. En cliquant sur les boutons de marche avant ou arrière, le véhicule parcourt la distance définie. En cliquant sur les boutons gauche ou droite, le véhicule tourne autour de l'angle défini.

En cliquant sur le bouton Apprendre, vous passez en mode Apprentissage. Chaque commande saisie est désormais enregistrée et peut être exécutée automatiquement par la suite. Un nouveau clic sur le bouton Apprendre met fin au mode d'apprentissage. Maintenant, les commandes stockées peuvent être exécutées automatiquement en cliquant sur le bouton Exécuter.

Le nombre de lignes de commande enregistrées est affiché en bas. Un maximum de 30 lignes de commande peut être stocké. Lors du passage en mode apprentissage, le compteur de la ligne de commande est remis à 0.

Le sketch

Outre le paquet pour l'ESP32, vous avez besoin de la bibliothèque Blynk, qui peut être installée via la gestion des bibliothèques.

 #include 
 #include
 
 // Vous devriez obtenir le jeton d'authentification dans l'application BLYNK. // Aller aux paramètres du projet (icône de noix).
 
 // clé d'authentification bylnk
 #define Auth "*********************************"
 // SSID de votre WLAN
 #define SSID "*******************************"
 // PASSEKKY POUR VOTRE WLAN
 #define Pass "***********************************"
 // Nom du serveur privé BLYNK, ou "" Si vous utilisez le serveur BLYNK public
 #define srv "raspberrypi4"
 
 
 #define maxcommands 30 // Anzahl der Befehlszeilen, Die Gespeichert Werden Können
 
 #define bylynk_print série
 
 // bits im schieberegister zu moteur zuordnung
 #define m1a 2 // motor1 a
 #define m1b 3 // motor1 b
 #define m2a 1 // motor2 a
 #define m2b 4 // motor2 b
 #define m3a 5 // motor3 a
 #define m3b 7 // motor3 b
 #define m4a 0 // motor4 a
 #define m4b 6 // motor4 b
 
 // épingles für das drehrichtungs schieberegister
 #define shift_in 12 // dateneingang arduino d8
 #define shift_clk 17// schiebetackt arduino d4
 #define latch_clk 19 // Speichertakt Arduino D12
 #define out_enable 14// mit low ausgang aktivieren arduino d7
 
 // PWM Für Motoren Geschwindigkeit Zwischen 0 und 1023
 #define m1pwm 23 // Pin Für Motor1 Arduino D11
 #define mright 25// broche für motor2 arduino d3
 #define m3pwm 27 // broche für motor3 arduino d6
 #define mleft 16 // pin für motor4 arduino d5
 
 // servo Anschlüssse
 #define servo1 5// broche für servo1 d10
 #define servo2 13 // broche für servo2 d9
 
 // Moteur Zuordnung
 #define Tright 2
 #define dleft 4
 
 // konstantten für drehrichtung
 #define stop 0
 #define en avant 1
 #define en arrière 2
 
 #define speedleft 35
 #define speedright 34
 
 // Aktueller Inhalt des Richtungs-SchiebereGisters
 uint32_t directions = 0;
 
 typée
 structurer {
   carboniser cmd;
   uint16_t valourdine;
 } Cmdline;
 
 Cmdline commandes[Maxcommands];
 uint8_t cmdcnt = 0;
 
 int32_t cn-pi = 0;
 int32_t cntright = 0;
 uint16_t strate = 0;
 uint16_t winkel = 0;
 booléen bouton = 0;
 flotter Winkelfaktor, Streckenfaktor;
 booléen apprentissage = faux;
 booléen programme = faux;
 uint8_t prgstep;
 
 // synchronisation d'interruption für
 PortMux_TYPE gauche = PortMux_Initializer_unlocked_unlocked;
 PortMux_TYPE mûres = PortMux_Initializer_unlocked_unlocked;
 
 
 // Routine de service d'interruption Für Linken Speedsensor
 annuler Iram_attr isrleft() {
   Portenter_Critical(&gauche);
   cn-pi--;
   Portexit_critique(&gauche);
   si ((cn-pi <= 0) && (cntright<=0)) {
     moteurs(0,0);
     si (programme) L'étape suivante();
  }
 }
 
 // interrompre la routine de service Für rechten Speedsensor
 annuler Iram_attr isright() {
   Portenter_Critical(&mûres);
   cntright--;
   Portexit_critique(&mûres);
   si ((cn-pi <= 0) && (cntright<=0)) {
     moteurs(0,0);
     si (programme) L'étape suivante();
  }
 }
 
 
 
 // füllt das schieberegister zur motorseuerung
 // mit dem par inhalte von directions
 annuler senddirections() {
   uint8_t je;
   denadewrite(Latch_clk, FAIBLE);  // Speicher Speren
   denadewrite(Shift_in, FAIBLE);   // eingang auf 0
   pour (je=0; je<8; je++) {
     denadewrite(Shift_clk, FAIBLE);// bit für bit einlesen
     si (directions & bit(7-je)) {
       denadewrite(Shift_in, HAUTE);
    } autre {
       denadewrite(Shift_in, FAIBLE);
    }
     denadewrite(Shift_clk, HAUTE);
  }
   denadewrite(Latch_clk, HAUTE); // mit der positiven flanke speichern
 }
 
 annuler L'étape suivante() {
   si (prgstep < cmdcnt) {
      changer (commandes[prgstep].cmd) {
        Cas 'F' :
        Cas 'B' : conduire(commandes[prgstep].cmd,commandes[prgstep].valourdine);
               Pause;
        Cas "L ' :
        Cas "R ' : tour(commandes[prgstep].cmd,commandes[prgstep].valourdine);
               Pause;
      }
      prgstep++;
  } autre {
     programme = faux;
  }
 }
 
 // Die Drehrichtung Für Einen Motor Festlegen
 annuler setDirection(uint8_t moteur, uint8_t direction) {
   uint8_t une=0, b=0;
   // BitNumMern für den gewählten Bestimmen
   changer (moteur) {
     Cas 1: une=M1a; b=M1B; Pause;
     Cas 2: une=M2a; b=M2b; Pause;
     Cas 3: une=M3a; b=M3b; Pause;
     Cas 4: une=M4a; b=M4b; Pause;
  }
   // mettre d'abord les deux bits pour le moteur à 0 signifie arrêter
   les directions &= ~ bit(une) & ~ bit(b);
 
   changer (direction) {
     cube Avant: les directions |= bit(une); Pause; // pour le bit avant A à 1
     cube En arrière: les directions |= bit(b); Pause;// pour bit backb b sur 1
  }
   //Serial.printf ("Directions =% x \ n", directions);
   Senddirections(); // Envoyer un nouveau paramètre au registre de travail
 }
 
 
 //La vitesse
 int Z;
 
 
 annuler moteur(Int16_t la gauche, Int16_t Droite) {
   //Serial.printf("links% i, à droite% i \ n ", à gauche, à droite);
   //Direction
   SI (la gauche<0) {
     setDirection(du quotidien,En arrière);
  } Autre SI (la gauche == 0){
     setDirection(du quotidien,ARRÊTER);
  } Autre {
     setDirection(du quotidien,Avant);
  }
   SI (Droite<0) {
     setDirection(Drapeau,En arrière);
  } Autre SI (Droite == 0){
     setDirection(Drapeau,ARRÊTER);
  } Autre {
     setDirection(Drapeau,Avant);
  }
   //La vitesse
   LEDCWRITE(du quotidien,Section(la gauche));
   LEDCWRITE(Drapeau,Section(Droite));
 }
 
 annuler conduire(Carboniser direction, uint16_t Valourdine) {
   SI (apprentissage) {
     SI (Cmdcnt < Maxcommands) {
       commandes[Cmdcnt].Cmd = direction;
       commandes[Cmdcnt].Valourdine = Valourdine;
       Cmdcnt++;
    }
  } Autre {
     cn-pi = Valourdine;
     cntright = Valourdine;
     SI (direction == 'F') {
       moteur(Z,Z);
    } Autre {
       moteur(-Z,-Z);
    }
  }      
 }
 
 annuler tour(Carboniser direction, uint16_t Valourdine) {
   SI (apprentissage) {
     SI (Cmdcnt < Maxcommands) {
       commandes[Cmdcnt].Cmd = direction;
       commandes[Cmdcnt].Valourdine = Valourdine;
       Cmdcnt++;
    }
  } Autre {
     cn-pi = Valourdine;
     cntright = Valourdine;
     SI (direction == "L ') {
       moteur(-Z,Z);
    } Autre {
       moteur(Z,-Z);
    }
  }      
 }
 
 annuler d'installation() {
   En série.Commencer(115200);
   En série.Imprimeur();
   En série.Imprimeur("Initialisation");
   // mettre toutes les broches utilisées comme sortie
   punaise(Shift_in,PRODUCTION);
   punaise(Shift_clk,PRODUCTION);
   punaise(Latch_clk,PRODUCTION);
   punaise(Out_enable,PRODUCTION);
   LEDCsetup(du quotidien, 100, 10);
   LEDCsetup(Drapeau,100, 10);
   LEDCATTACHPIN(Melief,du quotidien);
   LEDCATTACHPIN(Midight,Drapeau);
   // tous les moteurs s'arrêtent
   les directions = 0;
   // calculer les paramètres d'odométrie
   // facteur d'étirement = diamètre de la roue * PI / Number_schlitze
   facteur d'étirement = 67 * 3.14 /20; // = 10.524 mm / pouls
   // facteur d'angle = 360 degrés / (Distance de l'axe * PI) * Facteur étirement
   facteur d'angle = (360 * 67)/(130 * 20); // = 9,277 degré / pouls
   Senddirections();  // Envoyer au registre de travail
   denadewrite(Out_enable,0); // libère des sorties du registre de décalage
   Z=1023;
   punaise(Speedleft,Contribution);
   punaise(Accéléré,Contribution);
   cn-pi=0;
   cntright=0;
   rattrapine rupture(Speedleft,Isrleft,Chute);
   rattrapine rupture(Accéléré,Isright,Chute);
   
 
   En série.Imprimeur("Démarrer Blynk");
   #Ifdef srv
     Blenk.Commencer(Autorité, SSID, PASSEPORT, Srv, 8080);
   #else
     Blenk.Commencer(Autorité, SSID, PASSEPORT);
   #endif
   bouton = 0;
 }
 
 // boucle de test
 annuler boucle() {
     Blenk.Cours();
 }
 
 Bylnk_write(V0)
    { route = paramètre[0].asine(); }
 Bylnk_write(V1)
    { angle = paramètre[0].asine(); }
 Bylnk_write(V2)
 { SI (paramètre[0].asine() == 0) {
       bouton = faux;
    } Autre {
         SI (!bouton) {
             bouton = vrai;
             conduire('F',route / facteur d'étirement);
        }
    }
 }
   
 Bylnk_write(V3)
 { SI (paramètre[0].asine() == 0) {
       bouton = faux;
    } Autre {
         SI (!bouton) {
             bouton = vrai;
             conduire("B ',route /facteur d'étirement);
        }
    }
 }
 Bylnk_write(V4)
 { SI (paramètre[0].asine() == 0) {
       bouton = faux;
    } Autre {
       SI (!bouton) {
         bouton = vrai;
         tour("L ',angle / facteur d'angle);
      }
    }
 }
 Bylnk_write(V5)
 { SI (paramètre[0].asine() == 0) {
     bouton = faux;
    } Autre {
         SI (!bouton) {
             bouton = vrai;
             tour("R ',angle /facteur d'angle);
        }
    }
 }
 
 Bylnk_write(V6)
 {
     SI (!apprentissage) {
         prgstep=0;
         programme = vrai;
         L'étape suivante();
    }
 }
 
 Bylnk_write(V7)
 {
     apprentissage = (paramètre[0].asine() != 0);
     SI (apprentissage) Cmdcnt = 0;
 }
 
 Bynk_read(V8)
 {
     Blenk.virtualwrite(V8,Cmdcnt);
 }

Code source  à télécharger

Amusez-vous avec la Robot Car


Esp-32Projets pour les débutants

2 commentaires

Gerald Lechner

Gerald Lechner

Wenn in Zeile 72 und 73 die Strecke auf 300 und der Winkel auf 90 voreingestellt werden, dann stimmen die Werte nach dem Start mit den Schiebern in der Blynk-App überein. Das Problem mit der Verbindung kommt daher, dass das Board eine relativ schlechte Wlan Empfindlichkeit hat

Walter

Walter

Sehr schönes Projekt, und einfacher als erst gedacht. Vor allem die Odometrie ist so ein Kinderspiel.
Umgesetzt mit ein ESP32 Dev Board, motordriver L289N und lokalen Blynkserver.

Ein offenes Problem ist, dass der Blynkserver keine initiale Werte gibt ( oder ich nicht weis wie ). Was bedeutet das erst die Schieber für Distanz und Winkel betätigt werden müssen, sonst ist der Wert der den man im Programm festlegt ( = 0 und dann passiert nichts ).
Der Blynkserver ist für mich sowie so eine Blackbox, wobei manchmal keine Verbindung zu Stande kommt, scheinbar ohne Ursache. Nach einigen Reboots funktioniert es dann auf einmal .

Laisser un commentaire

Tous les commentaires sont modérés avant d'être publiés

Messages de blogs recommandés

  1. Installez maintenant ESP32 via l'administrateur de la carte
  2. Lüftersteuerung Raspberry Pi
  3. Arduino IDE - Programmieren für Einsteiger - Teil 1
  4. ESP32 - das Multitalent
  5. OTA-Over the Air-ESP Programmation par WiFi