-         
Seite 1 von 2 12 LetzteLetzte
Ergebnis 1 bis 10 von 18

Thema: delay-Ersatz ohne loop-Bremse

  1. #1
    Erfahrener Benutzer Fleißiges Mitglied
    Registriert seit
    07.06.2019
    Beiträge
    123

    delay-Ersatz ohne loop-Bremse

    Anzeige

    Hallo zusammen.

    ( Dieses Bsp ist nur ein Teilschritte zur späteren Tastenentprellung (mehrerer Tasten über Interrupt) ohne delay(),
    daher bitte NUR schrittweise (Konzept)Hinweise, und KEINE fertigen Lösunge, sonst lerne ich das nie... )

    1. Primär geht es mir darum, Zeitberechnungen in eine Funktion auszulagern, ohne den loop() mit delay() etc. zu Bremsen!
    2. Mehrer parallele Zeitberechnungen möglich.
    3. Möglichst nur eine Zeitberechnungs-Funktion für alle Anwendungen, auf die Jeder, zu jeder Zeit zugreifen kann.

    Bsp:
    loop(){
    //kein delay()
    //kein while()
    ...macht irgend etwas
    Start: LED1, ein, für 20ms, danach aus für 1000ms
    ...macht irgend etwas
    Start: LED2, ein, für 100ms, danach aus für 100ms
    ...macht irgend etwas
    }
    Alle loop()-Schritte sind unabhängig voneinander.
    Eine Funktion(), Bsp.Ausg() als "EierLegendeWollMilchSau". Problem ist hierbei, dass ich nur eine "volatile long msStart=0;" zur Verfügung habe.


    Mein (falscher) Ansatz, ohne delay();
    HTML-Code:
    void loop() {
    ...
    Ausg(LED1Pin, 1, 20);
    ...
    Ausg(LED1Pin, 0, 1000);
    ...
    Ausg(LED2Pin, 1, 100);
    ...
    Ausg(LED2Pin, 0, 100);
    ...
    }
    
    void Ausg(int Pin, int OnOff, long Dauer)  {  // Dauer=0...dauerhaft, ohne Zeitlimit
      if(Dauer != 0)  {
        if(msStart == 0)  {
          msStart = millis();
        }
        if(millis() <= msStart + Dauer) {
          digitalWrite(Pin, OnOff); 
        }
        else  {
          digitalWrite(Pin, !OnOff);
          msStart = 0;
        }
      }
      else  {
        digitalWrite(Pin, OnOff);
      }
    }
    PS: Besser kann ich meine Gedanken gerade nicht formulieren. Daher bitte Fragen, wenn euch irgend eine Info fehlt.

    - - - Aktualisiert - - -

    PS:
    Für jeden Ein/Ausgang eine eigene Funktion?
    ... mit eigenem Zähler?
    ... und eigener volatile long Variablen?
    Sollte das eine gute Lösung sein?
    Statt dessen würde ich gerne alles in kleine und kleinste Funktionsblöcke unterteilen.
    __________________________________________________ _
    | Sprache: C | Teensy 3.2 | Status: EwigerAnfaenger |

  2. #2
    Erfahrener Benutzer Roboter-Spezialist
    Registriert seit
    07.04.2015
    Beiträge
    577
    Beispiel:
    PortBit // Parameter (Bitnummer)
    OffTime // Parameter (in millis)
    OnTime // Parameter (in millis)
    InitialState // Parameter (On/Off)
    *Callback // Parameter (ggf. aufzurufender Funktionszeiger, wenn mehr als der Port getoggelt werden soll)
    State //Puffer (aktuell On/Off)
    Start //Puffer (letzter Flankenwechsel-millis)

    So etwas kannst Du Dir als Strukturtyp definieren und für jeden Ausgang instanziieren. Die Parameter definiert (setzt) man beim Applikationsstart einmalig. Die Puffervariablen werden im loop-Durchlauf gebraucht.

    Anstelle der einzelnen Infos steckt man dann einfach einen Zeiger auf die Strukturinstanz in die Ausg(…)-Funktion.

    In C++ geht's komfortabler mit Klassen (wobei ich nicht glaube, dass Du die Objektorientierung schneller verstehst als Strukturen).
    Geändert von Holomino (07.04.2020 um 14:06 Uhr)

  3. #3
    Erfahrener Benutzer Fleißiges Mitglied
    Registriert seit
    07.06.2019
    Beiträge
    123
    Danke erst einmal für Rü

    Zitat Zitat von Holomino Beitrag anzeigen
    Beispiel:
    In C++ geht's komfortabler mit Klassen (wobei ich nicht glaube, dass Du die Objektorientierung schneller verstehst als Strukturen).
    Tatsächlich gehts mir um universelle Funktionen, vorallem aber Einfachheit. Damit ich die nach 1/2 Nichtstun schnell rein komme.

    Zitat Zitat von Holomino Beitrag anzeigen
    Beispiel:
    So etwas kannst Du Dir als Strukturtyp definieren und für jeden Ausgang instanziieren. Die Parameter definiert (setzt) man beim Applikationsstart einmalig. Die Puffervariablen werden im loop-Durchlauf gebraucht.
    Klingt erst einmal kompliziert!
    Wenn das dennoch ein einfacher Weg ist, werde mich mit dem Thema "Struktur" und "Funktionszeiger" beschäftigen.
    __________________________________________________ _
    | Sprache: C | Teensy 3.2 | Status: EwigerAnfaenger |

  4. #4
    Erfahrener Benutzer Roboter-Spezialist
    Registriert seit
    07.04.2015
    Beiträge
    577
    Sieh es einmal so:
    Was Du gelernt hast, hast Du im Sack.
    Programmiersprachenentwickler bauen keine Features, um etwas zu verkomplizieren, sondern um es zu vereinfachen, d.h. nach jeder neu gelernten syntaktischen Feinheit geht es Dir besser, weil Du Sachen im Code einfacher, schneller, kürzer und damit auch verständlicher ausdrücken kannst.


    (P.S.: Natürlich hauen Programmiersprachenentwickler auch manchmal daneben, aber nach knapp 50 Jahren kannst Du davon ausgehen, dass das Konstrukt "Struktur" ausgereift ist.
    C++ ist syntaktisch nicht komplizierter, aber umfangreicher)
    Geändert von Holomino (07.04.2020 um 15:14 Uhr)

  5. #5
    Erfahrener Benutzer Robotik Visionär
    Registriert seit
    09.10.2014
    Beiträge
    5.076
    am einfachsten könnte man dazu mit elapsedMillis() beginnen:
    https://playground.arduino.cc/Code/ElapsedMillis/
    https://github.com/pfeerick/elapsedM...ive/master.zip



    Code:
    /*  
      Simple demo of using all the timing helpers elapsedMillis makes available.
    
      Either attach LEDs with series resistors to the indicated pins, or a
      six led / six bit 'Chartreuse' module plugged into pins 8 through GND. 
      
      Wired up in order, the leds have a nice walking/counting effect.
      
      This example code is in the public domain.
    */
    
    #include <elapsedMillis.h>
    
    //declare these global if you don't want them reset every time loop runs
    elapsedMicros LED1micro;
    elapsedMicros LED2micro;
    elapsedMillis LED3millis;
    elapsedMillis LED4millis;
    elapsedSeconds LED5seconds;
    elapsedSeconds LED6seconds;
    
    const int LED1 = 8;
    const int LED2 = 9;
    const int LED3 = 10;
    const int LED4 = 11;
    const int LED5 = 12;
    const int LED6 = 13;
    
    // delay between blinks of the LED
    unsigned long LED1_Interval = 62500;
    unsigned long LED2_Interval = 125000;
    unsigned int LED3_Interval = 250;
    unsigned int LED4_Interval = 500;
    unsigned int LED5_Interval = 1;
    unsigned int LED6_Interval = 2;
    
    void setup()
    {
      // initialize the LED pins as outputs
      pinMode(LED1, OUTPUT);
      pinMode(LED2, OUTPUT);
      pinMode(LED3, OUTPUT);
      pinMode(LED4, OUTPUT);
      pinMode(LED5, OUTPUT);
      pinMode(LED6, OUTPUT);
    }
    
    void loop()
    {
      if (LED1micro >= LED1_Interval)
      {
        digitalWrite(LED1, !(digitalRead(LED1))); // toggle the LED state
        LED1micro = 0;                            // reset the counter to 0 so the counting starts over...
      }
    
      if (LED2micro >= LED2_Interval)
      {
        digitalWrite(LED2, !(digitalRead(LED2))); // toggle the LED state
        LED2micro = 0;                            // reset the counter to 0 so the counting starts over...
      }
    
      if (LED3millis >= LED3_Interval)
      {
        digitalWrite(LED3, !(digitalRead(LED3))); // toggle the LED state
        LED3millis = 0;                           // reset the counter to 0 so the counting starts over...
      }
    
      if (LED4millis >= LED4_Interval)
      {
        digitalWrite(LED4, !(digitalRead(LED4))); // toggle the LED state
        LED4millis = 0;                           // reset the counter to 0 so the counting starts over...
      }
    
      if (LED5seconds >= LED5_Interval)
      {
        digitalWrite(LED5, !(digitalRead(LED5))); // toggle the LED state
        LED5seconds = 0;                          // reset the counter to 0 so the counting starts over...
      }
    
      if (LED6seconds >= LED6_Interval)
      {
        digitalWrite(LED6, !(digitalRead(LED6))); // toggle the LED state
        LED6seconds = 0;                          // reset the counter to 0 so the counting starts over...
      }
    }
    ·±≠≡≈³αγελΔΣΩ∞ Schachroboter:www.youtube.com/watch?v=Cv-yzuebC7E Rasenmäher-Robot:www.youtube.com/watch?v=z7mqnaU_9A8

  6. #6
    Erfahrener Benutzer Fleißiges Mitglied
    Registriert seit
    07.06.2019
    Beiträge
    123
    struktur in c
    Weitestgehend Verstanden!
    Macht bei großen, zusammenhängenden Datenvariablen (Bsp: Adressbuch) Sinn.

    Aber was hat das mit meinem Bsp. "parallele Zeitberechnungen" zu tun?
    Sind da nicht eher static-Variablen und Referenzen (&Variable) gefragt?
    __________________________________________________ _
    | Sprache: C | Teensy 3.2 | Status: EwigerAnfaenger |

  7. #7
    Erfahrener Benutzer Robotik Einstein Avatar von Rabenauge
    Registriert seit
    13.10.2007
    Ort
    Osterzgebirge
    Alter
    51
    Beiträge
    1.653
    Viel einfacher: das mitgelieferte Beispielprogramm "blinkWithoutDelay" ansehen und verstehen-das enthält alles, was man braucht.
    Keine Extra-Lib's, keine Zaubertricks.
    Auf diesem einfachen Beispiel basieren meine Timer, die ich in letzter Zeit ja schon einige Male erwähnt hatte..und die funktionieren prächtig, wenn man sie richtig einsetzt.
    Grüssle, Sly
    ..dem Inschenör ist nix zu schwör..

  8. #8
    Erfahrener Benutzer Robotik Einstein Avatar von Moppi
    Registriert seit
    18.03.2018
    Beiträge
    1.911
    Blog-Einträge
    12
    Code:
    https://www.arduino.cc/en/tutorial/BlinkWithoutDelay
    Code:
    https://forum.arduino.cc/index.php?topic=423688.0
    MfG

  9. #9
    Erfahrener Benutzer Roboter Genie
    Registriert seit
    05.11.2007
    Ort
    Berlin
    Beiträge
    1.027
    Ich habe da folgende Vorgehensweise:

    Code:
    typedef unsigned int TTimeValue;   // ich nehme 16 Bit Werte für die Millisekunden Zeiten */
    
    typedef volatile struct         // in dieser Struktur werden alle Zeitwerte verwaltet
    {
      TTimeValue Led1BlinkTime;
      TTimeValue Led2BlinkTime;
      TTimeValue KeyTime;
     
      /* hier kann man beliebig erweitern */
    } TimerStruct;
    
    volatile TimerStruct Timers;   // das ist die gesamte Timerstruktur (die Instanz)
    
    //----------------------------------------------------------------
    // der 1 Millisekunden Timer Interrupt:
    // hier wird jeder Zeitwert, solange er noch nicht 0 ist, um eins erniedrigt
    
    void TIMER0_IRQHandler (void)
    { int i;
      TTimeValue *p = (TTimeValue*) &Timers;     /* initialize p to startaddress of the structure */
    
      for (i=0; i< (sizeof(Timers) / sizeof(TTimeValue)); i++)
      {
        if (*p)     /* if current addressed counter value is greater zero then */
          --*p;     /* decrement the counter value by one */
        p++;        /* p points now to the next counter value */
      }
    }
    //----------------------------------------------------------------
    // Jetzt kommen diverse Funktionen die ausgeführt werden sollen:
    
    void DoLed1(void)
    { static char BlinkPhase;
    
      if (Timers.Led1BlinkTime) return; // es gibt noch nichts zu tun, Zähler noch nicht 0
      if (BlinkPhase)
      {
    //     Led1On();
       Timers.Led1BlinkTime = 250;  // 250 ms ein
      } else 
      {
    //    Led1Off();
        Timers.Led1BlinkTime = 100;  // 100 ms aus
      }
      BlinkPhase = ! BlinkPhase;  // BlinkPhase umdrehen
    }
    
    
    void DoLed2(void)
    { static char BlinkPhase;
    
      if (Timers.Led2BlinkTime) return; // es gibt noch nichts zu tun, Zähler noch nicht 0
      if (BlinkPhase)
      {
    // Led2On();
       Timers.Led1BlinkTime = 500;  // 500 ms ein
      } else 
      {
    //  Led2Off();
        Timers.Led1BlinkTime = 250;  // 250 ms aus
      }
      BlinkPhase = ! BlinkPhase;  // BlinkPhase umdrehen
    }
    
    void DoKeys(void)
    { 
      if (Timers.KeyTime) return;  // noch nix zu tun
      Timers.KeyTime = 20;         // nächste Abfrage in 20ms
    
      //  Tastenstatus auswerten usw.....
    }
    
    void main(void)   // Hauptprogramm:
    {
      while (1)
      {
        DoLed1();
        DoLed2();
        DoKeys();
        // ....usw....
      }
    }
    aber viele Wege führen zum Ziel, da hat sicher jeder eine andere Lösung...

    Siro

  10. #10
    Erfahrener Benutzer Roboter-Spezialist
    Registriert seit
    07.04.2015
    Beiträge
    577
    Zitat Zitat von frabe Beitrag anzeigen
    struktur in c
    Weitestgehend Verstanden!
    Macht bei großen, zusammenhängenden Datenvariablen (Bsp: Adressbuch) Sinn.

    Aber was hat das mit meinem Bsp. "parallele Zeitberechnungen" zu tun?
    Sind da nicht eher static-Variablen und Referenzen (&Variable) gefragt?
    Die Verwendung einer Struktur hat nichts mit Größe oder Anzahl zu tun, sondern damit, die Variablen für einen Funktionsbaustein sinnvoll zusammenzuhalten und erweiterbar zu gestalten, so dass das weitermachen auch bei einem Fehlschlag oder einer neuen Anforderung noch Spaß macht! Guter Code entsteht niemals durch Zwang von Außen, sondern aus der einfachen Erkenntnis:
    Wenn es machbar ist und ein Erfolg winkt, tue ich es. Damit es machbar ist und bleibt, vermeide ich Codegräber und schreibe wartbaren Code.


    Dein Eingangsbeispiel zeigt doch schon drei Parameter auf. Mit denen funktioniert es nicht, da fehlt noch was. Das hast Du ja selber gemerkt.
    Das kannst Du jetzt mit zusätzlichen Übergabeparametern ergänzen. Nur musst Du dann auch die Variablen einzeln für die Übergabe definieren.
    Das gibt spätestens nach der 3. Änderungswelle ein heilloses, unwartbares Chaos. Bei jeder Erweiterung musst Du den aufgerufenen Funktionsrumpf ändern, alle Aufrufe anpassen und noch neue Variablen definieren.
    Mit Strukturen erweiterst Du nur den Strukturtyp, setzt die Initialwerte der Definitionen (Variablen) und kümmerst Dich um das Wesentliche - den Code in Deiner Funktion.

Seite 1 von 2 12 LetzteLetzte

Ähnliche Themen

  1. Servo-Dauerlauf ohne delay();
    Von KoQ im Forum Arduino -Plattform
    Antworten: 11
    Letzter Beitrag: 05.08.2013, 23:17
  2. Loop unterbrechen
    Von bomberman_z im Forum Basic-Programmierung (Bascom-Compiler)
    Antworten: 2
    Letzter Beitrag: 02.11.2008, 21:29
  3. Zeiten ohne Delay
    Von Spongebob85 im Forum C - Programmierung (GCC u.a.)
    Antworten: 21
    Letzter Beitrag: 22.10.2007, 00:22
  4. [Frage?] die Delay TIme nicht stimmt mit <util/delay.h>
    Von PaMan im Forum C - Programmierung (GCC u.a.)
    Antworten: 9
    Letzter Beitrag: 03.08.2007, 15:57
  5. Do Loop
    Von christian87 im Forum Basic-Programmierung (Bascom-Compiler)
    Antworten: 6
    Letzter Beitrag: 28.01.2005, 11:32

Stichworte

Berechtigungen

  • Neue Themen erstellen: Nein
  • Themen beantworten: Nein
  • Anhänge hochladen: Nein
  • Beiträge bearbeiten: Nein
  •