vendredi 29 novembre 2013

surprise et perplexité.

J'étais en train d'écrire une routine de division en assembleur sur PIC32MX lorsque j'ai réalisé que le core MIPS M4K n'a pas de registre d'état. Ça fait des mois que je travaille avec des PIC32MX et jusque là je n'avais pas porté attention à ce fait. En réalité c'est le seul processeur que je connais qui n'en possède pas et j'en ai vu pas mal ces 40 dernières années. Comme cette routine de division utilise un décalage vers la gauche sur 2 mots de 32 bits j'étais un peut perplexe. En effet habituellement lorsqu'on fait un décalage à gauche ou à droite sur plusieurs mots on utilise une instruction qui récupère le bit qui sort dans le carry bit et de là on le récupère pour le faire entrer dans le mot suivant. C'est du moins comme ça que ça se passe sur la majorité des micro-processeurs. J'ai donc du adapter ma routine en vérifiant l'état du bit avant de faire le décalage et faire un branchement conditionnel en fonction de l'état de ce bit. La routine nécessite donc plus d'instructions que sur un processeur ARM par exemple qui laisse le dernier bit sorti dans carry bit du registre d'état.

C'est encore une preuve que les habitudes nous rendent aveugle. Ce n'est pas que je n'avais pas étudier le modèle de programmation du core M4K mais je prenais pour acquis que tout processeur à un registre d'état ce qui fait que cette absence n'était pas passé au niveau conscient puisqu'il n'avais pas été requis dans ma programmation jusque là.

présentation des PIC24

Dans cette article je fais une brève présentation des micro-contrôleurs PIC24 de Microchip.

Architecture

Comme les autres PIC les PIC24 sont basés sur une architecture Harvard mais là s'arrête la ressemblance. Il s'agit de micro-contrôleurs 16 bits avec 16 registres généraux. Ils possèdent un multiplicateur en hardware ainsi qu'un support à la division.

Structure interne

Le compteur ordinal a 23 bits. Les instructions son encodées sur 24 bits et le compteur peut adresser 4Mi. Notez cependant que le bit le plus faible du compteur ordinal est toujours à zéro, les adresses impaires ne peuvent-être accédées. La mémoire est organisé en mots de 24 bits mais l'alignement du compteur ordinal se fait comme s'il s'agissait de 2 mots de 16 bits. Donc dans les faits le compteur ordinal est incrémenté de 2 à chaque instruction. Il n'y a pas d'octets perdus cependant car l'octet le plus lourd (bits 24-32) n'est pas implémenté en mémoire. Cette arrangement est pour rendre comptable l'adressage avec la mémoire RAM qui elle est organisée en mots de 16 bits.

Les registres généraux sont nommés W0 à W15. W15 sert de pointeur de pile, celle-ci étant en mémoire RAM. IL y a un registre SPLIM qui détermine la taille de la pile. S'il y a débordement de la pile l'exception 3 stack error est déclenchée. Notez la présence du registre RCOUNT, c'est un compteur de boucle qui fonctionne avec l'instruction assembleur REPEAT. Cette instruction utilisée avec les instructions DIV.SD, DIV.SW, DIV.UD et DIV.UW permet de faire une division en seulement 19 cycles machine. Les boucles REPEAT sont limitées à une seule instruction, celle qui suis le REPEAT. Mais comme l'instruction MOV encode la source et la destination par indirection via registre auto-incrémenté, une seule instruction permet de copier un bloc de mémoire d'un endroit à un autre ou vers un SFR de périphérique.

Contrairement à la plupart des MCU à registres comme les AVR, MIPS ou MSP430, les PIC24 peuvent utiliser une donnée en mémoire RAM comme argument d'une opération ALU, dans ce cas W0 alias WREG est utilisé comme autre argument. Le résultat peut-être enregistré dans WREG ou la variable en RAM. Ce type d'instruction même s'il exige une lecture et possiblement une écriture dans la RAM s'exécute en un seul cycle. Comme pour les PIC32MX les instructions à 3 arguments sont aussi possible comme ADD Wb,Ws,Wd qui additionne le contenu de Wb avec Ws et met le résultat dans Wd.

Interruptions

Les interruptions multi-niveaux sont supportées. Il y a 2 tables de vecteurs d'interruptions contenant chacune 126 entrée. Les 8 premières entrées sont réservés aux exceptions (trap). Ces tables commencent à l'adresse 0x000004 et se terminent à l'adresse 0x000200. L'interruption 0 est à l'adresse 0x14 pour la table principale et 0x114 pour la table alternative. Chaque table occupe 256 octets incluant les trap et le reset vector. La table alternative sert au débogage. Chaque entrée de table contient une adresse de 24 bits qui est le point d'entrée de l'ISR servant le vecteur correspondant. La priorité d'interruption est par ordre inverse du numéro de vecteur. Le vecteur 0 a la plus haute priorité et le 117 la plus faible.

Modèle de programmation

Programme démo en C

Plusieurs modèles de PIC24 sont disponibles en format PDIP-14, PDIP-20 et PDIP-28. Pour ce démo j'ai choisi un PIC24F16KA101-I/P ainsi qu'une matrice de LED 8x8. La matrice de LEDs est organisée en 8 lignes par 8 colonnes. Les cathodes sont connectées sur les colonnes et les anodes sur les lignes. Le PIC24F16KA101 possède 16Ko de mémoire flash et 1,5Ko de RAM et les périphériques qu'on retrouve le plus souvent sur un MCU, minuteries, convertisseur A/N, UART, I2C. Il fonctionne à une fréquence maximale de 32Mhz. Il peut-être programmé avec un PICKIT 2.

L'environnement de développement est MPLABX avec le compilateur XC16 disponible en version gratuite avec optimisation de code limité comme c'est l'habitude chez Microchip.

Le démo est une implémentation de l'automate cellulaire appelé Jeux de la vie. Le démo joue 3 configurations en séquence. Il passe à la configuration suivante après 16 générations. C'est la variable max_gen qui détermine le nombre de générations calculées pour chaque configuration initiale.

schématique

La grille de LED est multiplexé 1 LED à la fois. Le rapport cyclique de chaque LED est donc de 1/64 on obtient néanmoins une intensité d'affichage satisfaisante. Pour ne pas interrompre le multiplexeur d'affichage le calcul de la génération suivante est intercalé dans le multiplexeur par appel de la fonction next_gen(). Une seule cellule est recalculée par appel. Il y a 2 tableaux contenant l'état de l'univers, lifea et lifeb. Tandis qu'un tableau est affiché le calcul de la génération suivante est enregistré dans l'autre. La variable grid détermine quel est le tableau à afficher. Le tableau est commuté à tous les 100 cycles du multiplexeur d'affichage (variable k dans display_grid()). Ce délais donne un peu plus 0,5 seconde entre chaque commutation.

Pour la Configuration bits settings j'ai procédé comme je le fais avec les PIC32MX. C'est à dire que j'utilise le menu Window - PIC memory views - configuration bits. Après avoir configuré les bits dans cette grille j'utilise le bouton generate source code to Output et ensuite un copier-coller vers mon fichier source.

Pour ce démo le MCU fonctionne à 8Mhz sur l'oscillateur interne mais cette fréquence peut-être augmentée à 32Mhz grâce au PLL inclus dans le MCU.

Code source du démo

Vidéo du démo

Conclusion

Dans un prochain article je vais présenter un démo en assembleur.

dimanche 24 novembre 2013

moteur pas à pas

Dans cette article j'explique comment contrôler un moteur pas à pas . Pour ce démo j'ai utilisé un MSP430 launchpad et un C.I. L293D pour piloter le moteur. Comme moteur j'ai utilisé le mécanisme de transport de la tête de lecture d'un graveur de CD. On retrouve aussi le même type de mécanisme dans les lecteurs de disquettes.

schématique

Le moteur a 2 bobines et comme illustré ci-haut. Il s'agit d'un moteur bipolaire il y a donc 4 connections au moteur. Sur les moteurs unipolaire il y a en 6.

Description

En fait le programme pour contrôler un moteur pas à pas est simple. On a besoin d'un pont H pour chaque bobine et c'est le L293D qui contient 4 demi-pont H qui est utilisé dans ce but. Lorsqu'on alimente une bobine le rotor s'aligne sur le champ magnétique créé par la bobine. Si on alimente les 2 bobines en même temps le champ magnétique résultant est entre les 2 bobines et le rotor s'aligne donc entre celle-ci. Donc pour déplacé le rotor on déplace le champ magnétique du stator en alimentant alternativement les bobines.

Il y a plusieurs façon d'alimenter un moteur pas à pas mais celle qui donne le plus petit angle de rotation à chaque pas est la suivante:

pasa1b1a2b2
1+5v0v0v0v
2+5v+5v0v0v
30v+5v0v0v
40v+5v+5v0v
50v0v+5v0v
60v0v+5v+5v
70v0v0v+5v
8+5v0v0v+5v
Pour faire tourner le moteur en continu dans un direction il suffit de répéter ces 8 pas en boucle et pour le faire tourner dans l'autre sens on les répète à l'envers c'est à dire de 8 à 1. J'ai branché les 4 fils des bobinages sur le même port (PORT1) de sorte qu'il suffit de conserver les valeurs pour chaque pas dans un tableau indicé par la phase. Il faut écrire la valeur correspondant à la phase ou le moteur est rendu dans P1OUT. La valeur de chaque nombre dans le tableau correspond aux étapes de cette table.

Un moteur pas à pas il n'y a pas de rétroaction comme pour le cerveau moteur donc on ne connaît pas la position du moteur. Il faut compter les pas et habituellement on utilise des commutateurs en fin de course pour indiquer que la limite est atteinte. Mais si la charge est trop grande et que le moteur glisse le compteur de pas n'est plus valide il faut voir à ce que la charge ne dépasse pas la capacité du moteur. Il faut aussi tenir compte de l'inertie. Plus la charge est grande plus le moteur va prendre de temps pour s'aligner sur la nouvelle position. Donc le délais de pas doit-être augmenter avec la charge. Comme au départ je ne connaissait pas les caractéristiques du moteur j'ai commencer les tests avec un délais long (50msec), pour le réduire progressivement jusqu'à 1msec. Mais à 1 msec le moteur vibre. A 2msec c'est parfais. Mais si je mettais une charge sur le chariot il faudrait probablement augmenter ce délais.

Pour ce démo j'ai simplement vérifier à quelle vitesse je pouvais déplacer le chariot de tête du graveur en envoyant 200 impulsions dans un sens et ensuite 200 dans l'autre.

déplacement lent, 50msec/pas déplacement rapide 2msec/pas.

Conclusion

Comme on le voie un pilote de moteur pas à pas c'est simple. Il serait facile d'adapter ça en assembleur pour n'importe quel microcontrôleur.

vendredi 15 novembre 2013

indicateur de voltage barre-graphe

IL y a 2 semaines je présentais une alimentation variable éconmique et je concluais l'article en disant que je songeais à ajouter un indicateur de voltage barre-graphe. C'est chose faite.

Schématique

Description

La barre de LEDs contients 10 LEDs qui sont branchées en Charlieplexing sur GP0,GP1,GP2 et GP5. GP4 est configuré en entrée analogique pour la lecture du voltage de sortie de l'alimentation qui varie de 1,25 à 5,5 volt. Le circuit a son propre régulateur de tension 5 volt (7805) branché à la sortie du pont redresseur de l'alimentation.

L'échelle progresse par échelon de 0,5volt mais la logique du code est conçu de sorte que si la valeur lue tombe entre 2 LEDs, ces deux LEDs sont allumées. On a donc environ 0,25 volt de résolution.

Le convertisseur A/N du PIC12F675 a 10 bits de résolution mais le programme utilise seulement les 8 bits les plus significatifs. Ici le calcul pour déterminer quel LED allumée en fonction de la lecture est une simple règle de 3. LED=Vi*10/256. Le programme fait la multiplication par 10 mais il n'est pas nécessaire de faire la division puisque la variable PRODHI contient déjà le résultat de cette division après la multiplication.

Code source

lundi 11 novembre 2013

LED blanche sur 3 volt version 2

Dans l'article précédent je présentais une façon d'augmenter le voltage d'une lampe de poche de 3 volt pour obtenir le maximum d'intensité avec une LED blanche fonctionnant à 120ma. Le circuit d'hier utilisait une inductance. Aujourd'hui je présente un autre type de circuit qui lui permet de doubler le voltage par pompe de charge. Ce type de circuit n'utilise pas d'inductance mais 2 condensateurs.

Principe de fonctionnement

Il s'agit de charger le condensateur C1 et ensuite de transférer la charge accumulée dans C1 vers C2. Comme si on remplissais une chaudière d'eau pour ensuite la vidée dans une autre dont le fond est percé afin de garder son niveau d'eau constant.

Dans la première phase on place le transistor Q2 en conduction de sorte que C1 se charge à travers la diode D1. On bloque Q1 lorsque C1 est chargé. De la même façon que lorsqu'on doit vider une chaudière dans une autre il faut la soulevée au dessus de la première, il faut soulevé le voltage sur l'électrode négative de C1 pour qu'il se vide dans C2. Pour ce faire on met le transistor Q2 en conduction de sorte que le l'électrode négative de C1 est maintenant branchée sur le +3 volt de la pile. Donc le voltage aux bornes de C1 s'additionne à celui de la batterie et l'énergie accumulée dans C1 est transférée dans C2 à travers D2. La diode D3 aide C2 à demeuré chargée à un voltage près de 3 volt de sorte que C1 n'a pas besoin de fournir autant d'énergie pour augmenter le voltage de C1.

Ce circuit nécessite plus de composants que le précédent mais si le courant tirée par la charge était inférieur à 10ma on pourrait brancher le négatif de C1 directement sur une sortie du PIC10F200. Le PIC10F200 pouvant drainer ou sourcer 20ma ça permet un courant de charge moyen de la moitié de cette valeur.

Ce circuit est moins efficace en terme de conversion de voltage. En effet le système inductif permet de monter le voltage beaucoup plus que du double. Sans charge sur le circuit inductif je mesurait 35 volt à la sortie. Par contre avec ce circuit je ne crains pas de griller la LED et je n'utilise donc pas de rétroaction.

voltages aux différents points du circuit.

Voltage au bornes de la LED avec une alimentation de 3 volt. Le voltage maximum est de 4,72 volt et descend à 4,48 volt entre chaque recharge pour un voltage moyen de 4,60 volt.


Voltage à la jonction de Q1 et Q2


Voltage à la jonction de C1 et D1.


voltage aux bornes de la résistance R3. Le courant dans la LED est donc 1,72/15=115ma.

code source

samedi 9 novembre 2013

LED blanche sur 3 volt

Voulant remplacé l'ampoule à incandescence par une LED blanche dans une lampe de poche fonctionnant sur 2 piles 1,5 volt il fallait pour obtenir l'intensité maximale de la LED rehaussé le voltage car une LED blanche donne son intensité maximale à 3,6 volt. La LED que j'ai utilisé consomme 120mA à 3,6 volt mais le courant tombe à 60ma à 3 volt donc seulement 50% de l'intensité et lorsque les piles faiblissent la chute de courant est encore plus rapide.

J'ai donc conçu le circuit suivant.


note: erreur sur le schéma, L1 est 27µH et non 270µH

Le code source pour faire fonctionner ça n'a que 13 instructions.

Fonctionnement

Il il s'agit d'un boost converter. Lorsque le transistor Q1 conduit le courant dans L1 augmente exponentiellement et avec le courant un champ magnétique est créé. Ce champ magnétique accumule l'énergie. Lorsque Q1 est bloqué le champ magnétique s'effondre ce qui a pour effet de créer un potentiel électrique aux bornes de L1 de polarité inverse à celui lorsque Q1 conduit. Ce voltage s'additionne donc à celui de l'alimentation et à travers la diode D1 charge le condensateur à un voltage supérieur à celui de l'alimentation. Il s'agit d'un transfert d'énergie du champ magnétique de l'inductance au champ électrique du condensateur.

Dans le premier circuit que j'ai fait je n'avais pas mis de contrôle du courant et j'ai brûlé une LED. J'ai donc modifié le circuit pour m'assurer que le courant qui circule dans la LED est limité. la résistance R3 en série avec la LED permet une rétroaction grossière mais néanmoins efficace. Le booster n'est activé que si GP1 est a 0 logique, alors le programme charge l'inductance et envoie une impulsion de boost au condensateur en bloquant Q1 après avoir chargé le champ magnétique de l'inductance. Ensuite le programme attend que le voltage sur GP1 retombe à 0 volt avant d'envoyer une autre impulsion de boost. Ça produit des pics de courant dans la LED mais ça ce fait à environ 50Khz trop rapide pour être perçu par l’œil et de plus R3 a été calculé pour que le courant moyen dans la LED ne dépasse pas les spécifications. Voici de quoi à l'air le voltage aux bornes de R3.

Alimentation à 3 volt. Courant moyen = 0,8v/6,8ohm = 117ma. Cette LED peut tolérée 120ma.
alimentation à 2,5 volt. Courant moyen = 0,66v/6,8ohm = 97ma.

montage

J'ai utilisé un petit morceau de protoboard et un MCU en format SOT23-6. Après avoir cassé le verre de l'ampoule à incandescence, j'ai collé le morceau de protoboard sur la base.

conclusion

L'ampoule à incandescence consommait plus de 500ma alors que la LED en consomme 120mA mettons 130mA pour le circuit au complet. La LED produit une lumière plus intense et sa durée de vie et plusieurs fois supérieure. Au coût actuel des piles je crois que ça valais la peine de faire cette modification. Cependant comme la LED est au bout du circuit imprimée et que la lampe de poche en question a une lentille au centre de la fenêtre la lampe produit maintenant un faisceau large au lieu d'un faisceau étroit. En effet la distance focale de la lentille a été calculé en tenant compte de la distance du filament hors le LED est beaucoup plus prêt de la lentille parce qu'elle est au bout du circuit imprimé et que ce dernier est plus long que l'ampoule originale. Je m'en doutais bien mais il m'était impossible de faire ce montage sur un circuit plus petit et en largeur il fallait que ça passe dans le trou de l'ampoule car la face avant est scellée.

jeudi 7 novembre 2013

alimentation variable économique

Voici une petite alimentation variable que j'ai fabriqué à très faible coût grâce à la récupération. Les seuls composants qui ne sont pas de récupération sont le potentiomètre 1K et son bouton, la LED ainsi que les 2 banana jack. Le boitier a été fabriquer à partir des morceaux de plastique récupéré d'une horloge pendule à pile. Le mouvement de l'horloge était dans ce qui m'a servi de base et la face frontale du boitier est un morceau découpé à l'extrémité d'une grande plaque de plastique qui était dernière le pendule. La majorité des composants électroniques ont été récupérés d'un adapteur AC/DC Radio Shack dont le fil était brisé et qui traînait sur une tablette depuis des années. J'ai dessoudé les composants du circuit imprimé original pour les ressouder sur un morceau de carte de prototypage de dimension plus approprié pour le montage sur cette base.

Spécifications de l'alimentation

  • variable de 1,25 à 5,5 volt
  • Courant maximum 500 ma
En utilisant un potentiomètre de 2 Kohm au lieu de 1 Kohm j'aurais pu faire monter le voltage jusqu'à 10Volt mais comme mon intention est d'utiliser celle-ci avec des montages de MCU je n'ai pas besoin de monter à plus de 5 volt. 500 ma c'est peu mais encore là les montages que je fais drainent rarement autant de courant.

Le schéma très simple utilise un régulateur LM317.
Je ne me suis pas donné la peine de fabriquer un couvercle pour couvrir le circuit.
La face frontale me plaît pour un morceau de plastique récupéré c'est pas si mal et le noir se mari bien avec le commutateur récupéré d'une vieille cafetière. À guauche de l'alimentation on aperçoit les 2 parties de la coquille de l'adapteur Radio Shack que j'ai éventré.

Ce qui manque à cette alimentation c'est un indicateur de voltage. Je dois brancher mon multimètre pour l'ajuster. Je songe à y ajouter un petite barre de LED à 10 segments contrôlé par un micro-processeur. J'aurais ainsi un afficheur avec une résolution de 0,5 volt.