Electronique > Réalisations > Jeux de lumière > Chenillard 026

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.

chenillards_patern_026

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.

chenillard_026

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 :

adafruit_pca9685_001a adafruit_pca9685_001b chenillard_026_proto_001c

Modules à octuple LED RVB (LED RGB V2 keyes) :

chenillard_026_proto_001db chenillard_026_proto_001dc

Et bien sûr le circuit sans soudure avec le PIC, programmé en ICSP avec un PICkit2 :

chenillard_026_proto_001a chenillard_026_proto_001b    

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.