Présentation
Cette carte à été réalisé à la base pour le projet Bleuette qui est un robot hexapode, qui possède 2 Servo-Moteurs par patte, soit un total de 12 Servo-Moteurs à gérer le plus précisément possible et bien sûr de manière totalement synchrone.
Pour ceux qui se demande de quoi je parle, cliquez sur le lien suivant pour en savoir plus sur les Servo-Moteurs.
En premier lieu, j'ai utilisé l'excellent programme de commande de 8 servos des Fribottes (je me suis d'ailleurs amusé à rajouté un système pour gérer la vitesse des servos, j'essaierai d'ici peu de faire une page dessus) qui permet en fait de piloter 64 servos avec l'aide de 8 pics 16F84. Je me suis rapidement trouvé avec un problème de taille, en effet, comment synchronisé toutes ces pattes en même temps, autrement dit, comment faire pour que par exemple, tous les servos se mettent au neutre exactement en même temps car l'envoie des ordres série au micro controleur est décomposé ainsi :
- On envoie un entête
- L'adresse de la carte
- Le numéro du servo moteur
- La position souahité
Lors d'envoie d'ordre de mise au neutre de toutes les pattes, il y avait un décalage entre la première patte recevant l'ordre de mise au neutre et la dernière patte. Il n'était donc pas possible de synchroniser précisément 12 pattes avec 2 pic 16F84, j'ai alors décidé de développer ma propre carte.
Caractéristiques :
- Commande de 24 Servo-Moteurs le plus précisément possible
- Position sur 8 bits (0 pour repos, et de 1 à 254, 255 étant réservé)
- Réception des trames série
- 3 modes de fonctionnement en réception
- SERVO_MODE_CMD_UNIT : La trame ne concerne qu'un seul et unique servo
- SERVO_MODE_CMD_MASK : Un masque de bit est envoyé et peu ainsi concerné un, plusieurs ou tous les servos en même temps
- SERVO_MODE_CMD_MASK_3BLOCK : 3 masques (3 octets) de bit suivi de 3 octets de position sont envoyés permettant d'envoyer plusieurs consignes différentes à plusieurs servos en une seul trame de 7 octets
- Pour le moment, uniquement en mode EXTENDED (impulsion comprise entre 400us et 2.4ms)
- Prix de revient dérisoire < 15€ (des modules du marché vendent des version pour piloter 20 servos à 50€)
Détail technique :
- uC : 18F452 @ 40Mhz (PLL active)
- Programmé en assembleur avec MPLAB
Todo :
- Gestion de la vitesse
- Réception des ordres I2C à la manières d'une mémoire série
- Optimiser la routine de tri
Software
Plusieurs méthodes existent pour commander plusieurs servos avec un seul micro controleur, ainsi, le programme des Fribottes à divisé les 20ms en 8, soit 2,5ms pour le traitement de la durée de l'impulsion, le chronogramme d'une telle méthode se trouve ci dessous :
On constate bien grâce au chronogramme que le servo dispose de 2.5ms (rectangle rouge) à chaque nouveau cycle de 20ms, ce qui est amplement suffisant pour effectuer divers traitements : lecture consigne courante, configuration du timer...etc...
Cette méthode est particulièrement bien adapté au traitement de 8 servos, on peut même passer à 10 servos avec cette méthode en perdant du débattement.
Malheureusement, il est simple de constater que cette méthode ne peut gérer 12 servos, voici donc un chronogramme d'une méthode radicalement différente qui nous permettra de commander autant de servos qu'on le souhaite, théoriquement bien sûr !
Comme le montre le chronogramme, toutes les impulsions partent au même moment, un atout indéniable pour avoir une parfaite synchronisation des servos.
Etant donné que les impulsions démarre en même temps et duront au minimum 400us (la plage s'étant de 400us à 2.4ms), il faudrait, une fois arrivé à 400us déterminé l'impulsion qui doit être arrêté en concordance avec sa consigne donc il faudrait lire toutes les consignes et chercher qui à la plus courte, en théorie, c'est possible, mais en pratique, c'est un vrai casse tête car notre micro controleur à beau tourner à 40Mhz, on n'aura jamais le temps de trié sans que ce soit préceptible sur les mouvements du servos ! La méthode logique est donc de trier les servos pendant la période d'inactivité des impulsions, c'est à dire quand elles sont toute à l'état bas !
Le traitement est divisé en 5 grandes phases :
- PHASE 1 "Tri & Préparation" : Dans cette phase, nous allons venir renseigner 3 tableaux en mémoire, le premier sera un tableau triés des consignes des servos, le deuxième tableau est un état des ports à chaque changement de consigne (séquence) et enfin un tableau contenant le nombre de port actif pour chaque séquence.Ensuite, nous allons préparer certaine variables et mettre à 1 les ports des servos
Exemple avec 4 servos : Consigne servo 0: 128, servo 1: 128, servo 2: 80, servo 3: 254
Voici les tableaux générés après le tri :
Tableau des consignes triées (FSR0)
Numéro de servo | Consigne |
---|---|
2 | 80 |
0 | 128 |
1 | 128 |
3 | 254 |
Tableau de l'état des ports (FSR1)
Num Sequences | Port3 | Port2 | Port1 | Port0 |
---|---|---|---|---|
1 | 0 | 1 | 0 | 0 |
2 | 0 | 0 | 1 | 1 |
3 | 1 | 0 | 0 | 0 |
A chaque changement de consignes et une fois le temps de la consigne passé, le tableau correpondant à la séquence en cours est envoyé au port du PIC.
Tableau des nombre de ports actifs (FSR2)
Num Sequences | Nombre de servos |
---|---|
1 | 1 |
2 | 2 |
3 | 1 |
Ce tableau permet de compter le nombre de servos passés à chaque séquence
- PHASE 2 "Servo(s) courant(s)" : Ici, on vient lire la consigne courante, le nombre de servos actifs...
- PHASE 3 "Comptage" : C'est ici qu'on vient faire la temporisation
- PHASE 4 : On vient éteindre les ports actifs de la séquence
- PHASE 5 : On sort de la boucle de gestion des timings et on y revient dans ~20ms
Déroulement du programme de temporisation, mise à jour des servos :
Cette manière de faire à de gros avantages, en effet, elle permet de se passer des choses prenant beaucoup de temps CPU entre 2 consignes, elle a tout de même un inconvénient, elle consomme tout de même beaucoup en temps CPU mais comme elle se fait avant la mise à 1 des ports des servos, elle n'est pas ressenti sur la présision du système. Pour ceux qui souhaitent en savoir plus, je leur conseil de lire les sources que j'ai essayé de commenté le plus possible.
Hardware
Cette carte possède un PIC18F452 au format DIP et est donc imposant, je mettrai d'ici peu une carte possédant un PIC au format PLCC voir dans un format plus petit pour faciliter l'intégration dans de petits montages.
Le schéma de principe :
Le schéma d'implantation :
Les fichiers originaux au format Eagle
Liste des composants :
Dénomination | Valeurs |
---|---|
C1, C2, C3, C4 | 100nf |
C10, C11 | 22pf |
R1,R2 | 1Kohm |
IC1 | PIC18F452P |
IC2 | MAX232 |
Q1 | 10mhz |
X1 | SubD9 Femelle |
SERVO0 à SERVO23 | Barette secable |
Mapping des ports :
bit7 | bit6 | bit5 | bit4 | bit3 | bit2 | bit1 | bit0 | |
---|---|---|---|---|---|---|---|---|
Servo 0 à 7 | RC2 | RC1 | RC0 | RA4 | RA3 | RA2 | RA1 | RA0 |
Servo 8 à 15 | RE1 | RE0 | RB5 | RB4 | RB3 | RB2 | RB1 | RB0 |
Servo 16 à 23 | RD7 | RD6 | RD5 | RD4 | RD3 | RD2 | RD1 | RD0 |
Les sorties RB6 et RB7 ne sont pas utilisés pour pouvoir garder une connectivité avec un éventuel module ICD.
Envoi de commande
Vous pouvez envoyer les commandes directement avec un autre PIC ou encore sous Window$ avec Hyper Terminal.
Pour cela, la connection RS232 doit être configuré en 9600b (oui, c'est beaucoup mais indispensable car le pic tourne à 40Mhz), 1bit de start, 1bit de stop. En mode SERVO_MODE_CMD_UNIT, il suffit d'envoyer 3 octets pour piloter UN seul servo :
- L'entête : 255
- Le numéro du servo : 0 à 23 (0 pour le premier servo, 23 pour le dernier bien sûr)
- La position voulue : 0 pour désactiver le servo, 1 à 254 pour la position (255 étant réservé)
Ainsi, pour mettre le servo 1 au neutre, il faut envoyer : 255 1 128
En mode SERVO_MODE_CMD_MASK, il faut envoyer un masque de bit :
- L'entête : 255
- Les 8 premiers servos (0 à 7)
- Les servos 8 à 15
- Les servos 16 à 23
- La position voulue : 0 pour désactiver le servo, 1 à 254 pour la position (255 étant réservé)
Pour mettre le servo 1 au neutre, il faut envoyer : 255 1 0 0 128 (en binaire : 11111111 00000001 00000000 00000000 10000000) Pour mettre tous les servos au neutre, il faut envoyer : 255 255 255 255 128 (en binaire : 11111111 11111111 11111111 11111111 10000000)
En mode SERVO_MODE_CMD_MASK_3BLOCK, il faut envoyer un masque de bit :
- L'entête : 255
- Les servos 16 à 23
- Les servos 8 à 15
- Les servos 0 à 7
- La position voulue des servos 16 à 23
- La position voulue des servos 8 à 15
- La position voulue des servos 0 à 7
Pour mettre le servo 1 au neutre, il faut envoyer : 255 0 0 1 0 0 128 (en binaire : 11111111 00000000 00000000 00000001 00000000 00000000 10000000) Pour mettre tous les servos au neutre, il faut envoyer : 255 255 255 255 128 128 128 (en binaire : 11111111 11111111 11111111 11111111 10000000 10000000 10000000)
Capture d'écran d'oscillo !
Voici 2 captures illustrant le principe de fonctionnement du programme, la première capture montre différentes consignes, à savoir : 0 pour le canal 1 (en jaune), 2 pour la canal 2 (en bleu), 128 pour le canal 3 (en violet) et enfin 255 pour le canal 4 en vert :
Enfin, dans cette seconde capture, toutes les consignes avaient été positionnées à 1 de manière à générer 400us, le canal 1 était connecté à SERVO0, le canal 2 à SERVO1, le canal 3 à SERVO22 et le canal 4 à SERVO23, on constate ainsi que l'erreur est inférieur à ~0.1us entre le premier servo et le dernier qui reçoit la consigne, ce qui était le but de ce montage.
Téléchargements
Ce programme est fourni sous les termes de la licence GNU General Public License
- Les sources complètent datées du 11 janvier 2006 (version 1.2) 24Servos-1.2.tar.gz
- Le .HEX seul datées du 11 janvier 2006 (version 1.2) 24Servos-1.2.hex
- changelog.txt