- Labornetzteil AliExpress         
Ergebnis 1 bis 8 von 8

Thema: einfaches multitasking mit arduino

  1. #1
    Erfahrener Benutzer Robotik Einstein Avatar von inka
    Registriert seit
    29.10.2006
    Ort
    nahe Dresden
    Alter
    77
    Beiträge
    2.180

    einfaches multitasking mit arduino

    Anzeige

    LiFePo4 Akku selber bauen - Video
    hallo,
    neulich fand ich auf garage_lab

    folgenden
    Code:
    #include <Servo.h>
    const int SERVO_PIN = 6;
    const int BUTTON_PIN = 8;
    const int LED_PIN = 13;
    Servo SRV_servo;
    int SRV_pos;
    boolean SRV_moveFoward;
    long SRV_nextWakeUp;
    int LED_value;
    boolean LED_moveFoward;
    long LED_nextWakeUp;
    
    void setup()
    {
      pinMode(LED_PIN, OUTPUT);
      pinMode(BUTTON_PIN, INPUT);
      // init the compontent’s states
      SRV_servo.attach(SERVO_PIN);
      SRV_pos = 0;
      SRV_moveFoward = true;
      SRV_nextWakeUp = millis();
    
      LED_value = 0;
      LED_moveFoward = true;
      LED_nextWakeUp = millis();
    }
    
    void loop()
    {
      long currentTime = millis();
      long nextWakeUpSRV = SRV_doStep(currentTime);
      long nextWakeUpLED = LED_doStep(currentTime);
      long nextMinWakeUp = (nextWakeUpSRV < nextWakeUpLED) ? nextWakeUpSRV : nextWakeUpLED;
      delay(nextMinWakeUp - currentTime);
    }
    
    /* ** SERVO ** */
    long SRV_doStep(long currentMillis)
    {
      if (currentMillis > SRV_nextWakeUp)
      {
        if (SRV_moveFoward)
        {
          SRV_pos += SRV_getIncrement();
          if (SRV_pos > 180)
          {
            SRV_moveFoward = false;
            SRV_pos = 180;
          }
        } else
        {
          SRV_pos -= SRV_getIncrement();
          if (SRV_pos < 0)
          {
            SRV_moveFoward = true;
            SRV_pos = 0;
          }
        }
        SRV_servo.write(SRV_pos);
        SRV_nextWakeUp = currentMillis + 100;
      }
      return SRV_nextWakeUp;
    }
    
    int SRV_getIncrement()
    {
      if (digitalRead(BUTTON_PIN))
      {
        return 1;
      } else
      {
        return 5;
      }
    }
    
    /* ** LED ** */
    long LED_doStep(long currentMillis)
    {
      if (currentMillis > LED_nextWakeUp)
      {
        if (LED_moveFoward)
        {
          LED_value += 3;
          if (LED_value >= 200)
          {
            LED_moveFoward = false;
          }
        } else
        {
          LED_value -= 3;
          if (LED_value <= 0)
          {
            LED_moveFoward = true;
          }
        }
        analogWrite(LED_PIN, LED_value);
        LED_nextWakeUp = currentMillis + 1;
      }
      return LED_nextWakeUp;
    }
    er funktioniert super, ich habe den ursprungscode um eine zweite LED und einen SR-04 erweitert und wollte ihn hier einfach mal weitergeben. Eine passage im code (in der loop) verstehe ich allerdings nicht:
    Code:
      long nextMinWakeUp = (nextWakeUpSRV < nextWakeUpLED) ? nextWakeUpSRV : nextWakeUpLED;
      delay(nextMinWakeUp - currentTime);
    könnte mir bitte jemand erklären wozu er ist? Der code funktioniert nämlich auch ohne die passage, zumindest erkenne ich keinen unterschied
    gruß inka

  2. #2
    Erfahrener Benutzer Robotik Einstein Avatar von i_make_it
    Registriert seit
    29.07.2008
    Ort
    Raum DA
    Alter
    56
    Beiträge
    2.814
    Dazu muß man die Notation "long nextMinWakeUp = (nextWakeUpSRV < nextWakeUpLED) ? nextWakeUpSRV : nextWakeUpLED;" kennen.
    http://forum.arduino.cc/index.php?topic=205334.0

    Das entspricht also:

    IF nextWakeUpSRV < nextWakeUpLED
    THEN nextMinWakeUp = nextWakeUpSRV
    ELSE nextMinWakeUp = nextWakeUpLED

    Damit wird dann schlußendlich das "delay(nextMinWakeUp - currentTime)" mit einem Zeitwert gefüttert.
    Lässt man es weg läuft "void loop();" einfach schneller durch.

    Kann man weglassen kann man aber auch behalten wenn die CPU zu schnell ist.

    Da das ganze ein kooperatives Multitasking ist, wird mit nextWakeUpSRV und nextWakeUpLED von den einzelnen Tasks mitgeteilt, wie lange es dauert bis sie wieder auf der Zeitscheibe dran sind.
    Da bei Batteriebetrieb ein Delay() schon mal etwas Energie spart, ist is dort sinnvoll.
    Denn dann wartet die CPU immer bis der Task mit der kleineren Restwartezeit drangenommern werden will.
    Springt dann beide Tasks an und bekommt die aktualisierte Restwartezeit zurück.
    Werden es dann mal mehr als zwei Tasks, wird dieser Codeteil natürlich umfangreicher oder man lässt ihn halt weg.
    Geändert von i_make_it (28.11.2016 um 16:37 Uhr)

  3. #3
    Erfahrener Benutzer Robotik Einstein Avatar von inka
    Registriert seit
    29.10.2006
    Ort
    nahe Dresden
    Alter
    77
    Beiträge
    2.180
    aha, danke
    Zitat Zitat von i_make_it;
    Werden es dann mal mehr als zwei Tasks, wird dieser Codeteil natürlich umfangreicher oder man lässt ihn halt weg.
    bedeutet, man muss dann von den vorhandenen tasks mit einer verschachtelten if/then/else abfrage den task mit der kürzesten wartezeit finden und die ist dann das nächste "nextMinWakeUp". Spielen die anderen dann noch eine rolle? Ok, ich denke nein, weil ja die kürzeste wartezeit bei jedem durchlauf von loop neu berechnet wird...
    gruß inka

  4. #4
    Benutzer Stammmitglied
    Registriert seit
    19.05.2015
    Beiträge
    69
    inka,
    du kannst diese Rechenspielerei getrost weglassen.
    Bei den AVRs bringt ein delay keinerlei Vorteile, da hier kein Sleep-Mode aktiviert wird, der Energie sparen könnte (selbst im Due Code wird das nicht gemacht).

    Sinnvoller wäre es, wenn du mal das Schlüsselwort "static" und dessen Funktion nachliesst und dann mal die ganzen globalen Variablen elemenieren würdest. Dann wird dein Code im Laufe der Zeit übersichtlicher und damit lesbarer.

    Meine 2cent

    botty

  5. #5
    Erfahrener Benutzer Roboter-Spezialist
    Registriert seit
    13.01.2014
    Beiträge
    454
    Blog-Einträge
    3
    Hi inka,

    in die Richtung hab ich auch mal was gebastelt, um die Sketches mit mehreren gezeiteten Aufgaben übersichtlich zu halten:
    Code:
    #include "SimpleTimerMillis.hpp"
    using Timer = SimpleTimerMillis;
    #define SEC *1000
    
    void taskA() {
       static Timer t(2 SEC, Timer::FOREVER, Timer::START_IMMEDIATELY);
       if(t.elapsed()) Serial.println("TaskA");
    }
    
    void taskB() {
       static Timer t(0.4 SEC, Timer::FOREVER, Timer::START_IMMEDIATELY);
       if(t.elapsed()) Serial.println("TaskB");
    }
    
    void setup() { 
      Serial.begin(9600);
    }
    
    void loop() {
      taskA();
      taskB();
    }
    Die Mini-Bibliothek dazu:
    Code:
    #ifndef __SIMPLETIMER__
    #define __SIMPLETIMER__
    
    class SimpleTimerMillis {
    using millis_t = unsigned long;
    public:
      static const bool ONCE = false;
      static const bool FOREVER = true;
      static const bool START_IMMEDIATELY = true;
    
      SimpleTimerMillis() = default;
      SimpleTimerMillis(millis_t timeSpan, bool forever, bool start=false) 
        : timeSpan(timeSpan), isContinous(forever) {
          if(start) this->start();
      }
      void start() {
        startTime = millis();
      }
      void start(millis_t timeSpan) {
        this->timeSpan = timeSpan;
        start();
      }  
      bool elapsed() {
        bool elapsed = millis()-startTime > timeSpan;
        if(elapsed && isContinous) start();
        return elapsed;
      }
      bool isCountious() {
        return isContinous;
      }
      void once() { isContinous = false; }
      void forever() { isContinous = true; }
    private:
      bool isContinous = false;
      millis_t startTime = 0;
      millis_t timeSpan  = 0;
    };
    
    #endif //__SIMPLETIMER__

  6. #6
    HaWe
    Gast
    wenn es komplizierter wird, wird das mit den Timern höchst unübersichtlich und ineffizient.

    Daher gibt es ja auch für die AVR Arduinos MT-Libs:
    http://forum.arduino.cc/index.php?topic=347188.0
    http://www.rtos48.com/

    für den Due gibt es ja schon ewig die Scheduler Lib und auch Babix,
    https://www.arduino.cc/en/Reference/Scheduler
    http://forum.arduino.cc/index.php?topic=318084.0

    doch seit nicht allzulanger Zeit gibt es auch Scheduler-Libs für AVR:
    http://playground.arduino.cc/Code/Scheduler
    http://playground.arduino.cc/Code/TaskScheduler
    Geändert von HaWe (28.11.2016 um 21:56 Uhr)

  7. #7
    Erfahrener Benutzer Robotik Einstein Avatar von inka
    Registriert seit
    29.10.2006
    Ort
    nahe Dresden
    Alter
    77
    Beiträge
    2.180
    hallo allerseits,

    danke für euere tipps, ich werde mich nun etwas genauer mit RTOS48 auseinandersetzen, da scheint die doku (auf den ersten blick) verständlich und recht ausführlich zu sein...

    @botty:

    Sinnvoller wäre es, wenn du mal das Schlüsselwort "static" und dessen Funktion nachliesst und dann mal die ganzen globalen Variablen elemenieren würdest. Dann wird dein Code im Laufe der Zeit übersichtlicher und damit lesbarer.
    so ganz genau habe ich glaube ich nicht verstanden wie du das meinst? Da es aber nichts mit multitasking zu tun hat wäre evtl. ein seprater thread /tutorial für die anwendung von globalen, lokalen variablen, von static, const int und defines, extern und was es sonst noch so gibt in der richtung definition und deklaration, mit beispielen und code-schnipseln (so ähnlich wie sisors tutorial zur erstellung von libs). Was hälst du davon? So aus der sicht eines praktikers und nicht von der theoretischen seite her? Würden sicher viele begrüßen! In diesem sinne...
    gruß inka

  8. #8
    HaWe
    Gast
    ein seprater thread /tutorial für die anwendung von globalen, lokalen variablen, von static, const int und defines, extern und was es sonst noch so gibt in der richtung definition und deklaration, mit beispielen und code-schnipseln (so ähnlich wie sisors tutorial zur erstellung von libs).
    ich denke, da kaufst du dir am besten mal ein Lehrbuch zu C nd C++ oder suchst Tutorials im web, denn die gibt es da zu Hauf, u.a. bei www.cplusplus.com .
    gerade hier kannst du auch sehr gut über Suchbegriffe gezielt Infos zu C/C++ Befehlen oder Bezeichnern finden, samt Programmier-Beispielen. Ich nutze es selber sehr gern als Quelle.

Ähnliche Themen

  1. [Arduino Uno] - Multitasking und Serielle Befehle
    Von neo3000 im Forum Arduino -Plattform
    Antworten: 8
    Letzter Beitrag: 17.04.2011, 10:04
  2. Multitasking Projekt
    Von Osser im Forum Asuro
    Antworten: 26
    Letzter Beitrag: 14.03.2008, 14:24
  3. Multitasking für den Asuro (II)
    Von Giwo im Forum Asuro
    Antworten: 8
    Letzter Beitrag: 27.12.2006, 08:23
  4. Multitasking
    Von Exodus im Forum AVR Hardwarethemen
    Antworten: 44
    Letzter Beitrag: 22.06.2006, 16:18
  5. Multitasking
    Von FancanTeik im Forum Software, Algorithmen und KI
    Antworten: 11
    Letzter Beitrag: 25.04.2005, 08:16

Berechtigungen

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

Labornetzteil AliExpress