dimanche 30 décembre 2012

programmateur d'eeprom i2c

Pour un projet sur lequel je travaille j'avais besoin d'un programmateur de mémoire eeprom sériel avec interface I2C mais en regardant sur le site de Microchip et celui de digikey.ca le prix m'a fait reculer. Avec les coûts de transport et les taxes j'aurais du débourser plus de 80$ pour un appareil qui ne me servira probablement que très rarement. J'ai donc entrepris de fabriquer mon propre programmateur. Ce programmateur est conçu pour les mémoires eeprom sérielles avec interface I2C de Microchip. Le projet comprend 2 parties, le montage électronique avec le firmware pour le MCU qui contrôle la programmation eeprom et le logiciel hôte qui tourne sur le PC. Pour le logiciel PC j'ai choisi de l'écrire en python pour qu'il puisse être utilisé aussi bien sous Windows que Linux ou même OSX.

Matériel requis

QtNo.Piècedescriptionprix $CANfournisseur
2A100204-NDembases DIL-80,20Digikey.ca
1RB-Ada-30perma-proto 1/48,95/pqt de 3Robotshop.com/ca
3P5148-NDcondensateur électrolytique 10uF/25V0,21digikey.ca
2445-8421-NDcondensateur céramique 100nF0,32digikey.ca
12N3904-APCT-NDtransistor NPN 2N39040,45digikey.ca
12N3906-APCT-NDtransistor PNP 2N39060,45digikey.ca
1PIC12F1822-I/P-NDMicrocontrolleur Micropchip PIC12F18221,50digikey.ca
11N4148-TAPCT-NDdiode 1N41480,25digikey.ca
1P2.0KBACT-NDresistance 2K/0,25Watt0,10digikey.ca
1CF14JT4K70CT-NDresistance 4K7/0,25Watt0,09digikey.ca
3CF14JT10K0CT-NDrésistance 10K/0,25Watt0,09digikey.ca
5609-3466-NDcontact pin0,11digikey.ca

schéma électronique


Le programmateur communique avec l'ordinateur via un port série à 115200 BAUD, 8bits, pas de parité et 1 stop. La partie à droite du schéma, constituée de Q1 et Q2 est un convertisseur de niveaux de tension pour le RS-232. C'est le même circuit que j'ai déjà présenté sur ce blog. Le MCU PIC12F1822 communique donc avec le PC à travers ce circuit et d'autre part avec l'eeprom via les broches 2,3 et 5. La broche 2 est la sortie SCL et la broche 3 est l'E/S pour SDA du protocole I2C. La broche 5 contrôle le WP de l'eeprom et est gardée au niveau haut sauf pendant l'écriture de données dans l'eeprom. Les eeprom 24LCxxxx ont 3 entrées d'addressage A0-A2, qui servent à sélectionner le circuit intégré sur le bus I2C. Puisqu'il y a 3 bits d'adresse on peut mettre jusqu'à 8 I.C. sur le même bus I2C. Sur le schéma du programmateur j'ai mis A2=A0 à Vdd, l'adresse est donc 0b111. Pour les 24LC1025 il faut que la broche A2 soit à Vdd car le bit de la commande qui correspond à A2 dans les eeprom de plus de 64KB est utilisé pour sélectionner le block de 64K, la mémoire étant divisé en 2 block de 64KB.

montage

Pour le montage j'ai utilisé une platine produite par Adafruit et distribuée par Robotshop.com. C'est la première fois que j'utilise ce produit et je suis très satisfait. La qualité est bonne, les oeillets de soudure sont passant donc on peut soudé du côté composant sans avoir à retourner la platine. Le dessus de la platine est une représentation exacte d'une platine sans soudure. Donc pour faire le montage pas besoin de refaire un schéma de montage il suffit de recopier simplement ce qu'on a fait sur la platine sans soudure. Le montage a été plus rapide que si je l'avais fait sur une platine à grille de points 100mil. C'est un produit intéressant que je recommande.
Côté cuivre de la platine entre les contacts TX et RX j'ai coupé la trace du circuit imprimé pour isoler les contacts l'un de l'autre puisqu'il sont montés sur la même rangée.


firmware PIC12F1822

En ce qui concerne le firmware du PIC12F1822 ça a été assé simple. Pour la communication avec le PC comme le MCU a un périphérique USART incorporé le travail au niveau logiciel a été très simple. Le gros du travail c'est fait au niveau de l'interface I2C avec l'eeprom, mais pas de quoi s'arracher les cheveux.

code source firmware PIC12F1822


programme hôte

Comme je l'ai mentionné en introduction j'ai écris le programme en python. Je ne l'ai pas testé sous Linux mais en principe il devrait fonctionner sans modification. Il s'agit d'une application ligne de commande mais l'utilisation est simple.
i2cprog.py port_série mode fichier nombres_octets [-l opp] [-f32]
port_série est le nom du port utilisé pour la communication avec le programmateur.
Sous windows c'est quelque chose comme com3 alors que sous linux ça ressemble à /dev/ttyS0 ou encore /dev/ttyUSB0.
mode est p pour programmer l'eeprom ou r pour lire le contenu de l'eepom.
fichier est le nom du fichier qui contient les données à programmer ou pour le mode r le fichier dans lequel les données seront enregistrées.
nombres_octets est le nombre d'octets à programmer ou lire.
-l opp n'est utilisé que pour la programmation et indique le nombre d'octets par page de l'eeprom. Ce paramètre est essentiel pour la programmation et se retrouve dans le datasheet de l'eeprom utilisée. Par exemple pour 24LC512 ce paramètre est 128.
-f32 n'est utilisé que pour la lecture et sert produire un fichier au format Intel HEX32 plutôt que d'enregistrer les données en binaire brute.
Notez qu'en mode programmation i2cprog.py reconnais les fichiers Intel HEX32 et peut donc en extraire les données pour la programmation. I2cprog.py reconnait aussi les fichiers audio *.WAV 8 et 16bits non compressés. Donc si le nom du fichier se termine par .wav i2cprog.py en extrait le nombre d'octets contenu dans le segment data et l'inscris au début (4 premier octets little indian) ensuite il inscris tous les echantillons dans l'eeprom. J'ai ajouté cette fonctionnalité car c'est exactement ce que j'ai besoin pour mon projet actuel qui sera plublié bientôt sur ce blog.

code source i2cprog.py

tous les fichiers du projet sont disponibles ici.

dimanche 16 décembre 2012

découverte archélogique

Ce soir en fouillant dans le débarras au sous-sol j'ai fait une découverte archéologique. Le 3ième ordinateur personnel que j'ai possédé était un TRS-80 color computer 2 (coco 2). J'ai donné cet ordinateur il y a très longtemps mais j'avais encore en ma possession l'enregistreuse à cassette qui me servait à sauvegarder mes programmes et mes données. Sans surprise après 30+ années d'inactivité elle ne fonctionne plus. Les courroies de catoutchouc du moteur et du cabestan sont éventées. Cependant il y avait aussi une cassette qui a servie à enregistrer des données. Comme l'enregistreuse à un compteur, j'indiquais sur l'index la position de début et fin de chaque enregistrement.

  1. compers 0-6
  2. trie-rapide 10-15
  3. pascal32 20-32

Pour récupérer un enregistrement il fallait faire une avance rapide FAST-F jusqu'à la position désirée avant de peser sur PLAY/CLOAD pour débuter le chargement. Évidemment pour ajouter un enregistrement il fallait dérouler jusqu'après le dernier. Il semble qu'on était pas pressé dans ce temps là.

J'ai encore un lecteur de cassette sur ma chaîne stéréo. J'ai écouté la cassette par curiosité et j'ai reconnu le son caractéristique de ce genre d'enregistrement qui le plus souvent utilisait un standard appellé KCS pour Kansas City Standard. A l'époque il se vendait des cassettes dites numériques qui supposément assurait une meilleure fiabilité des enregistrements, ces dernières coûtaient évidemment plus cher que les cassettes audio standard. Mais comme on peut le voir sur la photo ci-bas. Je me servais de cassettes audio bas de gamme achetées chez Canadian Tire et je n'ai jamais eu de problème. Je suis même confiant que si j'avais encore mon coco 2 je pourrais recharger les données contenue sur celle-ci.





jeudi 13 décembre 2012

premiers pas avec MCU Atmel AVR

Ça faisait déjà plus d'un mois que j'avais acheter un programmeur Polulu AVR. Ajourd'hui j'ai décidé qu'il était temps de m'y mettre en commencant par le plus simple.

La première étape est de télécharger et installer Atmel studio 6.0.
Il faut ensuite installer le logiciel de Polulu pour le programmeur.

Je dois dire que j'avais préalablement acheter et lu le datasheet du AtTiny13A que j'ai utiliser pour programmer une variante de la LED qui clignote.

Atmel studio 6.0

En suivant les instructions du manuel de démarrage du programmeur Polulu. Ça a été simple de me retrouver dans Atmel studio et d'écrire la première version du programme en C. En effet le studio installe le compilateur avr-gcc ce qui permet de programmer en 'C' dès le départ. J'ai donc branché une LED RBG au AtTiny13A comme suit:


et j'ai relié le programmeur au MCU comme ceci:


Le programme que j'ai écris cycle entre les 3 couleurs du LED RGB et le code source est le suivant:

#define F_CPU 9600000
#define DLY 200
#include <avr/io.h>
#include <util/delay.h>

int main(void)
{
CLKPR= (1<<7);
CLKPR = 0 ; // désactivation du diviseur
PORTB |= (1<<PORTB5); // pullup sur RESET
DDRB |= (0x11<<DDB3|1); // met PORTB broche 0, 3 et 4 en sortie
PORTB &= ~(0x11<<PORTB3|1) ; // eteint tous les LED
while (1){ //boucle infinie
PORTB |= (1<<PORTB3); // allume le LED sur PB3
_delay_ms(DLY);
PORTB &= ~(1<<PORTB3); // éteint le LED sur PB3
PORTB |= (1<<PORTB4); // allume le led sur PB4
_delay_ms(DLY);
PORTB &= ~(1<<PORTB4); // éteint LED sur PB4
PORTB |= 1; // allume LED sur PB0
_delay_ms(DLY);
PORTB &=0xFE ; // éteint LED sur PB0
}

}


Ce programme compilé occupe 164 octets sur les 1K de mémoire flash du ATTiny13A.
Je voulais comparé ça avec le code écris en assembleur. Comme je n'ai jamais programmé en assembleur pour les AVR j'ai fait une recherche rapide dans google pour trouver des exemples et me suis inspiré de ce que j'ai trouvé.

/*
* BlinkRGB.asm
*
* Created: 2012-12-13 13:10:32
* Author: Jacques
* REF: http://jaxcoder.com/Projects.aspx?id=912541054
* http://www.avrfreaks.net/index.php?name=PNphpBB2&file=viewtopic&t=94232
* DESCRIPTION: une LED RGB est branché sur PB0,PB3 et PB4 le programme cycle les 3 couleurs
*/


.NOLIST
.include "tn13adef.inc"
.LIST

.equ DLY = 500 ; 500 msec
.equ F_OSC = 9600000 ; 9.6Mhz
.equ LED1 = PORTB0
.equ LED2 = PORTB3
.equ LED3 = PORTB4


.cseg
.org 0
rjmp init
.org 0x20 ; les 32 première addresses sont réservée aux vecteurs d'interruption.
init:
ldi r16, LOW(RAMEND)
out SPL, r16 ; initialisation du pointeur de pile.
ldi r16, 1<<7
ldi r17, 0
out CLKPR, r16
out CLKPR, r17 ; pas de diviseur sur horloge cpu
ldi r16, 1<<PORTB5
out PORTB, r16 ; pullup sur PORTB5 (reset)
ldi r16, (1<<LED2|1<<LED3|LED1)
out DDRB, r16 ; broche LED1,LED2 et LED3 en sortie
ldi r16, ~(1<<LED2|1<<LED3|LED1)
out PORTB, r16 ; éteint les 3 LEDs

main:
sbi PORTB, LED1 ; allume LED1
rcall delay_ms
cbi PORTB, LED1 ; éteint LED1
sbi PORTB, LED2 ; allume LED2
rcall delay_ms
cbi PORTB, LED2 ; éteint LED2
sbi PORTB, LED3 ; allume LED3
rcall delay_ms
cbi PORTB, LED3
rjmp main

delay_ms:
/* sous-routine de délais
count=(dly/Tboucle)=~(dly/Tcy*nbreCycles)
count=(dly/(nbreCycles/F_OSC))
count=(dly*F_OSC/nbreClycles)
*/
ldi r16, 0xFF & (DLY*F_OSC/4000) ; initialise le compteur délais
ldi r17, 0xFF & (DLY*F_OSC/4000)>>8
ldi r18, 0xFF & (DLY*F_OSC/4000)>>16
dly_loop:
dec r16 ; 1tcy
nop ; 1tcy
brne dly_loop ; 2tcy
dec r17
brne dly_loop
dec r18
brne dly_loop
ret

Le code assembleur occupe 68 octets ce qui représente 41% de la version 'C', mais avec un programme plus gros cet 'overhead' paraîtrait moins coûteux. J'ai examiné le code assembleur résultant du 'C' pour voir la différence. Ça tient principalement au code d'initialisation généré par le compilateur et au fait que le délais est inséré comme une macro plutôt que défini comme une sous-routine comme c'est le cas dans ma version en assembleur. J'observe aussi une différence dans la routine de délais. La macro du programme 'C' est la suivante pour _delay_ms

; r24,r25 et r26 servent de registre 24 bits pour le compteur de délais.
.macro _delay_ms ; voir note 1
ldi r24, LOW(@0) ; octet faible du premier argument, aussi: BYTE1(@0)
ldi r25, HIGH(@0) ; 2ième octet du premier argument, aussi: BYTE2(@0)
ldi r26, BYTE3(@0) ; 3ième octet du premier argument
dly_loop:
subi r24, 0x01 ; soustrait 1 à (r24-r25-r26)
sbci r25, 0x00 ; sustraction en tenant compte du carry bit.
sbci r26, 0x00
brne dly_loop
.endmacro

Cette macro utilise une soustraction sur 24 bits au lieu de décrémenter successivement les compteurs. J'ai modifié mon code assembleur pour utiliser cette méthode et je sauve 6 octets:
; constantes ajoutées au début du fichier
; maintenant on divise par 5000 au lieu de 4000
; car il y a 5 cycles dans la boucle au lieu de 4.
; le 1000 c'est pour les millisecondes DLY=500/1000 sec.
.equ DLY1 = 0xFF & (DLY*F_OSC/5000)
.equ DLY2 = 0xFF & (DLY*F_OSC/5000)>>8
.equ DLY3 = 0xFF & (DLY*F_OSC/5000)>>16

delay_ms:
/*
sous-routine de délais
version améliorée
*/
ldi r16, DLY1 ; initialise le compteur délais
ldi r17, DLY2
ldi r18, DLY3
dly_loop:
subi r16, 1 ; 1tcy
sbci r17, 0 ; 1tcy
sbci r18, 0 ; 1tcy
brne dly_loop ; 2tcy
ret

Comparaison avec MCU PIC

Prenons la sous-routine delay_ms et comparons là avec ce qu'on ferais avec un PIC baseline ou mid-range:

ms_delay
movlw DLY1
movwf dly_cntr
movlw DLY2
movwf dly_cntr+1
movlw DLY3
movwf dly_cntr+2 ; 6 instructions pour initialiser le compteur au lieu de 3.
dly_loop
movlw 1
subwf dly_cntr,F
clrw
skpc
subwf dly_cntr+1, F
skpc
subwf dly_cntr+2, F
skpnc
goto dly_loop ; 9 instructions pour la boucle au lieu de 4
return

Ça prend 2 fois plus d'instructions sur un PIC!!. Essayons avec un enhanced midrange:

ms_delay
movlw DLY1
movwf dly_cntr
movlw DLY2
movwf dly_cntr+1
movlw DLY3
movwf dly_cntr+2 ; aucun gain par rapport aux baseline/midrange
dly_loop
movlw 1
subwf dly_cntr, F
clrw
subwfb dly_cntr+1, F ; instruction disponible seulement
subwfb dly_cntr+2, F ; sur les enhanced et extended.
skpnc
goto dly_loop ; gain de 2 instructions grâce à subwfb
return

Grâce à l'instruction subwfb disponible sur les cores enhanced, on sauve 2 instructions mais on est encore à 14/8 en comparaison avec le AVR. De plus grâce aux 32 registres interne au core AVR a n'a utilisé aucune mémoire RAM alors que les PIC en utilisent 3 pour le compteur.

Beaucoup de points positifs pour le core AVR mais tout n'est pas positif. En effet une instruction AVR occupe 2 octets et certaines en prennent 4. Donc pour le AtTiny13a qui a 1K de flash ça veut dire un maximum de 512 instructions. Il faut en tenir compte lorsqu'on choisi un mcu AVR pour un projet. L'autre point négatif est que l'accès à la RAM prend 2 cycles au lieu de 1 pour les PIC. Par contre un cycle AVR c'est un cycle d'horloge alors qu'un cycle PIC c'est 4 cycles d'horloges. Donc un PIC qui a une horloge interne de 16Mhz comme le PIC10F322 a un cycle d'instruction de 250nsec alors qu'un AVR AtTiny13A avec son horloge à 9.6Mhz a un cycle d'instruction de 104nsec. Donc ce qui semblait-être un point négatif au départ est en fait positif. A fréquence d'horloge égales l'AVR est 4 fois plus rapide pour les opérations arithmétiques et logiques qui se font sur ses registres internes et 2 fois plus rapide pour les accès à la RAM. Par contre s'il doit faire une opération sur une variable dans la RAM il doit d'abord la ramené dans un registre internet faire l'opération et la réécrire dans la RAM. Avec 1 PIC si on veut par exemple incrémenter une variable eu peut le faire en 1 seule instruction et 1 seul cycle. Mais avec ses 32 registres internes au core les AVR tiny peuvent faire pas mal de chemin sans utiliser la RAM.

Conclusion

L'expérience a été intéressante et ce n'est surement la dernière fois que je travaille avec des AVR. Au niveau de l'assembleur la richesse du jeux d'instructions à comparer à la pauvreté du jeux PIC baseline et mid-range rends l'expérience plus agréable. Le fait de pouvoir programmer en 'C' sans avoir à acheter un compilateur coûteux est aussi un point intéressant.



NOTES:
1) contrairement à mpasm avrasm n'utilise pas de noms pour les arguments de macros.
le nombre maximum d'arguments est de 10 et ils sont nommé @0-@9.
Une définition de macro peut se terminée par .endm ou .endmacro
Toutes les directives de l'asembleur commence par un '.'

dimanche 9 décembre 2012

tictactoe 3D, conclusion

Ce projet est maintenant complété. J'ai fait un montage sommaire du circuit sur un morceau de bois qui trainait dans le garage. Comme les modules LED ne tenaient pas bien à la vertical j'ai ajouté un morceau d'acrylique pour les tenirs droit.


J'ai ajouté un petit haut-parleur au circuit de la carte mère pour signaler certains événements aux joueurs. Voici le schéma corrigé.


Schéma des manettes de contrôle:





PIC12F1822

Comme c'est la première fois que j'utilise un PIC12F1822 sur ce blogue je vais en faire une brève présentation. Il s'agit d'un MCU à 8 broches avec un coeur enhanced mid-range avec 2KBi de mémoire flash, 128 octets de RAM et 256 octets EEPROM. Mais ce qui rends intéressant les enhanced mid-range c'est l'adressage indexé relatif via les 2 registres FSR. J'ai profité de cette fonctionnalité pour utiliser une façon différence de programmer. Tout en travaillant en assembleur, j'ai en quelque sorte imité le travail d'un compilateur 'C'. C'est à dire que j'ai créé une pile (stack) pour passer les arguments aux sous-routines et aussi pour les variables locales. J'ai défini un ensemble de macros pour faciliter ce travail avec la pile. Le programme ne fait donc pas usage de variables temporaires autres que celles qui sont empilées. L'ensemble des fichiers du projet sont ici.

fonctionnalités

Il ne s'agit pas seulement d'un jeux de tictactoe, le cube de LED peut-être contrôlé à partir d'un PC grâce à un cable sériel RS-232. les paramètres de transmission sont 19200BAUD/8N1 pas de contrôle de flux. Vous trouverez dans le dossier google docs du projet 3 scripts python à titre d'exemple.

Lorsque le jeux est allumé et avant de démarrer la partie, le PC peut transmettre des commandes au contrôleur maître qui les relais au cube. Cependant lorsque la partie est débutée les commandes ne sont plus relayées.


liste des fichiers source.

fichiercontenu
tictactoe3d.asmfirmware des modules LEDs.
pic10f322_m.incmacros d'usage général pour PIC10F322
tictactoe-master.asmfirmware du contrôleur principal sur la carte-mère.
pic12f1822_m.incmacros d'usage général pour PIC12F1822


difficultés rencontrées

Je dois dire que le développement du firmware a été plus difficile que je l'aurais cru surtout pour le contrôleur maître. En bonne partie du à ma nouvelle façon de travailler avec une pile. Il faut toujours un certain temps pour s'adapter à une nouvelle méthode de travail. Mais cette méthode vaut la peine d'être explorée et améliorée. Vous noterez dans le code source du fichier controleur-maitre.asm la présence de 2 sous-routines qui n'ont pas été compilées dans la version finales. send_to_pc et display_byte n'étaient que des outils de débogage. La première sous-routine envoie un octet vers le PC et l'autre utilise les modules 1 et 4 du cube pour afficher un octet en base 4. Sans ces outils le travail le n'aurais peut-être jamais aboutis. Ce sont deux exemples de la façon d'utiliser des ressources qui sont déjà disponible dans le projet pour faire du débogage.


conclusion

tictactoe-master.asm n'utilise que 51% de la mémoire programme et 12% de la RAM. Tictactoe3D.asm utilise 63% de la mémoire programme et 23% de la RAM il y a donc encore de la place pour apporter des améliorations et nouvelles fonctionnalités au projet.

mise à jours

2016-09-23 ajout d'une vidéo sur youtube suite à une demande.

mercredi 28 novembre 2012

tictactoe 3D, partie 3

Le cube est maintenant complété mais pour le moment il n'est contrôlé que par l'ordinateur via le port série. Il me reste à fabriquer 2 gamepads, et à écrire le firmware pour le contrôleur principal qui est un PIC12F1822.





tous les fichiers pour ce projet sont ici

Puisque c'est noël bientôt

puisque que c'est noël bientôt, le script python suivant donne au cube une allure de décoration avec ses 27 LEDS qui changent de couleur continuellement au hasard.

# NOM: random-led.py
# DESCRIPTION: contrôle aléatoire du cube 3x3x3 construit pour le jeux de tictactoe

import serial
import time
import argparse
import random
import msvcrt # windows seulement

done = False

parser=argparse.ArgumentParser(description='script de test pour module 3LED bi-couleurs',
usage='module-test.py [-h] device-name module_id [-n nouvel_id]')
parser.add_argument('serial', help='nom du port serie')
cmd_line=parser.parse_args()

device=cmd_line.serial
ser=serial.Serial(device, 19200,timeout=0)
ser.write(chr(3<<4)) while not done :



module=random.randrange(1,10)
led=random.randrange(0,3)
cmd=random.randrange(1,4)
ser.write(chr(module | led << 4 | cmd << 6)) time.sleep(.05) if msvcrt.kbhit() : # windows seulement, n'importe qu'elle touche arrête le programme.
done=True

ser.close()


J'ai filmé avec mon appareil photo mais la qualité est médiocre.

mercredi 21 novembre 2012

tictactoe 3D, partie 2

détail du montage des modules LEDs

matériel requis

  • 27 LEDs bi-couleurs rouge/vert digikey P/N 67-1124-ND, 52C/10+
  • 9 condensateurs céramic 10uF/10V SMD 1206, digikey P/N 445-4057-1-ND, 25,6C/10+
  • 9 condensateurs cérmaic 100nF/10V SMD 0402, digikey P/N 445-1265-1-ND, 2,7C/10+
  • 9 MCU 10F322T-I/OT, digikey P/N PIC10F322T-I/OTCT-ND, 62,8C/10+
  • fil 30 AWG 100', digikey P/N K325-ND, 13,15$
  • 1 protoboard robotshop P/N RB-Spa-233, 9,95$
  • 45 broches 100mil,roboshop 2 x P/N RB-Spa-153, 1,50$

Plan de montage

étapes

partie LED
  1. Découpez dans la platine 18 morceaux de 2x3 trous. Ces morceaux servent à relier les 3 DELs ensembles et sont repréentés par P1 et P2 sur le dessin.
  2. Découpez dans la platine 9 morceaux de 2x7 trous. Ces morceaux servent pour le montage de la base avec le connecteur ICSP et le MCU.
  3. Faites les liens sur les morceaux 2x3 tel qu'illustré en bleu sur le dessin. Le lien bleu pâle est fait sur l'autre face.
  4. Les fils des LED ont une marque près de la capsule de plastique. Les 2 fils extérieurs, soit le fil pour l'anode rouge et celui de l'anode verte doivent-être écartés du fil central pour qu'il y est une distance de 100mil entre chaque fil. Servez-vous d'une pince à long bec (long nose) et pliez le fil vers l'extérieur juste en en haut de la marque à un angle de 45 degré. Déplacez la pince en bas de la marque et ramené l'extrémité du fil vers le centre pour qu'il soit en parrallèle avec celui de la cathode , comme illustré sur le dessin. Répétez l'opération avec le fil anode verte.
  5. Glissez la LED dan les 3 trous d'un morceaux 2x3 jusqu'à ce que le morceau appui sur les coudes. Soudez en place.
  6. Recommencez les 2 étapes précédentes avec une autre LED.ATTENTION! Le morceau n'est pas dans la même orientation. Sur le morceau P1 qui relie D1 et D2 se sont les fils Cathode et Vert qui sont croisés. Sur le morceau P2 qui relie D2 et D3 ce sont les fils Rouge et Cathode qui sont croisés.
  7. Soudez ensemble D1 et D2 ensuite soudez D3 sur la base de D2.
partie base
  1. Il n'y a que les 4 broches des extrémités qui sont reliés à des oeillets les broches du centre soit Vss et Vdd tombe entrent les oeillets. En vous servant d'un fil d'étain très fin ajoutez une goute d'étain sur les broches Vss et Vdd.
  2. Observez sur le dessin la position du MCU et ajouter une goûte d'étain sur le rebord des oeillets à l'endroit où les broches 1, 3, 4 et 6 seront soudées.
  3. En utilisant une pincette pour tenir le MCU par le corps faites refondre l'étain sur l'oeillet qui acceuille la broche 6 et positionnez le MCU en place pendant que l'étain est fondu et retiré le fer en tenant le MCU en place le temps que l'étain fige. Assurez-vous que le MCU est bien positionné. Les broches 2 et 5 ne doivent pas toucher au oeillets adjacents.

  4. Faites refondre l'étain pour souder les broches 1,3 et 4.
  5. Dans la languette de connecteur 100mil découpez une section de 5 borches et placez là à l'endroit indiqué sur le dessin ci-haut en ne soudant que la broche identifiée PGC sur le dessin.
  6. Coupez un bout de fil no 30 juste assé long pour rejoindre la broche 2 du MCU à la broche du connecteur identifiée V- sur le dessin. Soudez d'abord le bout qui va sur le MCU en faisant refondre la goûte d'étain qu'on y a mis. Soudez ensuite sur la broche du connecteur.
  7. Répétez cette opération pour la broche Vdd.
  8. reliez l'oeillet sur lequel est soudé la broche 6 du MCU à la broche du connecteur identifiée Vpp.
  9. Le condensateur 100nF au format 0402 est juste assé long pour relié les oeillets V- et V+ en leur partie la plus rapproché. Ce composant est vraiment minuscule et difficile à manipuler. Utilisez une pincette très pointu pour le tenir et faites refondre l'étain sur un des oeillet placez une extrémité du condensateur juste pour affleuré l'étain fondu. Enlevez le fer et laissé figé. Si le condensateur est bien positionné l'autre extrémité devrait effleuré l'autre oeillet. Faites refondre l'étain de cet oeillet pour souder cette extrémitée.
  10. Le condensateur 10uF est au format 1206 et et plus facile à manipuler. Il est trop long pour être glissé entre les broches comme l'autre. Il mesure 130mil de long, juste de la bonne longueur pour appuyer ses extrémités sur chaque broche adjacente V- et V+ et le souder en place par refonte de l'étain. Ajoutez de l'étain au besoin.
  11. Maintenant il faut positionné la partie LED sur la base. Le fil de l'anode rouge doit-être du côté extérieur tel qu'indiqué sur le dessin.
  12. la broche 1 du MCU (RA0) va sur le fil du centre (cathode LED) et continu son chemin jusque sur la broche PGD du connecteur.
  13. la broche 3 du MCU (RA1) va sur le fil à l'extérieur (anode rouge) et continu son chemin jusque sur la broche PGC du connecteur.
  14. Finalement la broche 4 du MCU (RA2) va sur le fil anode verte du LED.
  15. Il ne vous reste plus qu'à insérer le connecteur dans le Pickit 3 et à programmer le MCU et ensuite testez le module avec le script python fournis en partie 1.
  16. J'oubliais un petit détail, il faut refaire ça 9 fois. Si vous êtres très motivés en utilisant des PIC12F609 vous pourriez fabriquer 100 modules de 10 LEDS bicouleurs pour un magnifique cube de 10x10x10.



modification d'un servo-moteur pour rotation continue

Lorsque j'explore l'internet au sujet de l'utilisation des micro-controlleurs je constate qu'il y a beaucoup d'intérêt pour les véhicules robots suiveurs de lignes ou autres. Lorsque je magazine sur les sites comme robotshop je constate aussi que si le coût des composants électroniques est très abordable de nos jours il n'en va pas de même pour les pièces mécaniques qui entre dans la fabrication des robots. Entre autre les moteurs avec engreganes utilisés pour motoriser les véhicules robots coûtent chers comparativement à un servo-moteur. Je ne suis pas le seul à l'avoir constaté car nombreux sont ceux qui utilisent des servo-moteurs pour motoriser leur véhicules car ceux-ci sont très abordables contrairement aux premiers. Chez robotshop on peut avoir un petit servo moteur pour aussi peut que 4$. Uh HS-422 coûte 10.49$.


Mais pour utiliser un servo-moteur pour motoriser un véhicule il faut le modifier. Dans cette chronique j'explique comment faire cette modification.

Un servo-moteur est un système asservi. C'est à dire un système qui compare une consigne à un état et modifie l'état jusq'à ce que l'erreur entre la consigne et l'état soit nulle. Dans le cas d'un servo-moteur, l'état contrôlé est la position de l'axe d'un potentiomètre. Il y a donc à l'intérieur du boitier un moteur avec un engrenage et un potientiomètre relié à l'axe de sortie du servo-moteur. En tournant le moteur fait aussi tourner l'axe du potentiomètre. Donc si on remplace le potentiomètre par 2 résistances d'égales valeurs comme indiqué dans le desssin ci-bas, l'erreur ne sera jamais corrigée et le moteur tournera continuellement. Évidemment s'il y a une butée autre que celle qui est dans le potentiomètre il faut l'enlever aussi.
Avec cette modification on a un moteur à rotation continue dont le sens de la rotation peut-être contrôlé.

En fonctionnement pour arrêter le moteur il suffit de lui envoyer des impulsions dont la largeur correspond à la position centrale. Pour le faire tourner vers la gauche (anti-horaire) on lui envoie des impulsions plus étroites et pour le faire tourner vers la droite (sens horaire) on lui envoie des impulsions plus larges que la valeur médiane.






lundi 19 novembre 2012

projet TictacToe 3D

J'ai entrepris de construire un jeux de TicTacToe avec un cube de LED bi-couleurs. Au lieu d'utiliser un MCU qui a suffisamment d'E/S pour contrôler les 54 DELS (27 DELs bi-couleurs), j'ai choisi une approche modulaire dans le genre pixdel. Cependant au lieu de contrôler 1 seul DEL RGB avec un PIC10F202, j'utilise un PIC10F322 et je contrôle 3 DELS bi-couleurs rouge/verte. Chaque module représentera une colonne. Il en faudra donc 9. Pour le moment j'ai fait le dévelloppement du firmware pour le module et je l'ai testé en le branchant à un port COM de mon ordinateur. J'ai aussi construit le prototype #1. Au départ j'envisageais 9 modules pour former le cube 3x3x3 et un contrôleur maître servant à la logique du jeux et d'interface avec les 2 joueurs et pour contrôler le cube. Pour le moment seul la première phase est complétée, soit le dévelloppement et la construction d'un module 3 LEDs.
Sur la photo suivante on voie le montage de dévelloppement sur la platine sans soudure avec le premier prototype. Les 2 modules sont branchés sur le convertisseur de niveaux qui reçoit les commandes du script test-module.py. Tous les fichiers sont ici.

Sur cette photo on aperçoie a peine le MCU en format SOT23-6 qui est à l'extrémité droite du connecteur ICSP. Voici une vue en gros plan de la base du module.



jeudi 8 novembre 2012

expérimentation avec PIC10F322, partie 4, charlieplexing

La technique de multiplexage appellée charlieplexing tire avantage des interfaces 3 états comme ont les retrouvent sur les MCU. Par interface 3 états j'entends un port dont les connections externes peuvent-être configurées en entrée ou en sortie. Il y a effectivement 3 états puisqu'en configuration sortie, on peut avoir un niveau haut ou bas tandis que si la connection est configurée en entrée on a un 3ième état qui est la haute impédance (résistance).

Je disais donc que le charlieplexing tire avantage de ces 3 états en permettant de contrôler un nombre supérieur de dispositifs qu'il y a d'E/S. Le nombre possible est de
N*(N-1)
ou N est le nombre d'E/S utilisées.
Pour cette expérience puisqu'on utilise un PIC10F322 on dispose de 3 broches configurables en entrée ou en sortie. Ce qui nous donne la possibilité de contrôler 6 LEDs. Comme indiqué sur le schéma suivant:




fonctionnement du charlieplexing

Si on se réfère on schéma ci-haut on voit que les LEDs sont connectées entre 2 broches. Si par exemple on veut allumer D1 qui est branchée entre RA0 et RA1, on configure RA0 et RA1 en sortie et on laisse RA2 en mode entrée haute impédance. On met ensuite la Sortie RA1 à 1 et RA0 à 0 de sorte que le courant va passé de RA1 vers RA0 à travers D1. D2 reste éteinte puisque qu'une diode ne conduit pas dans le sens inverse. Pour allumer D2 on inverse les polaritées. C'est à dire qu'on mets RA1 à 0 et RA0 à 1. Les diodes électroluminescentes fonctionnent donc par paires branchées entre les 2 mêmes broches:

  • D1 et D2 entre RA0 et RA1
  • D3 et D4 entre RA0 et RA2
  • D5 et D6 entre RA1 et RA2

Donc pour contrôler D3 et D4 on laisse RA1 en mode entrée et on configure RA0 et RA2 en mode sortie. De même pour contrôler D5 et D6 on laisse RA0 en entrée haute impédance et on configure RA1 et RA2 en mode sortie. De cette manière chacune des 6 LEDs peut-être allumée individuellement. Évidemment on ne peut toutes les allumées en même temps mais à cause de la persistance rétinienne si on allume séquentiellement chacune d'elle à tour de rôle rapidement on a l'impression qu'elles sont toutes allumées en même temps, c'est ce qu'on appelle un affichage multiplexé. Tous les affichages qui utilise un nombre élevé d'éléments sont multiplexés, c'est le cas pour l'éran de votre ordinateur et de votre téléviseur et on a pourtant l'impression que tous les pixels sont allumés en même temps.

expérimentation

Cette expérience utilise le montage illustré dans le schéma ci-haut et le programme charlieplexing.asm. Le fichier de macros pic10f322_m.inc est aussi nécessaire.

Le logiciel a 2 modes de fonctionnement. Le premier mode est un compteur binaire qui compte de 0 à 63 en boucle et le deuxième est un LED allumé qui se promème de gauche à droite et de droite à gauche alternativement. On passe d'un mode à l'autre en pressant le bouton qui est branché sur RA3.

Description du logiciel

Le timer0 est configuré pour générer une interruption à tous les 256usec. La routine d'interruption appelle la sous-routine charlie qui gère l'afficheur. la s.r. charlie affiche le contenu de la variable dsp_byte. A chaque appelle de la s.r. un nouveau bit est affiché. On passe d'un bit à l'autre en boucle. Comme il y a 6 bits à afficher le cycle complet prend 6*256usec, soit 1,5msec. La fréquence de muliplexage est donc de 667Herz. Beaucoup trop rapide pour que l'oeil percoive qu'il n'y a qu'un seul LED d'allumé à la fois. À 70herz l'oeil ne perçoit déjà plus de scintillement.

La routine principale du programme ne fait que gérer la lecture du bouton et le mode de fonctionnement. Dans le mode 0 la variable dsp_byte est simplement incrémentée 4 fois par seconde. Dans le mode 1 tous les bits de dsp_byte sont à zéro sauf 1 et ce bit est déplacé de gauche à droite et de droite-gauche avec les instructions rlf et rrf. A chaque fois que le bit arrive à une extrémitée la direction du déplacement est inversée.


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.