Go Down

Topic: Frontblitzer ohne Delay (Read 1 time) previous topic - next topic

timschillert

Hallo zusammen,

ich möchte für ein kleines Projekt eine Fahrzeugbeleuchtung simulieren. Das ganze soll wie in einem Feuerwehrfahrzeug funktionieren. 
Bisher habe ich normales Abblendlicht, was dauerhaft leuchtet, sowie zwei LEDs, die in einem bestimmten Rhytmus blitzen sollen.

Bisher habe ich das nur über die Delay-Funktion geschafft. Jedoch soll das Projekt auch noch erweitert werden, daher denke ich, dass die Delay-Funktion dafür nicht geeignet ist.

Die blitzenden LEDs sollen 3mal mit einer kurzen Pause an und ausgehen, anschließend gibt es eine etwas längere Pause.

Bisher sieht mein Code so aus:

Code: [Select]
/*
 * Abblendlicht auf Pin G19 gesteckt
 * Rücklicht auf Pin G22 gesetzt
 * Blitzer auf Pin G23 gesetzt
 */
int Abblendlicht = 19; 
int Ruecklicht = 22; 
int Blitzer = 23;     

void setup() {
  /*
*Abblendlcht als Ausgang
*Rücklicht als Ausgang
*Blitzer als Ausgang
*/
pinMode(Abblendlicht, OUTPUT);
pinMode(Ruecklicht, OUTPUT);
pinMode(Blitzer, OUTPUT);
}

void loop() {
 
digitalWrite(Abblendlicht, HIGH);
digitalWrite(Ruecklicht, HIGH);

/*
 * Wenn Spannung anliegt, Blaue LED blinken lassen
*  50ms eingeschaltet, 300ms ausgeschaltet
 */

digitalWrite(Blitzer, HIGH);
delay(50);
digitalWrite(Blitzer, LOW);
delay(50);
digitalWrite(Blitzer, HIGH);
delay(50);
digitalWrite(Blitzer, LOW);
delay(50);
digitalWrite(Blitzer, HIGH);
delay(50);
digitalWrite(Blitzer, LOW);
delay(300);
}

combie

Ich glaube, du möchtest dich mit endlichen Automaten beschäftigen.
Hier könnten dir die Multitasking Macros den Weg bereiten.



Ablaufsteuerung
Meine Standardantwort zu Ablaufsteuerungen:
Quote
Eine Stichworte Sammlung für Google Suchen:
Endlicher Automat,
ProtoThreads,
State Machine,
Multitasking,
Coroutinen,
Ablaufsteuerung,
Schrittkette,
BlinkWithoutDelay, 
--
Automat (Informatik)
Blink Without Delay
Die Nachtwächter Erklärung
--
MicroBahner/MobaTools
Intervall Macro
Multitasking Macros
INTERVAL Ersatzstoff
CooperativeTask
Säge kein Sägemehl.

(deleted)

#2
Nov 22, 2020, 07:53 pm Last Edit: Nov 22, 2020, 07:55 pm by Peter-CAD-HST
(deleted)

uwefed

Welchen Controller / Arduino hast Du?
Grüße Uwe

noiasca

das kommt eh öfter. Da gibts verschiedene offizielle Blinkmuster.
Bei Hella gab es da mal ein Datenblatt dafür.

Ich würde es in etwa so machen:
Code: [Select]

/* Blink a LED in a specific rhythm

  Turns on and off light emitting diodes (LED) connected to a digital pin,
  without using the delay() function. This means that other code can run at the
  same time without being interrupted by the LED code.

  noiasca
  2019-05-05

*/

class BlinkLed {
    byte state = 1;       // 1 blink, 0 off
    unsigned long previousMillis;
    uint16_t on = 180;
    uint16_t off = 320;   // 180/320 is according ECE
    const byte ledPin;

  public:
    BlinkLed(byte attachTo):
      ledPin(attachTo)
    {}

    void begin()
    {
      pinMode(ledPin, OUTPUT);
    }

    void set(uint16_t _on, uint16_t _off)  // modify on/off times during runtime
    {
      on = _on;
      off = _off;
    }

    void setState(byte _state)            // 1 Switch on blinking; 0 switch off blinking
    {
      state = _state;
    }

    void tick()
    {
      if (state)
      {
        uint32_t currentMillis = millis();
        if (digitalRead(ledPin) && currentMillis - previousMillis >= on) {
          // save the last time you blinked the LED
          previousMillis = currentMillis;
          digitalWrite(ledPin, LOW);
        }
        if (!digitalRead(ledPin) && currentMillis - previousMillis >= off) {
          // save the last time you blinked the LED
          previousMillis = currentMillis;
          digitalWrite(ledPin, HIGH);
        }
      }
    }
};

class RhythmLed {
    byte state = 1;
    unsigned long previousMillis;
    const byte ledPin;
    uint8_t lengthOfPattern;
    // the intervall pattern
    //                          ON    OFF  ON   OFF
    //                          1     2    3    4
    uint16_t intervall[5] = {0, 150,  60, 20, 270};                  // ECE 2
    //uint16_t intervall[3] = {0, 180, 320};                         // ECE 1
    //uint16_t intervall[7] = {0, 25, 25, 25, 25, 25, 375};          // HELLA 3
    //uint16_t intervall[9] = {0, 40, 40, 40, 40, 40, 40, 40, 220 }; // HELLA 4
    //uint16_t intervall[5] = {0, 150,  60, 20, 400};                // wie gewünscht vom TO

  public:
    RhythmLed(byte attachTo):
      ledPin(attachTo)
    {}

    void begin()
    {
      pinMode(ledPin, OUTPUT);
      lengthOfPattern = sizeof(intervall) / sizeof(intervall[0]);
    }

    void setState(byte _state)
    {
      state = _state;
    }

    void setIntervall(uint16_t _intervall1, uint16_t _intervall2, uint16_t _intervall3, uint16_t _intervall4)       // Modify the intervalls to your needs
    {
      intervall[1] = _intervall1;
      intervall[2] = _intervall2;
      intervall[3] = _intervall3;
      if (lengthOfPattern>3) intervall[4] = _intervall4;   // if someone declares a dual-intervall, this line would crash the sketch, therefore this if on the index length ;-)
    }

    void tick()
    {
      uint32_t currentMillis = millis();
      if (state > 0)                            // iterate through the states 1 to n, we don't use state 0 because state 0 is reserved to "switch off" the light
      {
        if (currentMillis - previousMillis > intervall[state])
        {
          if (state % 2 == 1)  // all uneven states are ON, at the end of an intervall we switch to the oposite pin state
          {
            digitalWrite(ledPin, LOW);
          }
          else
          {
            digitalWrite(ledPin, HIGH);
          }
          state++;
          if (state > lengthOfPattern - 1) state = 1;
          previousMillis = currentMillis;
        }
      }
    }
};

BlinkLed myBlinkLed(5);       // a simple blink led
RhythmLed topRKL(13);         // define an output PIN for your LED
RhythmLed outOffSyncRKL(6);  // eine Rundumkennleuchte die wegen eines "Massefehlers" am Originalfahrzeugs eine leicht verschobene Blinkfrequenz hat ;-)

void setup()
{
  myBlinkLed.begin();
  topRKL.begin();
  outOffSyncRKL.begin();
  outOffSyncRKL.setIntervall(250,  90, 30, 400);  // Modify the intervalls for this LED
}

void loop()
{
  myBlinkLed.tick();  // each object has to be called once in the loop
  topRKL.tick();
  outOffSyncRKL.tick();

  // put here other code which needs to run:

}
how to react on postings:
- post helped: provide your final sketch, say thank you & give karma.
- post not understood: Ask as long as you understand the post
- post is off topic (or you think it is): Stay to your topic. Ask again.
- else: Ask again.

agmue

#5
Nov 22, 2020, 08:54 pm Last Edit: Nov 22, 2020, 09:09 pm by agmue
Auch Felder können ihren Reiz haben (getestet mit Mega2560):

Code: [Select]
/*
   Abblendlicht auf Pin G19 gesteckt
   Rücklicht auf Pin G22 gesetzt
   Blitzer auf Pin G23 gesetzt
*/
const int Abblendlicht = 19;
const int Ruecklicht = 22;
const int Blitzer = 23;
const uint16_t Blitzintervalle[] = {50, 50, 50, 50, 50, 300};
uint32_t jetzt;

void setup() {
  /*
    Abblendlcht als Ausgang
    Rücklicht als Ausgang
    Blitzer als Ausgang
  */
  pinMode(Abblendlicht, OUTPUT);
  pinMode(Ruecklicht, OUTPUT);
  pinMode(Blitzer, OUTPUT);
  digitalWrite(Abblendlicht, HIGH);
  digitalWrite(Ruecklicht, HIGH);
  digitalWrite(Blitzer, HIGH);
}

void loop() {
  jetzt = millis();
  blitzen();
}

void blitzen() {
  static byte intervallindex = 0;
  static uint32_t vorhin;
  if (jetzt - vorhin >= Blitzintervalle[intervallindex]) {
    vorhin = jetzt;
    digitalWrite(Blitzer, !digitalRead(Blitzer));
    intervallindex = ++intervallindex < (sizeof(Blitzintervalle) / sizeof(Blitzintervalle[0])) ? intervallindex : 0;
  }
}
Die Vorstellungskraft ist wichtiger als Wissen, denn Wissen ist begrenzt. (Albert Einstein)

combie

#6
Nov 22, 2020, 09:18 pm Last Edit: Nov 23, 2020, 12:18 am by combie
Quote
konstruktiven
Was das wohl bedeuten mag....
Immerhin habe ich 2 Konstanten von dir übernommen

Code: [Select]
#include <Streaming.h>
#include <TaskMacro.h>

constexpr unsigned long blitzMilliKurz =  50;
constexpr unsigned long blitzMilliLang = 300;

void blitzen()
{
  static int i;
  taskBegin();
  pinMode(LED_BUILTIN,OUTPUT);
  while(1)
  {
    for(i=0;i<3;i++)
    {
      digitalWrite(LED_BUILTIN,1);
      taskPause(blitzMilliKurz);
      digitalWrite(LED_BUILTIN,0);
      taskPause(blitzMilliKurz);
    }
    taskPause(blitzMilliLang-blitzMilliKurz);
  }
  taskEnd();
}

void loopCount()
{
  static unsigned long count;
  count++;
  taskBegin();
  while(1)
  {
    taskPause(1000);
    Serial << "Loops per Sec: "<< count << endl;
    count = 0;
  }
  taskEnd();
}

void setup()
{
  Serial.begin(9600);
  Serial << "Start: "<< __FILE__ << endl;
}

void loop()
{
  loopCount();
  blitzen();
}
Säge kein Sägemehl.

(deleted)

#7
Nov 22, 2020, 09:27 pm Last Edit: Nov 22, 2020, 09:33 pm by Peter-CAD-HST
(deleted)

michael_x

@combie: konstruktiv wäre, wenn du das Wesentliche an deinem Beispiel nicht weggelassen  hättest:
Woher/Was ist TaskMacro.h ? (und Streaming.h?)

Und selbst mit Quellenangabe ist der Sinn deiner Kapselung, zu verbergen wie es geht. Ob die Library wohl mit oder ohne delay() funktioniert, soll ja gerade egal sein. 

Also, wie du schon befürchtet hast: schön, aber nicht die Antwort auf die Frage wie es ohne delay(), aber mit Arduino Funktionen,  geht.

combie

#9
Nov 23, 2020, 12:15 am Last Edit: Nov 23, 2020, 04:48 pm by combie
Quote
Woher/Was ist TaskMacro.h ?
Habe ich vorher schon verlinkt.
Da drauf klicken, dann finden sich Erklärungen und auch der Code.
Wenigstens das runterladen, installieren, und kompilieren, sollte einen nicht überfordern ....

Aber hier gerne nochmal: Multitasking Macros


Quote
(und Streaming.h?)
Kann man finden.
Alternativ: Raus operieren.

Quote
Also, wie du schon befürchtet hast: schön, aber nicht die Antwort auf die Frage wie es ohne delay(), aber mit Arduino Funktionen,  geht.
Habe ich nicht befürchtet.
Und natürlich ist es eine der möglichen Lösungen für das Problem.
Damit auch eine Antwort auf die Frage.
Und ebenso natürlich: Alles mit den mitgelieferten Werkzeugen/Mitteln.

Klarer:
Auch die TaskMacros basieren auf dem "blink without delay" Prinzip.
Eingebettet in einen "verschlankten" ProtoThread Nachbau.
Keine Geheimnisse.


Quote
Und selbst mit Quellenangabe ist der Sinn deiner Kapselung, zu verbergen wie es geht.
Wenn ich der Argumentation folge:
Dann darf ich kein Wire verwenden, weil es die I2C Statemachine verbirgt.
Gleiches/Vergleichbares gilt für alle gefühlten 50000 Libraries
Alle haben den Zweck, die Komplexität eines Problems zu verbergen, zu abstrahieren und eine möglichst einfache Schnittstelle zu liefern.
Ich denke, da befinde ich mich in guter Gesellschaft, eigentlich.

Ich verstehe deine Kritik nicht.
Betrachte dieses Unverständnis bitte als Merkmal meiner ****.
(bei **** ein beliebiges Wort, deiner Wahl einsetzen)



Säge kein Sägemehl.

agmue

Die Idee mit dem Feld hat mir super gefallen und ich mußte die gleich umsetzen  :)
Code: [Select]
blitzMilliInterval[digitalRead(BlitzLED)]

Moin!

Freut mich, allerdings erfüllt Deine Variante nicht die gewünschten Kriterien des ursprünglichen Programms, denn das Blitzmuster ist unterschiedlich.

Code: [Select]
const unsigned long blitzMilliKurz = 50;
const unsigned long blitzMilliLang = 300;
unsigned long blitzMilliInterval[]={blitzMilliLang,blitzMilliKurz};

würde ich abkürzen auf

Code: [Select]
const unsigned long blitzMilliInterval[]={300, 50};  // lange und kurze Blitzzeit
denn die Konstanten blitzMilliKurz und blitzMilliLang werden sonst nirgendwo verwendet.

Nur so meine Gedanken :)

Die Vorstellungskraft ist wichtiger als Wissen, denn Wissen ist begrenzt. (Albert Einstein)

(deleted)


timschillert

Hallo zusammen,

danke erstmal für die Hilfe. Zur Info noch, ich benutze einen ESP32 Mikrocontroller. (Haben wir für das Projekt in der Technikerschule genommen)

Da ich noch am Anfang mit dem Thema Programmierung stecke, würde es mich freuen, wenn mir jemand noch die ganzen Begriffe in dem Sketch erklären könnte.

Ich habe jetzt den ersten Sketch von agmue verwendet.
Könntest du mir die ganze Geschichte in der "Blitzen" Stelle noch erklären?

combie

#13
Nov 23, 2020, 06:15 pm Last Edit: Nov 23, 2020, 06:20 pm by combie
Quote
ich benutze einen ESP32 Mikrocontroller.
Dieser hat FreeRtos und 2(+1) Kerne im Bauch.
Es ist also überhaupt kein Problem nebenläufige Dinge damit zu realisieren.
(nur eben ein "wenig" Lernaufwand)

Säge kein Sägemehl.

agmue

Könntest du mir die ganze Geschichte in der "Blitzen" Stelle noch erklären?
Da bin ich nicht so gut drin, aber ich probier's:

jetzt ist die aktuelle Zeit in Millisekunden seit Reset.

vorhin ist die Zeit beim letzten Wechsel in Millisekunden seit Reset.

Statische Variablen behalten am Ende der Funktion ihren Wert.

Die Intervalle, die Du bei delay verwendest hast, wandern in ein Feld. Die Anzahl der Feldelemente steckt in sizeof(Blitzintervalle) / sizeof(Blitzintervalle[0]). Der intervallindex durchläuft 0 bis 5.

Das ist es, oder?

Die Vorstellungskraft ist wichtiger als Wissen, denn Wissen ist begrenzt. (Albert Einstein)

Go Up