0

Arduino community. I have had experience with Arduino for 3 years now and have finally come to the conclusion to get rid of the delay function entirely.

Below is the code to blink two LEDs a complete 10 times. The problem is that the setup() doesn't repeat like a loop(), which means it doesn't last a long enough to find a time difference between PreviousMillis and CurrentMillis because it runs once; thus, defeating the idea of blinking a LED in the setup(). But, I have researched ways to imitate the loop() with while loops; I have used Adafruit's method to spice things up(Constructors and classes!), https://learn.adafruit.com/multi-tasking-the-arduino-part-1/overview.

But I need a little help because it doesn't work, instead, it blinks forever(Mission half-complete =)).

Notice how I have used while loops in the Update(), which is located within the Flasher Class, to mimic a loop() until the condition becomes true.

The problem is, I don't know why this code doesn't work and what to do from here.

The ultimate goal is to blink the LEDs at pin 12 and pin 13 a total of 10 Times, instead of repeatedly blinking for an eternity. I am using an Arduino Uno R3 and a Serial baud rate of 115200.

Ignore what I did in the loop(). It's the same function as the setup() code, instead, the led blinks an eternity (unfortunately), when a value of "1" is typed.

    class Flasher{
    // Class Member Variables
    // These are initialized at startup
    int ledPin;      // the number of the LED pin
    long OnTime;     // milliseconds of on-time
    long OffTime;    // milliseconds of off-time

    // These maintain the current state
    int ledState;                 // ledState used to set the LED
    unsigned long previousMillis;   // will store last time LED was updated
    unsigned long currentMillis = 0;

  public: Flasher (int pin, long on, long off)    
{            // Constructor - creates a Flasher
    // and initializes the member variables and state


      ledPin = pin;
      pinMode(ledPin, OUTPUT);

      OnTime = on;
      OffTime = off;

      ledState = LOW;
      previousMillis = 0;
    }

    void Update(int a){
      // check to see if it's time to change the state of the LED
      for (int i = 0; i < a; i++) {
        while ((currentMillis - previousMillis <= OnTime) || ((currentMillis - previousMillis <= OffTime))) {
          currentMillis = millis();

          if ((ledState == HIGH) && (currentMillis - previousMillis >= OnTime))
          {
            ledState = LOW;  // Turn it off
            previousMillis = currentMillis;  // Remember the time
            digitalWrite(ledPin, ledState);  // Update the actual LED
          }
          else if ((ledState == LOW) && (currentMillis - previousMillis >=OffTime))
          {
            ledState = HIGH;  // turn it on
            previousMillis = currentMillis;   // Remember the time
            digitalWrite(ledPin, ledState);   // Update the actual LED
          }
        }
      }
    }
};


Flasher led1(12, 100, 400);
Flasher led2(13, 350, 350);

void setup(){

  Serial.begin(115200);
  led1.Update(10);

}

void loop(){

   /* if (Serial.available()) {
      String str = Serial.readString();

      if (str.substring(0, 1).equals("1")) {
        led1.Update(10);

      }
  }*/
}
1

SimpleTimer and similar millis()-based timer libraries are made for just this kind of job. SimpleTimer even allows you to specify a number of repetitions as well. The gist of it is you set a timer to an interval and perhaps a number of repetitions, and a callback function to be called at the end of each interval. Your main code just calls the timer's update function, "run()" in this case, very frequently. Your callback function will be called at the appropriate times. This is one of the easiest ways to implement this kind of job, mimicking foreground/background but without the complexity of interrupts and interrupt service routines.

0

For such a simple task, the code is very complex.

First, write a piece of code that blinks the LEDs if sufficient passage of time has been met.

You can implement a blink counter, either in the main loop or the blink routine mentioned earlier.

Should be fairly simple.

edit: here is how I would have implemented it.

//blink the led for a given number of times
//cnt: number of times of the blinks needed
uint8_t led_blinky(uint8_t cnt) {
    static uint8_t led_cnt=0;       //blinky count
    static uint32_t millis_prev=0;  //previous millies

    if (led_cnt>=cnt) return led_cnt;   //return blink count
    if (millis() > millis_prev + LED_ms) {    //enough time has passed
        millis_prev += LED_ms;                      //update the time
        digitalWrite(LED, (digitalRead(LED)==HIGH)?LOW:HIGH);       //flip led
        led_cnt+=1;                 //increment the led count
    }
    return led_cnt;                 //return blinky count
}

the code itself is fairly self-explanatory -> the only (marginally) tricky part is how it maintains timing accuracy over a long period of time. in this particular implementation, the test is done inside the led_blinky() routine so it is self-contained -> it does return the number of blinks that have been executed.

Here is the execution of performing 100ms blinks 4 times:

enter image description here

0

I've modified your sketch so that when you instantiate a LED Flasher object with a 4th argument, it flashes forever. If you instantiate a Flasher object with 3 arguments, use the Start() function to start the LED flashing the number of times you specify. Just call it once, not repeatedly in the loop() function (e.g. when a button is pressed). You can call the Start() function again and specify a different number of flashes. You can have multiple LED flasher objects. Each object can have different on/off times. Some LEDs can flash forever, and some the number of times specified.

EDIT

I've added a few functions in the class to make it more versatile: Stop(), SetPinHighTime(), SetPinLowTime() and SetFlashForever().

class Flasher{

  // Class Member Variables. These are initialized at startup.
  byte ledPin;
  byte ledState;
  byte flashForever;
  unsigned int flashCounter;
  unsigned long highTime;
  unsigned long lowTime;
  unsigned long previousMillis;

  // Constructor. Create a LED Flasher object.
  // Initialize the member variables and LED state.
  public:

  Flasher(byte pin, unsigned long on, unsigned long off, byte continueFlashing = 0){
    ledPin = pin;
    pinMode(ledPin, OUTPUT);
    highTime = on;
    lowTime = off;      
    ledState = LOW;
    flashForever = continueFlashing;
    previousMillis = 0;
  }

  void Update(){

    // Check to see if it's time to change the state of the LED.
    unsigned long currentMillis = millis();

    if((ledState == HIGH) && (currentMillis - previousMillis >= highTime) && ((flashCounter > 0) || (flashForever == 1))){
      ledState = LOW;
      previousMillis = currentMillis;        // Remember the time.
      digitalWrite(ledPin, ledState);        // Update the actual LED.
      if(flashCounter > 0){flashCounter--;}  // Update the flash counter.
    }
    else if((ledState == LOW) && (currentMillis - previousMillis >= lowTime) && ((flashCounter > 0) || (flashForever == 1))){
      ledState = HIGH;
      previousMillis = currentMillis;        // Remember the time.
      digitalWrite(ledPin, ledState);        // Update the actual LED.
      if(flashCounter > 0){flashCounter--;}  // Update the flash counter.
    }
  }

  void Start(unsigned int flashNumberOfTimes){
    flashCounter = flashNumberOfTimes * 2;
    flashForever = 0;
    ledState = LOW;
    digitalWrite(ledPin, ledState);
  }

  void Stop(){
    Start(0);
  }

  void SetPinHighTime(unsigned long pinHighTime){
    highTime = pinHighTime;
  }

  void SetPinLowTime(unsigned long pinLowTime){
    lowTime = pinLowTime;
  }

  void SetFlashForever(byte oneOrZero){
    flashForever = oneOrZero;
    if(oneOrZero == 0){Start(0);}
  }

  void SetPinToInput(){
    pinMode(ledPin, INPUT);
  }

};

// Used for testing purposes only.
byte doOnce = 0;
const byte led1PinNumber = 2;
const byte led2PinNumber = 3;
const byte led3PinNumber = 4;

// Instantiate LED Flasher Object(s).
// e.g. Flasher object_name(Pin Number, ON Time, OFF Time, OPTIONAL Flash Forever);

// Three argument constructor.
// The number of times to flash the LED is specified
// when you call the Start() function. The LED will NOT
// start flashing until you call Start().
Flasher led1(led1PinNumber, 10, 990);
Flasher led2(led2PinNumber, 100, 400);

// Four argument constructor.
// Flash an LED forever. This will start the LED flashing immediately.
Flasher led3(led3PinNumber, 1000, 1000, 1);

void setup(){}

void loop(){

  // Call the Update function as fast as possible.
  led1.Update();
  led2.Update();
  led3.Update();

  // Test output. Flash 3 LEDs with different on/off times.
  // Use the Start() function to flash 2 of the LEDs X number
  // of times, then restart each LED flasher object with
  // a different number of flashes. Set 1 LED to flash forever,
  // then stop it and start a different LED flashing forever,
  // altering the flash rates of one LED before restarting it.
  // Finally, set the 3 LED pins to INPUT.

  // Start the led1 object 4 seconds after Arduino startup.
  if(millis() > 4000 && millis() < 5000 && doOnce == 0){
    led1.Start(3);  // Flash the LED 3 times.
    doOnce = 1;
  }

  // Start the led2 object 5 seconds after Arduino startup.
  if(millis() > 5000 && millis() < 6000 && doOnce == 1){
    led2.Start(5);  // Flash the LED 5 times.
    doOnce = 0;
  }

  // Restart the led1 object 10 seconds after Arduino startup.
  if(millis() > 10000 && millis() < 11000 && doOnce == 0){
    led1.Start(7);  // Flash the LED 7 times.
    doOnce = 1;
  }

  // Restart the led2 object 15 seconds after Arduino startup.
  if(millis() > 15000 && millis() < 16000 && doOnce == 1){
    led2.Start(9);  // Flash the LED 9 times.
    doOnce = 0;
  }

  // Stop flashing the led3 object.
  // Start flashing the led1 object forever.
  if(millis() > 30000 && millis() < 31000 && doOnce == 0){
    led3.SetFlashForever(0);
    led1.SetFlashForever(1);
    doOnce = 1;
  }

  // Stop flashing the led1 object.
  // Start flashing the led3 object forever and change
  // it's flash rate.
  if(millis() > 50000 && millis() < 51000 && doOnce == 1){
    led3.SetPinHighTime(250);
    led3.SetPinLowTime(500);
    led3.SetFlashForever(1);
    led1.SetFlashForever(0);
    doOnce = 0;
  }

  // Stop flashing the led3 object. No LEDs should be flashing.
  if(millis() > 60000 && millis() < 61000 && doOnce == 0){
    led3.Stop();
    doOnce = 1;

    // My test shield has one High and one Low LED per pin.
    // Set the pins to input to turn off the Low LEDs.
    led1.SetPinToInput();
    led2.SetPinToInput();
    led3.SetPinToInput();
  }

}

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.