Schleife im ms Takt durchlaufen



  • Hallo,

    ich öffne eine Textdatei die Folgendes Format hat:

    2352|010101
    2500|010101
    3000|101011
    3600|101101
    4500|110011
    5600|011001
    7500|011001
    10530|001101
    

    Die Zahlen vor dem Trennzeichen ( | ) sind die Millisekunden die danach Befehle um ein USB Interface zu steuern.
    Nun möchte ich das die Schleife den Text durchläuft und die Befehle wiedergebt.
    Da ich mich noch nicht so gut mit Schleifen auskenne möchte ich gerne eure Hilfe haben. HIer mal mein Code:

    // Stringliste erstellen
      TStringList *List = new TStringList();
      // Datei Laden
      List->LoadFromFile("C:\\commands.txt");
    
      for(int i = 0; i < List->Count; i++)
      {
        if(List->Strings[i].Pos("|") > 0)
        {
    
          // Hier sollen die Befehle in Millisekunden ausgegeben werden
    
          String Text = List->Strings[i];
          // Nach dem Trennzeichen suchen
          int CharPos = List->Strings[i].Pos("|");
          // Der Text wird nach dem Trennzeichen ausgelesen
          Text = Text.SubString(CharPos+1,7);
          // Befehle ins Memofeld schreiben
          Memo1->Lines->Add(Text);
        }
      }
      delete List;
    

    Kann mir jemand weiterhelfen?



  • Kann mir jemand weiterhelfen?

    wobei genau?
    du stellst keine genaue Frage.



  • Ich glaube du suchst folgende Funktion:

    void TForm1::Delay(int Wartezeit_ms)
    {
      // =========================================================
      // Diese Funktion unterbricht die Abarbeitung einer Funktion
      // für eine bestimmte Zeit [ms]
      // =========================================================
    
      // Deklaration lokaler Variablen
      // =============================
      int ilStartTime = 0;
    
      // Aktuelle Zeit speichern
      ilStartTime = ::GetTickCount();
    
      // Prüfen, ob die als Parameter übergebene Wartezeit
      // abgelaufen ist
      // Wenn nein, dann die anfallenden Erreignisse abarbeiten,
      // damit während der Wartezeit das Programm bedienbar bleibt
      // =========================================================
      while (int(::GetTickCount() - ilStartTime) < Wartezeit_ms)
      {
       Application->ProcessMessages();
      }
    }
    


  • Ich würde ja den eingelesen Text mit DelimitedText ausandernehmen anstelle den String so manuel zu zerlegen.



  • Naja, du könntest auch Sleep benutzen um die Schleife für eine bestimmte Anzahl von Sekunden anzuhalten z.B. so

    TStringList *List = new TStringList();
      // Datei Laden
      List->LoadFromFile("C:\\commands.txt");
      int wartezeit_ms=0;
      for(int i = 0; i < List->Count; i++)
      {
        if(List->Strings[i].Pos("|") > 0)
        {
    
          // Hier sollen die Befehle in Millisekunden ausgegeben werden
    
          wartezeit_ms=1000; //-----hier die ms aus jeder Textzeile parsen hier z.B. 1 Sekunde
          String Text = List->Strings[i];
          // Nach dem Trennzeichen suchen
          int CharPos = List->Strings[i].Pos("|");
          // Der Text wird nach dem Trennzeichen ausgelesen
          Text = Text.SubString(CharPos+1,7);
          // Befehle ins Memofeld schreiben
          Memo1->Lines->Add(Text);
    
          Application->ProcessMessages(); //----Messages an Application weiterleiten
         ::Sleep(wartezeit_ms); //------Schleife für wartezeit_ms Millisekunden anhalten
    }
      }
      delete List;
    

    Das müsste reichen. Zwar wäre ein Thread besser, aber wenn die Befehle nicht zuviele sind, dann ist diese Methode besser.



  • Danke, die beiden Codes funktionieren. Hawkxxx bei deinem Beispiel fängt er immer von vorne an zu zählen, ich will aber das es nicht von vorne anfängt. Beispiel

    Bei 2352 Millisekunden wird ein Befehl ausgeführt kurz darauf bei 2500 wird schon der nächste Befehl ausgeführt sprich nach 148 Millisekunden. und so soll es die ganze Liste durchgehen. Die Liste hier am Anfang ist nur ein Auszug d.h. sie ist schon 2000 Zeilen lang.



  • Hallo,

    du müsstest die Differenz der jeweiligen Zeiten bilden ( für Sleep ) und den alten Startwert zwischenspeichern. So in etwa:

    TStringList *List = new TStringList();
       List->LoadFromFile("C:\\commands.txt");
       int wartezeit_ms    = 0;
       int old_wartezeit_ms = 0;
       int tick         = 0;
    
       for(int i = 0; i < List->Count; i++) {
    
          if(List->Strings[i].Pos("|") > 0) {
    
             String Text = List->Strings[i];
    
             int CharPos = List->Strings[i].Pos("|");
             wartezeit_ms = StrToInt(Text.SubString(1, CharPos -1));
             // Zeitdifferenz bilden
             tick = wartezeit_ms - old_wartezeit_ms;
    
             Text = Text.SubString(CharPos+1,7);
             // Testausgabe
             Memo1->Lines->Add(Text + ", warte " + IntToStr(wartezeit_ms) + " ms, Tick: " + IntToStr(tick));
             Application->ProcessMessages();
             ::Sleep(tick);
             // alte Startzeit speichern
             old_wartezeit_ms = wartezeit_ms;
          }
       }
        delete List;
    

    mfg
    kpeter



  • Danke! Genau das was ich suchte 👍



  • Falsche Ansatz. Windows ist kein Echtzeitbetriebssystem. Du kannst dich nicht darauf verlassen, dass nach genau x Sekunden dein Code ausgeführt wird. So bald das System etwas ausgelastet ist, wird das nicht mehr sicher funktionieren, weil andere Threads Rechenzeit zugewiesen bekommen und dein Thread in den zuteilungsfähigen Zustand versetzt wird und somit keinen Code ausführen kann. Erst wenn er wieder Rechenzeit zugeteilt bekommt, kann er wieder Code ausführen. Aber wann und nach wie viel Millisekunden das ist, kannst du nicht vorhersagen bzw. bestimmen.

    Die Zuteilung von Rechenzeit erfolgt in sogenannten Zeitscheiben, wobei pro Thread ca 20 ms zugeteilt werden. Hinzu kommt, dass Threads mit einer höheren Priorität bei der Zuteilung priorisiert werden.



  • Wie ist es möglich, dass die Zeiten genau eingehalten werden?



  • Fregger schrieb:

    Wie ist es möglich, dass die Zeiten genau eingehalten werden?

    Unter Windows mit einer Echtzeiterweiterung. Ein deutsches Produkt wäre z.B. das Kithara Realtime Toolkit aus Berlin.

    Oder mit echzeitfähiger Hardware anstatt deines USB-Interfaces:

    - Als Billiglösung etwas selbstgebautes mit einem Mikrokontroller.

    - Eine Steckkarte oder USB-Interface mit eigenem Prozessor (z.B. Adwin)

    - Eine SPS mit guter PC-Anbindung
    - als Software z.B. TWinCat von Beckhoff
    - als Hardware z.B. eine MelsecQ von Mitsubishi


Anmelden zum Antworten