mercredi 31 octobre 2012

expérimentation avec PIC10F322, partie 3

Dans cette 3ième partie de mes expérimentations avec le PIC10F322, je l'utilise pour produire des sons. Il y a 2 programmes, soundfx.asm et pwm_synth.asm.
Les 2 programmes utilisent le fichier de macros pic10f322_m.inc

Pour réaliser ces expériences j'ai ajouté un petit potentiomètre de 5K sur la platine d'expérimentation présentée en partie 1 de cette série. Ce potientiomètre sert dans le mode VCO du programme soundfx.asm et dans pwm_synth.asm.

effets sonores

Pour réaliser cette expérience vous avez besoin du matériel suivant:

  • 1 PIC10F322 ou LF322
  • 1 petit haut-parleur
  • 1 résistance de 100 ohm
  • 1 potientiomètre de 5K (la valeur n'est pas critique)
  • 1 bouton à contact momentanée
  • 1 platine d'expérimentation sans soudure
  • 1 programmeur pickit 3 ou équivalent.

Le montage est le suivant:


Pour cette expérience tous les périphériques du PIC10F322 sont utilisés.

  • Le NCO sert de générateur de fréquence audio principal.
  • le PWM1 génère une fréquence audio fixe.
  • la CLC est utilisée pour additionner (mixer) les sorties du NCO et de PWM1
  • la sortie du CLC est connectée à RA2
  • Le convertisseur A/N fait la lecture du potentiomètre sur RA0
  • le timer 2 alimente le PWM
  • le timer 0 est utilisé pour mesurer le temps pour les intervalles.

Le programme a 5 modes de fonctionnement:
  1. Silence
  2. balayage de fréquence
  3. générateur de fréquence contrôlé par un voltage (VCO)
  4. gamme musicale
  5. mélodie

Le bouton branché sur RA3 permet de passer d'un mode à au suivant en boucle.
Le mode balayage de fréquence balaie de 100hz à 5Khz en montant et en descendant.
Ce signal est mélanger avec une fréquence fixe générée par PWM1 avec une fonction "ou exclusif" dans la cellule logique configurable. L'effet produit est très particulier.

Le mode VCO tant qu'à lui produit une fréquence qui est proportionnel au voltage lu sur le potentiomètre. En tournant le potentiomètre on fait varier la fréquence.

Le mode gamme utilise le NCO pour jouer la gamme musicale tempérée dont les valeurs de
fréquences sont inscrites dans la table scale_table.

Finalement le mode mélodie joue la mélodie We gonna fly now, musique thème du film Rocky 1.


synthès analogique par PWM

Le programme pwm_synth.asm est une illustration de l'utilisation de la modulation par largeur d'impulsion pour produire un signal analogique. Pour cette expérience le haut-parleur doit-être branché sur RA1 en série avec une résistance de 100R. Il faut aussi brancher un potentiomètre de 5K ou 10K aux bornes de l'alimentation avec le contact mobile (celui du centre) sur RA2. En tournant ce potentiomètre on sélectionne la note que le programme fait entendre.

Dans cette expérience le MCU est configuré pour fonctionner à sa vitesse maximale de 16Mhz et le canal PWM2 est utilisé pour générer une onde sinusoïdale. La fréquence du PWM est de 31Khz donc inaudible. J'ai utilisé OpenOffice calc pour calculer les valeurs de la table sine_table1. ainsi que les délais de transfert des échantillons au PWM. Ces valeurs détermine la largeur d'impulsion que doit générer le PWM au différents angles du cycle de l'onde et le délais de transmission des échantillons pour chaque fréquence. Il y a 90 échantillons, donc un échantillon à tous les 4 degrés considérant qu'un cycle complet représente 360 degrés. La fréquence de l'onde est déterminée par la vitesse avec laquelle on envoie les échantillons au PWM.

délais = (1/fr)/Ns

délais est le délais entre l'envoie de chaque échantillon au pwm.
fr est la fréquence qui doit-être générée.
Ns est le nombre d'échantillons.

exemple pour générer un fréquence 440hz avec les 90 échantillons de la table sine_table

délais = (1/440)/90 = 0,0023/90 = 25 uSec

les valeurs pour le timer0 sont calculées de la façon suivante.

T0val=256 - délais/Tcy + 9
T0val est la valeur d'initialisation du compteur timer0.
délais est la valeur calculée dans la formule précédente.
Tcy est la période de l'horloge système soit 1/(Fosc/4), ce qui à 16Mhz
donne 250nsec.
9 est le nombre de Tcy qui s'écoule avant que le timer0 ne soit réinitialisé par la routine d'interruption.

pour 440Hz on a donc:

T0val = 256 - 25e-6/250e-9 + 9 = 165

J'ai fait un fine tuning des valeurs en mesurant les fréquence réelle à l'oscilloscope, pour être le plus près possible des valeurs de la gamme tempérée.

On entend clairement la fréquence audio dans le haut-parleur mais si on branche un oscilloscope sur la broche RA1 le signale ressemble à ceci:


Ceci est le signal en p3 sur le schéma ci-bas. Difficile de voir une forme sinusoïdale ici.


Si on remplace le haut-parleur avec ce filtre passe-bas pour éliminer le signal PWM, voici ce qu'on voit à l'oscillope.

Au point 2 le signal PWM n'est pas complètement éliminé il chevauche la fréquence audio.

Au point 1 le signal PWM est à peine visible, il ne reste que la fréquence audio synthétisée.

Dans les années 80 tous les ordinateurs personnels n'avaient pas de carte son, un petit haut-parleur était branché à une sortie numérique et tout ce que l'ordinateur pouvait produire c'était des BEEP en ondes rectangulaires. Jusqu'à ce que quelqu'un est l'idée de créer un pilote de périphérique qui pouvait lire un fichier .WAV et le faire entendre dans le haut-parleur. La technique utilisée était celle décrite dans ce démo synthèse analogique par modulation de largeur d'impulsion.

Il faut faut donc pas s'étonner que les périphériques PWM soit si répandus sur les micro-controlleurs, après les minuteries ce sont les périphériques les plus utilisés sur MCU. Au cours de mes chroniques j'en ai illustrer plusieurs usages:

  • Contrôle de l'intensité lumineuse d'une DEL.
  • Contrôle de la position d'un servo-moteur.
  • Contrôle de la vitesse d'un moteur c.c.
  • Synthèse de signaux analogiques.

Il y a d'autres usages comme par exemple les régulateurs de tension. En fait le PWM est la méthode la plus efficace pour contrôler et produire des signaux analogiques avec du numérique.




NOTES:
1) Notez que pour la table sine_table j'ai utilisé une table da plutôt qu'une table dt. Ce type de table permet d'enregistrer des valeurs plus grandes que 255 dans une location mémoire flash. La mémoire flash étant de 14 bits on peut enregistrer des valeurs de 0 à 16383. j'économise ainsi 90 locations mémoire par rapport à l'utilisation d'une table dt, une réduction de 50%. De plus l'accès dans la routine d'interruption est plus rapide.





dimanche 28 octobre 2012

expérimentation avec PIC10F322, partie 2

Dans cette deuxième expérience avec le MCU PIC10F322 il s'agit de contrôler la vitesse d'un petit moteur en courant continu en utilisant la modulation de largeur d'impulsion, PWM pour son acronyme anglophone. Voici le schéma du circuit utilisé pour cette expérience.


La broche RA1 est la sortie PWM qui contrôle le transistor Q1 qui lui-même contrôle le moteur en mode ON/OFF. De plus l'entrée RA2 est configuré pour une lecture analogique du voltage au collecteur de Q1. Cette lecture permet de savoir si le moteur tourne vraiment ou s'il est bloqué. Dans l'éventualité d'un blocage le moteur est mis à l'arrêt après un certain délais.

principe de fonctionnement

Le moteur est alimenté par des impulsions plutôt que par un voltage continu comme il le devrait dans un usage normal. Ces impulsions sont répétées à une fréquence régulière mais leur durée varie. Plus la durée des impulsions est longue plus le moteur reçois d'énergie donc il tourne plus vite. A cause de l'inertie lorsque l'alimentation du moteur est coupée celui-ci continue à tourner jusqu'à la prochaine impulsion. Du fait de l'inertie du moteur il se fait naturellement une intégration des impulsions et le résultat est équivalent à celui qu'on obtiendrait si on alimentait le moteur avec un courant continu dont on varie le voltage.

Les petits moteurs de ce type sont fabriqués avec 2 aimants permanents qui servent de stator avec un pôle NORD et un SUD. Le rotor lui est constitué d'un bobinage sur une armature ferro-magnétique et forme donc un électro-aimant. Donc lorsque le rotor est alimenté le champ magnétique résultant du passage du courant dans le bobinage du rotor interagit avec celui du stator pour faire tourner le moteur.

Lorsqu'un conducteur se déplace dans un champ magnétique une force électro-motrice est générée dans le conducdeur. C'est le principe de fonctionnement de toute génératrice électrique. Les moteurs n'échappent pas à cette loi de la physique et se comportent aussi comme des générateurs. Donc lorsque le moteur tourne une force électro-motrice est générée dans le rotor. On l'appelle Force Contre Électro-Motrice car sa polarité s'oppose à celle de l'alimentation du moteur. C'est la raison pour laquelle un moteur tire un maximum de courant lorsqu'il est à l'arrêt et que ce courant diminue avec la vitesse car la F.C.É.M. est soustraite du voltage d'alimentation.

Ir = (Valim. - Vf.é.c.m.)/Rrotor
Ir est le courant circulant dans le rotor
Valim est le voltage d'alimentation
Vf.c.é.m. est le voltage généré par la Force Contre Életro Motrice
Rrotor est la résistance du rotor.

Ce qui est intéressant c'est l'usage qu'on peut faire de cette F.C.É.M. Puisqu'on alimente le moteur par impulsions, entre 2 impulsions Q1 ne conduit pas et donc si on mesure le voltage au collecteur de Q1 pendant cette phase ce qu'on obtient c'est

Vcq1 = Valim - Vf.c.é.m

Mais comme je viens de l'expliquer si le moteur ne tourne pas la Vf.c.é.m. est nulle. Donc on peut savoir si le moteur tourne ou pas en mesurant la valeur de ce voltage. C'est ce que fait le programme. Il mesure 16 fois cette valeur pour en faire une moyenne et si ce voltage moyen est plus grand qu'une certaine valeur il considère que le moteur est mécaniquement bloqué et au bout d'un délais il coupe l' alimentation. Si vous fabriquez un petit robot sur roues vous pouvez savoir si le robot bute sur un obstacle simplement en utilisant cette technique, donc pas besoin de détecteur d'obstacle.

Le code source est disponible ici; controle-moteur-cc-pic10f322.asm


jeudi 25 octobre 2012

expérimentation avec le PIC10(L)F322, partie 1

Dernièrement j'ai entrepris d'étudier les particularités du PIC10(L)F3221. J'ai commencé par me fabriquer un platine d'expérimentation. Il y a quelques temps j'ai vue sur le site Hackaday.com2 une platine d'expérimentation conçu avec une platine à oeillets 100mil et un MCU ARM en format QFN. Je me suis dit que le gars qui avait fait ça devait-être très patient. Mais aussi que s'il l'a fait je devrais être capable de le faire aussi. Mais pour un premier essai j'ai choisi un MCU beaucoup plus modeste, soit un PIC10LF322-E/MC en format 8 DFN. Le DFN est semblable au QFN sauf que les contacts ne sont que sur 2 côtés au lieu des 4. Le boitier mesure à peine 2x3 mm et l'espace entre le centre d'un contact et son voisin n'est que de 0,5mm.


La pointe de mon fer à souder fait plus d'un mm au plus étroit, difficile de ne pas faire de pont d'étain entre les contacts. Je me suis donc retrouvé avec 1 pont d'étain de chaque côté qui reliait tous les contacts. Pas de panique, que je me suis dit, la pompe à dessouder va régler ça. Et effectement j'ai réussi à enlever le surplus d'étain simplement avec la pompe à dessouder.

J'ai installé sur la platine côté MCU des broches qui vont me permette de brancher le pickit 3 ainsi que de relier avec des cavaliers les E/S à différents composants comme la LED RGB et le bouton momentané installé sur l'autre face de la platine.




Ma méthode pour souder le MCU est la suivante.

  1. Collé le MCU sur la platine avec une goûte de colle rapide locktite.
  2. Souder 6 fils no. 30 AWG sur les oeillets entourant le MCU.
  3. Couper les fils juste de la longueur nécessaire pour qu'ils touchent le contact qui leur est destiné.
  4. Mettre du tack flux sur les contacts
  5. Souder avec un fil d'étain ultra fin.
  6. Utiliser la pompe à dessouder pour enlever le surplus d'étain qui fait pont entre les contacts
  7. Souder un fil sur la plaque de métal au centre du boitier et à un oeillet qui sera relié au V- de l'alimentation.
schéma de la platine


Des périphériques spéciaux

Le PIC10(L)F322 possèdent des périphériques qu'on ne voit pas souvent sur les MCU:

  • 1 générateur de fréquence numériquement programmable NCO
  • 1 cellule logique configurable CLC
  • 1 générateur d'onde complémentaire CWG

objet de cette expérience:
  • exemple d'utilisation du périphérique CLC
  • exemple d'utilisation du périphérique NCO
  • exemple d'utilisation du périphérique CWG

CLC

Le périphérique CLC est celui qui m'a demandé le plus de réflexion qu'en à l'usage que je pourrais en faire. Dans cette première expérience. J'ai branché l'anode rouge de la LED RGB sur RA0, la verte sur RA1 et le bouton momentané sur RA2. le programme s'appelle ColorSweep car il s'agit de faire varier progressivement l'intensité des 2 couleurs à l'inverse l'une de l'autre. C'est à dire que lorsque l'intensité de l'une augmente celle de l'autre diminue. On a donc un balayage de couleur qui passe progressivement du rouge au vert en passant par le jaune. Mais le logiciel comprend aussi un mode flipflop ou on passe du vert au rouge alternativement sans progression. Le rôle du bouton momentané est de faire passé le logiciel d'un mode à l'autre.

Dans cette expérience le CLC est utilisé pour filter les rebonds du bouton plutôt que ce soit fait en software. Pour configurer le CLC j'ai utilisé l'outil graphique fournis par Microchip: CLC designer. La capture d'écran suivante présente la configuration utilisé.


table de vérités
GATE 1GATE 3
RA2NCOFbRA2NCOFb
001000
010010
100100
110111

Par application du théorème de De Morgan

Fb(GATE 1) = ~RA2 ET ~NCO = ~( RA2 OU NCO )
Fb(GATE 3) = RA2 ET NCO = ~ ( ~RA2 OU ~NCO)

Dans cette configuration la CLC est configuré comme un SR lacth le signal du bouton qui est branché sur RA2 passe par GATE 1 et le gate OU pour atteintre l'entrée S(et) du SR latch. L'entrée R(eset) et activé par un pulse qui provient du périphérique NCO qui est programmé pour produire ce pulse à toutes les 50msec.
Cependant dans le cas d'un SR lacth les entréres S et R ne doivent jamais se retourvé au niveau 1 en même temps sinon l'état de la sortie Q serait imprévisible. Donc j'utilise une configuration logique sur GATE 1 et GATE 3 pour que les 2 signaux se bloquent mutuellements. Cette configuration fait en sorte que pour que le S(et) passe à 1 il faut que les 2 entrées du GATE 1 soient à zéro. Mais je ne veut pas non plus que le pulse en provenance du NCO R(eset) le latch tant que le bouton est enfoncé (RA2=0) la sortie du GATE 3 doit donc passé à 1 seulement lorsque RA2=1 et que la sortie du NCO=1.


NCO

Le générateur de fréquence numériquement programmable utilise un accumulateur, un additionneur et un incrément et est alimenté par un signal d'horloge. A chaque impulsion reçu de l'horloge la valeur de l'incrément est ajouté au contenu de l'accumulateur et lorsque l'accumulateur déborde la sortie du NCO génère un pulse.
La fréquence de ce pulse dépend de la fréquence du signal d'horlogue et de la valeur de l'incrément. Plus l'incrément est petit plus il faut d'additions pour faire déborder l'accumulateur et vice-versa. On modifie donc la fréquence des pulses en modifiant la valeur de l'incrément. Ce pulse de sortie peut-être utilisé pour faire basculer un flipflop. Dans ce mode la sortie du flipflop est une onde carré (duty cycle = 50%) dont la fréquence est la moitié de celle à la sortie NCO. Mais le NCO peut aussi être programmé en mode impulsion. Dans ce cas chaque débordement produit une impulsion dont la durée est programmable de 1 à 128 périodes d'horloge.

Dans cette exemple le NCO est été programmé en mode impulsion dont période de répétition est de 50msec. Sa fonction est de remettre à zéro la sortie du SR latch dans le CLC.


CWG

Le générateur d'onde complémentaire prend simplement à son entrée un signal rectangulaire et produit 2 sorties complémentaires, c'est à dire lorsqu'une sortie est à 1 l'autre est à zéro et vice-versa. Mais en plus il est possible de programmer un temps mort au début et à la fin des changements d'états. Temps mort pendant lequel les 2 sorties sont dans le même état. Ce type de générateur est utile pour généer des signaux en opposition de phase pour alimenter des moteurs pas à pas ou encore des ponts en H et autres applications du genre.

Dans cette exemple je m'en sert en conjonction avec le périphérique PWM1 dont la sortie alimente le CWG pour contrôler l'intensité de 2 LED de façon complémentaire. C'est à dire que lorsque l'intensité de la LED verte augemente celle de la rouge diminue et vice-versa.


le code assembleur pour réaliser cette expérience se retrouve ici.




NOTES:

1) Attention le PicKit 2 ne semble pas en mesure de programmer le PIC10F322, en tout cas ça n'a pas fonctionné pour moi dans mplabx, j'ai du utilisé le pickit 3.

2) Je ne retrouve malheuresement pas cette entrée sur le site.