Flashing 2 or more LEDs at the same time

The idea was that begin() would prime the pump ant the led would go high next time you call flashWhenNeeded()

flashWhenNeeded() could also take an optional parameter to get going

No, I'm talking about new Arduino users.
When a new Arduino user sees this page, then reading the text "unsigned long" is different from "uint32_t".
Arduino has it as "unsigned long", and there is no need to change it, therefor I prefer to keep it simple.

There is no need to think three steps ahead and call it "uint32_t".

Proof : :wink:
Suppose you are with someone else in the desert and you are both very thirsty. Someone comes along and has a bottle with the text "water" on it. Then other person says: "water, water", and you say: "dihydrogen monoxide with added minerals, dihydrogen monoxide with added minerals", then the other person gets the water first.
You see ? Water is water, because that is what the label says.

1 Like

Independently fade 32 (connected) LEDs with an ESP32. Totally non-blocking.

OK - So it’s more a design decision than a bug.

Blinking is a continuous alternating state, you need to look at a full period to decide if the code is correct or not.

Not sure what is non-blocking, it just loops through 16 LEDs and sets pwm value from 16 element array. Also what is the difference between duty[j & 15] and duty[j]?

Do you can see any sketch ?

Likewise ... however I just meant there's no delay()s used. Ironically, a small blocking delay at the end of loop() improves the simulator's response.

Can't use duty[j] as it will index beyond the array size, however using duty[j & 15] allows indexing through the array in both forward and reverse direction without overflow. Timing of direction change is determined by line 18. Timing of fade is determined by line 19.

How come? j is 0…15 array is 16 elements long, what am I missing?

j is a byte counter variable, counts up or down 0 to 31 to 0 etc.

Gotcha, didn’t notice the loop was using i not j

Things wouldn't get so mixed up if a 'millis_t' and 'micros_t' type were standard.

It wouldn't be 'standard' but, couldn't one simulate such with:

typedef  uint32_t millis_t;
millis_t onTime = 300;

?

edit: or, according to convention, the new type in all caps

typedef  uint32_t MILLIS_t;
MILLIS_t onTime = 300;

You could, actually it wouldn't be a bad addition to the sketch in the first post. Making it standard would enhance a lot of example code and encourage its use in user code; often eliminate newbie mistakes in using the wrong data type there.

Thanks for posting the concrete example.

It be looking like:

typedef  uint32_t millis_t;

const int LED_PIN2 = 2;
const int LED_PIN3 = 3;

void setup() {
  Serial.begin(115200);
  pinMode(LED_PIN2, OUTPUT);
  pinMode(LED_PIN3, OUTPUT);
  char fileName[] = {__FILE__};
  Serial.println(fileName);
  Serial.println("Setup complete");
}

void loop() {
  flashEqualOnOffPin2();
  flashUnequalOnOffPin3();
}

void flashEqualOnOffPin2() {
  millis_t currentMillis = millis();
  static millis_t lastMillis;
  const millis_t onOffTime = 500;                 //Duration for LED to be on or off before changing state, in miliseconds

  if (currentMillis - lastMillis >= onOffTime) {
    lastMillis += onOffTime;
    digitalWrite(LED_PIN2, !(digitalRead(LED_PIN2)));     // Chnage the state of pin 2 by reading its current state then writing the opposite state back to the pin
  }
}

void flashUnequalOnOffPin3() {
  millis_t currentMillis = millis();
  static millis_t lastMillis;
  const millis_t onTime = 1750;     //Duration for LED to be on, in miliseconds
  const millis_t offTime = 350;     //Duration for LED to be off, in miliseconds

  if (digitalRead(LED_PIN3)) {                              // Read the current state of pin 3
    if (currentMillis - lastMillis >= onTime) {     // Pin 3 is high (LED on), check on time and turn LED off if time has expired
      lastMillis += onTime;                       // Add the value of onTime to lastMillis ready to start the next timing interval
      digitalWrite(LED_PIN3, LOW);                       // Turn LED off
    }
  } else {
    if (currentMillis - lastMillis >= offTime) {    // Pin 3 is low (LED off), check off time and turn LED on if time has expired
      lastMillis += offTime;                      // Add the value of offTime to lastMillis ready to start the next timing interval
      digitalWrite(LED_PIN3, HIGH);                      // Turn LED on
    }
  }
}

You lost me. When did that convention happen? I'm only familiar with the habit of using all uppercase for defined constants. My "inspiration" comes from 'time_t'.

Just going by this:

I think by now we ruined @PerryBebbington initial idea of posting a simple tutorial…. :man_shrugging:

3 Likes

It happens every time someone attempts a simple tutorial for cooperative multitasking. I believe the reason is, cooperative multitasking isn't as simple in practice as it is in theory. Also, it's one of those things that seem simple once you "get it", mysterious and arcane until you do.

The method that is most congruent with existing examples, is to use 'unsigned long'. However that is neither more, nor less, obscure than 'millis_t' to someone that barely understands what data types even are.

3 Likes

@J-M-L , @anon57585045 ,

Ruined it? You have all completely destroyed it! :sob:

Seriously, all the comments are very helpful and appreciated. I have created a new version here: Flashing multiple LEDs at the same time, which I intend to keep 'clean'. I've invited @J-M-L and @Paulpaulson to contribute their code so there are 3 versions for people to study.

I am grateful to all the other contributors to this topic, but, in the spirit of only presenting different ideas for non-blocking blink code, I have not included them in the new version. If any of you have a version that's substantially different and contains something new then I'm happy to consider it. Please post here.

I thank you all.

I posted again a slightly modified version to take into account @killzone_kid comment on the timing (at least my view on how the timing should be managed, that is begin() gets the blinking going by turning the led ON)

1 Like

Flashing 1 to 16 leds couldn't be any easier ...

digWrite()

Description
  • Non-blocking millisecond timer control for up to 16 pins.
  • Automatic pin management and configuration.
  • Writes a timed HIGH and timed LOW value to a digital pin.

Syntax

ms.digWrite(pin, on, off)
Parameters
  • pin The pin number *(uint8_t)
  • on timer value in milliseconds (uint16_t)
  • off timer value width in milliseconds (uint16_t)
Returns
  • nothing

Add more LEDs if you want (here's 5)...

#include "digWrite.h"
dw ms = dw();

const byte led1 = 3;
const byte led2 = 4;
const byte led3 = 5;
const byte led4 = 6;
const byte led5 = 7;

void setup() {
}

void loop() {
ms.digWrite(led1, 2000, 2000);
ms.digWrite(led2, 1000, 1000);
ms.digWrite(led3, 500, 500);
ms.digWrite(led4, 800, 200);
ms.digWrite(led5, 50, 150);
}