2

I can't find any information that relates to my problem. The few things I did find confused me (I'm quite new to this).

I'm trying to flash 2 sequences of 4 lights at the same time. I can get 1 set flashing but I don't know how to run other sequences at the same time. My probably laughable attempt at the code is below:

int led1 = D0; 
int led2 = D1; 
int led3 = D2; 
int led4 = D3; 
int led5 = D4; 
int led6 = D5; 
int led7 = D6; 
int led8 = D7; 

void setup() {
  setupPart1();
  pinMode(led1, OUTPUT);
  pinMode(led2, OUTPUT);
  pinMode(led3, OUTPUT);
  pinMode(led4, OUTPUT);
  setupPart2();
  pinMode(led5, OUTPUT);
  pinMode(led6, OUTPUT);
  pinMode(led7, OUTPUT);
  pinMode(led8, OUTPUT);
}

void loop() {
  loopPart1();
  digitalWrite(led1, HIGH);
  delay(500); // delayed for half a second
  digitalWrite(led1, LOW);
  digitalWrite(led2, HIGH);
  delay(500); // delayed for half a second
  digitalWrite(led2, LOW);
  digitalWrite(led3, HIGH);
  delay(500); // delayed for half a second
  digitalWrite(led3, LOW);
  digitalWrite(led4, HIGH);
  delay(500); // delayed for half a second
  digitalWrite(led4, LOW);
  loopPart2();
  digitalWrite(led5, HIGH);
  delay(500); // delayed for half a second
  digitalWrite(led5, LOW);
  digitalWrite(led6, HIGH);
  delay(500); // delayed for half a second
  digitalWrite(led6, LOW);
  digitalWrite(led7, HIGH);
  delay(500); // delayed for half a second
  digitalWrite(led7, LOW);
  digitalWrite(led8, HIGH);
  delay(500); // delayed for half a second
  digitalWrite(led8, LOW);
}
2

2 Answers 2

1

I cover this exact question in my web page: http://www.gammon.com.au/blink

Example code that blinks two LEDs at different rates:

// Which pins are connected to which LED
const byte greenLED = 12;
const byte redLED = 13;

// Time periods of blinks in milliseconds (1000 to a second).
const unsigned long greenLEDinterval = 500;
const unsigned long redLEDinterval = 1000;

// Variable holding the timer value so far. One for each "Timer"
unsigned long greenLEDtimer;
unsigned long redLEDtimer;

void setup () 
  {
  pinMode (greenLED, OUTPUT);
  pinMode (redLED, OUTPUT);
  greenLEDtimer = millis ();
  redLEDtimer = millis ();
  }  // end of setup

void toggleGreenLED ()
  {
   if (digitalRead (greenLED) == LOW)
      digitalWrite (greenLED, HIGH);
   else
      digitalWrite (greenLED, LOW);

  // remember when we toggled it
  greenLEDtimer = millis ();  
  }  // end of toggleGreenLED

void toggleRedLED ()
  {
   if (digitalRead (redLED) == LOW)
      digitalWrite (redLED, HIGH);
   else
      digitalWrite (redLED, LOW);

  // remember when we toggled it
  redLEDtimer = millis ();  
  }  // end of toggleRedLED

void loop ()
  {

  // Handling the blink of one LED.
  if ( (millis () - greenLEDtimer) >= greenLEDinterval)
     toggleGreenLED ();

  // The other LED is controlled the same way. Repeat for more LEDs
  if ( (millis () - redLEDtimer) >= redLEDinterval) 
    toggleRedLED ();

/* Other code that needs to execute goes here.
   It will be called many thousand times per second because the above code
   does not wait for the LED blink interval to finish. */

}  // end of loop
1
  • thank you very much, i dont understand it but i will sit down tonight and try to figure it all out from the guide on your site
    – Ben Millen
    Commented Sep 5, 2017 at 10:57
1

This kind of problem (doing several things in parallel) is frequent enough to merit a more elegant solution. While projects like this are excellent (Tasks: A Time-Triggered Scheduler for Arduino), I can't get it working.

I wrote this minimal self-contained example of how to do two things simultaneously. It will blink the built-in LED and write "*" to the serial monitor:

--- Task Scheduler ---
Runtime in SS:MMMM
10:9 **********
110:64 **********
210:89 ***

This is the sketch. Study it and adapt it to your own problem:

/*
 * Task Scheduler for Arduino/ESP2866 by Look Alterno - 2017/8/9.0
 * Show how to execute tasks at regular intervals without using delay() or interrupts.
 * For educational purposes only; not production ready. 
 *
 * This sketch have two example tasks running:
 * - Task 1 blinks the builtin led every second
 * - Task 2 write lines with run time and one "*" every ten seconds in the Serial Monitor. 
 * Tasks are run in sequence, so keep them short.
 * No interrupts are used; you have to call runTasks() in each loop() pass.
 */

// Definition: Every task must receive nothing and return nothing.
typedef void (*fcnptr)();
//  Here we must declare our task functions (required by C)
void fcnBlink();      // Task 1
void fcnSerial();     // Task 2
//  Add more tasks here.

//  The interval between fcnBlink execution. Adjustable between 25 to 250 ms.
//  LED still will blink every second at the same freq (250ms on, 750ms off).
#define BLINK_LEN 25

//  The task list
struct {
    uint8_t  runnable;  // The task is runnable (true/false).
    uint32_t start;     // Next start time for the task (ms).
    uint32_t interval;  // Execution interval in ms.
    fcnptr fcn;          // Function to execute.
} taskList[] = {
    {true, 0, BLINK_LEN,fcnBlink}, // Execute fcnBlink every 25 ms, blink LED every second
    {true, 0, 10000,    fcnSerial} // Execute fcnSerial every 10 seconds.
    // Here you can add other tasks.
};
// The number of task in our task list.
const uint8_t nTasks = sizeof(taskList) / sizeof(taskList[0]);

void setup() {
  // Just a standard setup. Nothing is required for task execution.
  Serial.begin(9600);
  while(!Serial) {};
  randomSeed(analogRead(A0));
  Serial.println("");
  Serial.println("--- Task Scheduler ---");
  Serial.println("Runtime in SS:MMMM");
  pinMode(LED_BUILTIN, OUTPUT);
}

void loop() {
  // Here you write your processing code (without using delay())
  // --- Start of your code.
  // Some random delays to simulate work
  // Just a bit less than half fcnBlink interval length.
  // You can change BLINK_LEN to test other scenarios.

  delay(random(1, BLINK_LEN / 2));  

  // --- End of your code
  runTasks();  // At the end of the loop(), but can be anywhere.
}

/*
 * Check the task list and execute them.
 * Sequence of execution guaranteed: tasks could be delayed,
 * but not omitted or executed of order.
 */
void runTasks() {
  uint32_t now = millis();
  for(uint8_t i=0; i < nTasks; i++) {
    if(taskList[i].runnable) {
      uint32_t diff = now - taskList[i].start; // ms since last execution.
      if(diff >= taskList[i].interval) {
        taskList[i].start = now; // Have to be the same for all task, to keep sync.
        taskList[i].fcn();
      }
    }
  }
}

/*
 * Blink the led.
 */
void fcnBlink() {
  // Called every 25 milliseconds. Turn on the led in the
  // 10 first passes and turn off in the next 30.
  static uint8_t count = 0;
  count++;
  if(count <= 250 / BLINK_LEN) {
    digitalWrite(LED_BUILTIN, HIGH);
  } else {
    digitalWrite(LED_BUILTIN, LOW);
    if(count == 1000 / BLINK_LEN) {
      count = 0;
    }
  }
}

/*
 * Print run time (s) and a row of ten "*"
 */
void fcnSerial() {
  static uint8_t count = 0;
  count++;
  // Print run time in seconds:miliseconds at the start of each line
  if (count == 1) {
    uint32_t now = millis();
    Serial.print(now/1000);
    Serial.print(":");
    Serial.print(now%1000);
    Serial.print(" ");
  }
  Serial.print("*");
  if(count == 10) {
    Serial.println();
    count = 0;
  }
}
1
  • thanks for your advice, will study both replies, it looks like a massive jump in knowledge from my code so ill just have to knuckle down and study, cheers :)
    – Ben Millen
    Commented Sep 5, 2017 at 10:59

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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