Hallo, ich möchte gerne eine Nachlaufsteuerung von 1-60 Sekunden für eine LED einbauen, und zwar hier: ... // Größer als..... if ((o == (1) && u == (1))) { if (temp_val.i/100 > t || humid_val.i/100 > h) { DDRD |= (1 << DDD0); // Setzen } else { DDRD &= ~(1 << DDD0); // Rücksetzen <--- hier soll eine Nachlaufsteuerung rein } } ... Allerdings soll die Nachlaufsteuerung nicht den ganzen Programmablauf blockieren, während sie aktiv ist. Ich habe Timer getestet, allerdings stoppte während der Timer lief das ganze Programm. Ich habe echt keine Idee mehr, wie ich das realisieren kann und wende mich deshalb an Euch. Danke im Vorraus. Gruss Stefan
Stefan B. schrieb: > Allerdings soll die Nachlaufsteuerung nicht den ganzen Programmablauf > blockieren, während sie aktiv ist. > Ich habe Timer getestet, allerdings stoppte während der Timer lief das > ganze Programm. Dann hast du was falsch gemacht. > Ich habe echt keine Idee mehr, wie ich das realisieren kann Lerne programmieren.
Danke für den Tipp, allerdings hätte ich mir ein paar konstruktivere Vorschläge erhofft.
so ganz blicke ich durch deinen Code geraden nicht durch. Prizipiell würde ich folgendemaßen vorgehen: Benutze einen Timer, der in regelmäßigen Abständen aufgerufen wird und eine Variable (initialisiert mit 0) hochzählt. Sobalt die Variable einen bestimten Wert überschreitet, wird die LED abgeschaltet und es wird nicht mehr weitergezählt. Ich hoffe das hilft dir weiter!
Brech das ganze runter in eigenständig funktionierende Teile, die mal dann auch einzeln testen kann. Lass die PeDa "Lib" in eigenem File, das zeigt wo du sie her hast und du Must sie nicht immer durchblättern. Includiere NUR .h Files. Spart Compiler/Linker-Gemeckere. Lese PeDa's Thread in der Codesammlung zum Thema [[Wartezeiten effektiv (Scheduler)]] (irgendwie bin ich zu blöd für's verlinken!?)
Stefan B. schrieb: > DDRD &= ~(1 << DDD0); // Rücksetzen <--- hier soll eine > Nachlaufsteuerung rein (...) > Ich habe Timer getestet, allerdings stoppte während der Timer lief das > ganze Programm. Und wie sahen deine Timertests konkret aus?
Erstmal danke für die Antworten. Zur Info, da mit der main.c niemand was anfangen kann. Das wird ein Thermo-/Hygrometer mit einer einstellbaren Alarmgrenze für größer oder kleiner Feuchtigkeit und ebenso die Temperatur und einem MinMax-Speicher. Funktioniert ja auch soweit. Siehe Bilder. Die Led wird irgendwann mal ein Lüfter o.Ä. Ich möchte gerne, dass die Led eine Nachlaufzeit hat, denn wenn die Temperatur zwischen der einstellbaren Grenze schwankt, wird sie dementsprechend auf high und dann wieder auf low geschalten, zu deutsch blink sie dann....das würde ich gerne vemeiden wollen und deswegen der Gedanke mit der Nachlaufzeit. Ich habe wahrscheinlich einen Denkfehler gemacht. Ich werde das nochmal mit einem Timer probieren und falls ich nichtmehr weiter komme, mich nochmal hier melden. Gruss Stefan
Denkfehler ist der richtige Ansatz. Du benötigst eine Hysterese. Der Einschaltwert liegt ein paar Punkte über dem Ausschaltwert und fertig.
hysteriker schrieb: > Denkfehler ist der richtige Ansatz. Du benötigst eine Hysterese. Der > Einschaltwert liegt ein paar Punkte über dem Ausschaltwert und fertig. Mercy, oder so.....
Noch ein Tip
1 | if (temp_val.i/100 > t || humid_val.i/100 > h) |
2 | {
|
3 | DDRD |= (1 << DDD0); // Setzen |
4 | }
|
5 | else
|
6 | {
|
7 | DDRD &= ~(1 << DDD0); // Rücksetzen |
8 | }
|
du willst da ganz sicher nicht an den DDR Registers rumpfriemeln. Mit DDRx stellst du ganz am Programmanfang den Portpin auf Ausgang und dann benutzt du das PORTx Register um den Pin auf 0 oder 1 zu schalten.
1 | if (temp_val.i/100 > t || humid_val.i/100 > h) |
2 | {
|
3 | PORTD |= (1 << PD0); // Setzen |
4 | }
|
5 | else
|
6 | {
|
7 | PORTD &= ~(1 << PD0); // Rücksetzen |
8 | }
|
Für den Fall, dass du tatsächlich mal irgendwo einen Nachlauf brauchst. Du hast bereits einen Timer im System. Das ist gut so, denn über den führt der Weg. Dein Timer 'tickt' mit 10ms (d.h. in diesen Intervallen wird die ISR aufgerufen)
1 | volatile uint16_t shutdownTime; |
2 | |
3 | ...
|
4 | |
5 | ISR( ... ) |
6 | {
|
7 | |
8 | ....
|
9 | |
10 | if( shutdownTime > 0 ) |
11 | {
|
12 | shutdownTime--; |
13 | if( shutdownTime == 0 ) |
14 | PORTD &= ~( 1 << PD0 ); |
15 | }
|
16 | }
|
alle 10ms wird also die noch verbleibende Restzeit geprüft, ob sie noch größer 0 ist. Wenn ja, wird die Restzeit verringert und wenn dann 0 rauskommt, dann wird abgeschaltet. Bleibt nur noch das einschalten. Das passiert aufgrund irgendwelcher Bedingungen zb in main
1 | int main() |
2 | {
|
3 | DDRD |= ( 1 << PD0 ); // Pin auf Ausgang |
4 | |
5 | ....
|
6 | |
7 | while( 1 ) |
8 | {
|
9 | |
10 | if( irgendwas ganz wichtiges ist passiert ) |
11 | {
|
12 | cli(); // Interrupts disablen, damit gefahrlos auf shutdownTime |
13 | // zugegriffen werden kann. Ist ja ein 16 Bit Wert
|
14 | |
15 | shutdownTime = 500; // 5 Sekunden * 10 Millisekunden macht einen |
16 | // Wert von 500
|
17 | PORTD |= ( 1 << PD0 ); // ... und einschalten |
18 | |
19 | sei(); // Gefahr vorüber, Interrupts sind wieder erlaubt |
20 | }
|
21 | ....
|
22 | }
|
23 | |
24 | }
|
in main wird eingeschaltet und die abzulaufende Zeit eingestellt. Wird immer wieder zugewiesen, dann fängt die Zeit auch immer wieder neu zu laufen an. Wird irgendwann die Zuweisung nicht mehr gemacht, dann wird in der Timer-ISR die 'Zeitvariable' sukzessive bei jedem Aufruf ein wenig runtergezählt, bis dann irgendwann 0 erreicht wird und der Ausgang in der ISR abgeschaltet wird. Voila: ein Nachlauf ist entstanden - 5 Sekunden nachdem die Bedingung 'irgendwas wichtiges' nicht mehr zutrifft, schaltet der Ausgang ab.
:
Bearbeitet durch User
Und teil dein Programm besser in Funktionen auf. So eine Programmwurscht ist doch furchtbar zu lesen!
Hi @all, ich habe es hinbekommen mit der Hysterese. Allerdings die "Programmwurscht" ist immernoch vorhanden. Sobald ich da was durcheinander bringe, funktioniert meine Umrechnerei von +Graden zu -Graden nichtmehr. Irgendwie blicke ich, wenn es so weiter geht, selbst nichtmehr durch ;-) Das Ding ist auf keinen Fall perfekt (vom Programmierstil her), aber die Funktionen, die ich haben wollte, sind vorhanden. Vielleicht bette ich iwann noch ne Uhr mit Datum ein. Damit man immer schön sieht, wann es am kältesten draussen war. Die Hysterese ist jetzt variabel wählbar und funzt perfekt. Und ich habe wieder einiges an Erfahrung/Wissen dazugewonnen, wozu das Projekt letztendlich auch gedacht war. Wenn es Sinn machen sollte, auch wenn niemand in der main.c durchsteigt, könnte ich mein "Projekt" in die Codesammlung stellen. Aber davor würde ich gerne paar Meinungen hören.
Karl Heinz Buchegger schrieb: > while( 1 ) > { > > if( irgendwas ganz wichtiges ist passiert ) > { > cli(); // Interrupts disablen, damit gefahrlos auf shutdownTime > // zugegriffen werden kann. Ist ja ein 16 Bit Wert > > shutdownTime = 500; // 5 Sekunden * 10 Millisekunden macht > einen > // Wert von 500 > PORTD |= ( 1 << PD0 ); // ... und einschalten > > sei(); // Gefahr vorüber, Interrupts sind wieder erlaubt > } Mittlerweile kann ich ja schon so ein bisschen, aber KEINER und auch kein Buch erklärt das so schön wie du, lieber Karl Heinz!
Besser wäre aber:
1 | #include <util/atomic.h> |
2 | ...
|
3 | while( 1 ) |
4 | {
|
5 | |
6 | if( irgendwas ganz wichtiges ist passiert ) |
7 | |
8 | ATOMIC_BLOCK(ATOMIC_RESTORESTATE) |
9 | {
|
10 | shutdownTime = 500; // 5 Sekunden * 10 Millisekunden macht einen |
11 | // Wert von 500
|
12 | PORTD |= ( 1 << PD0 ); // ... und einschalten |
13 | }
|
14 | |
15 | }
|
Denn eigentlich will man das I-Flag im Zustand davor, der nicht "1" sein muß. Oder man mag unerklärliche Fehler suchen ;-)
F. Fo schrieb: > aber KEINER und > auch kein Buch erklärt das so schön wie du, lieber Karl Heinz! Da stimme ich Dir voll und ganz zu.......
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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.