Funktion millims

Hallo zusammen,
Ich möchte 2 leds an z.B port 9 und 10 unterschiedlich blinken lassen.
Jetzt meine Frage muss ich den millis code immer für jede led neu schreiben? z.B
Oder geht das alles in 1 loop?

danke im vorraus

//LED 1
unsigned long startTime; // Startzeit
unsigned long currentTime; // Aktuelle Zeit
const unsigned long period = 3000;// Pausenlänge (Intervall)

//LED2

unsigned long startTime1; // Startzeit
unsigned long currentTime1; // Aktuelle Zeit
const unsigned long period1 = 400;// Pausenlänge (Intervall)

void setup(){

pinMode(9,OUTPUT); //LED output
pinMode(10,OUTPUT); //LED output

}

void loop(){

//LED1
currentTime= millis();
if (currentTime - startTime >= period){ //Pause abgelaufen?
startTime = currentTime;
digitalWrite(9,!digitalRead(9));}

//LED2
currentTime1 = millis();
if (currentTime1 - startTime1 >= period1){ //Pause abgelaufen?
startTime1 = currentTime1;
digitalWrite(10,!digitalRead(10));}

}

Geht in einer loop().
currentTime kannst Du wiederverwenden - die Zeit schreitet durch die Bearbeitung der ersten LED nur unwesentlich voran.
Startzeit und Periode brauchst du tatsächlich für jede LED einzeln.

Bitte editiere deinen Beitrag nochmal (Stift-Symbol), markiere den Code und drücke dann </>. Das sind die berühmten Code-Tags, von denen man hier häufig liest :slightly_smiling_face:

Viele Wege führen nach Rom
Einer

//LED 1
unsigned long startTime; // Startzeit
unsigned long currentTime; // Aktuelle Zeit
const unsigned long period = 3000;// Pausenlänge (Intervall)
const byte ledPin = 9;

//LED2
unsigned long startTime1; // Startzeit
unsigned long currentTime1; // Aktuelle Zeit
const unsigned long period1 = 400;// Pausenlänge (Intervall)
const byte led1Pin = 10;

//intern:
unsigned long tikTime;

void setup()
{
  pinMode(ledPin, OUTPUT); //LED output
  pinMode(led1Pin, OUTPUT); //LED output
  pinMode(LED_BUILTIN, OUTPUT);
}

void blinkLed(unsigned long &myTime, const unsigned long &period, const byte &ledPin)
{
  if (millis() - myTime >= period)
  {
    digitalWrite(ledPin, !digitalRead(ledPin));
    myTime = millis();
  }
}

void loop()
{
  blinkLed(startTime, period,  ledPin);
  blinkLed(startTime1, period1, led1Pin); 
  blinkLed(tikTime, 2000, LED_BUILTIN);
}
1 Like

Das geht alles in der loop().

Mach dir eine Struktur:

struct LEDBLINK
{
  const byte Pin;
  unsigned long duration;   // memory for interval time
  unsigned long stamp;      // memory for actual time
};

und fülle die Struktur als Array mit Leben:

LEDBLINK ledBlinks[]
{
  {9, 3000, 0},
  {10, 400, 0},
};

Und dann kümmert sich ein Service, Methode oder was auch immer, mit einem Timer um die Bearbeitung der Informationen.
Werf mal einen Blick rein. Du kannst auch die Anzahl der LEDs ändern, solange du den Spannungsregler auf den Arduino nicht stresst.

/* BLOCK COMMENT
  ATTENTION: This Sketch contains elements of C++.
  https://www.learncpp.com/cpp-tutorial/
  Many thanks to LarryD
  https://europe1.discourse-cdn.com/arduino/original/4X/7/e/0/7e0ee1e51f1df32e30893550c85f0dd33244fb0e.jpeg
  https://forum.arduino.cc/t/funktion-millims/1009958
  Tested with Arduino: Mega[X] - UNO [ ] - Nano [ ]
*/
#define ProjectName "Funktion millims"
#define  OutPutTest
unsigned int OutPutTestTime {1000};
struct LEDBLINK
{
  const byte Pin;
  unsigned long duration;   // memory for interval time
  unsigned long stamp;      // memory for actual time
};
LEDBLINK ledBlinks[]
{
  {9, 3000, 0},
  {10, 400, 0},
};

// -------------------------------------------------------------------
void setup() {
  Serial.begin(9600);
  Serial.println(F("."));
  Serial.print(F("File   : ")), Serial.println(__FILE__);
  Serial.print(F("Date   : ")), Serial.println(__DATE__);
  Serial.print(F("Project: ")), Serial.println(ProjectName);
  pinMode (LED_BUILTIN, OUTPUT);  // used as heartbeat indicator
  //  https://www.learncpp.com/cpp-tutorial/for-each-loops/
  for (auto ledBlink : ledBlinks) pinMode(ledBlink.Pin, OUTPUT);
#ifdef OutPutTest
  // check outputs
  for (auto ledBlink : ledBlinks) digitalWrite(ledBlink.Pin, HIGH), delay(OutPutTestTime);
  for (auto ledBlink : ledBlinks) digitalWrite(ledBlink.Pin, LOW), delay(OutPutTestTime);
#endif
}
void loop () 
{
  unsigned long currentTime = millis();
  digitalWrite(LED_BUILTIN, (currentTime / 500) % 2);
  for (auto &ledBlink : ledBlinks) 
  {
    if (currentTime-ledBlink.stamp >= ledBlink.duration) 
    {
      ledBlink.stamp=currentTime;
      digitalWrite(ledBlink.Pin,!digitalRead(ledBlink.Pin));
    }
  }
}

Ich wünsche einen geschmeidigen Abend und viel Spass beim Programmieren in C++.

Wenn es um eine Demo-code-Sammlung geht mache ich mit :wink:

const byte LED1 = 4;
const byte LED2 = 5;

unsigned long LED1_Timer;
unsigned long LED1_OnTime  = 3000;
unsigned long LED1_OFFTime = 2000;
unsigned long LED1_WaitTime;

unsigned long LED2_Timer;
unsigned long LED2_OnTime  = 1000;
unsigned long LED2_OFFTime = 2500;
unsigned long LED2_WaitTime;

// easy to use helper-function for non-blocking timing
boolean TimePeriodIsOver (unsigned long &startOfPeriod, unsigned long TimePeriod) {
  unsigned long currentMillis  = millis();
  if ( currentMillis - startOfPeriod >= TimePeriod ) {
    // more time than TimePeriod has elapsed since last time if-condition was true
    startOfPeriod = currentMillis; // a new period starts right here so set new starttime
    return true;
  }
  else return false;            // actual TimePeriod is NOT yet over
}

void setup(){
  pinMode(LED1, OUTPUT);
  pinMode(LED2, OUTPUT);
  LED1_WaitTime = LED1_OnTime;
  LED2_WaitTime = LED2_OnTime;
}

void loop() {

  if ( TimePeriodIsOver(LED1_Timer,LED1_WaitTime) ) { // check if WaitTime is over
    // if the amount of milliseconds stored in variable LED1_WaitTime
    // have REALLY passed by
    if ( digitalRead(LED1) == HIGH) { // if LED1 is switched on
      digitalWrite(LED1,LOW); 
      LED1_WaitTime = LED1_OFFTime;
    }
    else { // LED1 is switched off
      digitalWrite(LED1,HIGH);
      LED1_WaitTime = LED1_OnTime;      
    }    
  }

  if ( TimePeriodIsOver(LED2_Timer,LED2_WaitTime) ) { // check if WaitTime is over
    // if the amount of milliseconds stored in variable LED2_WaitTime
    // have REALLY passed by
    if ( digitalRead(LED2) == HIGH) {
      digitalWrite(LED2,LOW);
      LED1_WaitTime = LED2_OFFTime;
    }
    else { // LED2 is switched off
      digitalWrite(LED2,HIGH);
      LED2_WaitTime = LED2_OnTime;      
    }    
  }

}

hier wurden die Codezeilen die das Blinken machen in zwei functions gepackt

const byte LED1 = 4;
const byte LED2 = 5;

unsigned long LED1_Timer;
unsigned long LED1_OnTime  = 3000;
unsigned long LED1_OFFTime = 2000;
unsigned long LED1_WaitTime;

unsigned long LED2_Timer;
unsigned long LED2_OnTime  = 1000;
unsigned long LED2_OFFTime = 2500;
unsigned long LED2_WaitTime;

// easy to use helper-function for non-blocking timing
boolean TimePeriodIsOver (unsigned long &startOfPeriod, unsigned long TimePeriod) {
  unsigned long currentMillis  = millis();
  if ( currentMillis - startOfPeriod >= TimePeriod ) {
    // more time than TimePeriod has elapsed since last time if-condition was true
    startOfPeriod = currentMillis; // a new period starts right here so set new starttime
    return true;
  }
  else return false;            // actual TimePeriod is NOT yet over
}


void Blink_LED1() {
  if ( TimePeriodIsOver(LED1_Timer,LED1_WaitTime) ) { // check if WaitTime is over
    // if the amount of milliseconds stored in variable LED1_WaitTime
    // have REALLY passed by
    if ( digitalRead(LED1) == HIGH) { // if LED1 is switched on
      digitalWrite(LED1,LOW); 
      LED1_WaitTime = LED1_OFFTime;
    }
    else { // LED1 is switched off
      digitalWrite(LED1,HIGH);
      LED1_WaitTime = LED1_OnTime;      
    }    
  }
}

void Blink_LED2() {
  if ( TimePeriodIsOver(LED2_Timer,LED2_WaitTime) ) { // check if WaitTime is over
    // if the amount of milliseconds stored in variable LED2_WaitTime
    // have REALLY passed by
    if ( digitalRead(LED2) == HIGH) {
      digitalWrite(LED2,LOW);
      LED1_WaitTime = LED2_OFFTime;
    }
    else { // LED2 is switched off
      digitalWrite(LED2,HIGH);
      LED2_WaitTime = LED2_OnTime;      
    }    
  }
}


void setup(){
  pinMode(LED1, OUTPUT);
  pinMode(LED2, OUTPUT);
  LED1_WaitTime = LED1_OnTime;
  LED2_WaitTime = LED2_OnTime;
}

void loop() {
  Blink_LED1();

  Blink_LED2();

}

und bei dieser Version wird ein Anfänger erst mal nicht viel verstehen.

Alle Variablen die bei beiden LEDs gebraucht werden, wurden durch einen Array mit zwei Elementen ersetzt wurden.
Statt der Zahlen "1" bzw. "2" im Namen wird da die Indexzahl "i" bzw. LEDNr benutzt.

const byte LED_Pin[2] = {4,5};

unsigned long LED_Timer[2];
unsigned long LED_OnTime[2]  = {3000,1000};
unsigned long LED_OFFTime[2] = {2000,2500};
unsigned long LED_WaitTime[2];


// easy to use helper-function for non-blocking timing
boolean TimePeriodIsOver (unsigned long &startOfPeriod, unsigned long TimePeriod) {
  unsigned long currentMillis  = millis();
  if ( currentMillis - startOfPeriod >= TimePeriod ) {
    // more time than TimePeriod has elapsed since last time if-condition was true
    startOfPeriod = currentMillis; // a new period starts right here so set new starttime
    return true;
  }
  else return false;            // actual TimePeriod is NOT yet over
}


void Blink_LED(byte LEDNr) {
  if ( TimePeriodIsOver(LED_Timer[LEDNr],LED_WaitTime[LEDNr]) ) { // check if WaitTime is over
    // if the amount of milliseconds stored in variable LED1_WaitTime
    // have REALLY passed by
    if ( digitalRead(LED_Pin[LEDNr]) == HIGH) { // if LED1 is switched on
      digitalWrite(LED_Pin[LEDNr],LOW); 
      LED_WaitTime[LEDNr] = LED_OFFTime[LEDNr];
    }
    else { // LED1 is switched off
      digitalWrite(LED_Pin[LEDNr],HIGH);
      LED_WaitTime[LEDNr] = LED_OnTime[LEDNr];      
    }    
  }
}


void setup(){

  for (byte i = 0; i < 2; i++) {
    pinMode(LED_Pin[i], OUTPUT);
    LED_WaitTime[i] = LED_OnTime[i];
  }  
}


void loop() {
  for (byte i = 0; i < 2; i++) {
    Blink_LED(i);
  }  
}

vgs

Hi @StefanL38,
hab mir erlaubt das testen auf Speichervebrauch mit UNO
Beide Erste 1318 Bytes / 25 Bytes Ram
Letzter 1160 / 43
Persönlich wurde die Erste zwei nehmen :wink:
Grüße

PS. Der vom @my_xy_projekt hat 1112 / 31
Vom @paulpaulson nicht getestet wegen "Serial.print"

Ja sicher. Speicherverbrauch analysieren wird wichtig wenn man sich dem Maximum nähert und man anfangen muss bytes einzusparen.

Wenn man jetzt eine Umfrage macht was denn Anfänger für wichtig halten.

2% flash / 0,5% RAM Speicherbelegung Programm mittelschwer zu verstehen

oder

4% flash / 1% RAM Speicherbelegung Programm leichter zu verstehen

Was wird ein Anfänger wohl bevorzugen.
Fortgeschrittene und Experten bevorzugen ihre persönliche Lieblingsversion
ziemlich egal ob die nun ein paar Prozent mehr oder weniger Speicher braucht.

vgs

Das ist schon klar, was betrifft über 50% Neulinge, die denken das der Programmspeicherplatz ist wichtiger als RAM.

Du hast was vergessen.
Wenn Du den vergleichen willst, dann musst Du auskommentieren, das ich DREI Blinker am laufen habe.
LED_BUILTIN ist die LED an Pin 13 auf dem Uno, die ich parallel noch mitblinken lasse.
Wenn das ausgeklammert ist: (für einen UNO)

:wink:

Muss zugeben habe die Programme nicht analysiert, also Entschuldigung, nur den vom @paulpaulson nicht mit bezogen wegen den Serials, die konnte man nicht übersehen :wink:

Alles gut.
im Übrigen macht @paulpaulson seiner ohne serial und ohne outputtest 1106 / 27

Gute Nacht.

Gute Nacht Dir auch, und keine Alpträume :sweat_smile:

Von denen kann ich ruhig welche bekommen - ich war schon lange nicht mehr in den Bergen. Du meinst Albträume.
Beste Grüße

HIHI so schnell geht das :speak_no_evil:
Bleibt nix übrig als Urlaub in den Alpen !!!

Warum nicht mal mit Klassen arbeiten?

Das darf auch gerne "zerrissen" werden, wenn was besseres bei rumkommt :slight_smile:
Ich lerne gerne noch dazu.

um es mal so kurz zu halten wie deine den Code erklärenden Kommentare:

  • . - . - .
  • Was passiert, wenn du drei Instanzen erzeugst, z.B:
Led a;
Led b(13);
Led c(LED_BUILTIN);
  • Wenn du Led Objekte lokal erzeugst?
    Blinken nicht, sollte man also nicht machen.
  • Wofür ist _numOfLeds gut?
    Um zu zeigen, dass man statische Variable und Methoden eigentlich selten braucht. :slight_smile:
  • Wenn du eine Led blitzen ( kurz an, länger aus ) lassen willst?
    Könntest du eine Methode void setFlashingTime(uint32 tan, uint32 taus); erfinden, die das Prinzip des Überladens von Methoden zeigt.

Ist ein Schwachpunkt. Der dürfte aber auf Objekte von 90% aller Libraries zutreffen. Und das auch nur, weil diese Arduino loop() Funktion keine Übergabeparameter ermöglicht.

Man könnte natürlich die loop Funktion gar nicht nutzen und dafür eine Endlosschleife in setup()
dann hättest Du es auch schön lokal. Wenn man denn in diesem Arduino Raster bleiben will.

Die Frage nach den drei Instanzen verstehe ich nicht... es sind doch im Beispielcode fünf Instanzen angelegt. Da kannst Du doch sehen was passiert. Bei einer Instanzierung ohne Pinangabe wird LED_BUILTIN verwendet.

Ja ist ne Spielerei. Kann man auch weglassen. Ich wollte mal nen expliziten Destruktor verwenden. :wink:

Stimmt, das wäre eine gute Erweiterung.

@elektronikfreak
du hast jetzt Ansätze wie man mehrere LEDs blinken lassen kann.

Da man LEDs öfter mal nach gewissen Mustern aufleuchten lassen will, kann man sich die immer wieder benötigten Funktionalitäten auch in eine eigene Library packen.

#include <Noiasca_led.h>               // download library from http://werner.rothschopf.net/microcontroller/202202_tools_led_en.htm
BlinkPin blinkLed[] {13, 6};     // declare several blinking LED and assign pins 

void setup() {
  for (auto &obj : blinkLed) 
    obj.begin();   // you have to call the .begin() method for each LED object
              
  blinkLed[0].setOnInterval(3000);   // you can set different blink intervals for your LEDs 
  blinkLed[0].setOffInterval(3000); 
  blinkLed[1].setOnInterval(400);
  blinkLed[1].setOffInterval(400); 
}

void loop() {
  for (auto &obj : blinkLed) 
    obj.update();       // you have to call update() for each LED object
  // put other non blocking code here, to run repeatedly
}

Library Beschreibung und Download:
http://werner.rothschopf.net/microcontroller/202202_tools_led_en.htm

nicht zerreissen. Der Ansatz passt mir gut. Auch der Split in "Blinken" und der jeweiligen Hardwareumsetzung, einfach weil es schön erweiterbar ist (und ich es in meiner Lib ähnlich habe).

Ob's den LED Count braucht sei dahin gestellt. Wenn - dann würde ich die Variable aber schon im Konstruktor erhöhen - nicht erst im init. Den decrement machst ja auch im Destructor :wink: