Software-Fader

© Eberhard Haug 2003-2017

Optimale Darstellung dieser Website
bei aktiviertem
"Active Scripting" (LED-Menü-Buttons).

Bildschirm-Auflösung 800x600 wird unterstützt

Besucher seit 6.1.2004:
 

WEBCounter by GOWEB

 

LED-Crossfader mit Luminanz-Korrektur (27.4.2016)

Nach LED-Lauflicht und PWM-Poti-Dimmer gibt es nun noch einen µC-basierenden LED-Crossfader als s’AVR-Programm, wenn auch hier aufgrund des einfachen Programms mit nur zwei s’AVR-Strukturen.

Zum Umblenden zwischen zwei LED-Treibern dient wiederum ein Poti, wobei z.B. Links-Anschlag LED-Treiber #1 100% AUS und Rechts-Anschlag LED-Treiber #1 100% EIN und LED-Treiber #2 umgekehrt.

Beide LED-Treiber benötigen einen PWM-Dimm-Eingang (meist ein Enable-Eingang), der jeweils durch einen der beiden PWM-Ausgänge des AVR-µC angesteuert wird.

Beide PWM-Kanäle werden in diesem Beispiel mit Timer 1 des AVR-µC und für superweiches Umblenden mit 10 Bit Auflösung realisiert. Die PWM-Frequenz beträgt 225 Hz (bedingt durch 3,6864 MHz CPU-Takt).

Und so geradlinig schaut das s’AVR-Programm einschließlich der großen Tabelle für die 10-bit-Luminanz-Korrektur aus (wiederum eine Kopie aus der Atmel-Studio-Quelldatei, Assembler-Befehle sind blau markiert):

.def rmp = r16        ; rmp = temporary register (multi purpose)

.def ADCresultL = r20 ; ADC result

.def ADCresultH = r21 ; ADC result

.def PWMvalueL = r22  ; value for PWM

.def PWMvalueH = r23  ; value for PWM

 

clr  rmp

out  DDRC,rmp         ; all Port C pins are inputs (default)

                      ; ADC (using pin ADC5 at PORTC,5):

ldi  rmp,(1<<REFS0 | 1<< MUX2 | 1<< MUX0) ; 0b0100_0101

sts  ADMUX,rmp        ; select VCC ref, ADC5

clr  rmp

sts  ADCSRB,rmp       ; ADC free running mode (default setting)

ldi  rmp,1<<ADC5D     ; 0b0010_0000

sts  DIDR0,rmp        ; disable digital in for ADC5

ldi  rmp,(1<<ADEN | 1<<ADSC | 1<<ADPS2 | 1<<ADPS0) ; 0b1100_0101

sts  ADCSRA,rmp       ; enable ADC, 114 kHz sampling rate

                      ; for free running mode ADSC must be set as well!

 

                      ; PWM using TC1 at pin 15 and pin 16

                      ; (OC1A at PORTB,1 and OC1B at PORTB,2)

                      ; non-inverted mode, 10 bit PWM, 2 ports A and B:

ldi  rmp,(1<<COM1A1 | 1<<COM1B1| 1<<WGM11 | 1<<WGM10)

sts  TCCR1A,rmp

ldi  rmp,(1<<CS11)    ; WGM12/13 = 0 --> Phase Correct PWM mode,

sts  TCCR1B,rmp       ; prescaler /8 --> 225 Hz PWM @3,6864 MHz clock

sbi  DDRB,1           ; enable OC1A as output (pin 15)

sbi  DDRB,2           ; enable OC1B as output (pin 16)

cbi  PORTB,1          ; prepare Port B1 for LOW if set as input

cbi  PORTB,2          ; prepare Port B2 for LOW if set as input

 

LOOP                    ; main loop

 rcall LCDStart         ; display lpcnt

 lds   rmp,ADCSRA       ; read ADCSRA

 sbr   rmp,1<<ADSC      ; set start ADC bit

 sts   ADCSRA,rmp       ; write back ADCSRA

 REPEAT

  lds  rmp,ADCSRA       ; check ADCSRA

 UNTIL !rmp,ADSC        ; ADSC cleared after ADC ready

 lds   ADCresultL,ADCL  ; get ADC low byte

 lds   ADCresultH,ADCH  ; get ADC high byte

 ldi   zl,low(2*LumiTable)

 ldi   zh,high(2*LumiTable)

 mov   xl,ADCresultL    ; keep original ADC copy

 mov   xh,ADCresultH    ; keep original ADC copy

                        ; movw xl,ADCResultL

                        ; alternately MOVW instead of 2x MOV

 lsl   xl               ; *2 due to word data

 rol   xh               ; *2 due to word data

 add   zl,xl

 adc   zh,xh

 lpm   PWMvalueL,z+     ; get corrected value for PWM ...

 lpm   PWMvalueH,z      ; ... from LumiTable

 sts   OCR1AH,PWMvalueH ; initiate PWM, high byte first

 sts   OCR1AL,PWMvalueL

 ldi   rmp,0xff         ; now handle complementary PWM channel

 sub   rmp,ADCresultL   ; get 0xffff - ADCResult for channel B

 mov   ADCResultL,rmp

 ldi   rmp,0x03         ; take only 10 bits into account

 sbc   rmp,ADCresultH

 mov   ADCresultH,rmp   ; now complementary value available

 ldi   zl,low(2*LumiTable)

 ldi   zh,high(2*LumiTable)

 lsl   ADCresultL       ; *2 due to word data

 rol   ADCresultH       ; *2 due to word data

 add   zl,ADCresultL

 adc   zh,ADCresultH

 lpm   PWMvalueL,z+     ; get corrected value for PWM ...

 lpm   PWMvalueH,z      ; ... from LumiTable

 sts   OCR1BH,PWMvalueH ; initiate PWM, high byte first

 sts   OCR1BL,PWMvalueL

ENDL                    ; main loop (forever)

 

LumiTable:

.dw 0,0,0,0,0,1,1,1,1,1,1,1,1,1,2,2

.dw 2,2,2,2,2,2,2,3,3,3,3,3,3,3,3,3

.dw 4,4,4,4,4,4,4,4,4,5,5,5,5,5,5,5

.dw 5,5,6,6,6,6,6,6,6,6,6,7,7,7,7,7

.dw 7,7,7,7,8,8,8,8,8,8,8,8,8,9,9,9

.dw 9,9,9,9,9,9,10,10,10,10,10,10,10,10,10,11

.dw 11,11,11,11,11,11,12,12,12,12,12,12,12,12,13,13

.dw 13,13,13,13,13,14,14,14,14,14,14,14,15,15,15,15

.dw 15,15,16,16,16,16,16,16,17,17,17,17,17,17,18,18

.dw 18,18,18,18,19,19,19,19,19,19,20,20,20,20,20,21

.dw 21,21,21,21,22,22,22,22,22,23,23,23,23,23,24,24

.dw 24,24,24,25,25,25,25,26,26,26,26,26,27,27,27,27

.dw 28,28,28,28,29,29,29,29,29,30,30,30,30,31,31,31

.dw 31,32,32,32,32,33,33,33,34,34,34,34,35,35,35,35

.dw 36,36,36,37,37,37,37,38,38,38,39,39,39,39,40,40

.dw 40,41,41,41,42,42,42,42,43,43,43,44,44,44,45,45

.dw 45,46,46,46,47,47,47,48,48,48,49,49,49,50,50,50

.dw 51,51,51,52,52,52,53,53,54,54,54,55,55,55,56,56

.dw 56,57,57,58,58,58,59,59,60,60,60,61,61,61,62,62

.dw 63,63,63,64,64,65,65,66,66,66,67,67,68,68,68,69

.dw 69,70,70,71,71,72,72,72,73,73,74,74,75,75,76,76

.dw 76,77,77,78,78,79,79,80,80,81,81,82,82,83,83,84

.dw 84,85,85,86,86,86,87,87,88,89,89,90,90,91,91,92

.dw 92,93,93,94,94,95,95,96,96,97,97,98,98,99,100,100

.dw 101,101,102,102,103,103,104,105,105,106,106,107,107,108,109,109

.dw 110,110,111,111,112,113,113,114,114,115,116,116,117,118,118,119

.dw 119,120,121,121,122,122,123,124,124,125,126,126,127,128,128,129

.dw 129,130,131,131,132,133,133,134,135,135,136,137,137,138,139,140

.dw 140,141,142,142,143,144,144,145,146,146,147,148,149,149,150,151

.dw 152,152,153,154,154,155,156,157,157,158,159,160,160,161,162,163

.dw 163,164,165,166,166,167,168,169,170,170,171,172,173,173,174,175

.dw 176,177,177,178,179,180,181,182,182,183,184,185,186,186,187,188

.dw 189,190,191,192,192,193,194,195,196,197,197,198,199,200,201,202

.dw 203,204,204,205,206,207,208,209,210,211,212,213,213,214,215,216

.dw 217,218,219,220,221,222,223,224,225,225,226,227,228,229,230,231

.dw 232,233,234,235,236,237,238,239,240,241,242,243,244,245,246,247

.dw 248,249,250,251,252,253,254,255,256,257,258,259,260,261,262,263

.dw 264,265,266,268,269,270,271,272,273,274,275,276,277,278,279,280

.dw 281,283,284,285,286,287,288,289,290,291,293,294,295,296,297,298

.dw 299,300,302,303,304,305,306,307,309,310,311,312,313,314,316,317

.dw 318,319,320,322,323,324,325,326,328,329,330,331,332,334,335,336

.dw 337,339,340,341,342,344,345,346,347,349,350,351,352,354,355,356

.dw 357,359,360,361,363,364,365,367,368,369,370,372,373,374,376,377

.dw 378,380,381,382,384,385,386,388,389,391,392,393,395,396,397,399

.dw 400,402,403,404,406,407,408,410,411,413,414,416,417,418,420,421

.dw 423,424,426,427,428,430,431,433,434,436,437,439,440,442,443,445

.dw 446,448,449,451,452,454,455,457,458,460,461,463,464,466,467,469

.dw 470,472,473,475,476,478,480,481,483,484,486,487,489,491,492,494

.dw 495,497,499,500,502,503,505,507,508,510,511,513,515,516,518,520

.dw 521,523,525,526,528,530,531,533,535,536,538,540,541,543,545,546

.dw 548,550,552,553,555,557,558,560,562,564,565,567,569,571,572,574

.dw 576,578,579,581,583,585,587,588,590,592,594,596,597,599,601,603

.dw 605,606,608,610,612,614,616,617,619,621,623,625,627,629,630,632

.dw 634,636,638,640,642,644,646,647,649,651,653,655,657,659,661,663

.dw 665,667,669,671,673,674,676,678,680,682,684,686,688,690,692,694

.dw 696,698,700,702,704,706,708,710,712,714,716,719,721,723,725,727

.dw 729,731,733,735,737,739,741,743,745,748,750,752,754,756,758,760

.dw 762,764,767,769,771,773,775,777,779,782,784,786,788,790,792,795

.dw 797,799,801,803,806,808,810,812,814,817,819,821,823,826,828,830

.dw 832,835,837,839,841,844,846,848,851,853,855,857,860,862,864,867

.dw 869,871,874,876,878,881,883,885,888,890,892,895,897,899,902,904

.dw 907,909,911,914,916,919,921,923,926,928,931,933,936,938,940,943

.dw 945,948,950,953,955,958,960,963,965,968,970,973,975,978,980,983

.dw 985,988,990,993,995,998,1000,1003

.dw 1005,1008,1011,1013,1016,1018,1021,1023


Einzig die Include-Zeile für den jeweiligen AVR-µC (hier wiederum ein ATmega328P), die Interrupt-Sprungtabelle und die Stack-Initialisierung sind nicht im Quellprogramm dargestellt und müssen je nach verwendetem AVR-µC entsprechend ergänzt werden.

 

Komplement

 

Im vorliegenden Beispiel wird die Helligkeit zwischen links und rechts linear aufgeteilt und zwar so, dass die Summe immer 100% ist. D.h. wenn beim linken Kanal 0% eingestellt ist (also komplett dunkel), ergeben sich für den rechten Kanal 100% (also maximal hell).

 

Bei 10-bit-Auflösung des A/D-Wandlers ergibt sich folgende Formel:

 

Helligkeit_rechts = 0x3ff - Helligkeit_links

 

Aus den beiden Werten Helligkeit_links und Helligkeit_rechts wird das PWM-Tastverhältnis (also der LED-Strom) für beide Kanäle getrennt gemäß Luminanz-Kennlinie per Software bestimmt.

 

D.h., dass bei 50% Helligkeit beide Kanäle für einigermaßen richtiges Helligkeitsempfinden nur ca. 18,35% PWM-Tastverhältnis bzw. LED-Strom haben.

 

Screen-Shots

 

Hier ein paar Oszillogramme, zunächst beide Kanäle gleich hell eingestellt (Poti in Mittenstellung, Kanal #1 = 0x1ff, Kanal #2 = 0x200), wodurch sich ca. 18,35% PWM-Tastverhältnis ergeben:

 

CrossFader18,35

 

 

Hier Kanal #1 mit einem Helligkeitswert von 0xff (bzw. 4,4% LED-Strom) und Kanal #2 = 0x300:

 

Crossfader4,4

 

Und hier noch die entgegengesetzte Einstellung, nämlich Kanal # 1 = 0x2ff (bzw. 48,3% LED-Strom) und Kanal #2 = 0x100:

 

CrossFader48,3

 

Bei Poti-Anschlag links oder rechts ist einer der beiden LED-Treiber 100% ein und der andere 100% aus, so wie es sein soll.

 

Enable oder Shutdown

 

Falls die beiden mittels PWM angesteuerten LED-Treiber statt einem Enable-Eingang einen Shutdown-Eingang haben, muss man die PWM des µC per TCCR1A eben statt "non-inverting" als "inverting" konfigurieren. Der Rest des Programms bleibt unverändert.

 

Statt Poti

 

Dank µC ist man bezüglich Bedienelement natürlich sehr flexibel.

 

So könnte man zum Umblenden statt einem Potenziometer auch zwei entprellte Taster "Umblenden nach rechts" bzw. "Umblenden nach links" nehmen, oder gleich einen Mini-Joy-Stick oder Dreh-Encoder, mit deren Taster man den jeweils eingestellten Wert bei Bedarf in das EEPROM des µC abspeichert, damit die gewünschte Einstellung beim nächsten Einschalten erhalten bleibt (es sei denn, man wünscht eine beliebige andere Voreinstellung beim Einschalten).

 

Das Abspeichern der aktuellen Einstellung kann man sich bei Verwendung eines Potis natürlich ersparen.

 

nach oben