Seid gegrüßt,
ich rechne nun schon seit Stunden herum, komme aber auf keine
funktionierende Lösung.
Ich versuche ein Fading für eine LED (über PWM) hinzubekommen...
int16_t nFadeCount = 0; // Zähler für das Überblenden(Fading)
int16_t nFadingTime = 200;
int16_t nSavedPWM = 100; // Variable zur Speicherung des letzten
Helligkeitswertes
nFadeCount++;
if(nFadeCount <= nFadingTime)
OCR1A += nSavedPWM/nFadingTime;
... steh aber irgendwie auf dem Schlauch. Der hier gezeigte Ansatz geht
zwar 'irgendwie', aber nur, solang nSavedPWM>nFadingTime ist.
Wichtig: OCR1A kann nur int-Werte annehmen und das Fading soll relativ
gleichmäßig gehen
Wenn also z.B. nFadingTime=1000 und nSavedPWM=100 wäre, sollte OCR1A in
jedem 10sten Schritt um 1 erhöht werden.
Wie kann man das umsetzen?
Würde mich über jeden Ansatz freuen.
Viele Grüße
Newbie schrieb:> Wenn also z.B. nFadingTime=1000 und nSavedPWM=100 wäre, sollte OCR1A in> jedem 10sten Schritt um 1 erhöht werden.
Das ist der falsche Ansatz. Wenn das Fading gleichmäßig gehen soll, muß
die LED logarithmisch angesteuert werden (-> Weber-Fechner-Gesetz)
Newbie schrieb:
Abgesehen von der logarithmischen Verteilung von der Matthias gesprochen
hat.
> Wenn also z.B. nFadingTime=1000 und nSavedPWM=100 wäre, sollte OCR1A in> jedem 10sten Schritt um 1 erhöht werden.> Wie kann man das umsetzen?
Was hindert dich daran, auszurechnen, wieviele Schritte notwendig sind,
ehe OCR1A wieder um 1 erhöht werden soll? Wenn ein Computer etwas ganz
gut kann, dann ist das Berechnungen ausführen.
Hi Matthias,
ich glaub, du beziehst dich auf die LED-Kennlinie.
Ähm... jepp, ich hab mich da wohl falsch ausgedrückt. Ich meinte
eigentlich 'gleichmäßiges Abarbeiten des nSavedPWM-Wertes'.
(Für die Ansteuerung der LED-Helligkeit werd' ich mir später eine
Tabelle anlegen.)
LG
Newbie schrieb:> ich glaub, du beziehst dich auf die LED-Kennlinie.
Nein, auf die Helligkeitswahrnehmung. Bei PWM spielt die Kennlinie keine
Rolle, weil immer der volle Strom fließt.
Hallo Karl,
bei z.B. nFadingTime=1000 und nSavedPWM=100 ist das leicht. Da hab ich
int-Werte und vielfache von einander.
Was ist aber bei z.B. nFadingTime=133 und nSavedPWM=633?
Dann müßte bei jedem 133/633sten Schritt weitergezählt werden. Und dann
WIE den Faktor einbauen - es kann ja nur in int-Werten weitergezählt
werden?
Von Mathe versteh ich schon was, aber ich verzweifle langsam echt an der
Umsetzung.:(
Viele Grüße
> es kann ja nur in int-Werten weitergezählt werden?
Nö - auch mit Festkommazahlen.
int32_t nSavedPWM_32 = (int32_t)nSavedPWM << 16;
OCR1A += (nSavedPWM_32/nFadingTime) >> 16;
Einfach mal drüber schlafen. Morgen löst sich der Knoten von alleine
auf.
-- Grüße.
Newbie schrieb:> Hi,>> ich bekomme für die erste Zeile eine Fehlermeldung:> initializer element is not constant>> ?
Na, ja. Was ist dein ein 'Initializer'?
Das womit eine Variable initialisiert wird.
Und der muss an bestimmten Stellen (zb globale Variablen) konstant sein.
Bei dir ist er das nicht.
Mach halt eine normale Zuweisung draus, und dann passt es wieder
anstelle
1
int32_tnSavedPWM_32=(int32_t)nSavedPWM<<16;
dann eben
1
int32_tnSavedPWM_32;
2
3
4
intmain()
5
{
6
nSavedPWM=....;
7
nSavedPWM_32=(int32_t)nSavedPWM<<16;
8
}
oder wie es dann eben bei dir passt.
Im übrigen ist es doch einfach. Was tust du denn, wenn du in Euros
rechnen sollst, aber keine Kommazahlen haben darfst. Du sollstz 2.80
Euro + 3.40 Euro rechnen, ohne Kommazahlen. Dann rechnest du eben in
Cent! 280 Cent + 340 Cent. Und schon kannst du das rechnen, ohne
Kommazahlen benutzen zu müssen.
So auch hier
Wenn du 133/633 rechnen musst, dir aber nur das Ganzzahlige Ergebnis zu
wenig ist (weil 0), dann rechnest du eben 1330/633, das macht 2. Du
merkst dir einfach, dass die 2 (oder allgemeiner: die Einer deines
Ergebnisses) eigentlich schon die erste Kommastelle sind. Und wenn die 1
Kommastelle nicht reicht, dann rechnest du eben 13300/633, das mach 21
und du merkst dir, dass die Zehner und die Einer die ersten beiden
Kommastellen sind. Wenn du ans OCR zuweist, musst du die beiden Stellen
loswerden, das sollte aber einfach sein: dividieren durch 100 reicht.
Addierst du also
21
21
21
21
21
21
----
126
dann hast du laut deiner Systematik eigentlich 5 * 0.21 = 1.26
errechnet. Bei dir dann eben 126 / 100 -> 1, die ins OCR kommt. Und
schon hast du mit 2 Nachkommastellen gerechnet ohne Kommazahlen benutzen
zu müssen.
In einem Computerprogramm wird man natürlich sinnvollerweise nicht
Vielfache von 10 nehmen (so wie bei den Cent) sondern Vielfache von 2,
weil man die dann wieder leicht loswerden kann (anstelle von Dividieren
verschiebt man einfach die Bits), aber das Prinzip ist völlig identisch.
Hallo Karl,
sooooooooooooooooooooo, jetzt raucht mir der Kopf.;-)))
Ich glaube, diese etwas längere Übung mit der 0,21... hab' ich nicht so
wirklich verstanden - auch nach zwei Stunden Brainstorming!:(
ABER... nachdem ich mir nochmal ganz intensiv eure zwei Beiträge (u.a.
mein C-Buch zu Operatoren) durchlas, und zudem sah, dass mein ATMega88
bei Verwendung einer einzigen float-Variable gleich 400% meiner
ursprünglichen Speicherkapazität verbraucht (65% Speicherauslastung bei
etwa 200 Zeilen Programmcode^^), hab ich endlich die Shiftoperation
kappiert - da ich auch scheinbar gar nicht mehr daran vorbei komme.
Jippiiieieee, Schweinebacke;-)
DANKE!^^
Gott, ich hab's mir ja vorher so unglaublich schwer mit dem Basteln
einer passenden Gleichung gemacht. So sieht das jetzt schon mal aus:
OCR1A = nFadeCount*((nSavedPWM<<2)/(nFadingTime<<2));
Nun hab' ich nur noch ein ganz ein kleines Problem. Der
nSavedPWM-Maximalwert wird so niemals erreicht, da mit dieser Zeile ja
stets zumindest ein ganz ein kleines Stückerl abgeschnitten wird.
Mal guggn, wie lang ich brauche, um draufzukommen. ODER ein "Wissender"
schaut vl. mal kurz drüber und gibt mir einen 'Wink'.;-))
Liebe Grüße
Ok, jetzt scheint's zu gehen. Wie "Kein Name" schon aufzeigte:
int32_t nSavedPWM_32 = (int32_t)nSavedPWM << 16;
int32_t OCR1A_32 = (int32_t)OCR1A << 16;
OCR1A_32 = nFadeCount*(nSavedPWM_32/nFadingTime);
OCR1A = OCR1A_32 >> 16;
Ich muß die Bitmanipulation wohl doch noch mal gründlich studieren.;-)))
Danke!
LG
Eine eigene Frage?
Dieser Thread ist über 14 Jahre alt.
Stell sie in einem eigenen Thread – dort lesen mehr Leute mit, und sie wird öfter und schneller beantwortet.