Dernière mise à jour :
08/02/2015
Présentation
Ce chenillard est un "modèle de luxe". Contrairement à ses
prédécesseurs présentés sur le site, celui-ci permet un effet du style
"queue de comète normale ou inversée" avec seulement deux circuits intégrés.
Certes,
il ne
s'agit pas de n'importe quels circuits intégrés puisqu'on a affaire à
un PIC et à un circuit spécialisé de commande PWM à 16 canaux et de
résolution 12 bits par canal, le PCA9685. Pour ce projet,
l'idée n'était pas de faire
un "super-mega-chenillard" - même si l'effet obtenu est vraiment sympa
- mais plutôt de montrer comment mettre en oeuvre le PCA9685,
d'une manière assez originale. Et, comme les révisions ne font jamais
de mal, il m'a semblé sympa de rappeler à notre bon souvenir quelques lignes de code relatives
au convertisseur analogique/numérique (module ADC) du PIC.
Schéma
Le PCA9685 est tout de même un beau petit circuit ! Avec seulement
trois fils de commande (liaison I2C), il met à disposition 16 sorties PWM
(de résolution 12 bits) indépendantes ! De quoi faire travailler plusieurs
moteurs électriques ou doser de façon précise plusieurs ensembles
lumineux.
Comme je n'avais pas 16 moteurs à illuminer, j'ai fait tourner 16 LED.
Principe de fonctionnement
Le PIC joue le rôle d'un séquenceur,
qui décide quelles sont les sorties (lumières) à allumer. Mais plutôt
que de faire travailler les seize sorties en tout ou rien (lumières
complètement allumées ou complètement éteintes), il les pilote en mode
"progressif" (degré variable de luminosité), en fonction de la position
du curseur de cinq potentiomètres. Voici le déroulement d'une séquence :
1 - La première LED (câblée sur la sortie PWM1) s'allume plein feu.
2
- La seconde LED (câblée sur la sortie PWM2) s'allume plein feu et la
première LED s'allume avec un degré de luminosité qui dépend de la
position du potentiomètre RV1.
3 - La troisième LED (câblée sur
la sortie PWM3) s'allume plein feu, la seconde LED s'allume avec un
degré de luminosité qui dépend de la
position du potentiomètre RV1 et la première LED s'allume avec un
degré de luminosité qui dépend de la position du potentiomètre RV2.
4 - La quatrième LED (câblée sur la sortie PWM4) s'allume plein feu, la
troisième LED s'allume avec un degré de luminosité qui dépend de la
position du potentiomètre RV1, la seconde LED avec un degré
de luminosité qui dépend de la position du potentiomètre RV2 et la première LED avec un degré
de luminosité qui dépend de la position du potentiomètre RV3.
5 -
La cinquième LED (câblée sur la sortie PWM5) s'allume plein feu,
la quatrième LED s'allume avec un degré de luminosité qui dépend de la
position du potentiomètre RV1, la troisième LED avec un degré
de luminosité qui dépend de la position du potentiomètre RV2, la
seconde LED avec un degré
de luminosité qui dépend de la position du potentiomètre RV3 et la
première LED avec un degré
de luminosité qui dépend de la position du potentiomètre RV4.
6 -
La sixième LED (câblée sur la sortie PWM6) s'allume plein feu, la
cinquième LED s'allume avec un degré de luminosité qui dépend de la
position du potentiomètre RV1, la quatrième LED avec un degré
de luminosité qui dépend de la position du potentiomètre RV2, la
troisième LED avec un degré
de luminosité qui dépend de la position du potentiomètre RV3, la
seconde LED avec un degré
de luminosité qui dépend de la position du potentiomètre RV4 et la
première LED avec un degré
de luminosité qui dépend de la position du potentiomètre RV5.
7 - La septième LED (câblée sur la sortie PWM7) s'allume plein feu, la
sixième LED s'allume avec un degré de luminosité qui dépend de la
position du potentiomètre RV1, la cinquième LED avec un degré
de luminosité qui dépend de la position du potentiomètre RV2, la
quatrième LED avec un degré
de luminosité qui dépend de la position du potentiomètre RV3, la
troisième LED avec un degré
de luminosité qui dépend de la position du potentiomètre RV4 et la
seconde LED avec un degré
de luminosité qui dépend de la position du potentiomètre RV5. La première LED s'éteint complètement.
Comme
on peut le constater et pour résumer, on a affaire à une sorte de
registre à décalage,
où les valeurs fixées par les potentiomètres "glissent" sur les LED. Si
en partant du premier potentiomètre et en allant vers le dernier
les tensions décroissent, l'effet
visuel obtenu est celui d'une queue de comète normale. Mais toute forme
de queue peut être obtenue, et pas forcément avec un mode décroissant.
Acquisition des valeurs de la queue de comète
La
traine est composée de cinq points et donc de cinq LED. A tout instant,
on peut donc avoir six LED allumées, la première à fond et les
suivantes avec le degré de luminosité que vous choisissez avec les cinq
potentiomètres RV1 à RV5. Si on veut une traine plus courte (3 LED
seulement par exemple) il suffit de positionner les derniers
potentiomètres (RV4 et RV5 par exemple) à leur valeur minimale. La
tension issue de chaque potentiomètre est appliquée sur des entrées du
PIC qui accèptent de recevoir une tension analogique, et que l'on
reconnait sur le schéma grâce à leur appellation AnX, ou X représente
le rang de l'entrée analogique (AN0 pour la première entrée analogique,
AN1 pour la seconde, etc).
procedure ADC_GetValues;
begin
ArrADC[0] := ADC_Get_Sample(0);
ArrADC[1] := ADC_Get_Sample(1);
ArrADC[2] := ADC_Get_Sample(2);
ArrADC[3] := ADC_Get_Sample(3);
ArrADC[4] := ADC_Get_Sample(4);
end;
Notez que si j'ai choisi d'utiliser les cinq
premières entrées analogiques du PIC (AN0 à AN4), cela n'a rien
d'obligatoire. J'aurais très bien pu utiliser AN0, AN3, AN4, AN11 et
AN12, ce qui aurait conduit au code suivant :
procedure ADC_GetValues;
begin
ArrADC[0] := ADC_Get_Sample(0);
ArrADC[1] := ADC_Get_Sample(3);
ArrADC[2] := ADC_Get_Sample(4);
ArrADC[3] := ADC_Get_Sample(11);
ArrADC[4] := ADC_Get_Sample(12);
end;
Utilisation du PCA9685
Un
gros pavé plein de pattes à ajouter au PIC, il en faut bien un de temps
en temps pour ne pas s'ennuyer. Le PCA9685 comporte un générateur PWM
qui sert de façon indépendante, 16 sorties. Il s'agit d'un circuit qui
se pilote par un
bus I2C,
et il faut le configurer (de façon purement logicielle) avant de
pouvoir indiquer quelle valeur de largeur d'impulsion attribuer à
chaque sortie. Tout cela, bien sûr, est réalisé au moment de
l'initialisation du PIC. Notez le nombre élevé de broches dédiées à
l'adressage physique du composant et qui permettent d'en utiliser
plusieurs sur le même bus (de mon côté je me suis arrêté au pilotage de
3 circuits PCA9685 pour une interface à 48 canaux PWM). Ici toutes les
broches d'adresse du PCA9685 sont reliées à la masse, le code du PIC est donc
écrit pour piloter le circuit à son adresse de base qui est $80.
procedure PCA9685_Init;
begin
I2C1_Start; // Start
I2C1_wr(cPCA9685Addr); // Slave address (Addr = $80)
I2C1_wr(PCA9685_MODE1); // Mode 1 address
I2C1_wr($31); // Set mode to sleep, allow change default PWM frequency
I2C1_Stop; // Stop
delay_us(100); // Required 50 us delay
I2C1_Start; // Start
I2C1_wr(cPCA9685Addr); // Slave address
I2C1_wr($FE); // PWM frequency PRE_SCALE address
I2C1_wr($04); // osc_clk/(4096*update_rate) // 25000000/(4096*1500)= 4.069 ~4
I2C1_Stop; // Stop
delay_ms(1); // delay at least 500 us
I2C1_Start; // Start
I2C1_wr(cPCA9685Addr); // Slave address
I2C1_wr(PCA9685_MODE1); // Mode1 register address
I2C1_wr($A1); // Set mode (nota 1)
I2C1_Stop; // Stop
delay_ms(1); // delay at least 500 us
I2C1_Start; // Start
I2C1_wr(cPCA9685Addr); // Slave Address
I2C1_wr(PCA9685_MODE2); // Mode2 register address
I2C1_wr($04); // Set mode (Nota 2)
//I2C1_wr($14); // Set mode (Nota 2)
I2C1_Stop; // Stop
end;
Nota 1 : Reset, horloge interne, auto-incrément, mode normal.
Nota
2 : Etat des sorties logiques non inversé (valeur Mode2 = $04) ou
état des sorties logique inversées (valeur Mode2 = $14), changement des
sorties sur STOP, structure de sortie totem pole, sorties à 0
quand OE = 1 (OE = Output Enable).
Les valeurs de largeur d'impulsion de chaque sortie PWM sont transmises via le code suivant.
procedure PCA9685_SetValue(iOut: byte; iVal: word);
var
iOutIdx: byte;
iPwm: word;
begin
iPwm := iVal;
iOutIdx := PCA9685_LED0 + (4 * iOut);
if (iPwm > 4095) then // if larger than 4095 then full on (100%)
iPwm := 4095; // value can't be larger than 4095
I2C1_start; // Start
I2C1_wr(cPCA9685Addr); // PCA9685 address
I2C1_wr(iOutIdx); // LED address
I2C1_wr(0x00); // LED_ON_L
I2C1_wr(0x00); // LED_ON_H
I2C1_wr(lo(iPwm)); // LED_OFF_L
I2C1_wr(hi(iPwm)); // LED_OFF_H
I2C1_Stop; // Stop
end;
Les valeurs qui spécifient le rapport cyclique doivent
être codées sur 12 bits. Comme le module CAN du PIC possède une
résolution de 10 bits, on
procède à un petit décalage de 2 bits vers la gauche (SHL 2) des
valeurs de tension acquises
par le PIC (stockées dans le tableau de variables ArrPwm) avant de les
envoyer au PCA9685.
PCA9685_SetValue(i, ArrPwm[i] shl 2);
Oui,
à un instant donné, on déverse les valeurs acquises par le CAN
(stockées dans le tableau de variables ArrAdc) dans le tableau de
variables ArrPwm.
Remarques diverses
Pour
l'instant, le quartz (8 MHz) ne sert à rien, le code active l'oscillateur interne 8 MHz. A l'avenir, qui sait,
mettra-t-il ses talents à disposition pour la liaison UART1, qui comme
vous l'avez peut-être aussi remarqué, dispose de fils libellés Tx1
et Rx1 sur le schéma. Un mode programmable via PC à venir ? Allez
savoir... en tout cas je l'ai prévu.
Les
lignes RE0, RE1 et RE2 du PIC ne servent qu'à des fin de
vérification/débogage, pas besoin de les relier en usage normal.
Les lignes RB0 et RB1, ainsi que les boutons-poussoirs Prog+ et Prog- ne sont pas mis à contribution pour l'instant.
Sorties PWM
Comme
au bout du compte il faut bien utiliser les sorties du PCA9685, j'ai
décidé d'y relier de simples LED (anodes sur sorties PCA, cathodes
à la masse).
Vous pouvez aussi, bien sûr, ajouter des transistors de puissance
(bipolaires ou MOSFET) pour attaquer des "charges lourdes" (c'est ce
que
j'ai fait avec mon interface à 48 canaux PWM pour permettre le
pilotage de LED de puissance 1 W). Pour le prototype du chenillard
026, j'ai utilisé des LED RVB montées sur des modules keyes tout faits
(câblage différent de celui du schéma, j'en parle plus loin).
Suppression du PCA9685 ?
Avec
un code plus conséquent, il est possible de supprimer le circuit
spécialisé et de faire délivrer au PIC les signaux PWM (déjà fait avec
mes interfaces DMX). Si je ne l'ai pas fait ici, c'est parce que
j'avais l'intention, dès le début, de pouvoir jouer sur la luminosité
mais aussi sur la couleur de la trainée. Il est en effet possible de
piloter seize LED RVB avec trois circuits PCA9685, et obtenir une
trainée qui (ce n'est qu'un exemple parmi plein d'autres) passe du
rouge au bleu au fur et à mesure de son extinction (analogie avec le
passage du chaud au froid). Bref, j'aime bien mon petit PCA9685,
je le garde ;-)
Prototype
Réalisé
avec une plaque sans soudure pour le PIC et les quelques composants qui
l'entourent, un module Adafruit équipé du PCA9685 (circuit intégré
qu'on ne trouve malheureusement qu'en boîtier CMS) et deux petits
circuits "keyes" équipés chacun de 8 LED RVB. Ci-après le circuit
Adafruit et son PCA9685 acheté en "presque-kit", avant et après
assemblage des connecteurs :
Modules à octuple LED RVB (LED RGB V2 keyes) :
Et bien sûr le circuit sans soudure avec le PIC, programmé en ICSP avec un PICkit2 :
Remarque
: les LED des modules keyes sont câblées en cathode commune et
leur commande se fait avec des états bas. Pour mon prototype, j'ai
donc temporairement inversé l'état logique des sorties du PCA9685 en
configurant de manière adéquate le bit "Output invert" (bit 4) du
registre "Mode2". Ainsi, on obtient un état bas des
sorties PWM quand le rapport cyclique est de 100%, et un
état haut quand le rapport cyclique est de 0%. Comme on peut le
voir sur les photos, j'ai utilisé la couleur rouge pour le premier
groupe de 8 LED et la couleur bleue pour le second groupe, ce choix est
purement arbitraire.
Logiciel du PIC
Code compilé *.hex
disponible dans l'archive suivante.
Chenillard 026 - PIC 18F45K22 - (08/02/2015)
Si
vous souhaitez recevoir par la poste un PIC préprogrammé
et prêt à utiliser, merci de consulter la page
PIC - Sources.
Circuit imprimé
Non réalisé.
Historique
08/02/2015
- Première mise à disposition.