dimanche 22 décembre 2013

xmos startKIT

Au mois d'octobre via un lien sur le site hackaday.com j'ai découvert l'existence d'une compagnie localisée à Bristol (G.B.) et ses MCU xcore. Le lien faisait référence à ceci. A ce moment j'ai jeté un coup d'œil et j'ai lu la documentation de présentation des xcore. Je me suis dit alors que puisque la carte startKIT était offerte gratuitement je pouvais bien m'inscrire pour en avoir une.

Il y a quelques jours j'ai trouvé le startKIT dans ma boite à lettres. gracieuseté de XMOS, jeune compagnie fondée en 2005. Le marché des microcontrôleurs est déjà saturé d'offres et occupé par de gros joueurs. Quel sont les chances d'une startup de réussir dans ce domaine? Mais XMOS a maintenant plus de 8 ans et ils sont encore là. D'après leur site la croissance des ventes est de 30% semestre après semestre et ils ont trouvé des investisseurs prêt à y mettre 14 millions supplémentaire.

De tout évidence le produit a rencontré un besoin. Mais les géants du domaine ont surement remarqué son existence et je ne serais pas surpris de voir Microchip mettre en marché avant la fin de 2014 un produit en mesure de concurrencer les xcores. Il y a déjà des rumeurs à propos de PIC32 fonctionnant à 400Mhz et multi-cores. Après le multithread et multi-core sur les CPU d'usage général on l'a maintenant sur les MCU.

Qu'est-ce qui distingue les xcores?

Il sont multi-thread et muli-core (32 bits). La compagnie XMOS parle plutôt de multi-core logique et de tuile (tile). Les cores logiques ne sont pas des cores complets comme ceux du propeller de Parallax. Sure une tuile il peut y avoir jusqu'à 8 core logique mais il n'y a qu'une seule Unité Arithmétique et Logique (UAL). Un seul thread est en exécution à un moment donné. Un core logique n'est en fait qu'un ensemble de registres de sorte qu'il n'est pas nécessaire de sauvegarder les états en passant d'un thread à l'autre. Il n'y a donc pas de délais de commutation lorsque l'exécution passe d'un core logique à l'autre. Conceptuellement c'est très semblable à ce que Intel appelle le multi-thread sur ses CPU.

J'ai parlé de tuile (tile). Celle-ci est en fait un core complet, UAL, céduleur, mémoire RAM, minuterie, commutateur xCONNECT, accès aux périphériques, etc. Les xcores les plus puissants on jusqu'à 4 tuiles avec 8 cores logique chacune pour un total de 32 threads indépendants. Ces MCU ont une performance de 400 à 1000 MIPS/tuile dépendant des modèles.

Ce n'est pas la seule particularité des xcores. En autre les périphériques simples comme les UART, SPI, I2C et PWM sont définis en software. Au niveau hardware il n'y a que des sérialiseur et désérialiseur. Avec un MCU qui fonctionne à 500Mhz définir ces périphériques en software ne pose aucun problème. Pour les fonctions analogiques il y a un bloc ADC sur certains modèles. Le développeur n'a cependant pas à se tracasser avec la programmation de ces périphériques puisque XMOS les fournis gratuitement sous le nom générique xSOFTip.

xCONNECT

le xCONNECT est une autre particularité des MCU xcore. Il s'agit de lien de communication commutés entre tuiles, core et MCU. Il est donc possible de créer un réseau de MCU. Imaginez la puissance de calcul d'une carte avec 64 MCU xcore reliés en réseau. Les liens xCONNECT peuvent fonctionner en mode lent en utilisant 2 fils ou en mode rapide en utilisant 5 fils. Et je le rappelle il s'agit d'un réseau commuté. Chaque tuile possède un commutateur qui redirige les paquets au besoin à l'interne vers les cores et les autres tuiles mais aussi vers l'externe. Si vous avez envie de vous fabriquer une machine pour générer des bitcoins un réseau de xcore serait une solution intéressante.

startKIT

Pour en revenir au startKIT il s'agit d'une carte de 90mm X 50mm, avec un MCU XS1-A8A-64-FB96. Ce MCU possède une seule tuile avec 8 core logiques et un bloc convertisseur Analogique/numérique 10bits. La tuile contient 64Ko de RAM. Cette RAM contient programme et données. Il n'y a pas de mémoire flash sur ces MCU, les programmes sont enregistrés dans une mémoire flash externe avec interface SPI. Celle qui est sur la carte a une capacité de 256Ko et contient un programme démo préinstallé. Il y a un bootloader en ROM qui au démarrage du MCU charge en RAM le programme à partir de la flash SPI externe.

On retrouve sur la carte 11 LEDs dont 9 forment une grille 3x3. Un bouton momentané et 2 zone tactiles à 4 segments chacune, slide X et slide Y.

Au niveau de la connectique il y a un connecteur micro-USB qui sert à alimenter la carte, la programmer et la déboguer. Sur le côté opposé un il y a connecteur de type PCIe qui est utilisé avec des cartes vendu par XMOS. A côté du connecteur USB il y a 2 rangés de trous (J3) pour installer un connecteur compatible avec le Rasberry Pi. Il y a d'autres rangés de trous pour installer d'autre connecteurs J2 pour les entrées ADC, J8 pour les interfaces xCONNECT, J7 pour les GPIO et J6 pour les alimentations.

xTIMEcomposer studio

L'environnement de développement xTime composer studio est disponible gratuitement à condition de s'enregistrer. Il est basé sur Eclipse et fonctionne sous Windows, Mac et Linux.

A ce moment ci je n'ai encore rien programmé pour cette carte, j'en suis encore à lire la documentation et à me familiariser avec l'IDE. Je me demande encore ce que je vais faire avec une carte aussi puissante.

samedi 21 décembre 2013

générateur de nombre pseudo aléatoire

Je suis en train de lire A new kind of science de Stephen Wolfram. Au chapitre 4 il mentionne qu'il a fait l'expérience suivante.
soit un nombre entier N

  1. Si N est impaire on l'incrémente
  2. On multiplie N par 3 et on divise par 2
  3. On recommence à l'étape 1
C'est ce qu'on appelle une fonction itérative, la valeur de f(N)=f(N-1)*3/2

Wolfram mentionne que le bit le plus faible de cette fonction itérative est aléatoire. C'est à dire qu'il est impossible de prédire si le nombre à la position x de la suite de nombres générés par itération sera pair ou impaire.

Écrire une fonction pour multiplier un nombre par 3 pour ensuite le diviser par 2 est simple à réaliser même en assembleur sur un petit MCU comme le PIC10F200. Puisque les générateurs de nombres pseudo aléatoire sont très utiles en informatique j'ai voulu vérifier si je pouvais réellement obtenir une suite de bits aléatoires avec cette fonction. J'ai donc pris un PIC10F200 et un petit haut-parleur que j'ai branché sur GP2.

J'ai écris 4 versions de la fonction f(N)= f(N-1)*3/2 pour les de différentes grandeurs d'entiers, 8 bits, 16 bits, 24 bits et 32 bits.

façon simple de tester un PRNG

Pour vérifier si un PNRG est vraiment aléatoire il existe une méthode simple quoique pas très scientifique. On écoute la série de bits produits et si le son est du bruit blanc, (le bruit produit par une chute d'eau), alors le générateur est bon. Il ne faut pas distinguer de cycles dans le bruit produit. Seulement un shhhhhh uniforme.

Donc la boucle principale du programme appelle la fonction itérative et vérifie si le résultat est pair ou impaire. Si c'est pair la sortie GP2 est mise à 1 sinon elle est mise à zéro. Le TIMER0 est utiliser pour créer un délais entre chaque appel de la fonction itérative pour que le spectre sonore soit dans l'audible.

Résultat

  • fn_iter8b. Mauvais on a l'impression d'entendre une seule tonalité
  • fn_iter16b. Mieux mais encore mauvais. On entend une tonalité mais il y a du chirp.
  • fn_iter24b. Beaucoup mieux. Beaucoup de bruit blanc mais lorsqu'on est attentif on détecte des cycles. Bon pour une application pas trop exigeante.
  • fn_iter32b. Très bien. Qualité suffisante pour des jeux vidéo ou autres application non critique.

J'ai aussi tester la fonction lfsr_rand que j'ai utilisé pour la chandelle électronique. Le résultat est presque aussi bon que pour fn_iter32b. L'avantage du lfsr_prng est qu'il nécessite moins d'instructions. Disons que sur un MCU 16 ou 32 bits fn_iter32b serait un bon choix car le nombre d'instructions nécessaires serait réduit de 50% ou moins.

code source

jeudi 19 décembre 2013

LED scintillante

Cet article fait suite au précédent intitulé chandelle électronique. Ce matin je me suis mis dans la tête de fabriquer une LED scintillante aussi ressemblante que possible à celles made in China. Je suis plutôt satisfait du résultat. Voici donc les instructions pour sa fabrication.

Le matériel nécessaire est réduit un PIC10F200 en format SOT23-6 et une LED 5mm (T1-3/4).

  1. programmation du PIC10F200, méthode de l'araignée. Soudez 5 fils sur les pattes 1,2,3,5 et 6. En vous servant de pinces de test dont l'autre extrémité est terminé par un broche qui peut-être insérée dans le connecteur du PICKIT 2 ou 3, reliez les fils au programmeur.
  2. Lorsque la programamtion est complétée, coupez les broches 1,3,6 du PIC10F200 à raz le boitiez et dessoudez des broches les autres fils. Ensuite coincez la LED à l'envers dans une pince et posez le PIC10F200 sur la base de la LED avec la broche 4 (GP2) en contact avec l'anode. La broche 2 (Vss) en contact avec la cathode. Soudez ces 2 broches.
  3. Coupez le fil d'anode de la LED juste au dessus de la soudure, conservez le bout de fil. Si vous avez un forêt de 0,7mm ou moins, percez un petit trou peut profond juste à côté de la broche Vdd. Entrez l'extrémité du fil coupé dans ce trou. Si vous n'avez pas fait de trou ce n'est pas essentiel, appuyez simplement le fil sur le côté de la broche Vdd et maintenez la en place avec du ruban adhésif. Soudez le fil à la broche Vdd.
    C'est terminé pour la soudure le résultat est le suivant.
  4. Solidifiez ça avec de l'époxy. Enroulez du ruban adhésif tout le tour du corps de la LED en le laissant dépasser de la base pour former un cavité qui va accueillir l'époxy. Remplissez la cavité d'époxy.
  5. Lorsque l'époxy est séchée enlevez le ruban adhésif et le travail est terminé. Assurez-vous que la broche soudée sur Vss est plus courte que celle sur Vdd. C'est la méthode habituelle pour identifier le négatif des LED. Le travail est terminé il ne reste qu'à brancher ça sur une alimentation 3 à 5 volt DC.
    Si on regarde la LED par le dessus, à moins de faire très attention, on ne se rend pas compte que la LED a été modifiée.

Court vidéo pour conclure ça.

lundi 16 décembre 2013

chandelle électronique

Ce matin je suis tombé sur cet article. L'auteur de ce blog a analysé le signal d'une chandelle électronique afin de reproduire l'algorithme. Une chandelle électronique est en fait une LED dont l'intensité varie de façon aléatoire de manière à imiter le scintillement d'une vrai chandelle. Je n'ai jamais utiliser une telle LED j'étais donc curieux de voir de quoi il en retourne. J'ai donc examiner le code de l'auteur du blog cpldcpu. Le code est écris en 'C' pour un ATtiny mais je me suis dis que c'était un projet idéal à exécuter sur le plus simple et économique des MCU disponible sur le marché, soit le PIC10F200. En m'inspirant du code source original j'ai écris ma propre version en MPASM pour le PIC10F200. Rien de plus simple comme montage, un PIC10F200 avec une LED jaune directement branchée sur la broche GP2.

J'ai utilisé le même PRNG basé sur un LFSR de 32 bits. Cependant j'ai fait 2 modifications. D'abord dans le code original il y a un bogue2, la variable randflag n'est jamais remise à zéro à l'intérieur de la boucle while. Donc une fois qu'elle a été mise à 1 elle y reste et devient inutile.

L'algorithme original autorise des fluctuations d'intensité pouvant descendre jusqu'à 25% (si le bogue est corrigé1 sinon ça peut descendre jusqu'à zéro). J'ai essayé ça mais je n'étais pas satisfait du résultat. Je trouvais les écarts d'intensité trop grand par rapport à une vrai chandelle. J'ai donc modifier le programme de la manière suivante. D'abord je me suis débarrassé de randflag qui est inutile dans ma version. Deuxièmement j'ai fait en sorte que le rapport cyclique du PWM varie de 50% à 100% au lieu de 25% à 100%. Je trouve ainsi que l'effet est plus ressemblant à une chandelle.

Code source en MPASM

On a donc une modulateur d'intensité pwm_control avec une résolution de 4 bits . L'intensité est contrôlée par variation du rapport cyclique d'une onde rectangulaire dont la fréquence est d'environ 440hz. On a un générateur de nombres pseudo aléatoire lfsr_rand. Pour cette application on ne garde que les 5 bits les moins significatifs qu'on conserve dans rand_val. Le délais pour contrôler la fréquence du modulateur PWM est assuré par la minuterie TIMER0. l'intensité de la LED est modifiée à tous les 32 cycles PWM par la variable frame_cntr qui est incrémentée modulo 32. Pour la valeur du rapport cyclique pwm_val on procède comme suis. Si la valeur de rand_val est inférieur à 16 on utilise la valeur maximale soit 15 (LED à intensité maximale). Si La valeur est >=16 on divise rand_val par 2 et on utilise cette valeur comme rapport cyclique. Donc statistiquement l'intensité de la LED devrait-être à son maximum 50% du temps et pour les 50% restant n'importe quelle valeur entre 50% et 100%.


1) pour corriger le bogue du code 'C' disponible sur github remplacez la ligne:

if ((RAND&0x0c)!=0) randflag=1; // only update if valid 
par
if ((RAND&0x0c)!=0) randflag=1;else randflag=0; 

2) 2013-12-17: J'ai passé le message à l'auteur concernant le bogue et il a fait la correction.

dimanche 15 décembre 2013

mise à jour firwmare cube 4x4x4

J'ai mis à jour le firwmare du PIC24F16KA101 qui contrôle le cube 4x4x4.
version 0.3

  • Les routines UART ne fonctionnaient pas bien il y avait des erreurs overrun à la réception.
  • Ajout de 3 animations supplémentaires.
  • À partir du PC l'interface UART permet de ralentir (s) et accélérer (f) les animations.
  • Les touches 1-4 permettent de passer d'une animation à l'autre.
    1. plane_sweep
    2. random_led
    3. drop
    4. running_led

code source

jeudi 12 décembre 2013

PIC24, les interruptions

Dans cet article je traite des interruptions sur les PIC24. A titre de démo je vais utiliser le cube de LEDs 4x4x4 présenté dans un article précédent. J'ai modifié le firmware de sorte que l'affichage du cube est maintenant géré par une une interruption. J'ai aussi ajouter une interface RS-232 en utilisant le périphérique UART1. La réception des caractères est aussi géré par une interruption.

Les interruptions sur PIC24/dsPIC30/dsPIC33 sont multi-niveaux avec priorité programmable. Multi-niveaux (nested en anglais) signifie qu'une interruption en cours peut-être interrompue par une autre de priorité supérieure. Lorsque l'interruption de niveau supérieur se termine l'exécution continu dans le code d'interruption de niveau inférieur qui a été interrompu. chaque table d'interruption (la principale et l'alternative) contient 126 vecteurs. C'est vecteurs sont des adresses qui correspondent au point d'entré de la routine qui sert l'interruption (ISR entry point). Les 8 premiers vecteurs servent a gérer les exceptions. En fait actuellement sur les PIC24 seulement 4 sont utilisés les autres sont réservés. Les 118 autres vecteurs sont pour les périphériques. Encore là plusieurs de ces vecteurs sont marqués comme reserved et donc inutilisés. La table des vecteurs est disponible dans le document suivant: répertoire_installation/microchip/xc16/v1.20/docs/IntVectors/PIC24F_Interrupt_Vectors.html.

Le système d'interruption des PIC24 fonctionne de façon très similaire à celui des PIC32MX on n'est donc pas dépaysé si on connais déjà ce dernier. Il y a cependant des différences, entre autre il n'y a pas de sous-priorité. Les niveaux de priorité sont de 0-15 pour le CPU mais les niveaux programmables par l'utilisateur sont de 0-7 car les niveaux 8-15 sont réservés aux exceptions (traps). La priorité est dans l'ordre numérique c'est à dire que la plus basse est 0 et la plus haute est 15. Ça peut sembler évident mais sur certains MCU c'est l'inverse.

Si 2 interruptions de priorité égales sont déclenchées en même temps c'est l'ordre dans la table des vecteurs qui détermine laquelle sera servie en premier, plus petit IRQ# en premier.

Le CPU ne réponds qu'aux interruptions de niveau supérieur au niveau pour lequel il est programmé. C'est à dire qu'il y a 3 bits dans le registre d'état (SR), IPL0, IPL1 et IPL2 qui contrôlent le niveau de réponse. le registre core control register (CORCON) contient un 4ième bit IPL4. Si IPL4 est réglé à 1 le CPU ne répond plus qu'aux exceptions. A la mise sous tension ou après un RESET matériel ou logiciel le niveau de réponse est à zéro.

Configuration des interruptions

Il y a plusieurs registres spéciaux associés à la configuration des interruptions:

  • INTCON1 Contrôle global des interruptions. Contient le bit NSTDI qui sert à activer/désactiver les interruptions multi-niveaux. Contient aussi les bits qui indiquent la source d'une exception.
  • INTCON2 Contient le bit ALTIVT. Lorsque ce bit est à 1 la table de vecteurs alternative est utilisée (débogage). Contient aussi le bit DISI qui indique que les interruptions sont temporairement désactivés pour un nombres de cycles déterminé par le contenu du registre DISICNT (utile dans les sections de code critiques). Contient aussi les bits INTnEP qui détermine la polarité de réponse des interruptions externes (transition positive/négative).
  • SRL<7:5> IPL2:IPL0 contrôle le niveau de réponse du CPU
  • CORCON<3> IPL3 contrôle le niveau de réponse du CPU
  • IECn ces SFR servent à activer/désactiver l'interruption sur un périphérique particulier. Chaque périphérique a 1 bit qui lui est assigné dans un de ces registres.
  • IPCn ces SFR servent à déterminer le niveau de priorité de l'interruption. Chaque périphérique a 3 bits qui lui sont assigné dans un de ces registres.
  • IFSn ces SFR servent d'indicateurs booléens pour les interruptions (interrupt flag). Chaque interruption a 1 bit qui lui est réservé dans 1 de ces registres.

Si on veut que le CPU réponde à toutes les interruptions on laisse les IPLx à zéro (valeur par défaut). Mais cette valeur peut-être modifier en cours d'exécution selon les besoins.

Pour configurer une interruption sur périphérique il faut:

  1. Déterminer à quel IPCn est associé le périphérique et programmer le niveau de priorité désiré. Niveau 4 par défaut.
  2. Déterminer à quel IFSn est associé le périphérique et remettre à zéro son bit IFS.
  3. Déterminer à quel IECn est associé le périphérique et mettre à 1 sont bit IE pour rendre active l'interruption.
Exemple: TIMER1, niveau d'interruption 7 (le plus élevé).

Création de la routine de service d'interruption

Les routines d'interruption (ISR) ne doivent avoir aucun arguments et ne retournent aucune valeur pour des raisons évident elles sont donc de la forme void isr(void). Pour qu'une fonction soit reconnue comme ISR ou gestionnaire d'exception il faut lui attribué l'attibut interrupt. Exemple:
L'attribut no_auto_psv réduit le préambule de l'interruption donc son délais de réponse (latency) en évitant la sauvegarde du registre PSV. Pour les MCU avec 16Ko de mémoire flash ou moins ce registre est toujours à zéro donc inutile de le sauvegarder. Même chose si l'application n'utilise pas la fonction program space visibility2.
Les indicateurs booléens d'interruptions ne sont pas remis à zéro automatiquement il faut le faire avant de quitter la routine ISR sinon l'interruption va se déclencher en boucle.

Il existe 2 macros pour simplifier la déclaration des routines d'interruptions:
_ISR
_ISRFAST
Dans l'exemple ci-haut j'aurais plus déclarer:
_ISRFAST _T1Interrupt(void);

Désactivation globale des interruptions

Contrairement aux autres MCU PIC, les PIC24 n'ont pas de bit GIE dans INTCON ou ailleurs. Pour désactiver les interruptions de niveau 0-6 temporairement ont peut utiliser l'instruction DISI en assembleur. Pour les désactiver de façon permanente on peut modifier le niveau de réponse du CPU avec la macro SET_CPU_IPL(ipl). En mettant ipl=7 toutes les interruptions sont désactivées.

Programme démo

Ajout d'une interface RS-232 au cube.

Ce démo utilise le cube de LED 4x4x4 avec la même animation que dans l'article de présentation du cube sauf que l'affichage du cube est dirigé par une interruption sur le TIMER1 à 200µsec d'intervalle. l'ensemble du cube est donc mise à jour environ 78 fois par seconde. De plus la variable anim_delay est incrémentée en boucle dans la même ISR et est utilisée pour contrôler la vitesse de défilement de l'animation. Avec la constante ANIM_DLY servant de modulo. Pour la valeur 1000 on a un intervalle 0,2 seconde entre chaque configuration. Le programme comprends en plus 2 autres interruptions, l'une pour la transmission des caractères sur UART1 et une autre pour la réception des caractères. Transmission et réception utilisent une file circulaire, rxbuff pour la réception et txbuff pour la transmission. A partir d'un ordinateur en utilisant un émulateur de terminal on peut arrêter l'animation en envoyant le caractère 's' et la redémarrer avec le caractère 'r'. Le MCU répond à chaque commande en envoyant le message " OK\n\r".


notes

1) Le family reference manual des PIC24F contients 66 sections disponibles ici.

2) la fonction program space visibility permet de rendre accessible en lecture une section de la mémoire flash en mémoire RAM. Cette fonction est utile lorsqu'il y a des tables de données en mémoire flash. Le registre PSVPAG détermine l'adresse de départ du segment flash à rendre visible dans la RAM. Cette adresse doit-être un multiple de 16Ko. Cette section sera visible dans la RAM à partir de l'adresse 0x8000. Lorsqu'on programme en 'C' le compilateur s'occupe de ces détails. Par exemple dans le démo ci-haut la chaîne de caractère " OK\n\r" est conservée en mémoire flash et le compilateur fait ce qu'il faut pour que UartPrint() puisse l'accéder via le program space visibility.

mardi 10 décembre 2013

Les mcu les plus vendus

Juste par curiosité j'ai entré dans Google l'expression most successfull mcu et j'ai obtenu parmis les résultats ceci. A la page 5 de cette article Microchip affirme avoir vendu 7 millard de MCU de la famille PIC16. Aucun autre vendeur n'affiche un nombre aussi élevé. Il faut dire que Microchip a été le premier sur le marché des MCU ce qui leur donne un énorme avantage car les ingénieurs ont tendance à se cantonner dans ce qu'ils connaissent déjà.

Ce qui m'a le plus surpris est le résultat du sondage auprès des lecteurs à la dernière page. Les PIC16 scorent moins de 10% alors que les MSP430 obtiennent le meilleur résultat à plus de 40%. Texas Instruments affirme avoir vendu 500 million de msp430 launchpad. Il faut dire qu'à moins de 5$ au moment de son lancement c'était difficile d'y résister même à 10$US c'est encore un bon prix. Ce fut un excellent coup de marketing de la part de TI. Depuis on voit les concurrents qui s'ingénient à les imiter en offrant des cartes à bas prix eux aussi. Tant mieux pour les hobbyistes que nous sommes.

lundi 9 décembre 2013

PIC24F16KA101 et MSP430G2553

J'ai consacré plusieurs articles sur ce blog au msp430 launchpad parce que je suis très enthousiasmé par ce produit considérant son prix. Mais à ce moment là je n'avais jamais travaillé avec les PIC24 et franchement ceux-ci me plaisent encore plus. Dans cette article je fais une comparaison entre les deux.

comparatif PIC24F16KA101 et MSP430G2553 format PDIP-20

paramètrePIC24F16KA101MSP430G2553
architecture16 bits Harvard modifiée16 bits Von Neumann
FLASH Ko1616
RAM bytes1536512
EEPROM bytes512256
(information memory)
Tcy nSec62,562,5
encodage24bits16bits
interruptionsmulti-niveaux,
priorité programmable
multin-iveaux
priorité fixe
multiplicationmatériellelogicielle
divisionmatérielle/logiciel 19Tcyentièrement logicielle
registres 16 bits16
2 réservés
stack (W15) et frame (W14)
16
4 réservés
compteur ordinal (R0)
états (R1)
pointeur de pile(R2)
constantes (R3)
gestions des exceptionsoui
8 vecteurs 0-7
oui
2 vecteurs 30-31
nombre d'arguments
instructions assembleur
0,1,2,30,1,2
UART2
support LIN
2
support LIN
IrDAouioui
minuteries32
PWM15
ADC10bits
9 canaux 500KSPS
10bits
8 canaux 200KSPS
cap senseoui
9 entrées
oui
16 entrées
SPI11
I2C11
RTCCouinon
CRCouinon
LFOouioui
crystal 32Khzouioui
crystal HFouinon
E/S digitales1816
boot loader ROMnonoui
prix Digikey.ca3,30$CAN3,19$CAN

Biens que le PIC24F16KA101 peut fonctionner avec un oscillateur 32Mhz alors que le MSP430G2553 est limité à 16Mhz leur Tcy est le même car le PIC24F16KA101 utilise 2 cycles d'oscillateur par Tcy. La mémoire flash est de 16Ko dans les 2 cas mais le PIC utilise 3 octets par instructions alors que le MSP430 en utilise 2. Cependant le fait que le PIC24 peut utiliser un argument en mémoire RAM pour plusieurs de ses instructions il n'est pas forcément désavantagé en ce qui concerne la densité de code, pour savoir ce qu'il en est il faudrait faire des comparaisons sur plusieurs échantillons de code.

Il est évident que la multiplication en matériel ainsi que le support matériel à la division est un gros avantage en faveur du PIC24.

On a aussi un avantage pour le PIC24 en ce qui concerne le convertisseur ADC qui peut lire 500000 échantillons par seconde contre 200000 pour le MSP430. Par contre le MSP430 bénéficie d'un canal DMA sur le convertisseur.

Du côté de la gestion des exceptions et des interruptions le PIC24F est nettement avantagé par la programmabilité de la priorité des interruptions et les registres shadow. Mais il utilise beaucoup plus de mémoire flash pour les 2 tables de vecteurs, 512 octets contre 192 pour le MSP430.

Le code généré par le compilateur C de l'IDE CCS5 de TI et le compilateur XC8 de Microchip avec niveau d'optimisation à 1 est de bonne qualité dans les 2 cas mais encore là il faudrait faire des tests comparatifs entre les 2 pour avoir une idée exacte de la performance de chacun. Évidemment pour les programmes utilisant multiplications et divisions le PIC24F est avantagé.

Conclusion

Si les PIC 8 bits souffrent d'une architecture archaïque, surtout les versions baseline et midrange les plus gros défauts ayant été corrigés sur les PIC18, ce serait une erreur de se détourner des PIC24 à cause de leur petits frères à 8 bits. Les PIC24F n'ont rien d'archaïque et ont de nombreux avantages par rapports aux MSP430. Bien que mon expérience avec ces MCU est récente je trouve jusqu'ici l'expérience satisfaisante. Se familiariser avec une famille de MCU demande du temps. Il est donc avantageux de demeurer avec le même fournisseur car la nomenclature est uniforme et la programmation des périphériques est très semblable d'un famille à l'autre. L'effort est donc moindre. Et les coûts aussi puisque le même programmeur peut servir pour toutes les familles de MCU 8,16,32 bits et l'économique pickit 2 peut aussi programmer certains PIC24F comme c'est le cas pour le PIC24F16KA101. Si vous travaillez avec des PIC24/dsPIC30/dsPIC33 et qu'ensuite vous passez au PIC32MX vous allez trouver la transition facile surtout si vous programmez en C. Et si vous aimez travaillez avec des cartes de développement sans soudure, Microchip est le manufacturier qui offre la plus large gamme en format PDIP et ce sur toutes les familles 8,16,32 bits.

vendredi 6 décembre 2013

cube 4x4x4 avec PIC24F16KA101

Je poursuis mes expérimentations avec le PIC24F16KA101. Cette fois je présente un cube de LED 4x4x4 réalisé avec des LEDs vertes de 3mm. Le cube de LED fait 3cmx3cmx4cm, (oui je sais, pas vraiment cubique). Pour ce cube j'ai utilisé la méthode de multiplexage dite Charlieplexing car elle nécessite moins de E/S, 9 lieu de 16 comme ce fut le cas pour la matrice de LED 8x8 utilisé dans ma présentation du PIC24F16KA101. Voici un court vidéo du démo en action.

méthode de fabrication du cube

Sur une planche j'ai percé 16 trous de 3mm de diamètre sur une grille de 3cm x 3cm. Comme il faut 9 E/S pour contrôler 64 LEDs en Charlieplexing j'ai soudé ensemble les cathodes par groupe de 8. Il y a donc 2 cathodes par plan. Les cathodes des LEDs qui sont soudées ensemble se font face. La première étape est de relier ces cathodes par un fil comme illustré ici.

Ensuite on relie les anodes 2 par 2 comme indiqué dans le tableau ci-bas. Sauf qu'il y a toujours 2 anodes de reliées à la cathode du groupe opposé. Ainsi p1a2 est relié à p1c1 et p1a9 est relié à p1c1. Les informations concernant un plan sont groupées par couleur. Au final il ne devrait y avoir que 9 fils qui relie ce plan au plan suivant. J'ai assemblé les 4 plans pour ensuite assembler ceux-ci ensemble. Ce travail demande beaucoup d'attention car le câblage est très enchevêtré. Si vous faites ce montage je vous conseille de vérifier chaque plan avant de faire l'assemblage final.
Comme les fils s'entrecroisent j'ai utiliser des manchons en plastique pour recouvrir les fils afin d'éviter les court-circuits, ce n'est pas la meilleur idée que j'ai eu, ça grossi le diamètre des fils et masque les LEDs qui sont en arrière plan. Et j'ai choisi une couleur différente pour chaque plan pour éviter de les confondre. Si c'était à refaire je m'y prendrais autrement.

J'ai créé un schéma du circuit mais pour le montage j'ai utiliser un tableau moins confondant que ce câblage spaghetti.

Les lignes du tableau représente les électrodes qui sont reliées l'une à l'autre. p indique le numéro du plan. c indique le numéro de cathode et a indique le numéro d'anode. Ainsi p1a2 est l'anode de la LED 2 du plan 1. Les LEDs sont comptées de gauche à droite et du haut vers le bas lorsqu'elles sont plantées dans la planche.

Code source du démo

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.