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

Re: system.timer() Kategorie: Programmierung (von Wurl - 2.01.2011 21:32)
Als Antwort auf system.timer() von Detlef - 30.12.2010 17:09

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


    Antwort schreiben


Antworten:

Re: system.timer() (von nitraM - 4.01.2011 10:27)
    Re: system.timer() (von Detlef - 4.01.2011 11:35)
        Re: system.timer() (von nitraM - 5.01.2011 7:54)
            Re: system.timer() (von Wurl - 5.01.2011 10:48)
                Re: system.timer() (von Detlef - 5.01.2011 17:08)
        Re: system.timer() (von Wurl - 4.01.2011 21:41)
Re: system.timer() (von Detlef - 4.01.2011 8:50)