Forum: Mikrocontroller und Digitale Elektronik Gaslampen Zündung über Mikrocontroller in C


von Andreas Z (Gast)


Lesenswert?

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
volatile uint16_t tcount = 10;
10
volatile uint8_t led_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
  else if ((tcount <= 0)&&(OCR2 < 255))
24
  {
25
    OCR2++;
26
    tcount = 10;
27
  }
28
  
29
}
30
31
void init_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)
38
39
}
40
void init_timer0()
41
{
42
  TCCR0 |= (0 << CS02) | (1 << CS01) | (1 << CS00);
43
  TCCR0 |= (1 << WGM01) | (0 << WGM00);
44
  OCR0 = 250;
45
  TIMSK |= (1 << OCIE0);
46
}
47
48
int main(void)
49
{
50
  init_timer0(); // Aufruf Timer - 0
51
  init_timer2(); // Aufruf Timer - 2
52
  sei(); // Timer starten
53
  
54
  while(1){} // Endlosschleife
55
}

von holger (Gast)


Lesenswert?

tolles Beispiel, ein _delay_ms(1000) in einer Timer ISR

> Kommentare sind extra weg gelassen...

...

von Andreas Z (Gast)


Lesenswert?

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...

von Falk B. (falk)


Lesenswert?

Das hat wohl einer keinen Docht in der Laterne . . .

von Torben K. (tokuhila)


Lesenswert?

> 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.

von Andreas Z (Gast)


Lesenswert?

Falk B. schrieb:
> Das hat wohl einer keinen Docht in der Laterne . . .

Das spiegelt das Niveau in diesem Forum perfekt wieder. Vielen Dank.

von Joachim B. (jar)


Lesenswert?

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.

von Andreas Z (Gast)


Lesenswert?

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...

von Falk B. (falk)


Lesenswert?

Niemand ist unnütz, er kann auch als schlechtes Beispiel dienen.

von Joachim B. (jar)


Lesenswert?

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.

von Harry L. (mysth)


Lesenswert?

Die "Generation Arduino" interessiert sich nicht für Grundlagen.
Alles, was zählt, sind Quellen für Cut&Paste.

von Falk B. (falk)


Lesenswert?

@ 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!!! ;-)

von Max (Gast)


Lesenswert?

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..

von Wegstaben V. (wegstabenverbuchsler)


Lesenswert?

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

von Hubert G. (hubertg)


Lesenswert?

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.

von Martin S. (sirnails)


Lesenswert?

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.

von wendelsberg (Gast)


Lesenswert?

Was passiert eigentlich, wenn wahrend der 1000 ms Delay ein neuer 
Interrupt durch den Timer ausgeloest wird (was sehr wahrscheinlich 
passieren wird)?

wendelsberg

von Torben K. (tokuhila)


Lesenswert?

> 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 :)

von Hubert G. (hubertg)


Lesenswert?

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.

von Conny G. (conny_g)


Lesenswert?

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. :-)

von Martin S. (sirnails)


Lesenswert?

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.

von Wegstaben V. (wegstabenverbuchsler)


Lesenswert?

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.

von Hubert G. (hubertg)


Lesenswert?

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".

von Martin S. (sirnails)


Lesenswert?

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.

von Wegstaben V. (wegstabenverbuchsler)


Lesenswert?

ist mir zu kindisch, solch ein Rätselraten. Falls du sachlich was 
mitteilen möchtest, dann mach es. Ich steh nicht auf 
Wimmelbildchen-Suchspiele.

von Martin S. (sirnails)


Lesenswert?

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.

von Maik S. (yellowbird)


Lesenswert?

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.

von Carl D. (jcw2)


Lesenswert?

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".

von Dennis (Gast)


Lesenswert?

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>

von Der Andere (Gast)


Lesenswert?

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?

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.