Zur Übersicht - INFO - Neueste 50 Beiträge - Neuer Beitrag - Suchen - FAQ - Zum CC1-Forum - Zum CC-Pro-Forum

Re: system.timer() Kategorie: Programmierung (von Detlef - 4.01.2011 8:50)
Als Antwort auf Re: system.timer() von Wurl - 2.01.2011 21:32
Ich nutze:
C-Control II Station
> > Hallo Zusammen,
> >
> > ich habe Probleme mit einem Thread, der den Systemtimer verwendet.
> > Nach ca. 14 Tagen funktioniert er nicht mehr richtig, nach vier Wochen
> > werden die Fehlfunktionen so groÃ?, daÃ? ich einen Reset machen muÃ?.
> >
> > Grundsätzlich stehe ich mit der long Variable auf Kriegsfu�; obwohl ich mich
> > meiner Meinung nach an die Spec halte, gibt es bei groÃ?en Zahlenwerten immer Probleme.
> >
> > Deshalb glaube ich auch, da� der gro�e Zahlenwert des system.timer() Ursache für die
> > Probleme dieses Threads sind. Vielleicht erkennt ja einer von Euch sofort, was ich hier falsch mache.
> >
> > Anbei der Code.
> > Grundsätzliche Funktion des Threads:
> > Mehrere Funktionen nacheinander ausführen.
> > Beispiel: Jalousien runterfahren und nach 20 Sekunden abschalten
> > oder
> > Licht aufziehen, nach einiger Zeit runterdimmen, dann nach weiterer Zeit ganz ausschalten.
> >
> > Aktwert[a] ist der Aktor, der gesteuert wird
> > Aktwert[a+1] ist der Funtkionswert. Im Detail:
> >  0-9 sind Funktionen rund um Jalousiesteuerung
> >  10-19 sind Funktionen zur Relaissteuerung
> >  20-29 sind Funktionen für Lichtdimmung.
> > Aktwert[a+2] ist ein Parameter ( Wie weit sollen Jalousien fahren, wie hell das Dimmlicht usw.)
> > Aktzeit ist die Zeit in ms, die vergehen soll, bis die Aktwert-Funktion erneut aufgerufen wird.
> >
> > Aktwert[a], Aktwert[a+1] und Aktwert[a+2] werden in einer anderen Funktion befüllt.
> > Nach deren Befüllung wir das Aktflag auf 1 gesetzt, damit folgender Thread aktiv wird:
> >
>
>
> Hallo.
>
> Das mit dem system.timer() als 32bit long Variable gefällt mir auch nicht so.
> 32bit entsprechen rund 4Mrd. Millisekunden, also ca. 71500 Minuten oder 1193 Stunden oder 49,7 Tage.
> Für eine absolute Zeit ist das zu wenig.
> Sofern system.timer() bei Null startet (wobei ich mir nicht sicher bin) gibt es dann nach knapp 50 Tagen einen Overflow.
> Zeitvergleiche mit system.timer() werden also kompliziert, weil man den Overflow berücksichtigen muss.
> Und wenn - wie ich glaube - Werte grö�er 2^31 als Negativ (2er-Komplement) interpretiert werden, dann wird es noch schwieriger.
>
> Ich habe in meiner Anwendung vor, ein Zeitraster von 128ms zu verwenden und die TimerTicks in einer separaten Variable zählen.
> Damit kann ich meine Schaltvorgänge ausreichend gut bedienen.
>
> In Deiner Anwendung wird beim Overflow von 'wart' der system.timer() eine Zeit lang immer grö�er sein.
> Oder aber - 2er-Komplement angenommen - 'wart' oder 'system.timer()' oder 'Aktzeit[x]' wird,
> obwohl es grö�er werden sollte, dummerweise als Negativwert interpretiert.
> Wann der compiler was macht, kann ich auch nicht sagen - das ist im Handbuch sehr schwammig formuliert.
>
> Für Deinen Zweck würde ich eine andere Vorgehensweise vorschlagen:
> - Berechnung der Wartedauer anstatt der Zielzeit
> - Speichern von Relativzeiten
> - Merken des letzten system.timer()-Standes
> - Berechnen der Timer-Differenz
>
>  thread Ueberwachung
>  {
>    int a,wert;
>
>    long wart;              // wart ist jetzt die Zeitdauer, nach der reagiert werden soll.
>    long systimer_neu   // zum Zwischenspeichern von system.timer()
>    long systimer_alt   // Reagiert wird, wenn (system.timer_neu - system_timer_alt)
>                        // gröÃ?er als 'wart' wird.
>    long systimer_diff  // zum Zwischenspeichern von (system.timer_neu - system_timer_alt)
>

>    a=0;
>  
>
>    do
>    (
>      system_timer_neu = system.timer();
>      long systimer_diff = (long systimer_neu - long systimer_alt) & 0x7FFFFFFF; //Timer-Differenz
>                                                    // weg mit Negativ-Werten durch Veroderung
>    }
>    while (system.timer_diff >= wart) or Aktflag);  // Solange wart-ezeit noch nicht abgelaufen.
>    system_timer_alt = system.timer_neu;            // neuen Timer-Wert Speichern
>    wart = 3600000;                                 // jede Stunde zumindest ein Lauf.
>

>    Aktflag=0;                                     // Interuptflag zurücknehmen.
>  
>    while Aktwert[a]!= ENDE                        // Schleife durchführen
>      {
>      if Aktwert[a] == LEER                        // Wenn Aktwert[a]==LEER und nächster Eintrag
>        {                                          // ist ENDE, wir das ENDE um einen Eintrag
>        if Aktwert[a+3]==ENDE Aktwert[a]=ENDE;     // vorgeholt.
>        }
>      else
>
>        Aktzeit[a] = Aktzeit[a] - system.timer_diff  // wartezeit um vergangene Zeit reduzieren
>        if (Aktzeit[a] <= 0)                         // Ist diese Wartezeit abgelaufen?
>           //allerdings bin ich hier nicht sicher, ob Negativwerte <0 unterstützt werden
>           //es wird ja die Aktzeit[] wohl ein long sein, oder?
>

>          {
>          if Aktwert[a+1] < 10                    // Jalousien steuern
>            {
>            if Aktwert[a+1] == 0                  // Modus 0 = Jalousie hoch bis Endschalter
>              {
>              dwmodule.JalAbs(JalZi[Aktwert[a]],Auf);  // Jalousie hochfahren
>              sleep 100;
>
>              Aktzeit[a] = 30000;              // neue Wartezeit = 30 Sec
>

>              Aktwert[a+1]=1;                  // Modus auf 1 hochsetzen
>              }
>            else if Aktwert[a+1] == 1             // Modus 1 = Jalousien runterfahren.
>              {
>              if Aktwert[a+2] dwmodule.JalAbs(JalZi[Aktwert[a]],Ab);  // Jalousie runterfahren, wenn angegeben.
>              sleep 100;                                              // verhindert das Kleben der Relais
>
>              if Aktwert[a+2] == 1 Aktzeit[a] = 4000;    // Jalousie viertel runterfahren
>              else if Aktwert[a+2] == 2 Aktzeit[a] = 8000;  // Jalousie halb runter
>              else if Aktwert[a+2] == 3 Aktzeit[a] = 12000;  // Jalousie ganz runter
>              else if Aktwert[a+2] == 4 Aktzeit[a] = 21000;  // Jalousie ganz runter
>
>              Aktwert[a+1]=2;                   // Modi auf 2 hochsetzen
>              }
>            else if Aktwert[a+1] == 2           // Jalousien stoppen
>              {
>              dwmodule.JalAbs(JalZi[Aktwert[a]],Stop);
>              sleep 100;
>              Aktwert[a]=LEER;                  // Auftrag aus Aktwert löschen.
>              }
>            }
>          else if Aktwert[a+1] < 20             // Relais steuern
>            {
>            }
>          else if Aktwert[a+1] < 30             // Dimmer steuern
>            {          
>            }
>          }
>        if (wart-Aktzeit[a]) > 0 wart=Aktzeit[a]; // die kürzeste Wartzeit in wart eintragen
>        a=a+3;                                    // nächsten Aktwert Eintrag prüfen.
>      }
>  }

Danke für die Antwort.

Ich werde das am Wochenende mal so umsetzen und dann nochmal Feedback geben.
Grundsätzlich hatte schon den Gedanken ohne den system.timer() zu arbeiten. Schon allein,
weil die Umlaufzyklen mit 20-50 Tagen jeden vernünftigen Test der Software unmöglich machen.

Viele Grü�e

Detlef



    Antwort schreiben


Antworten: