Hallo MK-Gemeinde,
Wenn ich den Code unten auf einen mega8515 lade funktioniert das Faden
einer LED (langsam heller, dann wieder langsam dunkler) ganz gut bis auf
dass die LED, wenn sie ganz dunkel sein sollte ein mal kurz aufblitzt.
Ich habe schon ziemlich lange rumprobiert aber sehe keinen Fehler oder
Grund für dieses eine kurze Aufblitzen.
Kennt jemand einen Lösungsvorschlag?
Schade, dass so wenig Resonanz kam aber ich bin den Code noch einmal mit
einem Kolegen durchgegangen und wir haben wahrscheinlich die Lösung, die
ich euch nicht vorenthalten möchte.
Wir haben hier wohl einen klassischen Fall von zu langer Interrupt
Routine.
Seztz man den unteren Wert
1
if(tblpos>0)
2
tblpos--;
3
elserichtung=0;
auf mindestens ca 95 klappt alles super.
1
if(tblpos>95)
Wahrscheinlich kommen sich die IR-Routinen da in die Queere...
Grüße,
Felix
Seh ich das richtig? Die Tabelle hat 256 Einträge, jedenfalls hat mein
Editor 255 Kommas gezählt. Die Stelle
if (tblpos < 255)
tblpos++;
Erhöht den Index aber auf 256, der nunmal nicht existiert. Das kann ich
nicht gut heissen :-)
@ Felix (Gast)
>Kennt jemand einen Lösungsvorschlag?>//Enthaltene Methoden>ISR(TIMER1_COMPA_vect);>ISR(TIMER1_OVF_vect);>int main(void);
Das ist schon mal Unsinn. Die ISRs werden NICHT deklariert. Main
ebensowenig. Und es sind auch keine Methoden!
>ISR(TIMER1_COMPA_vect) { //Timer Interrupt Compare Routine> PLED |= (1 << 0); //AN>};
???
Warum nutzt du ich direkt die Output COmpare Funktion? ist das Pin schon
aberweitig belegt?
> if(zyklcntr == 1) {
Warum 1? Sollte das Ding nicht von 0..255 zählen?
> zyklcntr = 0;
Denn hier wird ja wieder auf Null gesetzt.
Warum so kompliziert? Das Beispiel im Artikel LED-Fading ist
einfacher.
MFG
Falk
Die ISR's sind so kurz, da überlappt nichts.
Ich habe jetzt kein Datenblatt vom 8515 , aber in dem vom Mega32 steht
der nette Satz:
>If the interrupt is enabled, the interrupt handler routine can be used for >updating the TOP value. However, changing the TOP to a value close to BOTTOM >when the counter is running with none or a low prescaler value must be done>with care since the CTC mode does not have the double buffering feature. If>the new value written to OCR1A or ICR1 is lower than the current value of>TCNT1, the counter will miss the compare match. The counter will then have to >count to its maximum value (0xFFFF) and wrap around starting at 0x0000 before >the compare match can occur.
Das könnte dein Problem sein.
Ansonsten hat Falk schon alles gesagt - umständlicher geht es nicht.
Oliver
Herzlichen Dank für euer Feedback.
Den Artikel LED-Fading habe ich auch schon gelesen aber zum Einen wollte
ich nicht nur Copy-Paste coden sondern den ganzen Code selber schreiben,
man möchte ja was lernen ;). Zum Anderen kann man den Ausgangspin ja bei
dem Tutorial nicht frei wählen, man muss den PWM-Ausgangs-Pin verwenden.
Stimmt das?
Gibt es einen bestimten Grund, warum man die enthaltenen Methoden (oder
Prozeduren? - wie heißt es richtig @Falk) nicht deklarieren soll? Bzw.
gehört sowas eher in das Header-File? Es ging mir damit nur um die
Übersichtlichkeit.
>>ISR(TIMER1_COMPA_vect) { //Timer Interrupt Compare Routine>> PLED |= (1 << 0); //AN>>};>>???>Warum nutzt du ich direkt die Output COmpare Funktion? ist das Pin schon>aberweitig belegt?
Warum ein Pin belegen? Dafür ist doch der Compare Match ISR da...
@Oliver
Danke für das Raussuchen. Ich denke genau das wird es sein.
Grüße,
Felix
Vergessen:
Das
> if(zyklcntr == 1) {
ist beabsichtigt. Es dient nur dazu die Länge des Fade-Intervalls zu
verlängern. Bei 255 dauert es allerdings sehr lang, bis die LED ein mal
an und wieder aus war ;)
Man könnte den zykcntr auch weglassen...
@ Felix (Gast)
>man möchte ja was lernen ;). Zum Anderen kann man den Ausgangspin ja bei>dem Tutorial nicht frei wählen, man muss den PWM-Ausgangs-Pin verwenden.>Stimmt das?
Ja. Das hat auch seinen Grund. Eine 16 Bit PWM macht man nicht mal fix
in Software. Praktisch kann man keine 16 Bit PWM in Software machen. 10
Bit ist so ziemlich die Obergrenze, wenn man noch wenigsten 100 HZ PWM
Frequenz haben will. Und dann ist die CPU schon SEHR gut beschäftigt.
>Gibt es einen bestimten Grund, warum man die enthaltenen Methoden (oder>Prozeduren? - wie heißt es richtig @Falk) nicht deklarieren soll?
Es sind Interrupt-Service Routinen, ISRs. Das sind Sonderfälle im C.
> Bzw. gehört sowas eher in das Header-File?
ISRs werden nur einmal direkt definiert, OHNE Deklaration irgendwo.
Fertig.
>Warum ein Pin belegen? Dafür ist doch der Compare Match ISR da...
NEIN! Denn deine Routine kann keine 1 Takt breite Ansteuerung der LED
erreichen. Dazu ist der Interrupt prinzipiell zu langsam. Damit ist
deine "scheinbar 16 Bit PWM" effektiv bestenfalls 10 Bit. Von dreckigen
Nebeneffekten ganz zu schweigen.
>verlängern. Bei 255 dauert es allerdings sehr lang, bis die LED ein mal>an und wieder aus war ;)>Man könnte den zykcntr auch weglassen...
Man könnte es auch gleich richtig machen. Wie im Artikel. Der Autor hat
sich was dabei gedacht. Ich kenn den . . . ;-)
MfG
Falk
> Ja. Das hat auch seinen Grund. Eine 16 Bit PWM macht man nicht mal fix> in Software. Praktisch kann man keine 16 Bit PWM in Software machen. 10> Bit ist so ziemlich die Obergrenze, wenn man noch wenigsten 100 HZ PWM> Frequenz haben will. Und dann ist die CPU schon SEHR gut beschäftigt.
Ok macht Sinn. Kann man irgenwo in AVR-Studio sehen, in wie viele
Assembler Befehler bestimmte Teile des Codes compilliert werden oder
muss man sich dazu die Hex-Datei anschauen?
> Man könnte es auch gleich richtig machen. Wie im Artikel. Der Autor hat> sich was dabei gedacht. Ich kenn den . . . ;-)
Ja mag sein aber das ist ja nur ein Lösungsansatz. Ich muss aber den
Ausgangspin frei belegen können. Deshalb habe ich ja auch die Software
PWM geschrieben... (Der Autor hat sich da auch was bei gedacht ;) )
Und es funktioniert ja auch so. Die LED fadet schön wie sie soll.
Ressourcenspaaren ist sicherlich anders aber das ist auch mein erstes
C-Projekt bzw. überhaupt uC.
P.S. ISR Deklaration schon wieder entfernt :)
@ Felix C. (time2ride)
>Ok macht Sinn. Kann man irgenwo in AVR-Studio sehen, in wie viele>Assembler Befehler bestimmte Teile des Codes compilliert werden oder>muss man sich dazu die Hex-Datei anschauen?
In den Optionen kann man einstellen, dass ein List-file erzeugt wird,
endung .lss . Dort stehen zu jeder Zeie C die ASM Befehle drin.
>Ja mag sein aber das ist ja nur ein Lösungsansatz. Ich muss aber den>Ausgangspin frei belegen können. Deshalb habe ich ja auch die Software>PWM geschrieben...
Womit du 16 Bit direkt vergessen kannst. Ich wiederhole mich.
>Und es funktioniert ja auch so. Die LED fadet schön wie sie soll.
Das glaubst du. Die Dreckeffekte hast du ja schon gesehen.
MfG
Falk
> In den Optionen kann man einstellen, dass ein List-file erzeugt wird,> endung .lss . Dort stehen zu jeder Zeie C die ASM Befehle drin.
Klasse hat geklappt. Danke! Die 1. ISR hat 11 ASM Befehle, die 2. hat
66.
> Womit du 16 Bit direkt vergessen kannst. Ich wiederhole mich.>>>Und es funktioniert ja auch so. Die LED fadet schön wie sie soll.>> Das glaubst du. Die Dreckeffekte hast du ja schon gesehen.
Ich hab das mal durchgerechnet. 8000000 Hz -> Befehle in der Sekunde.
Der Timer läuft bis 65536, das ist (8000000/56536) 122 mal in der
Sekunde. Während einem Timer durchlauf müssen insgesamt (11+66) 77
Befehle in den ISRs abgearbeitet werden. Das sind (77*122) 9394 Befehle
in der Sekunde. Da ist die CPU doch nicht so krass ausgelastet oder hab
ich mich da verrechnet?
@ Felix C. (time2ride)
>Ich hab das mal durchgerechnet. 8000000 Hz -> Befehle in der Sekunde.
Nein, Takte. Es gibt einige Befehle die 2, 3 oder mehr Takte brauchen.
>Der Timer läuft bis 65536, das ist (8000000/56536) 122 mal in der>Sekunde.
Genau.
> Während einem Timer durchlauf müssen insgesamt (11+66) 77>Befehle in den ISRs abgearbeitet werden.
Stimmt.
> Das sind (77*122) 9394 Befehle in der Sekunde.
Stimmt auch.
> Da ist die CPU doch nicht so krass ausgelastet oder hab>ich mich da verrechnet?
Ist sie auch nicht, im MITTEL! Doch was passiert, wenn du die
PWM-Einstellung 1 erzeugen willst?
MFG
Falk
> Ist sie auch nicht, im MITTEL! Doch was passiert, wenn du die> PWM-Einstellung 1 erzeugen willst?
Ja stimmt und deshalb funktionieren die einstellungen für den
Comparewert, die unter 80 oder 90 (was ungefähr der abarbeitung der
einen ISR entspricht) oder so (ich habs vorher in dem pwmtbl
nachgeschaut) nicht mehr richtig und da kommt er dann ins straucheln
(siehe Beitrag von Oliver). Aber für Werte größer 90 klappt das. Aber
ich denke so kann ich den Code verwenden, wenn ich die Werte aus dem
pwmtbl kleiner als 90 rausnehme (siehe 2. Beitrag, da werden aus dem
pwmtbl die ersten 95 Einträge, die alle kleiner als 90 garnicht
gelesen). Dann ist zwar kurzzeitig die CPU Belastung hoch aber das geht
ja in Ordnung.
Vielen Dank nochmal Falk für deine Bemühung!!