Table des matières:

Rpibot - À propos de l'apprentissage de la robotique : 9 étapes
Rpibot - À propos de l'apprentissage de la robotique : 9 étapes

Vidéo: Rpibot - À propos de l'apprentissage de la robotique : 9 étapes

Vidéo: Rpibot - À propos de l'apprentissage de la robotique : 9 étapes
Vidéo: Créons des robots ! De l'imagination à la conception 2024, Décembre
Anonim
Rpibot - À propos de l'apprentissage de la robotique
Rpibot - À propos de l'apprentissage de la robotique

Je suis ingénieur logiciel embarqué dans une entreprise automobile allemande. J'ai commencé ce projet en tant que plate-forme d'apprentissage pour les systèmes embarqués. Le projet a été annulé tôt mais je l'ai tellement apprécié que j'ai continué pendant mon temps libre. Voici le résultat…

J'avais les exigences suivantes:

  • Matériel simple (l'accent est mis sur le logiciel)
  • Matériel pas cher (environ 100€)
  • Extensible (certaines options font déjà partie de la description)
  • Tension d'alimentation pour tous les composants à partir d'une seule source 5V (powerbank)

Il n'y avait pas vraiment d'objectif en dehors de l'apprentissage. La plateforme peut être utilisée pour l'apprentissage, la surveillance, les concours de robotique, …

Ce n'est pas un tutoriel pour débutant. Vous avez besoin de connaissances de base sur:

  • Programmation (Python)
  • Electronique de base (pour connecter les modules entre eux par la bonne tension)
  • Théorie de base du contrôle (PID)

Enfin, vous rencontrerez probablement des problèmes comme je l'ai fait. Avec un peu de curiosité et d'endurance, vous traverserez le projet et résoudrez les défis. Mon code est aussi simple que possible et les lignes de code critiques sont commentées pour donner des conseils.

Le code source complet et les fichiers sont disponibles ici:

Fournitures:

Mécanique

  • 1x panneau de contreplaqué (format A4, 4 mm d'épaisseur)
  • 3x M4 x 80 Vis et écrou
  • 2x Motoréducteurs avec arbre de sortie secondaire pour encodeur. Roues.
  • 1x roue libre

1x support de caméra panoramique et inclinable (en option)

Électronique

  • 1x Raspberry Pi Zero avec en-tête et caméra
  • 1x servocommande PCA 9685
  • 2x roue codeuse optique et circuit
  • 1x cavaliers femelles
  • 1x batterie externe USB
  • 1x pilote de moteur double DRV8833
  • 2x Micro servos SG90 pour le panoramique et l'inclinaison de la caméra (en option)
  • 1x IMU MPU9250 (en option)
  • 1x capteur de distance à ultrasons HC-SR04 (en option)
  • 1x carte perforée et fil à souder, en-têtes, …

Étape 1: Construisez le châssis

Construire le châssis
Construire le châssis
Construire le châssis
Construire le châssis
Construire le châssis
Construire le châssis

Je ne suis pas un bon concepteur mécanicien. De plus, l'objectif du projet est de ne pas passer trop de temps dans le châssis. Quoi qu'il en soit, j'ai défini les exigences suivantes:

  • Matériaux bon marché
  • Montage et démontage rapides
  • Extensible (par exemple, espace pour des capteurs supplémentaires)
  • Des matériaux légers pour économiser de l'énergie pour l'électronique

Un châssis simple et bon marché peut être fabriqué en contreplaqué. Il est facile à usiner avec une scie à chantourner et une perceuse à main. Vous pouvez coller de petites pièces en bois pour créer les supports pour les capteurs et les moteurs.

Pensez au remplacement des composants défectueux ou au débogage électrique. Les pièces principales doivent être fixées par des vis pour être remplaçables. Un pistolet à colle chaude peut être simple, mais probablement pas la meilleure façon de construire un châssis… J'ai eu besoin de beaucoup de temps pour réfléchir à un concept simple pour démonter les pièces facilement. L'impression 3D est une bonne alternative, mais peut être assez coûteuse ou prendre du temps.

La roue libre est enfin très légère et facile à monter. Les alternatives étaient toutes lourdes ou pleines de frictions (j'en ai essayé quelques-unes avant de trouver la dernière). Je n'ai eu qu'à couper une entretoise en bois pour niveler la roue libre de queue après avoir monté les roues principales.

Propriétés de la roue (pour les calculs logiciels)

Circonférence: 21, 5 cm Impulsions: 20 impulsions/tr. Résolution: 1 075 cm (enfin 1 impulsion correspond à environ 1 cm, ce qui est facile pour les calculs logiciels)

Étape 2: Électronique et câblage

Électronique et câblage
Électronique et câblage
Électronique et câblage
Électronique et câblage
Électronique et câblage
Électronique et câblage

Le projet utilise différents modules comme indiqué sur le schéma.

Le Raspberry Pi Zero est le contrôleur principal. Il lit les capteurs et contrôle les moteurs par un signal PWM. Il est connecté à un PC distant par wifi.

Le DRV8833 est un pont en H à double moteur. Il fournit le courant suffisant aux moteurs (ce que le Raspberry Pi ne peut pas faire car les sorties ne peuvent fournir que quelques mA).

L'encodeur optique fournit un signal de forme carrée à chaque fois que la lumière traverse les roues de l'encodeur. Nous utiliserons les interruptions matérielles du Raspberry Pi pour obtenir les informations à chaque fois que le signal bascule.

Le pca9695 est une carte de servocommande. Il communique par un bus série I2C. Cette carte fournit les signaux PWM et la tension d'alimentation qui contrôlent les servos pour le panoramique et l'inclinaison de la came.

Le MPU9265 est un capteur d'accélération 3 axes, de vitesse de rotation angulaire 3 axes et de flux magnétique 3 axes. Nous l'utiliserons principalement pour obtenir le cap de la boussole.

Les différents modules sont tous reliés entre eux par des cavaliers. Une maquette agit comme un répartiteur et fournit des tensions d'alimentation (5 V et 3,3 V) et des masses. Les connexions sont toutes décrites dans le tableau des connexions (voir pièce jointe). Connecter 5V à une entrée 3,3V détruira probablement votre puce. Faites attention et vérifiez deux fois tout votre câblage avant de l'alimenter (ici surtout l'encodeur doit être pris en compte). Vous devez mesurer les tensions d'alimentation principales sur la carte de répartition avec un multimètre avant de connecter toutes les cartes. Les modules ont été fixés par des vis en nylon dans le châssis. Là aussi j'étais content de les avoir réparés mais aussi démontables en cas de dysfonctionnement.

La seule soudure était finalement les moteurs et la maquette et les en-têtes. Pour être honnête, j'aime les fils volants, mais ils peuvent entraîner une mauvaise connexion. Dans certaines situations, certaines surveillances logicielles peuvent vous aider à analyser les connexions.

Étape 3: Infrastructure logicielle

Infrastructure logicielle
Infrastructure logicielle
Infrastructure logicielle
Infrastructure logicielle

Après avoir réalisé la mécanique, nous mettrons en place une infrastructure logicielle pour avoir des conditions de développement confortables.

Git

Il s'agit d'un système de contrôle de version gratuit et open source. Il est utilisé pour gérer de gros projets comme Linux, mais peut aussi facilement être utilisé pour de petits projets (voir Github et Bitbucket).

Les modifications du projet peuvent être suivies localement et également transmises à un serveur distant pour partager le logiciel avec la communauté.

Les principales commandes utilisées sont:

git clone https://github.com/makerobotics/RPIbot.git [Obtenir le code source et la configuration git]

git pull origin master [obtenir les dernières informations du référentiel distant]

git status [obtenir le statut du dépôt local. Y a-t-il des fichiers modifiés ?] git log [obtenir la liste des commits] git add. [ajouter tous les fichiers modifiés à l'étape à prendre en compte pour le prochain commit] git commit -m "comment for commit" [valider les modifications dans le référentiel local]git push origin master [pousser tous les commits vers le référentiel distant]

Enregistrement

Python fournit des fonctions de journalisation intégrées. La structure du logiciel doit déjà définir tout le cadre de journalisation avant de commencer le développement ultérieur.

L'enregistreur peut être configuré pour se connecter avec un format défini dans le terminal ou dans un fichier journal. Dans notre exemple, le logger est configuré par la classe webserver mais nous pouvons également le faire nous-mêmes. Ici, nous définissons uniquement le niveau de journalisation sur DEBUG:

logger = logging.getLogger(_name_)

logger.setLevel(logging. DEBUG)

Mesure et tracé

Pour analyser les signaux dans le temps, le mieux est de les tracer dans un graphique. Comme le Raspberry Pi n'a qu'un terminal de console, nous allons tracer les données dans un fichier csv séparé par des points-virgules et les tracer à partir du PC distant.

Le fichier de trace séparé par des points-virgules est généré par notre code Python principal et doit avoir des en-têtes comme celui-ci:

timestamp;yawCorr;encoderR;I_L;odoDistance;ax;encoderL;I_R;yaw;eSpeedR;eSpeedL;pwmL;speedL;CycleTimeControl;wz;pwmR;speedR;Iyaw;hdg;m_y;m_x;eYaw;cycleTimeSense;

1603466959.65;0;0;25;0.0;-0.02685546875;0;25;0;25;25;52;0.0;23;0.221252441406;16;0.0;0;252.069366413;-5.19555664062;-16.0563964844;0;6; 1603466959.71;0;0;50;0.0;0.29150390625;0;50;0;25;25;55;0.0;57;-8.53729248047;53;0.0;0;253.562118111;-5.04602050781;-17.1031494141;0;6; 1603466959.76;0;-1;75;0.0;-0.188232421875;1;75;2;25;25;57;0;52;-24.1851806641;55;0;0;251.433794171;-5.64416503906;-16.8040771484;2;7;

La première colonne contient l'horodatage. Les colonnes suivantes sont gratuites. Le script de traçage est appelé avec une liste de colonnes à tracer:

remote@pc:~/python rpibot_plotter -f trace.csv -p speedL, speedR, pwmL, pwmR

Le script de tracé est disponible dans le dossier de l'outil:

Le traceur utilise mathplotlib en Python. Vous devez le copier sur votre PC.

Pour plus de confort, le script python est appelé par un script bash (plot.sh) qui permet de copier le fichier de trace Raspberry Pi sur le PC distant et d'appeler le traceur avec une sélection de signal. Le script bash "plot.sh" demande si le fichier doit être copié. C'était plus pratique pour moi au lieu de copier manuellement à chaque fois. "sshpass" est utilisé pour copier le fichier du Raspberry Pi vers le PC distant via scp. Il est capable de copier un fichier sans demander le mot de passe (il est passé en paramètre).

Enfin, une fenêtre s'ouvre avec le tracé comme indiqué sur l'image.

Communication à distance

L'interface de développement du Raspberry Pi est SSH. Les fichiers peuvent être édités directement sur la cible ou copiés par scp.

Pour contrôler le robot, un serveur Web s'exécute sur le Pi, fournissant un contrôle via Websockets. Cette interface est décrite dans l'étape suivante.

Configurer le Raspberry Pi

Il existe un fichier décrivant la configuration du Raspberry Pi dans le dossier "doc" du code source (setup_rpi.txt). Il n'y a pas beaucoup d'explications mais de nombreuses commandes et liens utiles.

Étape 4: l'interface utilisateur

L'interface utilisateur
L'interface utilisateur

Nous utilisons le serveur Web léger Tornado pour héberger l'interface utilisateur. C'est un module Python que nous appelons lorsque nous démarrons le logiciel de contrôle du robot.

Architecture logicielle

L'interface utilisateur est construite à partir des fichiers suivants: gui.html [Description des commandes et de la mise en page de la page Web] gui.js [Contient le code javascript pour gérer les commandes et ouvrir une connexion Websocket à notre robot] gui.css [Contient les styles de les contrôles html. Les positions des commandes sont définies ici]

La communication websocket

L'interface utilisateur n'est pas la plus cool, mais elle fait le travail. Je me suis concentré ici sur des technologies qui étaient nouvelles pour moi comme les Websockets.

Le site Web communique avec le serveur Web du robot par Websockets. Il s'agit d'un canal de communication bidirectionnel qui restera ouvert tant que la connexion a été initiée. Nous envoyons les commandes du robot via Websocket au Raspberry Pi et récupérons les informations (vitesse, position, flux de la caméra) pour affichage.

La disposition de l'interface

L'interface utilisateur dispose d'une entrée manuelle pour les commandes. Cela a été utilisé au début pour envoyer des commandes au robot. Une case à cocher active et désactive le flux de la caméra. Les deux curseurs contrôlent le panoramique et l'inclinaison de la caméra. La partie supérieure droite de l'interface utilisateur contrôle le mouvement des robots. Vous pouvez contrôler la vitesse et la distance cible. Les informations de télémétrie de base sont affichées dans le dessin du robot.

Étape 5: Programmation de la plate-forme robotique

Programmation de la plate-forme robotique
Programmation de la plate-forme robotique
Programmation de la plate-forme robotique
Programmation de la plate-forme robotique
Programmation de la plate-forme robotique
Programmation de la plate-forme robotique

Cette partie était l'objectif principal du projet. J'ai remanié une grande partie du logiciel lors de l'introduction du nouveau châssis avec les moteurs à courant continu. J'ai utilisé Python comme langage de programmation pour différentes raisons:

  • C'est le langage principal du Raspberry Pi
  • C'est un langage de haut niveau avec de nombreuses fonctionnalités et extensions intégrées
  • Il est orienté objet mais peut également être utilisé pour la programmation séquentielle
  • Aucune compilation ni chaîne d'outils nécessaires. Modifiez le code et exécutez-le.

Architecture logicielle principale

Le logiciel est orienté objet, divisé en quelques objets. Mon idée était de diviser le code en 3 blocs fonctionnels:

Sens Penser Actionner

Sense.py

Acquisition et traitement du capteur principal. Les données sont stockées dans un dictionnaire pour être utilisées par l'étape suivante.

Contrôle.py

Une sous-classe d'actionnement contrôle les moteurs et les servos après une certaine abstraction. L'objet Contrôle principal gère les commandes de haut niveau ainsi que les algorithmes de contrôle (PID) pour le moteur.

rpibot.py

Cet objet principal gère le serveur Web Tornado et instancie les classes de détection et de contrôle dans des threads séparés.

Chaque module peut être exécuté seul ou dans le cadre de l'ensemble du projet. Vous pouvez uniquement détecter et imprimer les informations du capteur pour vérifier que les capteurs sont correctement connectés et fournissent les bonnes informations.

Le contrôle PID

La première tâche est de découvrir ce que nous voulons contrôler. J'ai commencé par essayer de contrôler la position, ce qui était très complexe et n'aidait pas beaucoup.

Enfin, nous voulons contrôler la vitesse de chaque roue ainsi que la direction du robot. Pour ce faire, nous devons cascader deux logiques de contrôle.

Pour augmenter la complexité étape par étape, le robot doit être contrôlé:

boucle ouverte (à puissance constante)

pwm = K

puis ajoutez l'algorithme de boucle fermée

pwm = Kp.speedError+Ki. Integration(speedError)

et enfin ajouter le contrôle de direction comme dernière étape.

Pour le contrôle de vitesse j'ai utilisé un contrôle "PI" et "P" uniquement pour le lacet. Je règle manuellement les paramètres en expérimentant. Probablement de bien meilleurs paramètres pourraient être utilisés ici. Mon objectif était juste une ligne droite et je l'ai presque atteint. J'ai créé une interface dans le logiciel pour écrire certaines variables par l'interface utilisateur. La définition du paramètre Kp sur 1.0 nécessite la commande suivante dans l'interface utilisateur:

SET;Kp;1.0

Je pouvais régler le paramètre P juste assez bas pour éviter tout dépassement. L'erreur restante est corrigée par le paramètre I (erreur intégrée)

Il m'a été difficile de trouver comment mettre en cascade les deux commandes. La solution est simple, mais j'ai essayé bien d'autres façons avant… Alors finalement, j'ai changé la cible de vitesse des roues pour tourner dans l'un ou l'autre sens. La modification directe de la sortie du contrôle de vitesse était une erreur car le contrôle de vitesse tentait de supprimer cette perturbation.

Le schéma de contrôle utilisé est joint. Il ne montre que le côté gauche de la commande du robot.

Étape 6: Les étalonnages du capteur

Les étalonnages des capteurs
Les étalonnages des capteurs
Les étalonnages des capteurs
Les étalonnages des capteurs
Les étalonnages des capteurs
Les étalonnages des capteurs

La première chose à considérer est que l'ensemble de l'IMU doit fonctionner correctement. J'ai commandé 3 pièces et les ai renvoyées jusqu'à ce que j'aie un capteur fonctionnel. Chaque capteur précédent avait certaines parties du capteur qui ne fonctionnaient pas correctement ou pas du tout. J'ai utilisé quelques exemples de scripts pour tester les bases avant de le monter dans le robot.

Les signaux du capteur IMU doivent être calibrés avant de l'utiliser. Certains signaux de capteur dépendent de l'angle et de la position de montage.

Les calibrations d'accélération et de vitesse de rotation

L'étalonnage le plus simple concerne l'accélération longitudinale (A_x). A l'arrêt, il devrait y avoir environ 0 m/s². Si vous tournez correctement le capteur, vous pouvez mesurer la gravité (environ 9, 8 m/s²). Pour calibrer a_x, il suffit de le monter correctement puis de définir l'offset pour obtenir 0 m/s² à l'arrêt. A_x est maintenant calibré. Vous pouvez obtenir les décalages pour les vitesses de rotation de la même manière à l'arrêt.

L'étalonnage du magnétomètre pour la boussole

Un étalonnage plus complexe est nécessaire pour les capteurs de champ magnétique. Nous utiliserons m_x et m_y pour obtenir le champ magnétique au niveau horizontal. Avoir m_x et m_y nous donnera la possibilité de calculer un cap compas.

Pour notre simple objectif, nous calibrerons uniquement la déviation du fer dur. Ceci doit être effectué lorsque le capteur est en position finale car il dépend des perturbations du champ magnétique.

Nous enregistrons m_x et m_y pendant que nous tournons le robot autour de l'axe z. Nous traçons le m_x vs m_y dans un graphique XY. Le résultat dans une ellipse comme indiqué dans l'image. L'ellipse doit être centrée sur l'origine. Ici, nous considérons les valeurs maximale et minimale de m_x et m_y pour obtenir les décalages dans les deux sens. Enfin, nous vérifions l'étalonnage et constatons que l'ellipse est maintenant centrée.

L'étalonnage du fer doux signifierait que nous changeons l'image d'une ellipse en un cercle. Cela peut être fait en ajoutant un facteur sur chaque valeur de capteur.

Une routine de test peut maintenant être codée pour recalibrer ou au moins pour vérifier que les capteurs sont toujours calibrés.

Le cap de la boussole

Les données du magnétomètre seront maintenant utilisées pour calculer le cap de la boussole. Pour cela, nous devons convertir les signaux m_x et m_y en un angle. Python fournit directement la fonction math.atan2 qui a cet objectif. Le calcul complet est défini dans le fichier mpu9250_i2c.py ("calcHeading(mx, my, mz)").

Étape 7: Conceptions alternatives

Conceptions alternatives
Conceptions alternatives
Conceptions alternatives
Conceptions alternatives
Conceptions alternatives
Conceptions alternatives

Le projet a pris beaucoup de temps car la conception était complètement ouverte. Pour chaque composant, j'ai réalisé une implémentation de prototype et j'ai expérimenté les limites du système.

Le sujet le plus complexe était l'encodeur de roue. J'ai testé 3 options différentes avant de trouver l'encodeur optique actuellement utilisé. Je pense que les solutions avortées sont aussi très intéressantes dans un tel projet. Cela concerne les parties où j'ai le plus appris.

Servo à rotation continue connecté au pca 9695

Pour éviter un pont en H supplémentaire pour un moteur à courant continu, j'ai d'abord commencé avec des servos à rotation continue. Ceux-ci étaient entraînés par le servomoteur pca 9695 déjà présent. Toute la mécanique de propulsion et l'électronique correspondante étaient beaucoup plus simples. Cette conception présentait deux inconvénients:

  • La mauvaise plage de contrôle des servos.
  • L'emplacement d'attente de l'encodeur manquant

Les servos commencent à se déplacer à 50% pwm et ont leur pleine vitesse à environ 55%. Il s'agit d'une plage de contrôle très faible.

Sans un encodeur, il était très difficile de trouver un encodeur prêt à l'emploi. J'ai testé 3 codeurs de réflectance différents qui ont été montés sur le châssis. J'ai scotché une roue codeuse faite maison à l'extérieur de la roue avec des sections en noir et blanc. J'ai utilisé les capteurs QTR-1RC qui nécessitent beaucoup de traitement du signal pour obtenir le bon signal. Le Raspberry Pi n'était pas en mesure d'effectuer ce type de traitement en temps réel. J'ai donc décidé d'ajouter un NodeMCU D1 mini comme contrôleur temps réel au robot. Il était connecté au Raspberry Pi par l'UART série pour fournir les données du capteur traitées. Le NodeMCU gérait également le capteur HC-SR04. La mécanique était difficile et pas très robuste, la ligne série recevait du bruit de la ligne I2C et des moteurs, j'ai donc finalement construit la deuxième version du châssis avec de simples moteurs à courant continu à engrenages entraînés par un pont en H. Ces moteurs ont un arbre de sortie secondaire pour placer un encodeur optique.

Étape 8: Traitement de l'image

Traitement d'image
Traitement d'image
Traitement d'image
Traitement d'image
Traitement d'image
Traitement d'image
Traitement d'image
Traitement d'image

Pour améliorer la conduite autonome, on peut faire quelques traitements d'images.

La bibliothèque opencv est une référence pour cela. Il peut être utilisé par Python pour implémenter rapidement la détection d'obstacles.

Nous capturons une image et appliquons certaines tâches de traitement d'image:

Les premiers tests ont été faits avec les transformations de Canny et Sobel. Canny peut être un bon candidat mais n'est pas assez sensé. Sobel est trop sensible (trop d'objets détectés).

Enfin j'ai fait mon propre filtre pour mélanger tous les dégradés horizontaux et verticaux (détecter les meubles):

  • Transformer l'image couleur en une image en niveaux de gris
  • Flou l'image pour supprimer le petit bruit
  • Seuil de l'image à une image en noir et blanc
  • Maintenant, nous détectons les gradients horizontaux et verticaux pour détecter les objets comme les murs et les meubles
  • On filtre uniquement les gros contours restants (voir contours colorés sur la photo)

Maintenant, nous pouvons utiliser ces nouvelles informations pour détecter les obstacles…

Étape 9: Étapes suivantes…

Prochaines étapes…
Prochaines étapes…
Prochaines étapes…
Prochaines étapes…

Maintenant, nous avons une plate-forme robotique simple avec des capteurs, des actionneurs et une caméra. Mon objectif est de me déplacer de manière autonome et de retourner à la station sans ajouter d'autres capteurs. Pour cela, j'aurai besoin des étapes suivantes:

  • Fusion de capteurs de signaux de lacet et de cap magnétique
  • Traitement de l'image de la caméra (seulement un processeur faible disponible pour cela)
  • Détection de collision (distance ultrasonique et caméra)
  • Construction de carte ou orientation

Allez maintenant créer vos propres défis ou objectifs…

Conseillé: