Hallo zusammen!,
ich hab hier für C Anfänger ein kleines Programm geschrieben, welches
ich auch auf meiner Modellbahnanlage für die "Zündung" vom Gaslaternen
benutze.
Die Leuchten blitzen am Anfang kurz auf und steigern dann innerhalb
weniger Sekunden ihre Helligkeit mittels PWM.
Bestimmt kann man das Programm auch kürzer gestalten, oder komplett
anders Programmieren...leider findet man hier nur sehr wenige Beispiele
von funktionierenden Codes...meistens wird man nur abgewimmelt mit
"...deine Hausaufgaben musst du schon selber schreiben...".
Sicher, man lernt nur durch selber Programmieren...wenn man aber keinen
Ansatz hat, vergeht den meisten schnell die Lust was eigendlich schade
ist.
Wer die Geschwindigkeit und die Helligkeit ändern möchte, sollte sich
einmal (für den Lerneffekt) damit beschäftigen wie Timer funktionieren.
Kommentare sind extra weg gelassen..
Gruß Andreas
1
#define F_CPU 16000000
2
3
#include<avr/io.h>
4
#include<util/delay.h>
5
#include<avr/interrupt.h>
6
#include<stdio.h>
7
8
9
volatileuint16_ttcount=10;
10
volatileuint8_tled_stat=0;
11
12
ISR(TIMER0_COMP_vect)
13
{
14
tcount--;
15
if((tcount<=0)&&(OCR2<10))
16
{
17
DDRD|=(1<<PD7);
18
_delay_ms(1000);
19
OCR2++;
20
tcount=10;
21
}
22
23
elseif((tcount<=0)&&(OCR2<255))
24
{
25
OCR2++;
26
tcount=10;
27
}
28
29
}
30
31
voidinit_timer2()
32
{
33
TCCR2|=(1<<CS22)|(1<<CS21)|(1<<CS20);
34
TCCR2|=(0<<WGM21)|(1<<WGM20);
35
TCCR2|=(1<<COM21)|(1<<COM20);
36
OCR2=0;
37
DDRD|=(1<<PD7);// PWM Ausgang (je nach Mikrocontroller ändern)
holger schrieb:> tolles Beispiel, ein _delay_ms(1000) in einer Timer ISR>>> Kommentare sind extra weg gelassen...>> ...
Bei dem Programm liegt mein Kriterium bei Funktion und nicht
Schnelligkeit...
> Bei dem Programm liegt mein Kriterium bei Funktion und nicht> Schnelligkeit...
Liebe C-Anfänger: Ein Delay in einer ISR hat nichts mit Schnelligkeit
oder Funktion zu tun, das ist einfach nur schlampig programmiert. Falls
ihr das nachprogrammieren möchtet, tut euch den Gefallen, spart euch die
Interrupts und fragt das Timer-Flag lieber in einer Endlosschleife ab.
Andreas Z schrieb:> Das spiegelt das Niveau in diesem Forum perfekt wieder. Vielen Dank.
aber DU kannst es verbessern, nimm das Delay aus der ISR und das Niveau
steigt.
Joachim B. schrieb:> aber DU kannst es verbessern, nimm das Delay aus der ISR und das Niveau> steigt.
Wer lesen kann ist klar im Vorteil:
Andreas Z schrieb:> Bestimmt kann man das Programm auch kürzer gestalten, oder komplett> anders Programmieren...
Ich bin kein Profi-C-Programmierer der seine ganze Kindheit vor dem
Computer verbracht hat, und will es auch nicht werden.
Es soll nur ein Beispiel sein, für Leute die schnell sowas zum laufen
kriegen wollen und sich daran erfreuen...
Andreas Z schrieb:> Ich bin kein Profi-C-Programmierer der seine ganze Kindheit vor dem> Computer verbracht hat, und will es auch nicht werden.
was hat das mit lernen und verstehen und Wissen anwenden zu tun?
Man muss kein Profi sein oder werden um grundlegende Fehler zu
vermeiden, das versuche ich täglich ohne Profi zu sein.
@ Harry L. (mysth)
>Alles, was zählt sind Quellen für Cut&Paste.
WOW! Die Zeiten werden härter! Früher hat man sich mit Copy&Paste
begnügt, heute wird sogar das Original weggeschnitten!!! ;-)
Die "Generation Arduino" interessiert sich nicht für Grundlagen.
Alles, was zählt, sind Quellen für Cut&Paste.
ich würde eher sagen, es zählt vorallem die Umsetzung einer Idee anstatt
jedes mal wieder das rad von vorne erfinden zu wollen.
wenn ein programm stabil läuft ist mir das egal wie und ob irgendwelche
delays verbaut sind...aber vielleicht bin ich da auch einfach zu wenig
nerdig dazu..
Max schrieb:> wenn ein programm stabil läuft ist mir das egal wie und ob irgendwelche> delays verbaut sind...aber vielleicht bin ich da auch einfach zu wenig> nerdig dazu..
Naja, delays in einer ISR sind halt ein vollkommen falscher
konzeptioneller Ansatz. Auch delays allgemein sind "schlechter Ansatz".
Dann steht Eingangs steht "Wer die Geschwindigkeit und die Helligkeit
ändern möchte, sollte sich einmal (für den Lerneffekt) damit
beschäftigen wie Timer funktionieren."
Anscheinend hat dann der Original Poster GRADE NICHT verstanden, wie
Timer funktionieren und wozu man die braucht.
--> Der "unbedarfte" Neuling ("für C Anfänger")könnte da grade den
Eindruck bekommen, das er da ein schönes Häppchen Programmcode bekommen
hat. Fakt ist jedoch, dieser Code taugt ziemlich gut als schlechtes
Beispiel, wie man es NICHT machen sollte.....
Andreas Z schrieb:> Kommentare sind extra weg gelassen..
grade die wären für einen Neuling interessant. Wo/Wie/Wodurch geschieht
das Eingangs-Blitzen, und wo / wie ist das mit den "mehreren Sekunden
Anstieg" gelöst?
Grade als Neuling habe ich ja vielleicht weniger das konkrete Problem
(Gaslampe) auf der Problemliste, sondern interessiere mich eher für die
Umsetzung/Anwendung als solche (Blitzen, Helligkeits-Rampe)
Max schrieb:> es zählt vorallem die Umsetzung einer Idee anstatt> jedes mal wieder das rad von vorne erfinden zu wollen.
Genau, die Umsetzung von zeitabhängigem Bit ein und Ausschalten. Ist
schon Millionenfach gemacht worden, und da braucht auch kein Rad neu
erfunden werden.
Es gibt aber ein innovativen Punkt im Beitrag des Ursprungsposters:
1. Er hat den Helligkeitsverlauf einer Gaslampen-Zündung erfasst
2. Er hat die Ansteuerung einer LED mit einem Mikrocontroller gelöst
Andreas Z schrieb:> Es soll nur ein Beispiel sein, für Leute die schnell sowas zum laufen> kriegen wollen und sich daran erfreuen...
Dafür wäre es aber hilfreich wenn man wüsste welchen Controller man
verwenden sollte.
Andreas Z schrieb:> Joachim B. schrieb:>> aber DU kannst es verbessern, nimm das Delay aus der ISR und das Niveau>> steigt.>> Wer lesen kann ist klar im Vorteil:>> Andreas Z schrieb:>> Bestimmt kann man das Programm auch kürzer gestalten, oder komplett>> anders Programmieren...>> Ich bin kein Profi-C-Programmierer der seine ganze Kindheit vor dem> Computer verbracht hat, und will es auch nicht werden.
Ich bin wahrlich kein Profi, aber verstehe durchaus, warum es hier so
massive kritik hagelt!
> Es soll nur ein Beispiel sein, für Leute die schnell sowas zum laufen> kriegen wollen und sich daran erfreuen...
Es ist allerhöchstens ein Beispiel, bei dem unbedarfte Anfänger ganz
elementare Fehler lernen!
Um zu verstehen, warum hier so auf Dich eingehämmert wird, muss man auch
erstmal verstehen, was ein Interrupt ist.
Ein Interrupt ist eine Unterbrechung im Programm, die durch einen
externen Pegel an einem IR-Pin ausgelöst wird, und den Prozessor anweist
"Egal was Du gerade tust, ich bin wichtiger.". Die Prioritätensteuerung
prüft dann, ob der eingetretene Interrupt wichtiger ist, als der
Programmcode, der gerade zu diesem Zeitpunkt aufgetreten ist, und
unterbricht knüppelhart einfach die Ausführung. Und entweder ist der
Interrupt niederer Priorität, dann springt das Programm zurück, und hält
die Abarbeitung der Interrupt Service Routine in der Warteschlange, oder
er führt den Code sofort aus.
Und damit begründet sich auch das Problem. Ein Interrupt gleicher
Priorität kann die Ausführung einer ISR nicht unterbrechen. Tritt also
der gleiche Interrupt mit der gleichen Priorität auf, dann bleibt der
Programmablauf dadurch zur Gänze unberührt. Und damit wird das Konzept
der ISR komplett ad adsurdum geführt, denn die angedachte
Prioritätensteuerung, aber auch die Echtzeitigkeitsbedingungen werden
dadurch verletzt und ausgehebelt.
Ziel der ISR ist ALLEINIG auf ein von außen eintreffendes Ereignis zu
reagieren. Und diese Reaktion muss so schnell wie möglich ablaufen.
Delays hingegen bewirken das genaue Gegenteil davon.
Und damit sind wir wieder am Anfang: Einem Anfänger beizubringen, dass
eine ISR auch für zeitunkritische Prozesse genutzt werden kann, ist
falsch.
Was passiert eigentlich, wenn wahrend der 1000 ms Delay ein neuer
Interrupt durch den Timer ausgeloest wird (was sehr wahrscheinlich
passieren wird)?
wendelsberg
> Was passiert eigentlich, wenn wahrend der 1000 ms Delay ein neuer> Interrupt durch den Timer ausgeloest wird (was sehr wahrscheinlich> passieren wird)?
Dann flackerts, wie ne richtige Gaslampe :)
wendelsberg schrieb:> Was passiert eigentlich, wenn wahrend der 1000 ms Delay ein neuer> Interrupt durch den Timer ausgeloest wird (was sehr wahrscheinlich> passieren wird)?>> wendelsberg
Das passiert sogar ganz sicher. Allerdings wartet dieser Interrupt bis
der vorhergehende abgearbeitet ist. Es wird hier, außer Interrupt
abarbeiten, nicht viel geschehen.
Alle 1000ms wird der Timer2 aktualisiert. Die PWM des Timer2 läuft ja
unabhängig.
wendelsberg schrieb:> Was passiert eigentlich, wenn wahrend der 1000 ms Delay ein neuer> Interrupt durch den Timer ausgeloest wird (was sehr wahrscheinlich> passieren wird)?>> wendelsberg
Das habe ich mir auch überlegt. Der zweite Int wird geblockt, bis der
erste abgearbeitet ist.
Die PWM auf dem anderen Timer braucht keinen Int, da hat der Autor Glück
gehabt.
Und der eine Int der verkraftet es zufällig, dass er nur nach Ende
wieder aufgerufen wird.
Ziemlicher Pfusch. :-)
Martin S. schrieb:> Und damit begründet sich auch das Problem. Ein Interrupt gleicher> Priorität kann die Ausführung einer ISR nicht unterbrechen. Tritt also> der gleiche Interrupt mit der gleichen Priorität auf, dann bleibt der> Programmablauf dadurch zur Gänze unberührt. Und damit wird das Konzept> der ISR komplett ad adsurdum geführt, denn die angedachte> Prioritätensteuerung, aber auch die Echtzeitigkeitsbedingungen werden> dadurch verletzt und ausgehebelt.
Ich möchte mich da mal selbst aus dem Beitrag direkt darüber zitieren:
Und damit begründet sich auch das Problem. Ein Interrupt gleicher
Priorität kann die Ausführung einer ISR nicht unterbrechen. Tritt also
der gleiche Interrupt mit der gleichen Priorität auf, dann bleibt der
Programmablauf dadurch zur Gänze unberührt. Und damit wird das Konzept
der ISR komplett ad adsurdum geführt, denn die angedachte
Prioritätensteuerung, aber auch die Echtzeitigkeitsbedingungen werden
dadurch verletzt und ausgehebelt.
Martin S. schrieb:> Ich möchte mich da mal selbst aus dem Beitrag direkt darüber zitieren:
und warum?
Das erschließt sich mir jetzt nicht direkt, warum du deinen Text nochmal
exakt identisch zitierst. Mir fehlt da irgendwie der Bezug zu der
Handlung. Bitte erleuchte mich.
Ganz ohne Auswirkung ist das delay nicht.
Die Variable tcount wird nicht wie beabsichtigt alle 16ms sondern nur
alle 1000ms geändert.
1
DDRD|=(1<<PD7);
2
_delay_ms(1000);
Es stellt sich ja auch die Frage wozu PD7 bei jedem ISR-Aufruf neu
gesetzt wird. PD7 wird in der init von Timer2 auch auf Ausgang gesetzt.
Beide Zeilen können ersatzlos entfallen.
Der TO kann das als Lernbeispiel ja "gut gemeint" haben. "gut gemeint"
ist aber sehr oft nur eine Steigerungsform von "schlecht gemacht".
Wegstaben V. schrieb:> Martin S. schrieb:>> Ich möchte mich da mal selbst aus dem Beitrag direkt darüber zitieren:>> und warum?
Frage ich mich auch.
> Das erschließt sich mir jetzt nicht direkt, warum du deinen Text nochmal> exakt identisch zitierst. Mir fehlt da irgendwie der Bezug zu der> Handlung. Bitte erleuchte mich.
Steht alles schon geschrieben. Man muss es halt nur lesen.
Wegstaben V. schrieb:> ist mir zu kindisch, solch ein Rätselraten. Falls du sachlich was> mitteilen möchtest, dann mach es. Ich steh nicht auf> Wimmelbildchen-Suchspiele.
Ich war sachlich genug. Wenn Du den Inhalt nicht verstehst, dann kann
ich dir leider auch nicht helfen.
Max schrieb:> wenn ein programm stabil läuft ist mir das egal wie und ob irgendwelche> delays verbaut sind...aber vielleicht bin ich da auch einfach zu wenig> nerdig dazu..
Du programmierst noch etwas, da weisst du nicht, ob es stabil läuft.
Wenn du den Teil, den du gerade programmierst "irgendwann" als fertig
erachtest, kann so eine Kontruktion später für Probleme sorgen.
Jede Auslösung des ISR sorgt dafür, das die Wartescheliefe durchlaufen
wird, egal was sonst gerade ansteht.
D.h. jeder ISR Aufruf zerkloppt dir deinen Programmablauf.
Daher sollte man alle Interrupt-Funktionen so kurz wie möglich halten
(zB nur Zählen) und die Änderung (Aktion aus der Zählung) im normalen
Programm abarbeiten.
Conny G. schrieb:> Der zweite Int wird geblockt, bis der erste abgearbeitet ist.> Die PWM auf dem anderen Timer braucht keinen Int, da hat der Autor Glück> gehabt.> Und der eine Int der verkraftet es zufällig, dass er nur nach Ende> wieder aufgerufen wird.>> Ziemlicher Pfusch. :-)
Das Problem mit diesem Codefragment, bei dessen Veröffentlichung der
Autor bestimmt viel Beifall erwartet hat, ist, daß es eben nur durch
Zufall tut was es soll. Und bei Änderungen daran wird eben neu
gewürfelt.
Mit "ich bin doch kein Nerd" will der Autor sicher sagen "mir doch egal
warum es funktioniert", nur wird er beim nächsten Mal genau so lange
dran dengeln müssen, denn er hat nie gelernt (lernen wollen), wie man
es macht. Dann kann er unter anderem Pseudonym ja die Nerds bitten, im
seine Fehler zu suchen.
Das ist das eigentliche "Arduino-Problem" und nicht diejenigen, die
fertige, funktionierende HW benutzen, um Programmieren zu lernen.
Ich glaube aber, der Autor hat in seinem Umfeld den Nerd-Status, denn
schließlich "kann er Microcontroller programmieren".
Carl D. schrieb:> Ich glaube aber, der Autor hat in seinem Umfeld den Nerd-Status, denn> schließlich "kann er Microcontroller programmieren".
<ironie>
Stellt euch doch mal vor, mit diesem Lebensgefühl rumzulaufen:
"I am a real embedded programmer!!! f*ck yeah! "
:-)
... da braucht man ja auch keine Korrekturen mehr von den Leuten, die
einen harmlosen delay als etwas "Schlechtes" ablegen. Und weshalb dieser
delay im INT falsch sein soll, das ist auch rätselhaft. Schließlich
hätte man ja auch ein paar Handvoll goto's reinpacken können...
Und schließlich: es funktioniert doch!
</ironie>
Dennis schrieb:> ... da braucht man ja auch keine Korrekturen mehr von den Leuten, die> einen harmlosen delay als etwas "Schlechtes" ablegen. Und weshalb dieser> delay im INT falsch sein soll, das ist auch rätselhaft. Schließlich> hätte man ja auch ein paar Handvoll goto's reinpacken können...
jaja, und ich bin gestern ohne zu schauen über die Straße, hat
funktioniert. Also solltest du das jetzt immer tun.
manmanman wie <selbstzensiert> kann man eigentlich sein?