Energiesparende LED-Beleuchtungsanwendungen: Eine Strom-Überwachungstechnik

Von Ezana Haile, leitender Anwendungstechniker, Abteilung für Analog- & Interface-Produkte

Microchip Technology Inc.

 

Das Gleichgewicht zwischen LED-Beleuchtungen und elektrischer Energie ist von hoher Bedeutung, wenn die Qualität des sichtbaren Lichts bei der Kontrolle eines LED-Satzes in einer Beleuchtungsanwendung ermittelt wird. Ein gleichzeitiges Beleuchten des gesamten LED-Satzes zwecks Erreichens der maximalen Lichtstärke kann bei Anwendungen mit niedrigem Energiebedarf auf Grund der eingeschränkten Stromquelle nicht möglich sein. Um eine optimale Leuchtkraft zu erzeugen, muss die Verlustleistung pro LED über eine Energiequelle mit geringer Leistungsaufnahme effizient gesteuert werden. Hierfür ist eine Strom-Überwachungstechnik erforderlich, bei der im Set nur eine LED-Reihe für eine bestimmte Zeit betrieben wird. Die sich abwechselnden LED-Reihen bleiben optisch unerkannt, wenn die gewünschte Lichtstärke erreicht ist.

 

Sowohl die verfügbare Leistung als auch die für die Anwendung erforderliche Lichtstärke müssen vorhanden sein, um die Anzahl der LEDs für ein vorgegebenes Zeitintervall bestimmen zu können. Lichtstärke und Durchlassstrom-Eigenschaften müssen verglichen werden, um die LEDs mit der gewünschten Lichtstärke auswählen zu können. Sobald die Anzahl der erforderlichen LEDs ermittelt wurde, kann diese LED-Anzahl für ein bestimmtes Zeitintervall betrieben werden. Dieses lässt sich aus dem Verhältnis des für die LEDs erforderlichen Gesamtstroms und dem verfügbaren Strom, wie folgt berechnen:

 

            # LEDs in einer Reihe = Insgesamt benötigter Strom für die LEDs / Insgesamt verfügbarer Quellenstrom

 

Die Frequenz mit der die LED-Reihe EIN/AUS (ON/OFF)-geschaltet wird, muss so eingestellt werden, dass die EIN-geschaltete Zeit für die volle Beleuchtung einer Reihe lange genug ist und die AUS-geschaltete Zeit durch die Zeit begrenzt wird, die benötigt wird, bevor die Lichtstärke der Reihe zusehends abnimmt. Die AUS-Zeit-Grenzwerte der Anzahl zusätzlicher LED-Reihen können über eine Zeitintervall-Steuerung kontrolliert werden.

 

Diese Technik kann mit geringem Kostenaufwand mit einer Taktquelle oder digitalen Flipflops eingerichtet werden, um die LED-Reihen sowie ein ODER-Gatter zu steuern, mit dem Ziel, eine Startbedingung mit einem einfachen Ein/Aus-Schalter erkennen zu können. Abbildung 1 zeigt ein Blockschaltbild einer D-Flipflop-Konfiguration zur Steuerung von vier LED-Reihen.

 

Abbildung 1: LED-Beleuchtungszeitintervall unter Verwendung einer Flipflop-Schaltung

 

Für den Start befindet sich das Flipflop in einem unveränderten Status und benötigt einen Startimpuls, der mindestens einen Taktzyklus lang andauert, sodass er vom ersten Flipflop bei der steigenden Taktflanke erkannt werden kann. Die Dauer des Startsignals muss von kurzer Dauer sein und kann nicht länger als ein Taktzyklus sein, andernfalls werden die ersten zwei Flipflop-Ausgänge gleichzeitig gesetzt und da der Quellenstrom begrenzt ist, wird die Beleuchtungsanwendung nicht ordnungsgemäß funktionieren. Bei der steigenden Flanke jedes Taktes wird bei dieser Einstellung eine LED-Reihe voll beleuchtet, was auf das menschliche Auge so wirkt, als ob alle LEDs gleichzeitig in voller Stärke eingeschaltet wären.  

 

Diese Umsetzung ist allerdings gleichförmig und bietet keinerlei Designflexibilität. Sie verfügt lediglich über einen Ein- oder Aus-Status. Diese Schaltung kann sich für Anwendungen wie LCD-Hintergrundbeleuchtungen eignen; wenn aber eine Dimm-Steuerung oder eine Mustererzeugung benötigt wird, bietet eine Mikrocontroller (MCU)-basierte Schaltung die größte Flexibilität bei einer gleichzeitig minimalen Auswirkung auf die Gesamtkosten der Lösung. Die Schaltung lässt sich mit weniger Komponenten einfacher herstellen, da der MCU jede LED-Reihe steuert, und kann ebenso Benutzereingaben zu Dimm-Steuerung und Musterauswahl erkennen. 

 

Ein kostengünstiger 8-Bit-Microcontroller mit einer niedrigen Stiftzahl, wie aus der PIC10F oder PIC12F-Serie von Microchip, mit einer E/A-Anschlusserweiterung wie der MCP23018 von Microchip würden eine kosteneffiziente Lösung bieten. E/A-Erweiterungen können auch zum Ansteuern von LEDs nützlich sein, wenn die Beleuchtungsschaltung weit vom MCU entfernt ist. 

 

E/A-Anschlusserweiterungen erweitern die E/A-Anschlüsse eines Microcontrollers. Bei dieser Anwendung steuert der MCU die E/A-Erweiterungsanschlüsse über das I2C™-Protokoll zum Ein- oder Ausschalten der LEDs. Zudem können hier die E/A-Stifte des MCU zum Erkennen von Benutzereingaben über einen Druckschalter oder zum Erkennen einer Potentiometerstufe für die Dimmer-Steuerung über den eingebauten Analog-Digital-Wandler verwendet werden.

 

E/A-Erweiterungen sind mit Ausgängen in Ausführungen Open-Drain oder Push-Pull verfügbar. Microcontroller können bei 3,3 V oder weniger betrieben werden, sodass eine E/A-Erweiterung mit Open-Drain-Ausgang für diese Anwendung gut geeignet ist. Der Vorteil hierbei ist, dass dadurch die LEDs bei 5V oder höher betrieben werden können, während Microcontroller und E/A-Erweiterung mit einer geringeren Spannung betrieben werden. Bei dem MCP23018 handelt es sich um eine 16-Bit-E/A-Anschlusserweiterung mit einem Open-Drain-Ausgang und einer I2C-Schnittstelle. Abbildung 2 zeigt einen Schaltplan für eine E/A-Erweiterung mit Open-Drain-Ausgang, die auf eine höhere Spannung als die MCU-Versorgungsspannung hochgeregelt wurde.

 

 

Abbildung 2: Kostengünstige, Microcontroller-basierte Beleuchtungslösung mit E/A-Anschlusserweiterung

 

Sobald der E/A-Anschluss klein eingestellt ist, ist die Spannung an der E/A-Erweiterung 0V und der Strom fließt, was die LED in Durchlassrichtung betreibt und einschaltet. Der LED-Vorspannungswiderstand begrenzt den Strom auf die LED für die benötigte Lichtstärke und fungiert ebenso als Pull-Up-Widerstand für den Open-Drain-Ausgang.

 

Wenn der Ausgangsanschluss der E/A-Erweiterung groß eingestellt ist, ist der Open-Drain-Ausgang ausgeschaltet oder der hohe Widerstand sowie die am E/A-Erweiterungsanschluss anliegende Spannung werden durch den Pull-Up-Widerstand auf 5V hochgeregelt. Die LED befindet sich in einem ausgeschalteten Status, da kein Strom fließt. Ein Vorteil des Open-Drain-Ausgangs ist auch, dass bei einer hochohmigen Konfiguration des Anschlusses die LED auf Grund der Paratisärkapazität eine längere Zeit zum Ausschalten benötigt. Hierdurch kann die nächste LED-Reihe für eine etwas längere Dauer eingeschaltet werden, verglichen mit ähnlichen Anwendungen mit einem Push-Pull-Ausgang.

 

 

Die 16 E/A-Anschlüsse von MCP23018 können bis zu 16 LEDs betreiben. Die Strommenge, die bei voll eingeschalteter LED in den E/A-Anschluss gelangen kann, kann durch die Ausgangssteuerung der E/A-Erweiterung begrenzt werden. Die Niederspannung des E/A-Anschlusses ist für maximal 0,6 V bei einer Stromstärke von 8,5 mA bestimmt. Wenn die Stromstärke größer als 8,5 mA ist, steigt die Niederspannung exponentiell an. Der absolute Maximalstrom beträgt 25 mA.

 

Falls der Quellenstrom beispielsweise auf 5V/50 mA begrenzt wird und eine Stromstärke von 2 mA für den  Microcontroller vorgesehen ist, können E/A-Erweiterung sowie die Widerstände zur Benutzereingabe-Erkennung und der Rest des verfügbaren Stromes für die LED-Beleuchtung verwendet werden. Es können vier LEDs pro Reihe gesteuert werden, wenn die Lichtstärke der LED von ungefähr 10 mA ausreichend ist. In diesem Beispiel ist der Wert des Strombegrenzungswiderstands ungefähr 440 W.

 

Die in Abbildung 1 dargestellte Zeitmessung kann über einen kurzen MCU-Befehlscode kopiert werden. So kann zum Beispiel unter Bezugnahme auf den Pseudo Code 1 das Hauptunterprogramm eine While-Endlosschleife sein. Bei MCU-Timerintervallen (Timer0) sendet ein Unterbrechungsservice-Programm einen I2C-Befehl an die E/A-Erweiterung, um nur eine LED-Reihe einzuschalten. Dieses Unterbrechungsservice-Programm zählt oder verfolgt den Status der LED-Reihe so wie die aktuell eingeschaltete Reihe und die Anschlusskonfiguration der entsprechenden E/A-Erweiterung als hoch oder niedrig. Anfänglich oder nach der Rücksetzung des MCU bei der ersten Timer0-Unterbrechung wird die Reihe 1 eingeschaltet. Bei der zweiten Unterbrechung ist die Reihe 1 ausgeschaltet und die Reihe 2 eingeschaltet. Bei der dritten Unterbrechung ist die Reihe 2 ausgeschaltet und die Reihe 3 eingeschaltet. Bei der vierten Unterbrechung ist die Reihe 3 ausgeschaltet und die Reihe 4 eingeschaltet. Zudem wird die Zählervariable der Reihe gelöscht. Bei der nächsten Unterbrechung wiederholt sich der Zyklus durch Einschalten von Reihe 1 und Ausschalten von Reihe 4. Andere Variablen wie Command_byte, Address_pointer_bank1n2 und Address_pointer_bank3n4 sind Konstanten, die in der Header-Datei definiert sind. Bei einer solchen Durchführung leistet die Schaltung die gewünschte Lichtstärke und es scheint, dass alle LEDs gleichzeitig von der verfügbaren Stromquelle eingeschaltet sind. 

 

void main (Void){

initialize();    //Inizialisieren der PICmicro-Peripheriegeräte einschließlich Timer0 sowie der Peripherigeräte der E/A-Erweiterung

bank_counter = 0;    //Zählervariable der Reihe löschen

while(1){}    //While-Endlosschleife

}

Void Interrupt int_service(void){

            TurnOffAll_LEDs();        //Unterprogramm zum Ausschalten aller zuvor eingeschalteten LEDs

            I2C_start();    //I2C - Protokoll  – Unterprogramm Signal Starten

            I2C_send(Comand_byte);  //I2C Protokoll – Unterprogramm Byte Senden

 

If(bank_counter == bank1){          // Reihe1 ist eine als 0 definierte Konstante

            I2C_send(Address_pionter_bank1n2);  //Adresszeiger des Peripherieregisters senden

            I2C_send(‘0000 1111’);  //I2C-Protokoll– Status der Reihe senden (Reihe 1 ein und Reihe 2 aus)

            bank_counter = bank_counter + 1;

}

If(bank_counter == bank2){      // Reihe1 ist eine als 1 definierte Konstante

            I2C_send(Address_pionter_bank1n2);  //Adresszeiger des Peripherieregisters senden

            I2C_send(‘1111 0000’);  //I2C-Protokoll– Status der Reihe senden (Reihe 2 ein und Reihe 1 aus)

            bank_counter = bank_counter + 1;

}

If(bank_counter == bank3){      // Reihe1 ist eine als 2 definierte Konstante

            I2C_send(Address_pionter_bank3n4);  //Adresszeiger des Peripherieregisters senden

            I2C_send(‘0000 1111’);  //I2C-Protokoll– Status der Reihe senden (Reihe 3 ein und Reihe 4 aus)

            bank_counter = bank_counter + 1;

}

If(bank_counter == bank4){      // Reihe1 ist eine als 3 definierte Konstante

            I2C_send(Address_pionter_bank3n4);  //Adresszeiger des Peripherieregisters senden

            I2C_send(‘1111 0000’);  //I2C-Protokoll– Status der Reihe senden (Reihe 4 ein und Reihe 3 aus)

            bank_counter = 0;

}

I2C_stop();    //I2C - Protokoll  – Unterprogramm Signal Starten

}

Pseudo Code 1: Codefluss des Microcontroller-Unterbrechungsservice-Programmes

 

Dimmer-Steuerung und LED-Mustererzeugung

Über eine Microcontroller-basierte Anwendung lassen sich interessante Beleuchtungsmuster auf einfache Weise erzeugen: Die Ausgangszustände der E/A-Anschlusserweiterung werden von 2 Bytes von RAM-Variablen geladen und als Bank1n2_pattern und Bank3n4_pattern bezeichnet.  Die Hälfte jedes Byte entspricht jeder Reihe. Eine vordefinierte Nachschlagetabelle enthält unterschiedliche Muster von 1s und 0s für jede Reihe.

 

Um den Ein/Aus-Status des Druckschalters kontinuierlich zu überwachen, wird eine IF THEN-Anweisung zum MCU-Code hinzugefügt, die While-Endlosschleife des Hauptunterprogrammes. Nach kurzem Betätigen des Druckschalters wird ein Muster aus der Nachschlagetabelle in die zwei Bytes des RAM geladen und als Bank1n2_pattern und Bank3n4_pattern bezeichnet. Sobald die Timer0-Unterbrechung auftritt, wird das neue Muster an die E/A-Erweiterung gesendet und die LEDs werden dem Muster entsprechend beleuchtet. Das Hauptunterprogramm durchläuft die Nachschlagetabelle, sobald der Druckschalter weiterhin durch den Benutzer kurz betätigt wird. Zum Anzeigen eines Wechsellichts muss einfach die Ergänzung des vorherigen Musters gesendet werden. Wenn zum Beispiel das Muster von Reihe1 ‘0101’ ist, ist die Ergänzung ‘1010,’ wie in Pseudo Code 2 gezeigt ist, einem Ausschnitt aus Pseudo Code 1.

 

*

*

*

If(bank_counter == bank1){          // Reihe1 ist eine als 0 definierte Konstante

            I2C_send(Address_pionter_bank1n2);  //Adresszeiger des Peripherieregisters senden

            Bank1n2_pattern = ~Bank1n2_pattern; //Ergänzung der Variable durch ‘~’

            I2C_send((Bank1n2_pattern | ‘0000 1111’));  //I2C-Protokoll – Status der Reihe senden

                                                                        //(use OR ‘|’ zum Einschalten von Reihe 1 und Ausschalten von Reihe 2)

            bank_counter = bank_counter + 1;

}

*

*

*

Pseudo Code 2: Mustererzeugung

 

 

Auf jeden Fall muss in dem Unterbrechungsunterprogramm eine Verzögerung vor die ein/aus IF THEN-Anweisungen der Reihe hinzugefügt werden, um die abwechselnden Muster einer Sichtprüfung unterziehen zu können. Dies wird mit einer Delay_ON-Flagge erreicht, so dass bei der folgenden Unterbrechung nur ein Verzögerungszähler die Anzahl der Verzögerungsunterbrechungen abwärts zählt. Der Verzögerungswert kann auch vom Benutzer über ein Potentiometer gewählt werden, bei dem die mittlere Registerkarte an den Eingang des auf dem Chip ausgeführten Analog-Digital-Wandlers (ADC) angeschlossen ist. Die digitalen Daten des ADC werden von der minimalen bis zur maximalen Verzögerung durch Erkennung der oberen vier Bits, die 16 Stufen liefern, skaliert. Ein feineres Verhältnis kann durch Ermitteln der oberen fünf Bits oder 32 Stufen eingestellt werden. Die maximale Verzögerung ist die Langsamste, bei der die LED blinken können. Darüber hinaus scheinen bei einer minimalen Verzögerung alle LEDs voll eingeschaltet zu sein. Das Zeitdiagramm in Abbildung 3 zeigt die Verzögerungsposition tDELAY.

 

*

*

*

Void Interrupt int_service(void){

            TurnOffAll_LEDs();        //Unterprogramm zum Ausschalten aller zuvor eingeschalteten LEDs

            If (Delay_ON == ON){    // ON ist eine als 1 definierte Konstante

                        Update_Timer0_Counter(Timer0delay_interval);        //Unterprogramm zum Aktualisieren von Timer0

                                                            // Timer0delay_interval ist eine Konstante zum Einstellen der minimalen Verzögerung

                        Delay_Counter = Delay_Counter – 1;  //Abwärtszählung der Anzahl der Verzögerungsunterbrechungen

                        If(Delay_Counter == 0){

                                    Delay_ON = OFF;    // Verzögerungsflagge für die nächste Unterbrechung löschen

                                    Delay_Counter  = Get_Delay_Counter();        //Unterprogramm zum Erkennen der Benutzereingabe

                                                            //und Einstellen der Verzögerungszähler-Variable

                        }else{

                                    Delay_ON = ON; // Verzögerungsflagge auf ON lassen

                                    Return;            //Unterbrechungsdienst-Programm verlassen

                        }

            }

 

            I2C_start();    //I2C - Protokoll  Unterprogramm Signal starten

            I2C_send(Comand_byte);  //I2C Protokoll – Unterprogramm Byte Senden

If(bank_counter == bank1){          // Reihe1 ist eine als 0 definierte Konstante

            I2C_send(Address_pionter_bank1n2);  //Adresszeiger des Peripherieregisters senden

            Bank1n2_pattern = ~Bank1n2_pattern; //Ergänzung der Variable durch ‘~’

            I2C_send((Bank1n2_pattern | ‘0000 1111’));  //I2C-Protokoll – Status der Reihe senden

                                                                        //(use OR ‘|’ zum Einschalten von Reihe 1 und Ausschalten von Reihe 2)

            bank_counter = bank_counter + 1;

                        Delay_ON = ON; // Verzögerungsflagge einschalten

}

*

*

*

Pseudo Code 3:  Umsetzung des Verzögerungscodes, um das Beleuchtungsmuster zu sehen

 

 

Zur Steuerung der Zeitintervall-Dauer jeder Reihe bedient sich die Dimmer-Steuerung der Pulsweitenmodulation (PWM). Die Timer0-Unterbrechungsdauer hat zwei Werte: einen für die lange Dauer und den anderen für eine kurze Dauer, und zwar proportional zum PWM-Prozentverhältnis, das über ein Rändelrad-Potentiometer eingestellt wird; die mittlere Registerkarte ist an den ADC-Eingang angeschlossen. Über die Auswahl der oberen 4 oder 5 Bits aus dem ADC kann die Auflösungsstufe eingestellt werden. Die Timer0-Zählerposition wird ratiometrisch eingestellt, und zwar mit den skalierten ACD-Daten, wobei der 100-%-PWM gleich der maximalen Zählerposition sowie die volle Beleuchtung und 0 % die minimale oder niedrigste Dimmerstufe ist. Pseudo Code 4 zeigt die PWM-Skalierungsgleichung für 16 Stufen; Abbildung 3 zeigt das Zeitdiagramm für die PWM-Dauer, tPWM_LOW und tPWM_HIGH.

 

Void get_PWM_ratio(void) {

            Double PotScale;         //lokale Variable zur Speicherung der ADC-Ausgangsskala

            Double PWM_Percentage;       //lokale Variable zur Speicherung des PWM-Änderungsprozentsatzes

 

PotScale = (ADRESH)/16 + 1; //Skalierung von ADC-Ausgang High-Byte

PWM_Percentage = 1/16 * PotScale;   //Skalieren des Ausganges von 0 bis 1, gleichwertig mit 100%

PWM_High = Frequency_counter * PWM_Percentage;           //Einstellen von PWM auf hohen Timer0-Wert

PWM_Low = Frequency_counter * (1 – PWM_Percentage);   //Einstellen von PWM auf niedrigen Timer0-Wert

                        //PWM_High und PWM_Low sind globale Variablen,

                        //und Frequency_counter ist ein konstanter Timer0-Wert zur Frequenzeinstellung.

}

 

Pseudo Code 4:  Unterprogramm zur Berechnung des PWM-Verhältnisses

 

Microchip's Figure 3.jpg

 

Abbildung 3: Zeitdiagramm für PWM-Ausgang und zeitliche Verzögerung

 

Das Unterbrechungsservice-Programm muss die Timer0-Zählerpositionen für die nächste Unterbrechung aktualisieren. Ebenso muss es erkennen, ob die Dauer für PWM lang oder kurz ist. Aus diesem Grund müssen ein paar Anweisungen hinzugefügt werden, um die Potentiometerstufe für die Dimmer-Steuerung zu erkennen und die Timer0-Zählerposition mit den im Pseudo Code 4 gezeigten Werten PWM_High und PWM_low ratiometrisch zu skalieren. Pseudo Code 5 zeigt den Code zum Einstellen des PWM; eine IF THEN-Anweisung wird zum Erkennen des PWM-Status verwendet.

 

 

*

*

*

If(bank_counter == bank1){    // Reihe1 ist eine als 0 definierte Konstante

            If (PWM_High_Low_flag == OFF){   //PWM-Statusflagge überprüfen

                        get_PWM_ratio();        //Benutzereingabe für das PWM-Verhältnis ermitteln

                                    Timer0_counter = 65535 – PWM_High;  //Timer0-Zählervariable einstellen                                                   Update_Timer0_Counter(Timer0_counter);        //Unterprogramm zum Aktualisieren von Timer0

                                                           

            I2C_send(Address_pionter_bank1n2);  //Adresszeiger des Peripherieregisters senden

            Bank1n2_pattern = ~Bank1n2_pattern; //Ergänzung der Variable durch ‘~’

            I2C_send((Bank1n2_pattern | ‘0000 1111’));  //I2C-Protokoll – Status der Reihe senden

                                                            //(use OR ‘|’ zum Einschalten von Reihe 1 und Ausschalten von Reihe 2)

p;                       PWM_High_Low_flag = ON;   //Flagge einstellen

                        Delay_ON = OFF;

 

}else{

                        Timer0_counter = 65535 – PWM_Low;  //Timer0-Zählervariable einstellen

                                    Update_Timer0_Counter(Timer0_counter);        //Unterprogramm zum Aktualisieren von Timer0

                                                                                     

            I2C_send(Address_pionter_bank1n2);  //Adresszeiger des Peripherieregisters senden

            I2C_send(‘1111 1111’));  //I2C-Protokoll – alle LEDs abschalten

                        bank_counter = bank_counter + 1;

                        PWM_High_Low_flag = OFF;  //Flagge löschen

                        Delay_ON = ON;

}

}

*

*

*

Pseudo Code 5:  Codefluss für die PWM-Verhältnis-Einstellung

 

Diese Methode kann auch an einem 8-Bit-Microcontroller aus dem mittleren Leistungsbereich mit einem zusätzlichen Programmspeicher, wie die PIC16F-Serie von Microchip. Über eine Aktualisierung ist das Hauptunterprogramm in der Lage, anspruchsvolle Lichtmuster, wie z. B. Lauflichter, verarbeiten zu können. Das MCU-Timer1-Modul kann dafür verwendet werden, um die Dauer zu verändern, wo die zwei RAM-Bytes für das Lauflicht-Muster aktualisiert werden.

 

Designer sind stets auf der Suche nach neuen, kostensparenden Lösungen, ohne dabei an Leistung einzubüßen. Es gibt viele Methoden, um die in LCD-Hintergrundbeleuchtungen oder Beleuchtungsmuster-Anwendungen verwendeten LED-Reihen für eine wirksame Beleuchtung effizient zu betreiben. Bei Anwendungen mit geringer Leistungsaufnahme können LEDs durch Verwalten des Zeitintervalls für jede LED-Reihe gesteuert werden. Hinzu kommt, dass Microcontroller mit niedriger Stiftzahl und E/A-Anschlußerweiterungen eine kostengünstige Alternative für Beleuchtungslösungen bei einer gleichzeitigen Design-Flexibilität bieten.