Applications LED à faible consommation : technique de gestion de l'énergie

Ezana Haile, Principal Applications Engineer, Analog & Interface Products Division

 

Microchip Technology Inc.

L'équilibre entre la luminosité des LED et la consommation électrique est une spécification essentielle pour déterminer la qualité de la lumière visible émise est contrôlée par une application. Dans certaines applications à faible consommation, les limitations de l'alimentation électrique ne permettent pas toujours d'obtenir la luminosité maximale et simultanée de toutes les diodes LED utilisées. Pour bénéficier d'une luminosité optimale sur chaque LED, la distribution d'énergie doit être gérée avec efficacité pour exploiter au mieux la source d'alimentation à basse tension. Ceci nécessite une technique de gestion de l'alimentation qui permet d'allumer consécutivement et rapidement les rangées de LED. Lorsque l'intensité lumineuse requise est atteinte sur une rangée de LED, les autres rangées ne sont pas perceptibles.

La puissance disponible et l'intensité lumineuse exigées pour l'application doivent être préalablement définies pour déterminer le nombre de LED allumées pendant un intervalle temps spécifique. Une comparaison entre l'intensité lumineuse et les caractéristiques du courant direct est nécessaire pour sélectionner les LED et le niveau d'intensité requis. Lorsque le nombre de LED requis est défini, elles peuvent être alimentées pendant les intervalles nécessaires proportionnellement au courant total disponible :

Nombre de LED par rangée = Courant total requis pour toutes les LED / Courant total disponible

La fréquence d'activation/ désactivation des LED doit être réglée pour que la durée d'activation suffise à obtenir l'intensité maximale d'une rangée entière. La durée de désactivation dépend du délai de baisse visible de la luminosité. La durée de désactivation limite le nombre de rangées de LED supplémentaires pouvant être contrôlées par la gestion des intervalles de temps.

Cette technique est réalisable à peu de frais avec une minuterie, des bascules numériques, pour contrôler des rangées de LED, et une porte OR, pour détecter une condition d'allumage avec un simple interrupteur Marche-Arrêt. Figure 1 : Schéma d'une configuration de bascules D pour contrôler quatre rangées de LED.

 

 

Figure 1 : Intervalles de temps d'allumage des LED avec un circuit à bascules

 

Initialement, les bascules sont en état neutre et nécessitent une impulsion initiale. Celle-ci doit durer au moins un cycle d'horloge pour être détectée par la première bascule au début du cycle d'horloge. La durée du signal de démarrage doit être inférieure à un cycle d'horloge, sinon, les sorties des deux premières bascules seraient simultanées. Dans ce cas, comme le courant d'alimentation est limité, l'application LED ne pourrait pas fonctionner correctement. Dans cette configuration, chaque rangée de LED est totalement allumée au début de chaque cycle d'horloge. Pour l'œil humain, toutes les LED semblent totalement allumées simultanément.

Cette implémentation n'offre qu'une seule couleur et aucune souplesse de design. Elle n'offre que deux états : activé et désactivé. Ce circuit peut répondre aux besoins de diverses applications, telles que le rétroéclairage d'écrans LCD. Si une fonction dimmer ou des séquences spécifiques sont nécessaires, un microcontrôleur (MCU) apportera une souplesse d'utilisation optimale avec un impact minime sur le coût total de la solution. La construction du circuit est simple, nécessite peu de composants, puisque le microcontrôleur gère chaque rangée de LED. Il peut aussi détecter les entrées d'utilisateur pour assurer le contrôle du dimmer et la sélection des séquences.

Un microcontrôleur économique 8 bits et à faible nombre de broches, tel qu'un PIC10F ou PIC12F Microchip, avec un module d'expansion de port E/S (MCP23018 Microchip, par exemple) permet une mise en œuvre rentable. Des modules d'expansion E/S peuvent aussi être utiles piloter des LED, lorsque le circuit doit être installé à distance du microcontrôleur.

Les modules d'expansion permettent d'étendre les ports E/S d'un microcontrôleur. Dans cette application, le microcontrôleur gère les ports d'expansion E/S avec le protocole I2C™ pour allumer et éteindre les LED. Les broches E/S du microcontrôleur servent à détecter les entrées utilisateur avec un interrupteur à bouton poussoir, ou un convertisseur analogique-numérique intégré pour détecter le niveau du potentiomètre qui contrôle le dimmer.

Des modules d'expansion E/S sont disponibles avec des configurations de sortie à drain ouvert ou push-pull. Les microcontrôleurs peuvent être alimentés en 3,3V ou une tension plus basse. Par conséquent, un module d'expansion E/S de sortie à drain ouvert est une excellente solution pour cette application. Cette configuration permet d'alimenter les LED en 5V ou plus, et d'utiliser une tension inférieure pour le microcontrôleur et le module d'expansion E/S. Le MCP23018 est un module d'expansion de port E/S 16 bits avec une sortie à drain ouvert et une interface I2C. La figure 2 présente un schéma de module d'expansion E/S avec une sortie à drain ouvert utilisant une tension plus haute que la tension d'alimentation du microcontrôleur.

 

 

Figure 2 : Solution économique de gestion des LED basée sur un microcontrôleur et un module d'expansion de port E/S.

 

Lorsque le port E/S est réglé sur bas, la tension du port d'expansion E/S est à 0V, le courant passe et allume le LED. La résistance de polarisation LED limite le courant arrivant au LED pour obtenir l'intensité lumineuse requise. Elle fonctionne aussi comme résistance de démarrage pour la sortie à drain ouvert.

Lorsque le port de sortie d'expansion E/S est réglé sur haut, la sortie à drain ouvert est désactivée, ou à haute impédance, et la résistance de démarrage porte la tension du port d'expansion E/S à 5V. La LED est désactivée parce que le courant ne peut pas passer. Une configuration de sortie à drain ouvert offre un avantage supplémentaire. Lorsque le port est configuré à haute impédance, la capacité d'interférence prolonge le délai d'extinction de la LED. Par conséquent, la durée d'activation de la prochaine rangée de LED peut être légèrement plus longue que celle fournie par des applications similaires avec sortie push-pull.

Les 16 ports E/S du MCP23018 peuvent contrôler jusqu'à 16 LED. La quantité de courant injectée dans le port E/S lorsque la LED est totalement activée peut être limitée par la sortie du module d'expansion E/S. La basse tension est au maximum de 0,6V à 8,5 mA sur le port E/S. Si le courant est supérieur à 8,5 mA, la basse tension augmentera exponentiellement. Le courant maximum absolu est de 25 mA.

Par exemple, si la source d'alimentation est de 5V/ 50 mA, dont 2 mA pour le microcontrôleur, le module d'expansion E/S et les résistances de détection des entrées utilisateur, le reste du courant disponible peut être réservé aux LED. Si une intensité LED d'environ 10 mA est considérée comme suffisante, le circuit peut gérer quatre LED par rangée. Dans cet exemple, la valeur de résistance nécessaire pour contrôler le courant sera de 440 ohms approximativement.

Le timing indiqué à la Figure 1 peut être répété à l'aide d'un code d'instruction dans le MCU. Par exemple le Pseudo Code 1, le principal sous-programme peut être une boucle WHILE infinie. Sur les intervalles de temps du microcontrôleur (Timer0), un sous-programme d'interruption envoie une commande I2C au module d'expansion E/S pour activer une seule des rangées de LED. Le sous-programme d'interruption compte ou suit l'état des rangées de LED, tel que la rangée activée, et l'état haut ou bas de la configuration du port du module d'expansion E/S correspondant. Initialement, ou après réinitialisation du microcontrôleur, sur la première interruption Timer0, la rangée 1 est activée. À la deuxième interruption, la rangée 1 s'éteint et la rangée 2 s'allume. Ensuite, à la troisième interruption, la rangée 2 s'éteint et la rangée 3 s'allume. Finalement, à la quatrième interruption, la rangée 3 s'éteint et la rangée 4 s'allume. Le compteur de rangées est remis à zéro. À l'interruption suivante, le cycle reprend et allume la rangée 1 et éteint la rangée 4. D'autres variables, telles que Command_byte, Address_pointer_bank1n2 et Address_pointer_bank3n4 sont des constantes définies dans le fichier « header ». Dans cette configuration, le circuit produit l'intensité lumineuse requise et toutes les LED semblent s'allumer simultanément, sur la source d'alimentation disponible.

 

void main (Void){

initialize(); //initialiser les périphériques PICmicro incluant Timer0, et les périphériques du module d'expansion E/S

bank_counter = 0; //Remise à zéro du compteur de rangées

while(1){} //Boucle WHILE infinie

}

Void Interrupt int_service(void){

            TurnOffAll_LEDs(); //sous-programme pour éteindre toutes les LED allumées précédemment

            I2C_start(); //protocole I2C – Lancer le sous-programme des signaux

            I2C_send(Comand_byte); //protocole I2C – Envoyer le sous-programme par octet

 

If(bank_counter == bank1){ // rangée 1 est une constante définie sur 0

            I2C_send(Address_pionter_bank1n2); //Envoyer le pointeur d'adresse du registre des périphériques

            I2C_send(‘0000 1111’); //protocole I2C – Envoyer l'état des rangées (rangée 1 allumée et rangée 2 éteinte)

            bank_counter = bank_counter + 1;

}

If(bank_counter == bank2){ // bank1 est une constante définie sur 1

            I2C_send(Address_pionter_bank1n2); //Envoyer le pointeur d'adresse du registre des périphériques

            I2C_send(‘1111 0000’); //protocole I2C – Envoyer l'état des rangées (rangée 2 allumée et rangée 1 éteinte)

            bank_counter = bank_counter + 1;

}

If(bank_counter == bank3){ // bank1 est une constante définie sur 2

            I2C_send(Address_pionter_bank3n4); //Envoyer le pointeur d'adresse du registre des périphériques

            I2C_send(‘0000 1111’); //protocole I2C – Envoyer l'état des rangées (rangée 3 allumée et rangée 4 éteinte)

            bank_counter = bank_counter + 1;

}

If(bank_counter == bank4){ // bank1 est une constante définie sur 3

            I2C_send(Address_pionter_bank3n4); //Envoyer le pointeur d'adresse du registre des périphériques

            I2C_send(‘1111 0000’); //protocole I2C – Envoyer l'état des rangées (rangée 4 allumée et rangée 3 éteinte)

            bank_counter = 0;

}

I2C_stop(); //protocole I2C – Arrêter le sous-programme des signaux

}

Pseudo Code 1 : Code du sous-programme d'interruption du microcontrôleur

 

Contrôle de dimmer et génération de séquences LED

Des séquences peuvent être aisément créées avec une application basée sur un microcontrôleur. Les états de sortie du port d'expansion E/S sont chargés à partir de deux octets de variables RAM, identifiés comme Bank1n2_pattern et Bank3n4_pattern. À chaque demi-octet correspond une rangée. Un tableau prédéfini liste les différentes séquences définies par des 1 et des 0 pour chacune des rangées.

Pour surveiller constamment l'état du bouton poussoir Marche/ Arrêt, une instruction IF THEN est ajoutée dans le code du microcontrôleur (la boucle WHILE infinie du sous-programme principal). Lorsque l'utilisateur appuie momentanément sur le bouton poussoir, une séquence du tableau est chargée dans les deux octets de RAM, identifiés comme Bank1n2_pattern et Bank3n4_pattern. L'interruption Timer0 déclenche l'envoi de la nouvelle séquence au module d'expansion E/S et les LED s'allument conformément à la séquence. Chaque fois que l'utilisateur appuie momentanément sur le bouton poussoir, le sous-programme lit cycliquement le tableau. Pour obtenir un clignotement, il suffit d'envoyer le complément de la séquence précédente. Par exemple, si la séquence bank1 est « 0101 », le complément est « 1010 », comme indiqué dans le Pseudo Code 2, qui est extrait du Pseudo Code 1.

*

*

*

If(bank_counter == bank1){ // bank1 est une constante définie sur 0

            I2C_send(Address_pionter_bank1n2); //Envoyer le pointeur d'adresse du registre des périphériques

            Bank1n2_pattern = ~Bank1n2_pattern; //compléter la variable avec ‘~’

            I2C_send((Bank1n2_pattern | ‘0000 1111’)); //protocole I2C – Envoyer l'état de la rangée

                                                                        //(utiliser OR ‘|’ pour définir la rangée 1 sur Activé et la rangée 2 sur Désactivé)

            bank_counter = bank_counter + 1;

}

*

*

*

Pseudo Code 2 : Génération de séquence

 

Toutefois, un délai doit être introduit dans le sous-programme d'interruption, avant les instructions IF THEN d'activation/ désactivation des rangées, pour inspecter visuellement les séquences. Ce délai est créé avec un flag Delay_ON, pour qu'à l'interruption suivante un compteur de délais soit décrémenté pour suivre le nombre d'interruptions pendant le délai. La valeur de délai peut aussi être sélectionnée avec un potentiomètre par l'utilisateur. Dans ce cas, la borne centrale est connectée à l'entrée du convertisseur analogique-numérique (CAN) embarqué sur le microcontrôleur. Les données du CAN sont calibrées sur les délais minimum et maximum en fonction des quatre bits supérieurs, ce qui donne 16 niveaux. Une résolution plus fine est possible en détectant les cinq bits supérieurs, pour utiliser 32 niveaux. Le délai maximum est la vitesse de clignotement la plus lente des LED. Avec le délai minimum, les LED semblent allumées en continu. Dans la Figure 3, le schéma de timing montre la position de délai tDELAY.

 

*

*

*

Void Interrupt int_service(void){

            TurnOffAll_LEDs(); //sous-programme pour éteindre toutes les LED allumées précédemment

            If (Delay_ON == ON){ // ON est une constante définie sur 1

                        Update_Timer0_Counter(Timer0delay_interval); //sous-programme pour actualiser Timer0

                                                            // Timer0delay_interval est une constante qui définit le délai minimum

                        Delay_Counter = Delay_Counter – 1;  //décompte le nombre d'interruptions pendant le délai

                        If(Delay_Counter == 0){

                                    Delay_ON = OFF; // Réinitialiser le flag Délai pour la prochaine interruption

                                    Delay_Counter = Get_Delay_Counter(); //sous-programme pour détecter l'entrée utilisateur

                                                            //et définir la variable du compteur de délais

                        }else{

                                    Delay_ON = ON; // laisser le flag Délai sur ON

                                    Return; //quitter le sous-programme d'interruption

                        }

            }

 

            I2C_start(); //protocole I2C – Lancer le sous-programme des signaux

            I2C_send(Comand_byte); //protocole I2C – Envoyer le sous-programme par octet

If(bank_counter == bank1){ // bank1 est une constante définie sur 0

            I2C_send(Address_pionter_bank1n2); //Envoyer le pointeur d'adresse du registre des périphériques

            Bank1n2_pattern = ~Bank1n2_pattern; //compléter la variable avec ‘~’

            I2C_send((Bank1n2_pattern | ‘0000 1111’)); //protocole I2C – Envoyer l'état de la rangée

                                                                        //(utiliser OR ‘|’ pour définir la rangée 1 sur Activé et la rangée 2 sur Désactivé)

            bank_counter = bank_counter + 1;

                        Delay_ON = ON; // mettre le flag Délai sur ON

}

*

*

*

Pseudo Code 3 : Code Délai, pour inspecter la séquence lumineuse.

 

Pour gérer la durée de l'intervalle sur chaque rangée, le contrôleur de dimmer utilise la modulation d'impulsions temporelles (MIT). La durée de l'interruption Timer0 a deux valeurs : une durée longue et une durée courte, proportionnellement au pourcentage de la MIT, qui sont définies avec un potentiomètre à molette. La borne centrale est connecte à l'entrée du CAN. Le niveau de résolution peut être réglé en sélectionnant les 4 ou 5 bits supérieurs du CAN. La position du compteur Timer0 est quotientométrique, basée sur les données calibrées du CAN : 100 % de la MIT est égale à la position maximale du compteur (intensité maximale), et 0 % est la valeur minimale ou l'intensité la plus basse possible du dimmer. Le Pseudo Code 4 indique l'équation de calibrage de la MIT sur 16 niveaux. La Figure 3 présente le schéma du timing pour la durée de MIT tPWM_LOW et PWM_HIGH.

Void get_PWM_ratio(void) {

            Double PotScale;         //variable locale pour enregistrer le calibrage de sortie du CAN

            Double PWM_Percentage;       //variable locale pour enregistrer le pourcentage de changement de la MIT

 

PotScale = (ADRESH)/16 + 1; //Calibrer l'octet supérieur de la sortie du CAN

PWM_Percentage = 1/16 * PotScale;   //Calibrer la sortie de 0 à 1, équivalent à 100 %

PWM_High = Frequency_counter * PWM_Percentage;           //Définir la valeur haute Timer0 MIT

PWM_Low = Frequency_counter * (1 – PWM_Percentage);   //Définir la valeur basse Timer0 MIT

                        //PWM_High et PWM_Low sont des variables globales,

                        //Frequency_counter est une valeur constante Timer0 qui règle la fréquence.

}

 

Pseudo Code 4 : Sous-programme pour calculer le pourcentage MIT

 

 

Figure 3 : Schéma du timing pour la sortie MIT et le délai de timing

 

Le sous-programme d'interruption doit actualiser les positions du compteur Timer0 pour la prochaine interruption. Il doit aussi détecter si la durée de la MIT est longue ou courte. Par conséquent, quelques instructions doivent être ajoutées pour détecter le niveau du potentiomètre du dimmer et régler quotientométriquement la position du compteur Timer0 par rapport aux valeurs PWM_High et PWM_low indiquées dans le Pseudo code 4. Le Pseudo Code 5 indique le code de réglage de la MIT. Une instruction IF THEN permet de détecter l'état de la MIT.

*

*

*

If(bank_counter == bank1){    // bank1 est une constante définie sur 0

            If (PWM_High_Low_flag == OFF){ //vérifier le flag d'état MIT

                        get_PWM_ratio();        //Détecter l'entrée utilisateur pour le pourcentage MIT

                                    Timer0_counter = 65535 – PWM_High; //Définir la variable du compteur Timer0                                                             Update_Timer0_Counter(Timer0_counter); //sous-programme pour actualiser Timer0

                                                     

            I2C_send(Address_pionter_bank1n2); //Envoyer le pointeur d'adresse du registre des périphériques

            Bank1n2_pattern = ~Bank1n2_pattern; //compléter la variable avec ‘~’

            I2C_send((Bank1n2_pattern | ‘0000 1111’)); //protocole I2C – Envoyer l'état de la rangée

                                                            //(utiliser OR ‘|’ pour définir la rangée 1 sur Activé et la rangée 2 sur Désactivé)

                        PWM_High_Low_flag = ON; //Définir le flag

                        Delay_ON = OFF;

 

}else{

                        Timer0_counter = 65535 – PWM_Low; //Définir la variable du compteur Timer0

                                    Update_Timer0_Counter(Timer0_counter); //sous-programme pour actualiser Timer0

                                                                              

            I2C_send(Address_pionter_bank1n2); //Envoyer le pointeur d'adresse du registre des périphériques

            I2C_send(‘1111 1111’)); //protocole I2C – Éteindre toutes les LED

                        bank_counter = bank_counter + 1;

                        PWM_High_Low_flag = OFF; //Mettre le flag à zéro

                        Delay_ON = ON;

}

}

*

*

*

Pseudo Code 5 : Code pour régler le pourcentage MIT

 

Cette méthodologie peut aussi être appliquée avec un microcontrôleur 8 bits milieu de gamme, une mémoire de programmation supplémentaire, telle que la gamme PIC16F de Microchip. Une mise à niveau permettrait au sous-programme principal de gérer des séquences sophistiquées, par exemple des voyants de suivi. Le module Timer1 du microcontrôleur peut être utilisé pour modifier la durée, deux octets de RAM étant actualisés pour la séquence voulue.

Les concepteurs cherchent toujours de nouvelles solutions pour réduire les coûts sans affecter la performance. Il existe de nombreuses méthodes pour piloter les rangées de LED utilisées dans les rétroéclairages LCD ou des applications de séquences lumineuses supportant un système d'indication visuel efficace. Dans des applications à basse consommation, les LED peuvent être contrôlées en gérant les intervalles de temps de chaque rangée de LED. En outre, les microcontrôleurs à faible nombre de broches et les modules d'expansion de port E/S sont des options à faible coût qui permettent de créer des solutions intégrant une plus grande flexibilité.