Forum: Mikrocontroller und Digitale Elektronik Unabhängiger Timer gesucht


von Stefan B. (sibbl) Benutzerseite


Angehängte Dateien:

Lesenswert?

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

von c-hater (Gast)


Lesenswert?

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.

von Stefan B. (sibbl) Benutzerseite


Lesenswert?

Danke für den Tipp, allerdings hätte ich mir ein paar konstruktivere 
Vorschläge erhofft.

von astroscout (Gast)


Lesenswert?

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!

von Bastler (Gast)


Lesenswert?

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!?)

von Magnus M. (magnetus) Benutzerseite


Lesenswert?

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?

von Stefan B. (sibbl) Benutzerseite


Angehängte Dateien:

Lesenswert?

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

von hysteriker (Gast)


Lesenswert?

Denkfehler ist der richtige Ansatz. Du benötigst eine Hysterese. Der 
Einschaltwert liegt ein paar Punkte über dem Ausschaltwert und fertig.

von Stefan B. (sibbl) Benutzerseite


Lesenswert?

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

von Karl H. (kbuchegg)


Lesenswert?

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
von Karl H. (kbuchegg)


Lesenswert?

Und teil dein Programm besser in Funktionen auf.
So eine Programmwurscht ist doch furchtbar zu lesen!

von Stefan B. (sibbl) Benutzerseite


Angehängte Dateien:

Lesenswert?

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.

von F. F. (foldi)


Lesenswert?

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!

von Bastler (Gast)


Lesenswert?

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

von Stefan B. (sibbl) Benutzerseite


Lesenswert?

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
Noch kein Account? Hier anmelden.