Maintaining Timing Between Separate LED Sequences

Hello …

Hoping for some assistance on a mockup I’ve been struggling with. I have two separate sequences of blinking leds that are staggered from one another by 50% of the first blink interval. (The first sequence has 8 leds that blink immediately after the other in a repeating cascading effect using a bitshift. The second sequence is the same except it initiates half way through the first blink of the first sequence. ) The speed of both sequences are controlled by a single potentiometer that is used to determine the ON interval of the leds. When the pot is left at it’s “0” position, the lights sequence as expected … staggered and they will maintain the pattern indefinitely. Both sequences will speed up and slow down when the pot is adjusted, but the more the pot is manipulated, the 50% staggered effect slowly diminishes until both sequences are exactly in sync as opposed to staggered. I suspects steps are being lost in my manipulation of the millis() function. Is there a way to be able to continuously adjust the pot and maintain the 50% staggered effect? The code is as follows …

const int POT = A0;
const int POT_LOW = 0 ;
const int POT_HIGH = 1023;
const int SLOW = 420;  // millis that led will be on at SLOWEST setting
const int FAST = 120;  // millis that led will be on at FASTEST setting

unsigned long currentMillis;
unsigned long interval;
unsigned long delayTime = 210;  // one time delay at the start of the program to stagger second sequence (half of SLOW)

bool delayRunning = true;  

byte LEDpins01[] = {5, 6, 7, 8, 9, 10, 11, 12};  
int LEDstate01 = 0x01;
unsigned long previousMillis01;

byte LEDpins02[] = {38, 39, 40, 41, 42, 43, 44, 45}; 
int LEDstate02 = 0x01;
unsigned long previousMillis02;

void setup() {
  Serial.begin(9600);
  
  for (int x = 0; x <= 7; x++) {
    pinMode(LEDpins01[x], OUTPUT);
  }
  for (int y = 38; y <= 45; y++) {
    pinMode(y, OUTPUT);
  }
}

void loop() {
  currentMillis = millis();   
  interval = getValue();      
  Serial.println(interval);   
  ledSequence01(interval);    
  ledSequence02 (interval);   
}

int getValue() {
  int val = analogRead(POT);
  val = map(val, POT_LOW, POT_HIGH, SLOW, FAST);   // remapping the values from the pot to be used for On interval
  return val;
}

//  first sequence
void ledSequence01(int led01Interval) {
  for (int x = 0; x <= 7; x++) {
    digitalWrite(LEDpins01[x], bitRead(LEDstate01, x));
  }
  if (currentMillis - previousMillis01 >= led01Interval) {
    previousMillis01 = + currentMillis;
    LEDstate01 = LEDstate01 << 1;
    if (LEDstate01 > 0x80) {
      LEDstate01 = 0x01;
    }
  }
}

// second sequence - delayed
void ledSequence02(int led02Interval) {
  if (delayRunning && ((currentMillis - previousMillis02) >= delayTime)) {  
    previousMillis02 = + currentMillis;
    delayRunning = false;
  }
  for (int x = 0; x <= 7; x++) {
    digitalWrite(LEDpins02[x], bitRead(LEDstate02, x));
  }
  if (currentMillis - previousMillis02 >= led02Interval) {
    previousMillis02 = + currentMillis;
    LEDstate02 = LEDstate02 << 1;
    if (LEDstate02 > 0x80) {
      LEDstate02 = 0x01;
    }
  }
}

Thanks in advance for taking a look and thanks for any help or suggestions.

*Edit … Using an Arduino Mega.

You need to implement a state machine this post in reply #16 shows you how.

Now to keep the two in sync you have to start off with one half the time you need and then on the first evocation of this animation double the time the display is updated. There after take a pot reading every time one of these two is run and change the time for both animations to reflect the new time delay, but change the start time of the other animation to half the value of the new time.

It would be somewhat simpler to produce code which runs at half the blink interval and alternates (use a counter, and switch according to the LSB) between advancing each of the two sequences. :grinning:

Why would you want to use a Mega 2560 for this? A Nano would be more appropriate. :astonished:

It would be somewhat simpler to produce code which runs at half the blink interval and alternates (use a counter, and switch according to the LSB) between advancing each of the two sequences.

Yes, I have just come on to say exactly that but you beat me too it. Except you make it run at twice the blink rate not half. Then each task gets to run at every other blink and hence the speed you want.

I said half the blink interval - twice the blink rate.

Thanks Grumpy_Mike and Paul__B. Splitting the blink interval is a clever solution I would never have thought of.

Thank you both!