Trois robots de grande taille à construire et à programmer : Deuxième robot "Filippo" (Deuxième partie)

Nous poursuivons la description de nos robots avec le deuxième : Filippo.
Dans cette partie, nous analyserons ensemble le logiciel commandant les mouvements et l’interaction de Filippo avec le monde extérieur.


Après avoir vu, dans la première partie, comment monter mécaniquement et électroniquement Filippo, nous allons étudier dans cette seconde partie le logiciel gérant la carte-mère montée sur le robot. Nous analyserons les codes des trois programmes écrits en Basic et qui permettent à Filippo de se déplacer et de répondre aux impulsions provenant de l’environnement.
Comme pour CarBot, nous procéderons par ordre de difficulté croissante : d’abord un programme simple permettant à Filippo de faire trois pas en avant, de manière à éclairer le principe même du mouvement, puis un deuxième “listing” consacré au détecteur à infrarouges, permettant au robot de voir les obstacles et enfin un troisième “listing” unissant les notions acquises et permettant à Filippo de se déplacer dans un espace, sans heurter les obstacles rencontrés.
Ce qui a été dit pour CarBot vaut encore ici : le but de l’article n’est pas de montrer tout ce que Filippo est capable de faire, mais seulement d’expliquer quels sont les concepts de base afin de donner à l’usager les connaissances nécessaires pour pouvoir réaliser ses propres applications.
Avant de passer au logiciel, revoyons toutefois rapidement quelques caractéristiques du matériel : toute la mécanique est gérée par une carte-mère dont le coeur est un microcontrôleur PIC16F876 disposant de trois ports de I/O (A, B et C) pour un total de 22 broches. Certaines de ces dernières sont utilisées pour commander les dispositifs externes : par exemple, le bit 1 du port A est connecté au “Speaker” (c’est un buzzer multiton), les bits 2 et 5 du port C commandent les émetteurs à infrarouges gauche (IFR2) et droite (IFR1), le bit 1 de ce même port est en revanche connecté au récepteur à infrarouges (IR1). Enfin les bits 1 et 2 du port B commandent les deux servomoteurs produisant le mouvement. L’un des deux moteurs est utilisé pour produire le mouvement avant/arrière des jambes (Servo1), l’autre servomoteur (Servo2) est en revanche utilisé pour déplacer le barycentre d’une jambe à l’autre. Il est possible de résumer le principe de la marche en avant :
– le barycentre se déplace sur la jambe droite,
– la jambe gauche avance,
– le barycentre se déplace sur la jambe gauche,
– la jambe droite avance.
En exécutant cycliquement ces quatre opérations, on obtient le mouvement en avant de Filippo. Les servomoteurs utilisés sont deux modèles Futuba S3003, utilisés normalement en modélisme. Les deux dispositifs sont alimentés par une tension entre 4,8 et 6 V et ils sont commandés par des trains d’impulsions dont la durée implique la position prise par l’axe.
Pour une durée de 1,5 ms, l’axe se met en position centrale, pour 1,2 ms, il se met complètement dans une direction et pour 1,8 ms complètement dans la direction opposée.
Si l’on envoie des impulsions dont la durée est comprise entre 1,2 et 1,5 ms et 1,5 et 1,8 ms, l’axe se met dans une position intermédiaire proportionnelle à la durée.
Dans les programmes en Basic, la production des impulsions se fait par l’instruction PulseOut Pin,Period produisant sur la broche Pin une impulsion de durée égale à 2.10-6.Period. Par conséquent, pour produire des impulsions de 1,2 ms, il faut spécifier une valeur de “Period” de 600. Pour des durées de 1,5 ms “Period” vaut 750. Enfin, pour des durées de 1,8 ms “Period” vaut 900. La Table de vérité de la figure 2 reprend ces valeurs.
La détection des obstacles se fait en utilisant deux émetteurs (un à droite, l’autre à gauche) et un récepteur à infrarouges. La logique de détection des obstacles est la suivante : le microcontrôleur habilite l’émission de IR1 (l’émetteur droit). Si un obstacle se présente dans le cône de lumière produit, il en réfléchit les photons vers le récepteur à infrarouges, lequel en identifie la présence. En même temps, le microcontrôleur se met à l’écoute sur le port I/O du récepteur : si le PIC détecte un signal, cela signifie que l’obstacle est à droite et par conséquent il arrête la marche en avant et prend les mesures nécessaires.
Ensuite, le PIC met IFR2 au niveau logique haut et exécute les mêmes opérations, mais, dans ce cas, il détecte un éventuel obstacle à gauche.
Avant de passer à l’analyse des “listings”, une dernière note : comme pour CarBot, nous avons ici introduit le concept de “bootloader”, soit ce système de programmation du microcontrôleur PIC16F876 qui, grâce à une connexion sérielle RS232 permet de transférer les programmes directement d’un PC à la carte-mère du robot. Naturellement, cela reste valable pour Filippo : grâce au “bootloader” la programmation est plus simple et plus rapide. Aucune platine externe de programmation n’est en effet requise, un simple câble sériel et le programme PICdownloader.exe, téléchargeable sur le site de la revue, suffisent.

Figure 1 : Liaison avec les dispositifs externes. Table de vérité.






Figure 2 : Logique de fonctionnement du détecteur à infrarouges.

Les deux émetteurs à infrarouges (droit et gauche) envoient, alternativement, le signal lumineux : si un obstacle est présent, le cône de lumière est réfléchi et donc détecté par le récepteur placé au centre.
Il est possible, par conséquent, de distinguer un obstacle à droite d’un obstacle à gauche.

Le logiciel 1 : trois pas en avant.
Il s’agit d’un logiciel simple faisant accomplir à Filippo trois pas en avant, puis le mouvement s’arrête. Regardons le “listing” : après certaines définitions de caractère général (Loader_Used utilisée par le “bootloader, Osc paramétrant l’horloge à 20 MHz et Adcon1 indiquant d’utiliser le port A en numérique) sont spécifiés les sens (“Input” ou “Output”) des broches des ports A, B et C. Pour cet exemple ils sont tous paramétrés en “outputs” (rappelons que 0 signifie bit en “output” et 1 bit en “input”). Ensuite, sont définies les liaisons entre les servomoteurs et les broches auxquelles ils sont reliés : en particulier il est spécifié que le servomoteur 1 (celui qui règle la position du barycentre) est relié à la broche 2 du port B, le servomoteur 2 (commandant le mouvement des jambes) est en revanche relié au bit 1 toujours du port B. Deux variables définies (Mcount et Icount) seront utilisées à l’intérieur des cycles “for” présents dans le programme. Ensuite des constantes sont définies : Retard indique la pause utilisée après chaque instruction “Pulsout”, Pas_B indique le pas utilisé dans le cycle de positionnement du barycentre et Pas_G celui utilisé dans le cycle de mouvement des jambes. Enfin, les limites maximales, minimales et centrales des deux servomoteurs sont définies.
Maintenant, après avoir mis à zéro les trois ports de I/O et les deux variables utilisées dans les cycles “for”, le programme proprement dit commence. Au moyen des appels de subroutines adéquates (M0 à M8), le mouvement se produit : au début, les deux servomoteurs se centrent, le barycentre se déplace ensuite sur la jambe droite et la jambe gauche avance. Ensuite, à l’intérieur d’un cycle “for” sont exécutés les trois pas selon la méthode expliquée au début de l’article :
– le barycentre se déplace sur la jambe gauche,
– la jambe droite avance,
– le barycentre se déplace sur la jambe droite,
– la jambe droite gauche.
Le cycle terminé, le dernier pas s’achève et ensuite les deux moteurs se recentrent.
On l’a vu, le mouvement des servomoteurs est géré à l’intérieur de 9 subroutines (M0 à M8) : M0 exécute le centrage, M1 déplace le barycentre à droite en maintenant les jambes dans une position centrée, M2 déplace la jambe gauche en avant en maintenant le barycentre à droite, M3 déplace le barycentre à gauche en maintenant en avant la jamais gauche, etc.
Analysons donc la première subroutine M0 : comme on peut le noter sur le “listing”, à travers l’instruction “PulsOut”, les deux servomoteurs sont centrés.
Comme second paramètre sont utilisées correctement les constantes Bar_Centre et Jam_Centre qui ont été définies à 750.
Passons à la subroutine M1 : elle exécute le positionnement du barycentre sur la jambe droite. En regardant le code, nous voyons que, à travers le cycle “for”, le Servomoteur 2 (celui commandant les jambes) est maintenu centré, alors que le Servomoteur 1 est déplacé graduellement de la position centrale (Bar_Centre) à celle correspondant au barycentre sur la droite (Bar_Droite). Quand on a compris comment fonctionne M1, il est très facile de comprendre les autres subroutines réglant la position du barycentre (M3, M5 et M8) : parmi les trois, la seule chose qui change est la condition initiale et finale du cycle “for” réglant le positionnement du barycentre et la position dans laquelle est maintenu le Servomoteur 2.
Voyons maintenant les subroutines qui règlent le mouvement des jambes et commençons par M2 : elle met les jambes en mouvement d’une position centrée à une position où la jambe gauche est avancée. Le tout est géré par un cycle “for” où le barycentre (Servomoteur 1) est maintenu constamment sur la jambe droite, alors que le Servomoteur 2 se déplace graduellement de la position centrale à celle où la jambe gauche est avancée. Dans ce cas aussi, quand le fonctionnement de M2 est compris, celui des subroutines M4, M6 et M7 l’est aussi.
Ainsi s’achève l’analyse du premier “listing”. Nous avons réussi à comprendre comment se produit la marche en avant par exécution séquentielle des 9 subroutines. Si, au lieu d’avancer, nous voulons reculer, la logique du mouvement demeure essentiellement la même : ce qui change, c’est l’ordre d’exécution des subroutines. Il faudrait donc agir ainsi :
– barycentre sur la jambe droite,
– avancée de la jambe droite (correspondant au recul de celle de gauche),
– barycentre sur la jambe gauche,
– avancée de la jambe gauche (correspondant au recul de celle de droite).
En utilisant la même logique de mouvement, il est en outre possible de faire faire des rotations à Filippo. Par exemple, pour tourner à gauche, il faudrait exécuter les opérations suivantes :
– barycentre sur la jambe gauche,
– avancée de la jambe droite,
– barycentre au centre,
– avancée de la jambe gauche,
– barycentre sur la jambe droite,
– avancée de la jambe droite,
– barycentre au centre,
– avancée de la jambe gauche.
Pour tourner à droite, il faudrait en revanche exécuter des opérations similaires.

Figure 3 : Trois pas en avant et “stop” !
LISTING
‘***********************************************************************************
‘ * Nom : Trois pas en avant et Stop *
‘ * Proces. : PIC16F876 *
‘ * Note : Trois pas en avant et s’arrête *
‘***********************************************************************************

‘-----[ Définitions ]---------------------------------------------------------------
DEFINE LOADER_USED ‘Utilisé pour boot-loader
DEFINE OSC 20 ‘Paramètre Clock a 20MHz
ADCON1 = 000111 ‘Port A = Numérique
‘-----[ Vers Ports ]----------------------------------------------------------------
TRISA = 000000 ‘Paramètre pin Port A tous en Output
TRISB = 000000 ‘Paramètre pin Port B tous en Output
TRISC = 000000 ‘Paramètre pin Port C tous en Output
------[ Définitions I/O ]-----------------------------------------------------------
Servo1 VAR PORTB.2 ‘Port Servo 1 (Barycentre)
Servo2 VAR PORTB.1 ‘Port Servo 2 (jambes)
‘-----[ Définitions Variables ]-----------------------------------------------------
Mcount VAR BYTE ‘Loop pour mouvements
Icount VAR WORD ‘Loop pour impulsions
‘-----[ Définitions Constantes ]----------------------------------------------------
Retard CON 25 ‘Pause pour PULSOUT en microsecondes
Pas_B CON 5 ‘Pas pour cycle barycentre
Bar_Droite CON 650 ‘Limites barycentre
Bar_Centre CON 750
Bar_Gauche CON 850
Pas_G CON 9 ‘Pas pour cycle jambes
Jam_Droite CON 600 ‘Limites Jambes
Jam_Centre CON 750
Jam_Gauche CON 900
‘-----[ Initialisation ]------------------------------------------------------------
PORTA =0
PORTB =0
PORTC =0
‘-----[ Début programme ]-----------------------------------------------------------
Mcount = 0
Icount = 0
Début :
GoSub M0 ‘Centrage servo
GoSub M1 ‘Barycentre Droite
GoSub M2 ‘Pas Gauche
For Mcount = 1 to 3
GoSub M3 ‘Barycentre Gauche
GoSub M4 ‘Pas Droite
GoSub M5 ‘Barycentre Droite
GoSub M6 ‘Pas Gauche
Next
GoSub M3 ‘Barycentre Gauche
GoSub M7 ‘Pieds au Centre
GoSub M8 ‘Centre servo
End
‘-----[ Subroutine ]----------------------------------------------------------------
M0: ‘Centre les deux servomoteurs
For Icount = 1 TO 100 STEP Pas_G
PulsOut Servo1, Bar_Centre
PulsOut Servo2, Jam_Centre
Pause Retard
Next
Return
M1: ‘Déplace le Barycentre du milieu à droite
For Icount = Bar_Centre TO Bar_Droite STEP -Pas_B
PulsOut Servo1, Icount
PulsOut Servo2, Jam_Centre
Pause Retard
Next
Return
M2: ‘Déplace les Jambes du centre à avant gauche
For Icount = Jam_Centre TO Jam_Gauche STEP Pas_G
PulsOut Servo1, Bar_Droite
PulsOut Servo2, Icount
Pause Retard
Next
Return
M3: ‘Déplace le Barycentre de droite à gauche
For Icount = Bar_Droite TO Bar_Gauche STEP Pas_B
PulsOut Servo1,Icount
PulsOut Servo2, Jam_Gauche
Pause Retard
Next
Return
M4: ‘Déplace les Jambes d’avant gauche à droite
For Icount = Jam_Gauche TO Jam_Droite STEP -Pas_G
PulsOut Servo1, Bar_Gauche
PulsOut Servo2, Icount
Pause Retard
Next
Return
M5: ‘Déplace le barycentre de gauche à droite
For Icount = Bar_Gauche TO Bar_Droite STEP -Pas_B
PulsOut Servo1,Icount
PulsOut Servo2, Jam_Droite
Pause Retard
Next
Return
M6: ‘Déplace les Jambes d’avant droit à gauche
For Icount = Jam_Droite TO Jam_Gauche STEP Pas_G
PulsOut Servo1,Bar_Droite
PulsOut Servo2, Icount
Pause Retard
Next
Return
M7: ‘Déplace les Jambes d’avant gauche au centre
For Icount = Jam_Gauche TO Jam_Centre STEP -Pas_G
PulsOut Servo1,Bar_Gauche
PulsOut Servo2, Icount
Pause Retard
Next
Return
M8: ‘Déplace le barycentre de gauche au centre
For Icount = Bar_Gauche TO Bar_Centre STEP -Pas_B
PulsOut Servo1, Icount
PulsOut Servo2, Jam_Centre
Pause Retard
Next
Return
End


Le logiciel 2 : test des émetteurs et du récepteur à infrarouges
Il s’agit d’un logiciel réalisant un petit test des émetteurs et du récepteur à infrarouges présents sur le robot : quand la présence d’un obstacle à droite ou à gauche est détectée, un son différent (10 à droite, 100 à gauche) est émis. Commençons l’analyse du “listing” : ici aussi le “Loader_used” utilisé par le “bootloader” et “Osc” spécifiant l’horloge à 20 MHz sont définis.
Ensuite, certains paramètres de débogage (“debug”) sont définis également : pour le moment, nous ne les prendrons pas en considération, nous les analyserons à la fin du “listing”. Ensuite, il est défini que le port A est de type numérique, sont définis aussi quelles broches des trois ports sont “Input” ou “Output” et les liaisons entre les portes et le “Speaker” (c’est un buzzer multiton), le récepteur à infrarouges et deux émetteurs droit et gauche. Sont ensuite déclarées les variables pour le récepteur à infrarouges et Note contenant la valeur des tons à produire. Enfin, la durée de chaque ton est définie. On passe ensuite à l’initialisation des 3 ports et des 3 variables définies au début du programme.
Une fois entré dans le cycle principal, tout d’abord c’est la présence d’un obstacle à droite qui est testée. On active donc l’émetteur à infrarouges droit : on attend un instant pour permettre au signal de se propager et au récepteur de détecter la réflexion des photons, l’état du récepteur à infrarouges est lu et l’émetteur droit s’éteint.
Alors, avec une instruction IF, on teste si l’obstacle est présent, auquel cas un son de tonalité 10 est émis. On passe alors à la vérification d’un obstacle à gauche : les opérations sont les mêmes qu’à droite. On active donc l’émetteur gauche et on lit l’état du récepteur, ici aussi, avec une instruction IF, on teste la présence de l’obstacle et éventuellement la note de ton 100 est émise. Le cycle de contrôle est donc terminé : on revient ensuite à l’étiquette Début et on répète le tout. L’émission du son est gérée par la subroutine Son : avec l’instruction “Sound Speaker”, [Note,Durée], la note est produite.
L’analyse du “listing” étant terminée, considérons les instructions de débogage.
Comme avec tous les compilateurs, elles servent à permettre au programme de contrôler l’exécution correcte du logiciel. Pour le fonctionnement du programme, ils sont en un certain sens inutiles (les opérations sont exécutées correctement même si elles sont éliminées). Il semble cependant intéressant de vous montrer comment il est possible de les utiliser. Les informations de contrôle sont transmises à l’extérieur en utilisant une broche d’un des trois ports, par transmission sérielle. A l’intérieur des définitions il est paramétré que, pour le débogage, on utilise le bit 6 du port C, qu’on utilise une vitesse de transmission de 9 600 bits/s et que les bits sont envoyés en mode normal. A la fin du “listing”, l’instruction Debug “Left= ”, BIN1 left_IR_det spécifie de transmettre sur le bit 6 du port C le flux composé de “Left= ” suivi de la valeur binaire prise par la variable left_IR_det. La seconde instruction indique en revanche de transmettre le flux “Right= ” suivi de la valeur binaire prise par la variable right_IR_det et par le caractère ASCII 13, correspondant à l’envoi.
Ainsi, en reliant un port sériel à la broche 6 du port C, il est possible de recevoir ces données et de vérifier l’exécution correcte du logiciel.

Figure 4 : Test des émetteurs et du récepteur à infrarouges.
LISTING
‘***********************************************************************************
‘ * Nom : Infrarouges test *
‘ * Proces. : PIC16F876 *
‘ * Note : Pour tester les émetteurs et le récepteur IR *
‘***********************************************************************************

‘-----[ Définitions ]---------------------------------------------------------------
DEFINE LOADER_USED 1 ‘Utilisé pour boot-loader
DEFINE OSC 20 ‘Paramètre Clock à 20MHz

‘-----[ Définitions pour débogage ]-------------------------------------------------

DEFINE DEBUG_MODE 0 ‘Données envoyées (0 = normal;
‘1= inversé)
DEFINE DEBUG_REG PORTC ‘Port pour Débogage
‘= PortC
DEFINE DEBUG_BIT 6 ‘Bit du port pour
‘Débogage = PortC.6
DEFINE DEBUG_BAUD 9600 ‘Vitesse = 9 600

‘-----[ Définitions configuration ports ]-------------------------------------------

ADCON1 = 000111 ‘Port A = Numérique

‘-----[ Vers Ports ]----------------------------------------------------------------

TRISA = 110000 ‘Paramètre pin 4,5 Port A..
‘..en Input; autres Output
TRISB = 000000 ‘Paramètre pin Port B tous..
‘..en Output
TRISC = 000011 ‘Paramètre pin 0,1 Port C..
‘..en Input; autres Output

‘-----[ Définitions I/O ]-----------------------------------------------------------

Speaker VAR PORTA.1 ‘Port Speaker
IR_1 VAR PORTC.1 ‘Port Récepteur IR
IFR_1 VAR PORTC.5 ‘Port Trx Infrarouge 1
IFR_2 VAR PORTC.2 ‘Port Trx Infrarouge 2

‘-----[ Définitions Variables ]-----------------------------------------------------

left_IR_det VAR BIT ‘Variable pour IR gauche
right_IR_det VAR BIT ‘Variable pour IR droite
Note VAR BYTE ‘Note pour sound

‘-----[ Définitions Constantes ]----------------------------------------------------
Durée CON 50 ‘Durée Note pour Sound

‘-----[ Initialisation ]------------------------------------------------------------
PORTA =0
PORTB =0
PORTC =0

left_IR_det = 0
right_IR_det = 0
Note = 0
‘-----[ Début programme ]-----------------------------------------------------------

Début :
‘Test présence des obstacles à Droite
High IFR_1 ‘Activer trx IFR de Droite
Pause 1 ‘Attendre un instant
right_IR_det = IR_1 ‘Lecture état récepteur IR
Low IFR_1 ‘Eteindre trx IFR de Droite

IF right_IR_det = 0 Then ‘Si état récepteur IR=0..
Nota = 10 ‘.. alors obstacle présent
GoSub Son ‘Signaler avec son
EndIF

‘Test présence des obstacles à Gauche
High IFR_2 ‘Activer trx IFR de Gauche
Pause 1 ‘Attendre un instant
left_IR_det = IR_1 ‘Lecture état récepteur IR
Low IFR_2 ‘Eteindre trx IFR de Gauche

IF left_IR_det = 0 Then ‘Si état récepteur IR=0..
Note = 100 ‘.. alors obstacle présent
GoSub Son ‘Signaler avec son
EndIF

Débogage “Left= “,BIN1 left_IR_det
Pause 20
Débogage “Right= “,BIN1 right_IR_det,13
Pause 20
GoTo Début ‘Répéter cycle

‘-----[ Subroutine ]----------------------------------------------------------------

‘ Subroutine de production du son
Son :
Sound Speaker, [Note,Durée] ‘Emission Note
Low Speaker ‘ Mise à zéro speaker
Return
End


Le logiciel 3 : mouvement avec détection des obstacles
C’est le logiciel le plus intéressant et le plus complet : il permet à Filippo de se déplacer et de détecter la présence des obstacles. Le mouvement a lieu vers l’avant : quand un obstacle est détecté à droite ou à gauche, la direction est modifiée par des rotations adéquates à gauche ou à droite. Si en revanche l’obstacle est frontal, le robot effectue un mouvement vers l’arrière.
Analysons le “listing” : après les définitions des ports et des liaisons des dispositifs, les variables utilisées par le programme sur déclarées. En particulier BarycentreActuel et JambeActuelle sont utilisés pour mémoriser la position courante du barycentre et des jambes, NouvelleValeur est en revanche utilisé pour mémoriser la position dans laquelle doit être déplacé soit le barycentre soit les jambes. Dx et Mx sont en revanche des variables de commodité qui, nous le verrons, sont utilisées pendant l’exécution du mouvement.
Ensuite, après l’initialisation de certains paramètres, sont définies les tables de mouvements. Quatre tables sont présentes : elles indiquent quelles actions à accomplir pour exécuter la marche avant, le recul, la rotation à gauche et à droite. Les constantes BS, BD, GS, etc., indiquent barycentre à gauche, barycentre à droite, jambe gauche en avant, etc. La constante xx est en revanche utilisée pour indiquer la fin de chaque mouvement.
Alors le programme commence : après avoir émis un son de “start”, les deux servomoteurs (subroutine Mise à 0) sont centrés. La présence des obstacles à droite et à gauche est ensuite testée, la technique utilisée est la même que pour l’exemple précédent.
En fonction des résultats de ces tests, il est calculé quel mouvement doit être exécuté : la variable Action est utilisée justement pour indiquer comment se déplacer. Si on a Action=0, cela signifie qu’aucun obstacle n’est présent (le mouvement en avant continue), si on a Action=1, cela signifie qu’il y a un obstacle à gauche, etc. Alors en VarAnd est écrite la valeur de Action, mais avec mise à zéro des 6 premiers bits.
A travers l’instruction suivante “LookUp” est écrite dans la variable Mx l’adresse de l’opération à exécuter. Si en effet VarAnd=0, en Mx est écrite l’adresse de l’étiquette Avancer. Pour VarAnd=1, en Mx est écrite l’adresse de l’étiquette TournerRaideDroite, etc.
Rappelons que ces étiquettes représentent les tables de mouvements définies préalablement. Alors, à travers la subroutine Mouvement, l’opération est exécutée et, à travers le saut à Début, le cycle recommence à l’infini.
Passons donc à l’analyse de la subroutine Mouvement : elle exécute l’opération en utilisant la table de mouvements indiquée par la variable Mx.
En Dx est écrite la première action à accomplir, ensuite Mx est augmenté de manière à passer à l’action suivante.
On vérifie que Dx=xx (ce qui, rappelons-le, est la condition de fin d’opération), dans ce cas on saute à MouvementOK où, à travers l’instruction “return” on retourne au cycle principal, sinon on saute à la subroutine Déplacés à laquelle est dévolue l’action.
Ensuite, on retourne à l’étiquette Mouvement : l’action suivante est lue et le cycle continue jusqu’à ce que soit lue la valeur xx.
Analysons maintenant comment sont exécutées les actions à l’intérieur de la subroutine Déplacés : initialement, par l’intermédiaire de l’instruction “Branch” on saute au point correct du code. Si, en effet, Dx=0, on saute à BarycentreGauche, si Dx=1, on saute à BarycentreCentre, si Dx=2, on saute à BarycentreDroite, etc. Rappelons que Dx contient une parmi les 6 codes possibles définis au début du programme (BS=0; BC=1; BD=2; etc.). Analysons par exemple le cas Dx=0, soit le saut à BarycentreGauche : on le voit, la variable NouvelleValeur, égale à Barycentre-Gauche (indiquant la position à donner au servomoteur 1), est paramétrée et un saut à la subroutine MouvementBarycentre est exécuté.
A l’intérieur de celle-ci, par l’intermédiaire d’un cycle “for” et de l’instruction “PulsOut”, le servomoteur du barycentre est positionné et la NouvelleValeur est sauvegardée à l’intérieur de BarycentreActuel. On note à l’intérieur de ce cycle “for” que la position du servomoteur 2 (celui des jambes) n’est pas modifiée (la variable JambeActuelle est utilisée). Comme nous avons vu le cas de BarycentreGauche, le fonctionnement des autres cas (BarycentreCentre et BarycentreDroite) devrait être clair aussi.
En revanche, voyons maintenant le cas où on doit exécuter le mouvement des jambes : par exemple, considérons le cas où DX=3, soit le saut à JambeGauche.
Dans ce cas, dans la variable NouvelleValeur est insérée JambeGauche et l’on saute donc à la subroutine MouvementJambe.
La logique de fonctionnement de cette subroutine est égale à MouvementBarycentre. Naturellement, à l’intérieur du cycle “for”, la position du servomoteur 2 (justement, celui commandant les jambes) est modifiée, alors que le servomoteur du barycentre est maintenu à la position actuelle. Ici aussi, si l’on a compris la logique de JambeGauche, le fonctionnement de JambeCentre et de JambeDroite devrait être clair.
L’analyse du “listing” est terminée : en effet, ce dernier programme est assez complexe, si malgré tout vous réussissez à comprendre les instructions “LookUp” et “Branch” et comment utiliser et adresser les différentes actions mémorisées à l’intérieur des tables de mouvements, il ne devrait pas être difficile pour vous d’augmenter les fonctions de Filippo.
Dans cette perspective, nous vous rappelons qu’il est possible, avec deux connecteurs d’extension SV1 et JP13/JP14/JP15, de superposer à la carte-mère d’autres platines supplémentaires, de façon à ajouter de nouveaux composants au système. Si, grâce à cet article et à ceux consacrés à Car-Bot, vous avez compris comment on peut gérer des périphériques externes, vous serez capables d’interagir aussi avec ces nouveaux éléments.

Figure 5 : Mouvement avec détection et évitement des obstacles.
LISTING
‘***********************************************************************************
‘ * Nom : PasIR *
‘ * Proces. : PIC16F876 *
‘ * Note : Marche et évite les obstacles avec capteurs IR *
‘***********************************************************************************

‘-----[ Définitions ]---------------------------------------------------------------
DEFINE LOADER_USED 1 ‘Utilisé pour boot-loader
DEFINE OSC 20 ‘Paramètre Clock à 20MHz

‘-----[ Définitions configuration ports ]-------------------------------------------
ADCON1 = 000111 ‘Port A = Numérique

‘-----[ Vers Ports ]----------------------------------------------------------------
TRISA = 110000 ‘Paramètre pin 4,5 Port A..
‘..en Input; autres Output
TRISB = 000000 ‘Paramètre pin Port B tous..
‘..en Output
TRISC = 000011 ‘Paramètre pin 0,1 Port C..
‘..en Input; autres Output

‘-----[ Définitions I/O ]-----------------------------------------------------------
Servo1 VAR PORTB.2 ‘Port Servo 1 Barycentre
Servo2 VAR PORTB.1 ‘Port Servo 2 Jambes
Speaker VAR PORTA.1 ‘Port Speaker
IR_1 VAR PORTC.1 ‘Port Récepteur IR
IFR_1 VAR PORTC.5 ‘Port Infrarouges droit
IFR_2 VAR PORTC.2 ‘Port Infrarouges gauche

‘-----[ Définitions Variables ]-----------------------------------------------------
Mcount VAR BYTE ‘Loop pour mouvements
Icount VAR WORD ‘Loop pour impulsions
BarycentreActuel VAR WORD
JambeActuelle VAR WORD
NouvelleValeur VAR WORD
Dx VAR BYTE ‘Utilisé pour lire l’action
Mx VAR BYTE ‘Indique quelle action est exécutée
IR_det_Gauche VAR BIT ‘Variables où sauvegarder..
IR_det_Droite VAR BIT ‘..la valeur des capteurs IR
Action VAR BYTE
VarAnd VAR BYTE ‘Variable pour and logique
Note VAR BYTE ‘Note pour sound

‘-----[ Définitions Constantes ]----------------------------------------------------
Durée CON 50 ‘Durée Note pour Sound
Retard CON 25 ‘Pause pour PULSOUT
Pas_Barycentre CON 10 ‘Pas pour cycle Barycentre
Barycentre_Droite CON 650 ‘Limites Barycentre
Barycentre_Centre CON 750
Baricentre_Gauche CON 850
Pas_Jambe CON 15 ‘Pas pour cycle Jambes
Jambe_Droite CON 600 ‘Limites Jambes
Jambe_Centre CON 750
Jambe_Gauche CON 900
BS CON 0 ‘Barycentre Gauche
BC CON 1 ‘Barycentre Centre
BD CON 2 ‘Barycentre Droite
GS CON 3 ‘Jambe Gauche
GC CON 4 ‘Jambe Centre
GD CON 5 ‘Jambe Droite
xx CON 255 ‘Fin table

‘-----[ Initialisation ]------------------------------------------------------------
PORTA =0
PORTB =0
PORTC =0
IR_det_Gauche = 0
IR_det_Droite = 0
Note = 0
VarAnd = 0

‘-----[ Table des mouvements ]------------------------------------------------------
Avance Data BD, GS, BS, GD, xx
Recule Data BD, GD, BS, GS, xx

TourneRaideGauche Data BS, GD, BC, GS, BD, GD, BC, GS, BS,..
‘..GD, BC, GS, BD, GD, BC, GS, xx

TourneRaideDroite Data BS, GS, BC, GD, BD, GS, BC, GD, BS,..
‘..GS, BC, GD, BD, GS, BC, GD, xx

‘-----[ Début programme ]-----------------------------------------------------------
Note = 100 ‘Exécuter son de..
GoSub Son ‘..début programme
GoSub Mise à 0 ‘Centrer les deux servomoteurs

Début :

‘Test présence des obstacles sur la Gauche
High IFR_2 ‘Activer TRX IR de Gauche
Pause 1
IR_det_Gauche = IR_1 ‘Lecture état récepteur IR
Low IFR_2 ‘Désactiver TRX IR de Gauche

IF IR_det_Gauche = 0 Then ‘Si obstacle à Gauche ..
Nota = 10 ‘..émettre son
GoSub Son
EndIF

‘Test présence des obstacles sur la Droite
High IFR_1 ‘Activer TRX IR de Droite
Pause 1
IR_det_Droite = IR_1 ‘Lecture état récepteur IR
Low IFR_1 ‘Désactiver TRX IR de Droite

IF IR_det_Droite = 0 Then ‘Si obstacle à Droite..
Note = 100 ‘..émettre son
GoSub Son
EndIF

‘Sur l’état de IR_droite et IR_gauche..
‘..calculer quelle Action exécuter
Action = 0 ‘Mise à 0 Action
IF IR_det_Gauche = 1 Then cont1

Action = Action +1

cont1:
IF IR_det_Droite = 1 Then cont2

‘***********************************************************************************
‘ * Nom : Centrer les ServoMoteurs *
‘ * Proces. : PIC16F876 *
‘ * Note : Permet de centrer les 2 ServoMoteurs *
‘***********************************************************************************

‘------[ Définitions ]--------------------------------------------------------------
DEFINE LOADER_USED 1 ‘Utilisé pour boot-loader
DEFINE OSC 20 ‘Paramètre Clock à 20MHz
ADCON1 = 000111 ‘Port A = Numérique

‘------[ Vers Ports ]---------------------------------------------------------------
TRISB = 000000

‘---- -[ Définitions I/O ]----------------------------------------------------------
Servo1 VAR PORTB.2 ‘Port Servo 1
Servo2 VAR PORTB.1 ‘Port Servo 2

‘------[ Initialisation ]-----------------------------------------------------------
PORTB = 0

‘------[ Début programme ]----------------------------------------------------------
Début :
PulsOut Servo1, 753 ‘Centrer le Servo 1 avec
‘1506 us
PulsOut Servo2, 750 ‘Centrer le Servo 2 avec
‘1500 us
Pause 20 ‘Attendre 20 ms
GoTo Début
End


Figure 6 : Le “bootloader”.
Pour faire fonctionner toute la série de nos robots, il est nécessaire d’écrire un programme qui fasse faire au robot ce que nous voulons, dans la limite des ressources disponibles. Ce programme peut être écrit en n’importe quel langage, du Basic au C en passant par l’Assembleur, etc. Il doit être ensuite compilé de manière à obtenir le fichier .HEX adapté à la mémorisation par le microcontrôleur. Nous expliquons ici comment ce fichier peut être chargé dans le microcontrôleur.
Normalement, cette opération s’effectue en utilisant un programmateur matériel adapté dans lequel le microcontrôleur est physiquement inséré. Toutefois, pour rendre plus facile cette opération, notre carte-mère prévoit un système de programmation “in-circuit” permettant de ne pas déposer le microcontrôleur de sa platine. En fait, la programmation se fait directement à partir du PC par l’intermédiaire du port sériel connecté à la prise DB9 de la carte-mère du robot.
Pour ce faire, il est nécessaire d’utiliser un système spécial de programmation appelé “bootloader” : ce système prévoit l’utilisation d’un logiciel spécifique (PICdownloader.exe) permettant de charger dans le microcontrôleur les programmes que nous avons développés (au format .HEX) par l’intermédiaire du port sériel. Cela est possible uniquement si on a préalablement chargé dans le microcontrôleur un bref programme de support (bootldr20Mhz-19200bps.hex) logé dans les premières cellules de mémoire : ce logiciel, bien sûr, doit être chargé avec un programmateur normal. Cependant, le microcontrôleur contenant déjà ce mini programme (“firmware”) est disponible.
Voyons donc comment utiliser le “bootloader” : avant tout il est nécessaire de charger le programme PICdownloader.exe sur le site de la revue, ensuite ce programme doit être installé sur votre PC. Alors, par l’intermédiaire d’un compilateur adéquat, vous devez produire un fichier au format .HEX de votre programme et, grâce au PICdownloader, le charger dans l’EEPROM du PIC présent sur la carte-mère.
Pour de plus amples informations sur les opérations à exécuter, nous vous renvoyons aux précédents articles sur les robots, rubrique “ Comment charger les programmes” : vous y trouverez des détails sur les étapes nécessaires à l’installation du programme sur PC et le chargement des fichiers .HEX à l’intérieur du microcontrôleur.

Figure 7 : Utilisation pratique.
On l’a vu dans l’article, les servomoteurs sont commandés par le paramètre “Period” de la fonction “PulsOut”. Nous avons déjà expliqué que pour des valeurs de “Period” de 900 ou 600 l’axe se place complètement dans un sens ou complètement dans l’autre, alors que pour une “Period” de 750, l’axe se place au centre. Ces valeurs ont été calculées théoriquement en partant de la formule T = 2.10-6.Period : si l’on remplace Inversement par les durées désirées, on obtient les valeurs correspondantes de “Period”. En réalité, dans l’utilisation pratique, les tolérances interviennent. Par exemple, au cours de nos tests, il nous est arrivé que pour une “Period” de 750 les deux moteurs ne fussent pas en position centrale, mais celui du barycentre était décalé d’un angle minimum. Nous avons donc dû centrer les deux moteurs (au moyen du “listing” ci-dessous), en trouvant que le moteur des jambes était centré pour une “Period” de 750 et celui du barycentre de 753. On le voit, ces variations sont minimes, elles relèvent des tolérances habituelles en électronique et dans ce cas elles ont pu être résolues par un procédé logiciel.

Conclusion
Pour conclure, nous vous rappelons que les codes originaux écrits en Basic des logiciels présentés dans cet article et des futurs programmes sont téléchargeables sur le site de la revue sous forme de fichier avec extension .bas, donc directement chargeables par le compilateur Basic et transférables dans le PIC au moyen du port sériel et grâce au “bootloader». Ultime suggestion : vous pouvez utiliser ces codes comme base à partir de laquelle écrire vos nouveaux programmes de gestion du robot.

Fin.

Trois robots de grande taille à construire et à programmer
Premier robot "CarBot" (Première partie)
Premier robot "CarBot" (Deuxième partie)
Deuxième robot "Filippo" (Première partie)
Troisième robot "Spider" (Première partie)
Troisième robot "Spider" (Deuxième partie)

À Découvrir

Schema Electronique