Équipement d'un véhicule autonome


AU MENU

  1. Plateforme
    1. Kit de chassis de véhicule
    2. Installation des moteurs, alimentation et commande
      1. Montage des 4 moteurs sur la plaque de base
      2. Module d'alimentation et de commande des moteurs
    3. Batterie embarquée
    4. Raspberry Pi 4B / Système batterie / moteurs /
      1. Connexions de base
      2. Commande de la puissance
      3. Conduite du véhicule à partir d'un smartphone
    5. Écran embarqué

  2. Distance et vitesse
    1. Élaboration de la distance parcourue et de la vitesse absolue
    2. Présentation de la distance parcourue et de la vitesse absolue dans une fenêtre graphique
    3. Afficher la distance parcourue et vitesse instantanée pour un véhicule en mouvement
      1. Méthodes de base
      2. Mise en oeuvre de l'utilitaire "terminator"
      3. Exécution simultanée de "car5.py" et "distance2.py" avec l’utilitaire "terminator"
    4. Détermination du sens du mouvement
      1. Mise en œuvre d'un capteur optique à rainure supplémentaire
      2. Intégration au système "véhicule autonome"
      3. Recours à la mémoire partagée

  3. Radar de recul avec avertisseur sonore
    1. Les composants
    2. Vues du véhicule autonome

  4. Équipement du véhicule autonome avec une caméra orientable
    1. Kit caméra, présentation et contenu
    2. Réception des servomoteurs
    3. Réception de la caméra
    4. Préparation de la platine chapeau du kit SunFounder
    5. Modification de configuration du véhicule
    6. Montage du kit caméra et intégration au véhicule
    7. Mise en œuvre du système caméra installé sur le véhicule

  5. Configuration globale avec caméra orientable
    1. Photos
    2. Commande du véhicule et de la caméra par BlueDot
    3. Visualisation sur PC distant
    4. Commande du véhicule et de la caméra par télécommande IR

  6. Prise en main à distance du véhicule avec caméra orientable

  7. Bras manipulateur avec télécommande IR
    1. Description mécanique du manipulateur
    2. Choix des moteurs et de la pince
    3. Montage
    4. Programmation du Raspberry Pi Pico2W
    5. Montage du manipulateur sur le véhicule


1 Plateforme

Dans un premier temps, l'ensemble fonctionne sur un Raspberry Pi 4B / 8Gb avec comme système d'exploitation 64-bit Raspberry Pi OS Debian GNU/linux 11(bullseye) et comme logiciel de programmation Python 3. Dans un second temps, le système d'exploitation Raspberry Pi OS Debian GNU/linux 12 (bookworm) permet d'augmenter les fonctionalités (commande InfraRouge).

L'ajout d'un bras manipulateur fera intervenir de façon complètement indépendante, une carte à microcontrôleur de type Raspberry Pi Pico et MicroPython comme logiciel de programmation. Comme alternative, une carte à microcontrôleur de type Raspberry Pi Pico2W est aussi envisagée pour augmenter les fonctionalités à l'aide du bluetooth et du WiFi.

1.1 Kit de chassis de véhicule

Comme base de la plateforme, on a choisi un kit de châssis de voiture comprenant 4 roues, 4 moteurs CC avec disques à fentes qui permettront plus tard de déterminer les distances parcourues et les vitesses.

Liste des composants Montage
Detail

Liens

Comme le véhicule que l'on veut dévelpper doit être autonome,

Dans un premier temps, on peut relier le Raspberry Pi 4B embarqué à l'écran extérieur par le câble HDMI et à l'alimentation extérieure par le câble UBSC.
En supportant le chassis à ses extrémités, les roues pourront tourner sans que le chassis ne se déplace.

1.2 Installation des moteurs, alimentation et commande

Liens internes principaux

Les spécifications des moteurs sont données dans la référence
https://www.techniscience.com/nl/cmsdata/artikelen/files/600_106597/106597%20com-motor01-specifications.pdf. .

La partie métallique contient le moteur électrique proprement dit. L'axe est longitudinal. Le moteur est solidaire du carter jaune grâce à une sangle en plastique transparent. La partie jaune cache le réducteur. La partie blanche est l'axe de rotation (transversal) disponible des deux côtés du carter jaune. Les méplats permettent de fixer les roues du véhicule et les disques à fentes sans ambiguïté.

Deux cosses métalliques sont disponibles du côté invisible de la partie métallique sur le dessin. Pour éviter qu'elle ne fonde, il faut faire ATTENTION de bien retirer la sangle en plastique transparent avant de souder les fils rouge et noir de l'alimentation électrique du moteur.

Le tableau suivant donne quelques spécifications.
Tension4.5V6.0V7.2V9.0V
Courant à vide190mA160mA180mA200mA
Rotation à vide90rpm190rpm230rpm300rpm
Couple gf/cm min80080010001200
Moteur

1.2.1 Montage des 4 moteurs sur la plaque de base

Les moteurs se montent sur une des 2 plaques perforées en plastique suivant la référence
https://www.gotronic.fr/pj2-35326-robot03-montage-1601.pdf ,
dont la dernière image est reprise ci-contre.
Ensuite, contrairement à la proposition de la notice, le chassis est retourné. Les moteurs sont ainsi tournés vers le bas. Le côté libre de la plaque est donc tourné vers le haut. Ceci a 2 avantages :
  • Il y a plus de surface pour l'implantation d'autres composants
  • La garde au sol est augmentée
Moteurs

Notons que les fils d'alimentation rouges et noirs ont été soudés à chacun des 4 moteurs de façon cohérente pour la commande des moteurs.

1.2.2 Module d'alimentation des moteurs

Liens internes principaux

Pour l'alimentation et la commande, c'est le module "L298N Dual H-Bridge Motor Driver" qui a été utilisé.

Il est fixé à l'avant de la plaque perforée en plastique supportant les moteurs. Le radiateur est tourné vers l'extérieur.

Rappelons que ce pilote de moteur bidirectionnel double est basé sur le circuit intégré de pilote de moteur à double pont en H L298. Le circuit permet de contrôler facilement et indépendamment deux moteurs jusqu'à 2A chacun dans les deux sens. Cette carte est équipée d'indicateurs LED de puissance, d'un régulateur + 5V intégré et de diodes de protection.
(Voir la référence
https://www.handsontec.com/dataspecs/module/L298N%20Motor%20Driver.pdf.
)

Module_L298N

L'image ci-contre montre les connexions du module.
Pour l'apport de puissance, c'est une des sorties 5V de la batterie qui sera utilisée (voir plus loin). De ce fait, le cavalier d'activation des 5V du module est enlevé et la borne 12V est reliée à la borne 5V. L'arrivée de puissance est connectée aux bornes masse et 5V. En fait, pour amener la puissance électrique, on utilise un câble USB dont la fiche USB qui sera reliée à la batterie a été conservée. L'autre embout a été coupé et les fils rouge et noir ont été reliés aux bornes 5V et masse du module.

Alim

1.3 Batterie embarquée

La seconde plaque de base a été montée au dessus de la première en utilisant les entretoises du kit.

La batterie externe est une batterie Adeqwat de 20Ah pour ordinateurs. Elle a été choisie pour ses possibilités de connexion et de puissance particulièrement adaptées aux besoins (alimentation du Raspberry Pi 4B, alimentation des moteurs, ...).
  • Bien que cette batterie soit lourde, elle est assez fine : LxHxP : 10 x 17 x 1.5cm.
  • Elle possède 2 ports USB 3.0 type A et un port USB type C bidirectionnel.
  • La tension de sortie minimale est de 5V et maximale de 20V. La puissance de sortie maximale est de 45W.
  • Le port USB C sert à la charge rapide (3A) de la batterie. A cet effet, on peut utiliser l'alimentation secteur du Raspberry Pi 4B,
  • mais aussi à alimenter le Raspberry Pi 4B sur le véhicule autonome (veiller à une longueur adéquate du câble UDB C vers USB C).
  • Un des deux ports USB type A sert à alimenter les moteurs.
  • L'autre port USB type A est en réserve pour d'autres équipements.
Batterie
La batterie est fixée à l'avant sur la deuxième plaque de base, la face avec les connecteurs USB et l'interrupteur sont à exterieur très accessibles.

1.4 Raspberry Pi 4B / Système batterie / moteurs

Une troisième plaque plastique et des entretoises ont été découpées. Elle a été montée au dessus des deux autres. Le Raspberry Pi 4B a été simplement posé sur cette nouvelle plaque.

1.4.1 Connexions de base

La figure montre les connexions filaires entre la batterie embarquée (Power Bank), le Raspberry Pi 4B (RasPi), l'alimentation/commande (module L298N Dual H-Bridge Motor Driver) et les 4 moteurs.

  • Les moteurs gauches doivent tourner à la même vitesse et sont donc reliés aux bornes d'alimentations des moteurs gauches (OUT1 et OUT2). Il en est de même pour les moteurs à droite (OUT3 et OUT4). Il faut bien veiller à la cohérence des connexions pour bien dominer le sens de rotation des moteurs. L'alimentation des moteurs droits est indépendante de l'alimentation des moteurs gauches.
    Chacune de ces 2 alimentations peut délivrer jusqu'à 2A, ce qui est amplement suffisant pour alimenter 2 moteurs du type mis en œuvre. Il ne faut donc pas 2 modules L298N.
  • L'alimentation en puissance du module "L298N Dual H-Bridge Motor Driver" est fournie par la sortie USB A 5V de la batterie embarquée (Power Bank). Ce sont les bornes 4, 5 et 6 qui sont concernées. Notons que les bornes 4 et 6 sont shuntées et que le cavalier 3 est enlevé.
  • Pour la commande, les fiches 8, 9, 10, 11 du module L298N sont reliées respectivement aux broches GPIO B17 (fil blanc), B18 (fil gris), B27 (fil violet), B22 (fil bleu) du RaspPi.
  • Pour vérifier les branchements, on commandera les moteurs en tout ou rien. Le cavalier 7 et le cavalier 12 sont laissés en place.
MoteursAlimentationCommande

Les 3 programmes python3 car1.py, car2.py et car3.py, dont la tâche est identique, permettent de vérifier le sytème.

Les mouvements avance, recule, tourne à droite, tourne à gauche sont programmés. Notons que pour tourner à droite, les moteurs gauches sont en marche avant, les moteurs droits en marche arrière. À l'inverse pour tourner à gauche. La rotation se fait donc autour d'un centre de rotation qui est le centre du rectangle reliant les 4 moteurs.

1.4.2 Commande de la puissance

Les connexions de base ont permis de tester les moteurs à pleine puissance. Ici, la commande de la puissance par (PWM = Pulse Width Modulation) est introduite.

Montage2 Montage3

Le programme python3 car4.py permet de tester le système. Comme car3.py, il met en oeuvre la sous-classe gpiozero.Motor mais aussi la sous-classe gpiozero.PWMOutputDevice.

Il est à noter que la commande des moteurs nécessite finalement 6 broches GPIO sur le Raspberry Pi 4B.

1.4.3 Conduite du véhicule à partir d'un smartphone

Liens internes principaux

En pratique, il faut pouvoir télécommander le véhicule pour pouvoir le conduire de l'extérieur. Python3 possède une classe bluedot qui associée à l'application Blue Dot sur smartphone permet de générer et d'utiliser des boutons de commandes. C'est le programme python qui définit la topologie des commandes (boutons de différentes couleurs et formes, disposés sur l'écran du smartphone). En principe, rien n'est à définir à partir du smartphone si ce n'est la connexion bluetooth vers le Raspberry Pi 4B, lorsque le programme python est lancé.
Le programme python3 car5.py permet ce pilotage à distance. La figure ci-contre montre le tableau de commande généré par le programme python sur le smartphone.
  • Le bouton rouge central est le bouton de démarrage et d'arrêt
  • Le bouton bleu du dessus permet de sélectionner la marche avant
  • Le bouton bleu du dessous permet de sélectionner la marche arrière
  • Le bouton bleu à gauche permet de tourner à gauche
  • Le bouton bleu à droite permet de tourner à droite
  • Le bouton vert supérieur permet d'augmenter la vitesse
  • Le bouton vert inférieur permet de diminuer la vitesse
Bluedot

1.5 Écran embarqué

A

L'écran embarqué a été conçu pour le Raspberry Pi 4B. Il est semblable à celui d'un smartphone. Il est donc tactile et on peut lancer et contrôler les processus en touchant l'écran. Cependant, ce n'est pas bien pratique et on utilisara de préférence une souris et un clavier sans fil.

Contenu de la livraison

  • Écran LCD DSI 5 pouces (B) x1
  • nappe de connection FPC 15 Pins Pas de 1.0m longueur 50mm (côtés opposés) x1
  • Lot de vis

Fonctionnalités

  • Écran TFT 5 pouces. Résolution matérielle 800x480
  • Écran tactile capacitif, prise en charge tactile à 5 points
  • Écran tactile capacitif en verre trempé, dureté jusqu'à 6H
  • Prend en charge Pi 4B/3B+/3A+/3B/2B/B+/A+. Une autre carte adaptateur CM-DSI-ADAPTER est nécessaire pour CM3/3+/4
  • Interface DSI, taux de rafraîchissement jusqu'à 60 Hz.
  • Lorsqu'il est utilisé avec un Raspberry Pi, prend en charge Raspberry Pi OS / Ubuntu / Kali et Retropie, sans pilote.
  • Prend en charge le contrôle logiciel de la luminosité du rétroéclairage

Commentaires

  • L'écran se connecte directement au port DSI du Raspberry Pi par l'intermédiaire de la natte fournie. Cette natte est bien visible au milieu à droite des photos D et E.
  • L'écran est alimenté en 5V en reliant les bornes visibles sur la photo E à une broche 5V et à une broche GND du Raspberry Pi.
  • L'écran est reconnu immédiatement par le Raspberry Pi et ne nécessite donc aucun pilote complémentaire.
  • L'écran peut être utilisé en combinaison avec d'autres écrans reliés aux ports HDMI. Un menu permet de configurer l'ensemble et le rôle de chaque écran (maître, ...)
  • Les photos montrent que l'écran est conçu comme un chapeau pour le Raspberry Pi. Son utilisation comme chapeau n'empêche pas la liaison habituelle à la plaque de prototypage. C'est la configuration qui a été choisie dans un premier temps.
B
C
D
E
https://yadom.fr/ecran-lcd-tactile-5-dsi-raspberry-pi-800x480-ips.html

2 Distance et vitesse

Liens internes principaux

L'estimation de la distance parcourue par le véhicule ainsi que sa vitesse se fonde sur la mise en oeuvre de capteurs optiques à rainure associés à des disques à fentes. Cette section présente de façon progressive quelques algorithmes de calcul de la vitesse et des distances parcourues par le véhicule "Robot Car Kit 4WD" développé dans cette section. CapteurFente Disque

2.1 Élaboration de la distance parcourue et de la vitesse absolue

Le programme distance1.py a été développé à partir de l’exemple donné par la vidéo Youtube Tracking Raspberry Pi Robot's Distance with Encoders. Un disque à fentes solidaire d’une roue du véhicule contient 20 fentes entourées par des rayons de l'épaisseur approximative d'une fente. On se propose de calculer

Comme les 2 roues de droite tournent à la même vitesse, on n'exploite qu'un disque à fentes à droite. De même à gauche. Les 2 disques à fente sont traités de la même façon.

IMPORTANT : Seules les vitesses absolues et les distances cumulées sont calculables. Le sens du mouvement ne peut pas être déterminé avec cette configuration matérielle.

Il s’agit donc du calcul de la distance parcourue par le véhicule et de sa vitesse sur la base des informations de rotation fournies par les 2 capteurs, l’un à gauche, l’autre à droite.

Contrairement au programme initial sur Youtube, on ne donne pas ici d’ordre aux moteurs. On considère le capteur permettant de calculer la distance comme indépendant et ne tient donc pas compte des ordres donnés aux moteurs.

Le programme montre qu’il n’y a pas de détection du sens de rotation et donc par conséquent la distance calculée ne pourra qu’augmenter et la vitesse sera toujours positive. C’est un problème qu’il faudra examiner mais d’ors et déjà il semble qu’un capteur complémentaire soit nécessaire.

Pour vérifier que le programme distance1.py fonctionne sans erreurs, il suffit de mettre le véhicule sur cales et de tourner les roues avec capteurs optiques à la main.

2.2 Présentation de la distance parcourue et de la vitesse absolue dans une fenêtre graphique

Les résultats du programme distance1.py ne sont pas observables confortablement. C’est pourquoi, une fenêtre graphique créée à partir de la classe python3 tkinter remplace les simples impressions de distance1.py.

Pour des raisons de facilité, la sortie graphique est développée séparément en mettant au point le programme test_tk.py qui prend en compte l’affichage des distances et des vitesses en temps réel. L’affichage graphique est donc fondé sur la classe python3 tkinter et est aussi simple que possible.

Voici le résultat graphique, les nombres ne signifient rien.

test_tk.png

La procédure développée ci-dessus est simplement appliquée au programme distance1.py pour devenir distance2.py.

2.3 Afficher la distance parcourue et vitesse instantanée pour un véhicule en mouvement

Il s’agit maintenant d’afficher la distance parcourue et vitesse instantanée pour le véhicule en mouvement.
D’une part, nous disposons du programme
car5.py où le pilotage intégral par smartphone permet d’actionner les moteurs et donc de faire tourner les roues, ce qui permet au véhicule d’avancer, de reculer, de tourner à gauche ou à droite, d’accélérer, de décélérer.
D’autre part, les programmes élaborant les distances et les vitesses sont indépendant de car5.py. Il faudrait donc exécuter simultanément car5.py et par exemple distance1.py.
Voici quelques façons d'exécuter simultanément plusieurs scripts python.

2.3.1 Méthodes de base

  1. Commandes Linux directement dans un terminal

    Par soucis de faciliter la présentation en organisant une progression, on met en oeuvre les programmes distance1.py et car5.py qui impriment des informations à l’écran. On lance un terminal à partir du répertoire commun aux 2 programmes puis on entre l'instruction d'exécution simultanée des programmes et car5.py :

    python3 distance1.py & python3 car5.py

    Ceci fonctionne bien : les écritures apparaissent à l’écran au fur et à mesure de leur génération.

    Par contre, à l’arrêt forcé par Crtl + c seul le dernier programme s’arrête (ici car5.py). Il suffit de tourner les roues à la main pour s’apercevoir que distance1.py ne s’est pas arrêté. Pour arrêter le premier programme, il faut ouvrir un nouveau terminal, y demander les processus actifs, identifier le n° du processus distance1.py et tuer le processus :

    ps x Imprime les processus actifs et on repère l’identificateur du processus à tuer par exemple 1550
    kill 1550Tue le processus

    Si maintenant, on met en oeuvre les programmes distance2.py et car5.pydistance2.py transmet ses informations à une fenêtre graphique gérée par tkinter, le départ est semblable au précédent :

    python3 distance2.py & python3 car5.py

    Les écritures issues de car5.py apparaissent à l’écran au fur et à mesure de leur génération et celles de distance2.py apparaissent dans la fenêtre graphique.
    Ici aussi, à l’arrêt forcé par Crtl + c seul le dernier programme s’arrête (car5.py). Par contre, il suffit de fermer la fenêtre graphique par un clic sur le X pour arrêter le programme distance2.py.

  2. Commandes Linux dans un programme python

    Les commandes Linux sont conservées dans un programme python appelé ici scripts.py :

    # Programme scripts.py
    from subprocess import run
    run("python3 distance1.py & python3 car5.py", shell=True)

    Dans un terminal ouvert à partir du répertoire où se trouvent les programmes, on exécute le programme scripts.py :

    python3 scripts.py

    Ceci fonctionne de façon identique à la méthode 1 avec les mêmes difficultés à l’arrêt et la même solution.

    L’intérêt par rapport à la méthode précédente est de pouvoir préparer les programmes qui doivent être exécutés ensemble et ainsi de ne pas devoir entrer à chaque fois une instruction complexe.

  3. Utilisation de 2 terminaux ouverts à partir du répertoire des programmes

    Dans le premier terminal, on lance distance1.py python3 distance1.py
    Dans le second terminal, on lance car5.py python3 car5.py

    Pour arrêter les programmes, il suffit de cliquer sur le terminal correspondant et appuyer sur Crtl + c.

    Cette méthode fonctionne bien mais devient laborieuse lorsque le nombre de programmes à exécuter simultanément augmente.

2.3.2 Mise en oeuvre de l'utilitaire "terminator"

Il y a moyen d'automatiser le processus d'ouverture de terminaux et de lancement des programmes python. L’utilitaire de terminal Linux terminator est à cet égard très pratique.
Note : Il est écrit en python.

Sous Raspberry Pi OS, on installe terminator en choisissant dans le menu principal l’onglet préférences et Add / Remove Software. On recherche ensuite terminator qui s’installe dans le menu principal sous l’onglet Outils système.

Les principales fonctionnalités de terminator sont les suivantes :

Pour préparer l’exécution simultanée du programme de calcul des vitesses et distances et du programme de pilotage du véhicule, l’utilitaire terminator a été configuré en une fenêtre divisée en 2 terminaux.

Voici la procédure utilisée :

Cette configuration a été appelée test et vient s’ajouter à la configuration par défaut qui est composée d’une simple fenêtre contenant un seul terminal.

terminator1

À partir de cette configuration par défaut, en cliquant droit sur la fenêtre, on peut choisir Préférences, puis Dispositions, cliquer sur la disposition test puis successivement sur terminal3 et terminal2. On obtient les images suivantes :

terminal3
terminal2

Le cadre "Type           Nom" a été généré automatiquement par terminator sur la base du découpage de la fenêtre et montre la structure interne des éléments générés.

En choisissant terminal3 dans ce cadre, on découvre la partie droite qui peut être en partie remplie par l’utilisateur.

En choisissant terminal2, la commande personnalisée à droite est ls && sleep 30. Elle est simplement là pour donner quelque chose à faire à ce terminal. Si la commande personnalisée était simplement ls, le terminal se serait fermé dès l’exécution de la commande, c’est-à-dire très vite. L’ajout de sleep 30 signifie qu’il faut attendre 30 secondes avant la fermeture du terminal dédié. La fenêtre continue à être ouverte et l’autre processus à être exécuté dans l’autre terminal q ui prendrait maintenant toute la fenêtre puisque ce serait le seul terminal actif.

Expérimentation numérique
ou
L’utilitaire terminator est simplement ouvert (Menu principal en haut à gauche, Outils système puis clic sur terminator) et la fenêtre par défaut spécifique de terminator apparaît à l’écran. On peut aussi lancer un terminal gnome traditionnel. L'instruction terminator -s fait apparaître un menu "Terminator Layout".
Un clic gauche dans cette fenêtre puis ALT + L fait apparaître un menu "Terminator Layout".
En sélectionnant test puis clic en bas à droite sur Launch, la configuration donnée par la capture d’écran en une fenêtre divisée en 2 terminaux apparait et chaque terminal exécute ce qui lui a été assigné et indique le déroulement du processus.
terminator2
Le terminal du dessus affiche le contenu du répertoire indiqué dans la configuration puis attend 30 secondes avant de se refermer.
Le terminal du dessous ouvre la fenêtre graphique où défilent le résultat des calculs de vitesse et de distance.
tk

Lorsque le terminal du dessus se referme, le terminal du dessous prend toute la place de la fenêtre et le processus continue à être exécuté jusqu’à ce qu’on clique sur la croix de la fenêtre graphique. Le seul terminal restant se ferme alors ainsi que la fenêtre hôte.

2.3.3 Exécution simultanée de "car5.py" et "distance2.py" avec l’utilitaire "terminator"

On revient maintenant au véhicule autonome où le système de détermination des vitesses et des distances est géré par le programme distance2.py et les moteurs du véhicules sont gérés par le programme car5.py lui-même relié par bluetooth au smartphone.
L’utilitaire terminator est ici mis en œuvre avec le couple de programmes python3 distance2.py et car5.py.

On peut utiliser la même découpage d'écran que pour la disposition test et remplacer les propriétés du terminal2 et du terminal3. Cette disposition est appelée car1 :

car1_terminal3
car1_terminal2

Les résultats correspondent à l’attente.

2.4 Détermination du sens du mouvement

2.4.1 Mise en oeuvre d'un capteur optique à rainure supplémentaire

Le capteur de mesure optique à rainure associé à un disque à fentes a permis de définir la distance parcourue et la vitesse MAIS sans tenir compte du sens du mouvement (marche avant, marche arrière, virage à gauche ou à droite). Si on change de sens, les distances se cumulent et la vitesse élaborée ne permet pas de préciser si le véhicule est en marche avant ou en marche arrière. Pour obtenir cette information, on a mis en œuvre un autre capteur de mesure optique à rainure sur le même disque à fentes positionné pour des raisons de commodité d'installation, en quadrature avec l’autre capteur.

La photo à droite montre les deux capteurs en quadrature sur le même disque à fentes. Le second disque a été monté sur un bloc en bois taillé pour recevoir le capteur et vissé sur la plaque de base.

Disque2.jpg

Comme le montre la figure ci-contre (par exemple en "Marche avant") prise par mise en œuvre d'un oscilloscope TWF102, les signaux des deux capteurs vont avoir la même forme mais décalée.

C’est ce déphasage qui va permettre de déterminer le sens de rotation des roues.

En effet, les figures à droite montrent le déphasage en marche avant et en marche arrière. La pulsation du second capteur a un grand déphasage en marche avant et un petit déphasage en marche arrière. C’est justement ce que l’on cherche. Bien sûr, il faut caler correctement le second capteur par rapport au premier et le cas échéant ajuster le support du second capteur.

Remarques

  • les pulsations ne sont pas égales entre fentes (pulsations les plus courtes) et rayons. Les pulsations dues aux fentes ne sont pas égales non plus. Cela peut être dû aux tolérances de fabrication des disques à fentes.
  • les signaux sont au niveau HAUT. Ils redescendent au niveau BAS lorsque le faisceau IR traverse les fentes.

TWF102_2a.jpg
Marche avant

TWF102_2b.jpg
Marche arrière

La figure ci-après permet d’analyser les différentes situations et possibilités. Ces analyses servent à orienter la programmation.

Pulse.jpg

Origine du temps et des distances

Une situation bien précise doit permettre de définir sans ambiguïté l’origine du temps et des distances. C’est le premier front descendant du capteur principal qui a été choisi. C’est-à-dire que le capteur principal vient juste de passer du niveau HAUT au niveau BAS. À ce moment, le capteur de signe est forcément au niveau HAUT, d’après les calages et les mesures.

En langage python, la méthode wait_for_edge() de RPi.GPIO aurait dû constituer un chemin rapide et élégant à l’objectif. Mais cela ne fonctionne pas car vraisemblablement à cause du trigger de Schmitt du capteur optique, le front est trop raide pour cette méthode, mais une autre voie a été trouvée en observant directement les niveaux HAUT et les niveaux BAS du signal du capteur principal.

Le programme test1.py fondé lui-aussi sur RPi.GPIO permet de fixer l’algorithme.

Détermination des vitesses et des distances avec leur signe

Par convention, une vitesse positive signifie un mouvement en marche avant, une vitesse négative signifie une marche arrière. Ici aussi par convention, les distances en marche arrière se déduisent des distances en marche avant mais on aurait pu choisir de cumuler les distances car c’est la distance totale qui contribue à l’usure du véhicule. Pour le reste, il faut suivre le programme distance3g.py en s’aidant de la figure ci-dessus.

Le raisonnement effectué pour le côté gauche peut être transposé au côté droit. Le programme distance3d.py en résulte. Bien entendu, comme l'illustre la figure ci-contre, un autre capteur optique à rainure est nécessaire sur le disque à fentes de la roue arrière droite.

Le dispositif de gauche fonctionne bien. Il n'en est pas de même de celui de droite. Le déphasage en marche avant est équivalent à celui en marche arrière. Il va falloir ajuster le support du capteur de signe. Nous y reviendrons plus loin.

Disques.jpg

2.4.2 Intégration au système "véhicule autonome"

Voici la situation : nous disposons des programmes python

Les 3 programmes sont indépendants, sauf qu'il faudrait coupler distance3d.py et distance3g.py pour qu'ils affichent sur le même afficheur graphique tkinter. C'est en effet une volonté à priori de n'avoir qu'un seul afficheur plutôt qu'une série d'afficheurs disséminés sur tout l'écran.

D'un autre côté, que ce soit dans distance3d.py ou dans distance3g.py, l'afficheur graphique tkinter est géré en même temps que les calculs de vitesse et de distance.

Faisons un petit calcul.

Supposons que le véhicule avance avec une vitesse maximale de 1m/s, la circonférence de roue étant approximativement de 0.2m, ça signifie 5 tours/s pour la roue. Comme il y a 20 fentes sur le disque à fentes, il faut compter sur le signal de l'ordre de 100 impulsions/s. Un cycle de capteur dure donc approximativement 0.010s. Or la gestion par tkinter exige une pause de 1ms entre itérations. cela signifie donc 10 échantillons par cycle. La précision n'est donc pas très grande sur l'estimation des vitesses et des distances.

En conclusion, il faudrait que l'échantillonnage pour le calcul des vitesses et distances soit indépendant de l'affichage.

2.4.3 Recours à la mémoire partagée

L'idée est de faire usage d'une mémoire partagée par plusieurs programmes en principe indépendants.
Un programme calculerait la vitesse et la distance à partir des signaux associés à la roue droite. Il écrirait ses résultats dans la mémoire partagée.
Parallèlement, un autre programme calculerait la vitesse et la distance à partir des signaux associés à la roue gauche. Il écrirait aussi ses résultats dans la mémoire partagée.
Un troisième programme exécuté parallèlement, lirait les vitesses et distances présentes dans la mémoire partagée et les publierait, à son propre rythme, dans la fenêtre graphique produite par tkinter.
Pour mémoire, un quatrième programme,
car5.py, serait aussi exécuté parallèlement mais sans besoin d'avoir accès à la mémoire partagée.

La technique de "mémoire partagée" peut être mise en oeuvre avec python.

Test de la technique

Pour tester cette technique, 2 programmes python ont été mis au point :

Les programmes sont indépendants et échangent des informations de façon asynchrone par l'intermédiaire de la mémoire partagée. Pour les lancer, le plus simple est d'ouvrir 2 terminaux à partir du répertoire hébergeant les deux programmes.
Dans le premier terminal, on lance MP_tk.py qui crée la mémoire partagée et ouvre l'afficheur tkinter.
Dans le second terminal, on lance MP_DV.py qui se lie à la mémoire partagée maintenant existante et produit les valeurs de vitesses et distances
Les valeurs produites apparaissent alors dans l'afficheur tkinter.

Pour terminer,

Remarque :

Chaque programme travaille à son rythme. Le calcul des valeurs de vitesse et de distance peut s'effectuer plus rapidement que l'affichage qui reste cependant correct et ne ralentit pas le rythme de calcul des distances et vitesses.

Application au véhicule autonome

D'abord, les programmes distance3d.py et distance3g.py ont été délestés de la partie concernant la représentation graphique des résultats. Ces parties ont été remplacées par la déclaration de mémoire virtuelle existante et l'utilisation de cette mémoire pour conserver les valeurs des vitesses et distances calculées. il en résulte les programmes distance3dMP.py et distance3gMP.py.

Avant de se servir de terminator, 4 terminaux ont été ouvert à partir du répertoire contenant les programmes. Les 4 terminaux servent aux programmes indépendants suivants :

Les écritures permettent de voir que la fréquence de lecture pour l'acquisition est de l'ordre de 45kHz (0.000022s). Un résultat de calcul est fourni toutes les 0.03s soit 1500 points pour échantillonner un pas de disque à fente qui en compte 20 ! Une centaine se points devraient suffire. Évidemment, ce résultat dépend exclusivement de la vitesse imposée au véhicule. Cette vitesse est ici maximale à 5V sur les moteurs. En plus le véhicule est ici sur cales.
Il y a donc encore une bonne marge de manoeuvre si nous voulons ajouter d'autres programmes.

Pour simplifier la programmation, distance3gMP.py et distance3dMP.py ont été repris pour donner distance3gMP1.py et distance3dMP1.py.

La logique est légèrement différente. Elle peut être comprise par l'intermédiaire de la figure ci-contre et des programmes.

  • Soulignons que la variable flag_ga devient True à partir du moment où le temps t0 a été touvé. Elle ne change plus après.
  • vga et vgs représentent les signaux des 2 capteurs optiques, respectivement pour l'amplitude et le sens de rotation.
  • Ces signaux ont été mesurés par oscilloscope multicanal TWF102 qui permet de sauvegarder les mesures des différents canaux et autour duquel, ont été développés ici des programmes python pour la représentation graphique.
  • la fréquence de lecture pour l'acquisition reste de l'ordre de 45kHz (0.000022s).
Analyse1.jpg

Tous les programmes d'acquisition pour le calcul de distance et de vitesse ont utilisé la classe python RPi.GPIO. Or la classe python gpiozero plus récente et plus dans l'esprit python peut aussi présenter un intérêt.

Les programmes distance3gMP1.py et distance3dMP1.py ont ainsi été "traduits" pour donner distance3dMP2.py et distance3gMP2.py.

NB :

Pour faciliter l'exécution, on peut ouvrir 4 fenêtres pour exécuter simultanément 4 programmes car5.py, MP_tk.py, distance3dMP2.py et distance3gMP2.py.

Mais il est plus simple de définir une disposition de "terminator". Cette disposition a été appelée CarV.

Ceci appelle cependant les remarques suivantes :

  • La gestion de sortie des programmes de plus en plus nombreux à devoir être exécutés simultanément est facilitée en donnant un nom aux différents onglets :
    • Changer le titre de l'onglet Ctrl + Alt + x
    • Changer le titre de la fenêtre Ctrl + Alt + w
  • La mise en oeuvre de la mémoire partagée par plusieurs programmes nécessite un précaution. En effet, le lancement des différents programmes par terminator fera qu'un programme pourrait demander l'accès à la mémoire partagée avant qu'elle ne soit créée.
    Ici, la mémoire partagée est créée par MP_tk.py. Il faut décaler légèrement le départ des programmes de calcul de vitesse et de distance. C'est ainsi que la commande personnalisée du terminal correspondant dans terminator deviendra par exemple sleep 1 && python3 distance3gMP1.py.
  • Une fausse manoeuvre de fermeture des terminaux peut faire en sorte que la mémoire partagée n'ait pas été clôturée proprement et soit toujours présente. Relancer la disposition (Layout) conduira à un échec. C'est pourquoi un petit programme python, appelé SupprimeMP.py a été écrit et doit être exécuté si nécessaire avant de relancer la disposition terminator.
  • Lancer la disposition terminator CarV peut se faire de 2 manières :
    • Alt + L dans un terminal terminator ouvre une fenêtre Layout, dans laquelle, on choisit CarV
    • dans nimporte quel terminal, on suffit d'exécuter terminator -l CarV (-l = -petit L pour layout)

Pour restreindre le nombre de programmes à exécuter simultanément, distance3dMP1.py et distance3gMP1.py peuvent être facilement agrégés pour donner distance3MP1.py.

Il en est de même pour distance3dMP2.py et distance3gMP2.py qui agrégés donnent distance3MP2.py.
En ce qui concerne ces programmes qui, rappelons le, utilise la classe gpiozero, une difficulté est apparue sur la broche GPIO04 qui a dû être remplacée par la broche GPIO20.


3 Radar de recul avec avertisseur sonore

3.1 Les composants

Liens internes principaux

L'idée est d'installer sur le véhicule autonome, un radar de recul avec avertisseur sonore. Le son doit être d'autant plus fort et aigu que le véhicule s'approche de l'obstacle. À cet effet deux composants sont utilisés :

Un capteur de distance à ultrasons HC-SR04 Ultrasons_HC-SR04 dont le montage est représenté sur la figure à droite

Les composants, y compris le capteur ultrasonique, sont tous soudés sur une plaquette perforée qui sert aussi de borne 3.3V et de borne Masse pour d'autres composants à proximité (Moteurs, ...). Cela évite d'alimenter beaucoup de composants à partir de la plaque de prototypage.

Radar.jpg Radar1.jpg
Montage_HC-SR04

Un buzzer actif TMB12A05 BuzzerA commandé par un transistor NPN S8050 pour augmenter l'intensité du signal sonore. (Voir le montage à droite).

Comme le montre la photo tout à droite, les composants sont fixés sur la plaque de prototypage montée à l'étage supérieur du véhicule autonome.

BuzzerNPN Buzzer.jpg

Le capteur de distance est pris en charge par la classe gpiozero.DistanceSensor de python3.

3.2 Vues du véhicule autonome

Vue éclatée du véhicule autonome
VueE.jpg

Autres vues du véhicule autonome
Vue.jpg Vue1.jpg

SUITE ...