mardi 17 juillet 2012

pixdel version 2

Dernièrement j'ai travaillé sur l'idée du PIXDEL. J'ai modifié le code et construit 2 autres prototypes.

Celui-ci est le dernier prototype. J'ai soudé directement le PIC10F202-I/OT sur les pattes de la DEL RVB et sur le connecteur 3 broches. C'est le prototype le plus compact que je peut obtenir.
Voici pour comparaison les 3 versions.

En ce qui concerne le code, dans la première version, la réception d'une commande interrompait la tâche PWM qui contrôle la DEL, il y avait donc une altération de la luminosité à chaque réception d'une commande. J'ai corrigé ce défaut en multiplexant les 2 tâches. Le code est plus complexe mais le résultat plus satisfaisant. L'idée est que la boucle principale s'exécute en un temps constant de 52usec. Ce temps correspondant à la période d'incrémentation de la minuterie PWM et aussi à la moitié du temps de la période 1 bit reçu à 9600 BAUD. A chaque cycle de la bouche principale l'état de GP3 est vérifié pour voir si un START bit est reçu. Si oui on initialise les variables nécessaires à la réception de l'octet. 1 bit est lu a tous les 2 cycles de la boucle principale. toutes les tâches à l'intérieure de la boucle doivent-être complétées en moins de 52usec. Ce qui est possible dans la majorité des cas. Avec cette nouvelle version du code on ne perçoit pas de fluctuation de l'intensité de la DEL pendant la réception d'une commande. J'ai cependant du sacrifié la fonction transition pour réduire le temps d'exécution de la boucle principale à moins de 52 usec.


liens autre version du pixdel

mercredi 4 juillet 2012

servo-moteur 2, contrôle par ordinateur

Dans ma chronique précédente je décrivais comment contrôler un servo-moteur avec un PIC10F202 et 2 boutons momentanés. Le code n'occupait même pas 50% de l'espace programme il y avait donc de la place pour ajouter des fonctionnalités. J'ai ajouter la possibilité de contrôler le servo-moteur à partir d'un ordinateur via un port série. Pour réaliser ce projet il faut utiliser l'adapteur de niveau RS-232 décris dans cette chronique ou un équivalent.

code source MPASM

Tous les fichiers sont disponible ici.
l'idée principale est qu'il y avait encore plusieurs milli-secondes de disponibles entre 2 pulses de contrôle du servo-moteur pour permettre l'envoie et la réception de courts messages avec le protocole UART. les routines utilisées pour la communications UART sont, uart_send, uart_receive et la macro uart_bit_delay. Les commandes reçu du PC ont 3 octets. Le premier caractère défini la commande et les 2 octets qui suivent un nombre de micro-secondes en little indian1. Les commandes sont:

  • 'A' position, positionnement absolu
  • 'D' delta, rotation vers la droite
  • 'G' delta, rotation vers la gauche
position est une valeur en micro-secondes qui défini la nouvelle consigne du servo-moteur.
delta est le nombre de micro-secondes qu'il faut ajouter ou soustraire à la position actuelle pour obtenir la nouvelle consigne.
C'est la routine check_for_command qui traite la commande reçue.

Le micro-contrôleur ne peut pas recevoir des commandes à n'importe quel moment. Il doit donc informer le PC hôte lorsqu'il est prêt à recevoir une commande. Pour ce faire il envoie un caractère XON à l'hôte.
A la réception de ce message et à nul autre moment le PC doit envoyer une seule commande de 3 octets. Commande reçu ou pas à 18 millisecondes du début du cycle un caractère XOFF est envoyé à l'hôte pour l'informer de cesser toute transmission. le MCU est à l'écoute du PC pour une durée qui varie entre environ 15msec et 17msec à toutes les 20msec. Pour tester ce projet j'ai écris un programme en OpenEuphoria2. Il est disponible ici ce module est aussi nécessaire.

Le plus difficile a été d'ajuster le délais de bit pour la réception sur le MCU. En transmission en utilisant un oscilloscope on peut voir si le duré du bit est trop longue ou trop courte et faire l'ajustement nécessaire. Pour la réception on sais que le timing du signal reçu est bon mais c'est plus difficile d'évaluer le temps d'exécution de la routine de réception sur le MCU. Quoi qu'il en soit le résultat final fonctionne bien avec le programme test que j'ai écris.



NOTES:
1)Little indian signifit que l'octet de poids faible est précède celui de poids fort. Le contraire, poids fort en premier, est dit big indian.

2) OpenEuphoria est un language de programmation procédural développé dans les années 90 par Robert Craig de RDS. Depuis quelques années le projet est passé dans le domaine du logiciel libre. Euphoria possède un machine virtuelle pour exécuter le byte code intermédiaire mais aussi un convertisseur en 'C' qui permet de compiler les programmes en language machine.

dimanche 1 juillet 2012

contrôle d'un servo-moteur avec PIC10F202

Dans cette chronique je montre comment contrôler un servo-moteur avec un PIC10F202 et 2 boutons momentanés. matériel requis:

  • 1 PIC10F202-I/P
  • 2 boutons momentanés
  • 1 servo-moteur

Montage

J'ai découvert un logiciel très intéressant et gratuit, ça s'appelle Fritzing. J'ai réalisé le plan de montage suivant avec ce logiciel. Il fait plus que ca, il permet aussi de réaliser le schéma électronique et le circuit imprimé.

Pour mon montage j'ai utilisé ce que j'avais en main, un Hitec HS-422 mais n'importe quel autre servo-moteur devrait faire l'affaire. Si vous ne connaissez pas les servo-moteurs lisez l'encadré à la fin de cette article.

Description du code MPASM

Vous pouvez télécharger le code assembleur ici ou vous référez au code source ci-bas.

Certains MCU possèdent des circuits PWM dédiés ce n'est pas le cas du PIC10F202. De plus il ne supporte pas les interruptions sur son TIMER. Il faut donc tout faire en code. Si on veut que le servo-moteur conserve sa position il est important de respecter la durée et la fréquence des impulsions. C'est ce qu'on appelle une application temps réel. Mais il faut aussi lire les 2 boutons sans altérer le timing de la tâche qui contrôle le servo-moteur. Pour régler ce problème j'ai décider de faire la lecture des boutons seulement dans l'intervalle de temps entre 2 impulsions. On dispose durant cette interval de près de 20 milli-secondes pour faire la lecture des boutons et modifier la variable servo_pos si requis. La logique de la boucle principale est la suivante:

  1. Envoyer un impulsion de contrôle au servo-moteur
  2. Faire une lecture des boutons
  3. Vérifier si un bouton est enfoncé et le cas échéant modifier la variable servo_pos
  4. Attendre la fin du cycle de 20 milli-secondes
  5. Retourner à 1

La variable 16 bits servo_pwm compte les micro-secondes. Le cycle du servo-moteur est de 20 000 micro-secondes. Donc lorsque ce compteur atteint 20 000 le cycle est terminé et on retourne au début (point 1). Comme on ne peut pas incrémenter le compteur servo_pwm par code il faut utiliser le TIMER0 qui est configuré pour incrémenter à chaque micro-seconde. A intervalle régulier on prend le contenu du TIMER0 et on l'additionne à la variable servo_pwm et on réinitialise le TIMER0. Notez qu'on ne réinitialise pas TIMER0 à la valeur 0 car il y a des cycles perdus pendant l'exécution de la macro add_timer. De plus lorsqu'on écris dans le registre TMR0 il y a 3 Tcy de perdu. En tenant compte de tout ça on initialise le TIMER0 à 5. La variable servo_pos contient la valeur de consigne et détermine donc la largeur de l'impulsion. Lorsque servo_pwm atteint cette valeur on termine l'impulsion et on sort de la routine servo_pulse, c'est la fin de l'étape 1. On appelle la routine read_buttons (étape 2). Cette routine utilise un compteur d'annulation de rebonds pour chaque bouton. Cette routine incrémente le compteur btnx_cntr à chaque fois qu'elle détecte qu'un bouton est enfoncé et décrémente le compteur lorsque il est relâché. Lorsque le cmpte atteint la valeur BTN_TRIGGER l'indicateur du bouton F_BTNx_ACT est mis à 1. La routine check_for_rotate (étape 3) vérifie les indicateurs booléens des boutons. Si F_BTN1_ACT est à 1 la variable servo_pos est diminuée de 8 micro-secondes. si l'indicateur F_BTN2_ACT et à 1 la variable servo_pos est augmentée de 8 micro-secondes. La routine servo_cycle_end (étape 4) attends simplement la fin du cycle, soit que le compteur servo_pwm atteigne la valeur 20 000 et on retourne au début (étape 5) pour commencer un nouveau cycle.

code source


Qu'est-ce qu'un servo-moteur

Un servo-moteur contrairement à un moteur électrique utilisé par exemple dans une perceuse ne tourne pas continuellement lorsqu'il est alimenté. Il tourne d'un certain angle défini par la consigne et s'arrête. Si la consigne est modifiée, il tourne pour atteindre la position de la nouvelle consigne. Les servo-moteurs sont utilisés couramment en radio-contrôle et en robotique lorsqu'on veut contrôler la position d'un élément mécanique. Par exemple pour faire pivoter les roues avant d'une voiture téléguidée. Lorsqu'on ouvre le boitier d'un servo-moteur on retrouve les éléments suivants:
  • un moteur électrique
  • un engrenage réducteur
  • un potentiomètre relié à l'axe qui sort du boitier
  • un circuit électronique
Cet ensemble d'éléments s'appelle un asservissement. Le potentiomètre fixé à l'axe qui sort du boitier sert à mesurer l'erreur entre la position actuel de l'axe et la consigne. Le moteur arrête de tourner lorsque cette erreur devient nulle. Il y a 3 fils qui sortent du boitier, rouge, noir et jaune (ou blanc). Les 2 premiers sont pour l'alimentation électrique comme pour n'importe quel autre moteur. Le jaune sert à envoyer au servo-moteur la consigne qui contrôle sa position. Cette consigne se présente sous la forme d'impulsions électriques d'une durée qui varie autour de 1500 micro-secondes et qui se répètent 50 fois par seconde. La position de l'axe de sortie du servo-moteur dépend de la largeur des impulsions. Par exemple pour le Hitec HS-422, la rotation totale est de 180 degrés. Le point milieu est obtenu avec des impulsions de 1500 micro-secondes. Si on diminue la largeur des impulsions le servo tourne dans le sens anti-horaire. Si on augmente la largeur des impulsions il tourne dans le sens horaire. L'image suivante qui est une capture d'oscilloscope montre les impulsions envoyées sur le fil jaune du servo-moteur.
Lorsqu'on utilise un servo-moteur il est important de ne pas dépasser les limites pour les consignes car si l'axe atteint une butée avant que l'erreur ne soit rendu à zéro le moteur va continuer à être alimenté mais comme il ne peut tourné il tire un courant maximun. Si le servo-moteur est alimenté par une pile, ca va la vider rapidement et ça peut aussi brisé le servo-moteur. C'est pour ça que dans mon code j'ai défini 2 constantes SERVO_MIN et SERVO_MAX. Même si un des boutons est gardé enfoncé la variable servo_pos ne sortira pas de ces limites. Pour en savoir plus sur les servo-moteur consultez l'article de wikipedia