Zeitabläufe mit µC (xMega)

OP #3386899
Lesenswert?

Hallo,

ich habe vor, bzw. bin gerade an der Umsetzung des folgenden Projekts:
Ich hab ein Board mit nem xMega16D4 auf dem soll folgendes geschehen, 
nach einem bestimmten Zeitplan sollen Dinge ausgeführt werden.

Das folgende (schreib das zur Vereinfachung nur mit LED an/aus)
Led1 an
  10s warten
Led1 aus
Led2 an
  15s warten
Led2 aus

Das mit wait zu machen is mal eine ganz schlechte Idee, also Timer.

Das hab ich mir so vorgestellt, den Timer so einstellen dass ein Tick 
alle 10ms stattfindet, dann wird immer eine Variable (ich nenn sie mal 
A) hochgezählt mit dem Takt.

Dann im Programm iwie an der Led1 an z.B. den aktuellen Wert von A 
merken, den 10s addieren und das in ne Zwischenvariable B speichern, und 
dann später überprüfen wann A = B ist und dann Led1 aus schalten.


Jeder der etwas Ahnung hat wird jetzt wahrscheinlich die Hände überm 
Kopf zusammen schlagen ... Ich übrigens auch, aber ich komm im Moment 
grad auf nix besseres (Betriebsblind? ...)

Daher die Frage, wie macht man sowas ordentlich?
Steh da grad etwas aufm Schlauch.

EDIT: ganz vergessen, eigentlich muss man es ja nicht Wissen, geht ja 
nur ums Prinzip wie man das umsetzt, aber für die dies interessiert, ich 
arbeit in C.

David
#3386927
Lesenswert?

Hi,
Das mit der Variable A im Timer ist schon richtig. Die zählst Du hoch.
Im Hauptprogramm tust Du nichts anderes als diese Variable auszuwerten.
(sinnvollerweise mit einem case Konstrukt)
Hier vergleichst Du die Variable mit den gewünschten Zeiten Deiner 
Ereignisse.
In Deinem Fall also:

case A
A=0:
Led1 an

#  10s warten
A=1000: #10ms x 1000
Led1 aus
Led2 an

#  15s warten
A=2500: #25ms x 1000 (ab A=1000 15s)
Led2 aus

endcase

Und wenn der Zyklus beendet ist, setzt Du A in Deinem Hauptprogramm 
wieder auf 0.

Das ist nichts anderes als eine Statemaschine.


Gruß
Andreas
#3386955
Lesenswert?

David .. schrieb:

> Das hab ich mir so vorgestellt, den Timer so einstellen dass ein Tick
> alle 10ms stattfindet, dann wird immer eine Variable (ich nenn sie mal
> A) hochgezählt mit dem Takt.
>
> Dann im Programm iwie an der Led1 an z.B. den aktuellen Wert von A
> merken, den 10s addieren und das in ne Zwischenvariable B speichern, und
> dann später überprüfen wann A = B ist und dann Led1 aus schalten.

Das kann man im Prinzip genau so machen, wie du das vorschlägst.

Ich machs ganz gerne anders rum.
Ich hab keinen Zähler der hochzäht, sondern pro LED einen Zähler der 
runterzählt. Quasi ein Countdown für jede LED, wie lange sie noch 
brennen soll.
In der Hauptschleife wird der Countdownzähler auf einen Wert gesetzt, 
der der gewünschten Zeitdauer der Brenndauer entspricht (unter 
Berücksichtigung der ISR-Aufrufzeiten) und die LED eingeschaltet. In der 
ISR wird der Zähler sukzessive wieder runter gezählt und wenn 0 erreicht 
ist, wird in der ISR die LED abgeschaltet (oder sonst irgendeine Aktion 
ausgelöst).

Variationen davon sind natürlich möglich. Worauf es mir ankommt ist, 
dass ich das Gefühl habe, dass Countdown-Steuerungen auf dieser Ebene 
oftmals ein bischen einfacher sind, als eine Uhr die hochzählt.
Gast #3386962
Lesenswert?

Karl Heinz schrieb:
> Worauf es mir ankommt ist,
> dass ich das Gefühl habe, dass Countdown-Steuerungen auf dieser Ebene
> oftmals ein bischen einfacher sind, als eine Uhr die hochzählt.

Vor allen Dingen muss man bei Änderungen von Zeiten nur an einer Stelle, 
nämlich dort wo der Countdown-Wert gesetzt wird, etwas ändern und nicht 
überall alle Schaltzeitpunkte umrechnen.
OP #3392821
Lesenswert?

Wow, vielen Dank für die Antworten, werde ich mir gleich ansehen.

Inzwischen hab ich aber auch schon eine Lösung:

ISR(RTC_OVF_vect)
{
  timerTime++;
}

und ein Zeitablauf sieht dann so aus:
      switch (timerTime)
      {
        case 0:
          //led1 an
        break;

        case 200:
          //led1 aus
          //led2 an
          //sound#2 starten
        break;

        case 800:
          //led2 aus
          //sound stoppen
          timerTime = 0;
        break;
      }

Ziemlich simpel und für mich derzeit schonmal ausreichend :)
Gast #3392833
Lesenswert?

du musst dabei halt sicherstellen, dass der switch-case oft genug 
aufgerufen wird, dass du nicht einen Timertick verpasst. Sonst könnte es 
passieren, dass z.B. timerTime > 800 wird und dann dauert es je nach 
Datentyp ein bisschen, bis die überläuft und wieder bei 0 anfängt ;)
OP #3392837
Lesenswert?

Sehr guter Punkt.

den RTC hab ich so eingestellt das es alle 10ms ein Tick gibt, das 
dürfte bei 32MHz der CPU wohl locker reichen.
Und da ich nichts delays mache sondern nur LEDs, Servos und nen externes 
Soundmodul (WTV020 von eBay aus China falls jemand sowas zufällig sucht) 
hab ich da auch kein Problem damit, zumindest derzeit nicht.


Hab bisher noch keine Probleme fest gestellt.
Ansonsten kann man die XMegas wohl auch noch übertakten :P
#3392974
Lesenswert?

David .. schrieb:

> Hab bisher noch keine Probleme fest gestellt.
> Ansonsten kann man die XMegas wohl auch noch übertakten :P

Übertakten brauchst du nicht.
Du brauchst nur so programmieren (wenn du mal in die Situation kommst), 
dass du defensiv arbeitest. Also nicht darauf bestehen, dass eine 
bestimmte Zahl exakt rauskommen muss, sondern berücksichtigen, dass du 
eventuell auch mal einen Tick verpassen kannst. Mit den geschilderten 
Techniken ist das ja auch kein Problem.

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren