• Willkommen im Geoclub - dem größten deutschsprachigen Geocaching-Forum. Registriere dich kostenlos, um alle Inhalte zu sehen und neue Beiträge zu erstellen.

LED per PWM dimmen

ksbender

Geocacher
Nachdem ja allerseits das Kochbuch schon verwendet und die entsprechenden RL massenhaft verkauft werden, möchte ich für einen neuen Nachtcache mal was anderes machen.
Warum sollten die LED´s eigentlich so auffällig blinken? Einfach die LED im RL nur einmal ganz langsam an- und dann wieder ausgehen lassen wäre doch auch mal was.
Wie baut man eine PWM in den Code ein?
Beim Attiny13 sind es wohl die Pins 5 und 6 bzw. PB0 und PB1 mit denen das funktionieren müßte. Aber wie sieht die Umsetzung im Basic-Code aus?
Hat damit schon jemand gearbeitet?
Wäre für gute Hinweise bzw. Code-Beisliele dankbar.
Gruß
ksbender
 

hendyp

Geocacher
ksbender schrieb:
Warum sollten die LED´s eigentlich so auffällig blinken? Einfach die LED im RL nur einmal ganz langsam an- und dann wieder ausgehen lassen wäre doch auch mal was.
Das habe ich mir auch schon einmal gedacht, blinkende LEDs sind irgendwie stressig... :roll:

ksbender schrieb:
Wie baut man eine PWM in den Code ein?
Beim Attiny13 sind es wohl die Pins 5 und 6 bzw. PB0 und PB1 mit denen das funktionieren müßte. Aber wie sieht die Umsetzung im Basic-Code aus?
Hat damit schon jemand gearbeitet?
Ich habe bisher nur Software-PWM und auch nur unter C gemacht :eek:ps: . Damit's aber so richtig schön aussah, habe ich zusätzlich noch diese Seite zur Festlegung des "PWM-Wertes" benutzt.
 

schnasemann

Geocacher
Zähler, der inkrementiert wird. Der wiederum die Schwelle einer großen Schleife abfragt.
Pseudocode, bin eher ein C-ler
Zähler = Zähler +1
for i = 1 to 100 do
led = 1
if i >= zähler
led =0;
next i
schleife nach ganz oben.

Das dimmt schonmal "aufwärts". Wobei man bedenken muss, dass das mit dem LED-Dimmen sicherlich logarithmisch ist (gerade Deinen 2. Link gelesen, Vermutung mit log war also richtig).
Warum ichs nicht nehmen würde ist, weil es Zeit kostet, weil es, ausser, dass es smooth ist, nichts bringt und schlechter ins Auge geht.
Krasses Blinken fällt mehr auf und spart Strom.
 

thomas_st

Geowizard
ksbender schrieb:
Warum sollten die LED´s eigentlich so auffällig blinken? Einfach die LED im RL nur einmal ganz langsam an- und dann wieder ausgehen lassen wäre doch auch mal was.
PWM mache ich bei meinen RL inzwischen grundsätzlich und zwar aus zwei Gründen:
1.) der erwähnte: An/Aus ist oft langweilig und so ein weiches Anschwellen/Abschwellen der Helligkeit empfinde ich als angenehmer. Insbesondere auch für Kinder ist so was irgendwie schöner / geheimnisvoller.
2.) Zum Stromsparen. Ich lege die RL-Hardware immer so aus, das der maximal erlaubte Strom durch die LEDs fließt. Wenn die damit erzielte Helligkeit zu hoch ist, wird mittels PWM runtergedimmt. So kann man die Helligkeit des RL per "Firmware-Update" anpassen und verringert die im LED-Vorwiderstand verbratene Leistung.

ksbender schrieb:
Wie baut man eine PWM in den Code ein?
Ich nutze hier die Hardware-PWM des Tiny. Die Ansteuerung in C würde (Codeausschnitte) so aussehen
Code:
const BYTE bSequenz[] PROGMEM = {  0,   0,   0,   0,   0,   1,   2,   3,
                                   4,   5,   7,  10,  13,  16,  21,  25,
[...]
                                   7,   5,   4,   3,   2,   1,   0,   0,
                                   0,   0,   0 };

void doBlink(void)
{
	// Start der Blinksequenz: Initialisieren des Timers und der PWM
	if(wBlinkCounter == 0)
	{
		TCCR0A = 1<<COM0A1 | 1<<COM0A0 |       // Set OC0A on Compare Match, clear OC0A at TOP
				 0<<COM0B1 | 0<<COM0B0 |       // Normal port operation, OC0B disconnected.
				 1<<WGM01  | 1<<WGM00;         // Fast PWM / TOP = 0xff
		TCCR0B = 0<<WGM02  |                   // Fast PWM / TOP = 0xff
				 0<<CS02 | 0<<CS01 | 1<<CS00; // clkI/O/(No prescaling)
	}
	
	if(wBlinkCounter < 155)
	{	// Neuen Helligkeitswert aus dem Feld laden und ins PWM-Vergeleichsregister schreiben
		OCR0A = 255-pgm_read_byte(&bSequenz[(BYTE)wBlinkCounter]);
	}
	else	// Wenn die Sequenz zuende ist: LEDs ausschalten und Timer+PWM ausschalten
	{
		TCCR0A = 0<<COM0A1 | 0<<COM0A0 |       // Normal port operation, OC0A disconnected.
				 0<<COM0B1 | 0<<COM0B0;        // Normal port operation, OC0B disconnected.
		TCCR0B = 0<<CS02 | 0<<CS01 | 0<<CS00; // No clock source (Timer/Counter stopped)
[...]
    }
[...]
}


int main (void)
{
[...]
    while(1)
	{
		if(!fBlinkMode)
			set_sleep_mode(SLEEP_MODE_PWR_DOWN);
		else
			set_sleep_mode(SLEEP_MODE_IDLE);
		sleep_enable();
		sleep_cpu();
	}
        
    return (0);
}
Eine Falle lauert in den Stromsparmodi: während die LEDs leuchten (also die PWM läuft), darf der Tiny nicht in den Powerdown-Modus versetzt werden, da hier der Oszillator gestoppt wird und damit auch der für die PWM nötige Timer steht - daher die Unterscheidung der Stromsparmodi in der Endlosschleife von main.

ksbender schrieb:
Aber wie sieht die Umsetzung im Basic-Code aus?
Sorry. Basic-Code habe ich nicht.

schnasemann schrieb:
Wobei man bedenken muss, dass das mit dem LED-Dimmen sicherlich logarithmisch ist (gerade Deinen 2. Link gelesen, Vermutung mit log war also richtig).
Ja, die Augen sehen leider (oder eigentlich: zum Glück) logarithmisch. Da ich die Werte aber vornweg berechnet hatte, konnte der Logarithmus gleich mit rein gerechnet werden.

Viele Grüße,
Thomas(_st)

Edit: einen groben Fehler im Programmcode beseitigt; er funktioniert zwar so, aber wehe, wenn man den Timer mit einer anderen Geschwindigkeit laufen lassen wollte. Jetzt sollte alles ok sein ;)
 

schnasemann

Geocacher
mit Soft-PWM unter Bascom sieht das dann so aus:
Code:
Blitz:                                                      'LED getaktet blinken lassen

Config Portb.4 = Output
Portb.4 = 0
For Anzahl = 1 To 20
   For Soft1 = 0 To 31
      Aktuell = Lookup(soft1 , Fade)
      For Soft2 = 0 To 255
      If Soft2 < Aktuell Then
      Portb.4 = 1
      Else
      Portb.4 = 0
      End If
      Next Soft2
      Gosub Warte
   Next Soft1
   For Soft1 = 0 To 31
      Zwisum = 31 - Soft1
      Aktuell = Lookup(zwisum , Fade)
      For Soft2 = 0 To 255
      If Soft2 < Aktuell Then
      Portb.4 = 1
      Else
      Portb.4 = 0
      End If
      Next Soft2
      Gosub Warte
   Next Soft1
   Portb.4 = 0
   Wdtcr = &B11010100                                       'Watchdog auf 250ms einstellen
   Reset Watchdog
   Powerdown
Next Anzahl
Return

Warte:
For Soft3 = 1 To 8000
nop
Next Soft3
Return

End

Fade:
Data 0 , 1 , 2 , 2 , 2 , 3 , 3 , 4 , 5 , 6 , 7 , 8 , 10 , 11 , 13 , 16 , 19 , 23 , 27 , 32 , 38 , 45 , 54 , 64 , 76 , 91 , 108 , 128 , 152 , 181 , 215 , 255

Kurze Erklärung. Ich bastel mir einen Zähler, der immer von 0-255 zählt. In dieser Schleife vergleiche ich aus einer Tabelle einen Wert mit dem aktuellen Zählerwert. Wird dieser überschritten, schalte ich die LED aus, sonst immer ein. Das ganze mache ich 32 Mal, weil ich eine Tabelle mit 32 Werten habe. Damit ich nicht nur hoch, sondern auch runter faden kann, muss hintendran die gleiche Sache nochmal rückwärts laufen.

Vielleicht kann ja einer was damit anfangen. Schöner kann man das sicherlich programmieren, aber so muss man nicht löten und braucht nicht die PWM-Ausgänge unbedingt benutzen.
Grüße schnasemann
 

Kappler

Geowizard
Hier ein kleines Codebeispiel in Bascom-Basic zur Nutzung des Hardware-PWM:
Code:
$regfile = "attiny13.dat"
$crystal = 128000
Config Portb = Output


'final use pwm mode of timer0
Config Timer0 = Pwm , Prescale = 1 , Compare A Pwm = Clear Down
Dim Aufab As Bit

Aufab = 0

Do
  If Aufab = 1 Then
   Pwm0a = Pwm0a + 1
   If Pwm0a > 254 Then
      Aufab = 0
   End If
  Else
   Pwm0a = Pwm0a - 1
   If Pwm0a < 2 Then Aufab = 1
  End If

 Waitms 10
Loop
Das Programm macht nichts anderes, als PortB.0 auf- und ab zu dimmen.
Der Wert, der in Pwm0a geschieben wird, entspricht dem Anteil an "Eingeschaltet" des Ausgangssignals (von 0/255 bis 255/255).
 

schnasemann

Geocacher
wobei das dann wiederum linear gedimmt ist und nicht, wie wir es hier bräuchten, logarithmisch.
Das könnte man wiederum dadurch machen, dass man Pwm0a-Werte aus einer Datentabelle entnimmt und in einer Schleife (in meinem Vorschlag 32) den Index der Datentabelle verwaltet.
 

Hucky3000

Geocacher
@Schnasemann

Wie dimensionierst du denn die Variablen ?!

Bei mir flackerts .

Habe alles Dim As Byte bis auf Soft3. Da habe ich DIm As Word, weil der Wert 8000 ist. So. Allerdingd scheint der wohl "etwas" hoch. Setzte ich den auf 2 funzt es schon fast - die LED flackert aber.

Was tun ?!

Tiny steht auf 128Khz - interner Teiler aus. Glaube ich zumindest...

Ist der Tiny13 zu lahm dafür ?!

Hucky
 
Oben