Two routines running at once

Hello, I'm new to the forum and not sure I've posted this in the correct place.

I've been working with Arduino now for about 5 years, but this has me stumped.

I have built a 6 unit 8x8 LED matrix scrolling sign, and am running code which works and allows me to change text if I want. All good.

I also have some duinotech (Aussie brand name) 595 4xRGB LED modules which I get to flash quite nicely with some code I have. All good.

However, at the moment, I have them combined into one sketch. The RGB routine is at the top of the code. So of course, when the code runs, the RGB LEDs flash and do their thing, then stop. The text message then scrolls, then the whole thing starts again.

Ideally, I would like the coloured LEDs to flash all the time while the text was scrolling simultaneously.

I've spent two days messing around with the millis function, but I'm getting nowhere. I'm sure it must be something quite simple.

Any assistance would be greatly appreciated!

Hope you are all keeping safe during this extraordinary time.

Maybe there is help if You attach the code. Read about code tags!
No code, no help.

#include <MaxMatrix.h>
#include <avr/pgmspace.h>
#include <duinotech595.h>


PROGMEM const unsigned char CH[] = {
3, 8, B00000000, B00000000, B00000000, B00000000, B00000000, // space
1, 8, B01011111, B00000000, B00000000, B00000000, B00000000, // !
3, 8, B00000011, B00000000, B00000011, B00000000, B00000000, // "
5, 8, B00010100, B00111110, B00010100, B00111110, B00010100, // #
4, 8, B00100100, B01101010, B00101011, B00010010, B00000000, // $
5, 8, B01100011, B00010011, B00001000, B01100100, B01100011, // %
5, 8, B00110110, B01001001, B01010110, B00100000, B01010000, // &
1, 8, B00000011, B00000000, B00000000, B00000000, B00000000, // '
3, 8, B00011100, B00100010, B01000001, B00000000, B00000000, // (
3, 8, B01000001, B00100010, B00011100, B00000000, B00000000, // )
5, 8, B00101000, B00011000, B00001110, B00011000, B00101000, // *
5, 8, B00001000, B00001000, B00111110, B00001000, B00001000, // +
2, 8, B10110000, B01110000, B00000000, B00000000, B00000000, // ,
4, 8, B00001000, B00001000, B00001000, B00001000, B00000000, // -
2, 8, B01100000, B01100000, B00000000, B00000000, B00000000, // .
4, 8, B01100000, B00011000, B00000110, B00000001, B00000000, // /
4, 8, B00111110, B01000001, B01000001, B00111110, B00000000, // 0
3, 8, B01000010, B01111111, B01000000, B00000000, B00000000, // 1
4, 8, B01100010, B01010001, B01001001, B01000110, B00000000, // 2
4, 8, B00100010, B01000001, B01001001, B00110110, B00000000, // 3
4, 8, B00011000, B00010100, B00010010, B01111111, B00000000, // 4
4, 8, B00100111, B01000101, B01000101, B00111001, B00000000, // 5
4, 8, B00111110, B01001001, B01001001, B00110000, B00000000, // 6
4, 8, B01100001, B00010001, B00001001, B00000111, B00000000, // 7
4, 8, B00110110, B01001001, B01001001, B00110110, B00000000, // 8
4, 8, B00000110, B01001001, B01001001, B00111110, B00000000, // 9
2, 8, B01010000, B00000000, B00000000, B00000000, B00000000, // :
2, 8, B10000000, B01010000, B00000000, B00000000, B00000000, // ;
3, 8, B00010000, B00101000, B01000100, B00000000, B00000000, // <
3, 8, B00010100, B00010100, B00010100, B00000000, B00000000, // =
3, 8, B01000100, B00101000, B00010000, B00000000, B00000000, // >
4, 8, B00000010, B01011001, B00001001, B00000110, B00000000, // ?
5, 8, B00111110, B01001001, B01010101, B01011101, B00001110, // @
4, 8, B01111110, B00010001, B00010001, B01111110, B00000000, // A
4, 8, B01111111, B01001001, B01001001, B00110110, B00000000, // B
4, 8, B00111110, B01000001, B01000001, B00100010, B00000000, // C
4, 8, B01111111, B01000001, B01000001, B00111110, B00000000, // D
4, 8, B01111111, B01001001, B01001001, B01000001, B00000000, // E
4, 8, B01111111, B00001001, B00001001, B00000001, B00000000, // F
4, 8, B00111110, B01000001, B01001001, B01111010, B00000000, // G
4, 8, B01111111, B00001000, B00001000, B01111111, B00000000, // H
3, 8, B01000001, B01111111, B01000001, B00000000, B00000000, // I
4, 8, B00110000, B01000000, B01000001, B00111111, B00000000, // J
4, 8, B01111111, B00001000, B00010100, B01100011, B00000000, // K
4, 8, B01111111, B01000000, B01000000, B01000000, B00000000, // L
5, 8, B01111111, B00000010, B00001100, B00000010, B01111111, // M
5, 8, B01111111, B00000100, B00001000, B00010000, B01111111, // N
4, 8, B00111110, B01000001, B01000001, B00111110, B00000000, // O
4, 8, B01111111, B00001001, B00001001, B00000110, B00000000, // P
4, 8, B00111110, B01000001, B01000001, B10111110, B00000000, // Q
4, 8, B01111111, B00001001, B00001001, B01110110, B00000000, // R
4, 8, B01000110, B01001001, B01001001, B00110010, B00000000, // S
5, 8, B00000001, B00000001, B01111111, B00000001, B00000001, // T
4, 8, B00111111, B01000000, B01000000, B00111111, B00000000, // U
5, 8, B00001111, B00110000, B01000000, B00110000, B00001111, // V
5, 8, B00111111, B01000000, B00111000, B01000000, B00111111, // W
5, 8, B01100011, B00010100, B00001000, B00010100, B01100011, // X
5, 8, B00000111, B00001000, B01110000, B00001000, B00000111, // Y
4, 8, B01100001, B01010001, B01001001, B01000111, B00000000, // Z
2, 8, B01111111, B01000001, B00000000, B00000000, B00000000, // [
4, 8, B00000001, B00000110, B00011000, B01100000, B00000000, // \ backslash
2, 8, B01000001, B01111111, B00000000, B00000000, B00000000, // ]
3, 8, B00000010, B00000001, B00000010, B00000000, B00000000, // hat
4, 8, B01000000, B01000000, B01000000, B01000000, B00000000, // _
2, 8, B00000001, B00000010, B00000000, B00000000, B00000000, // `
4, 8, B00100000, B01010100, B01010100, B01111000, B00000000, // a
4, 8, B01111111, B01000100, B01000100, B00111000, B00000000, // b
4, 8, B00111000, B01000100, B01000100, B00101000, B00000000, // c
4, 8, B00111000, B01000100, B01000100, B01111111, B00000000, // d
4, 8, B00111000, B01010100, B01010100, B00011000, B00000000, // e
3, 8, B00000100, B01111110, B00000101, B00000000, B00000000, // f
4, 8, B10011000, B10100100, B10100100, B01111000, B00000000, // g
4, 8, B01111111, B00000100, B00000100, B01111000, B00000000, // h
3, 8, B01000100, B01111101, B01000000, B00000000, B00000000, // i
4, 8, B01000000, B10000000, B10000100, B01111101, B00000000, // j
4, 8, B01111111, B00010000, B00101000, B01000100, B00000000, // k
3, 8, B01000001, B01111111, B01000000, B00000000, B00000000, // l
5, 8, B01111100, B00000100, B01111100, B00000100, B01111000, // m
4, 8, B01111100, B00000100, B00000100, B01111000, B00000000, // n
4, 8, B00111000, B01000100, B01000100, B00111000, B00000000, // o
4, 8, B11111100, B00100100, B00100100, B00011000, B00000000, // p
4, 8, B00011000, B00100100, B00100100, B11111100, B00000000, // q
4, 8, B01111100, B00001000, B00000100, B00000100, B00000000, // r
4, 8, B01001000, B01010100, B01010100, B00100100, B00000000, // s
3, 8, B00000100, B00111111, B01000100, B00000000, B00000000, // t
4, 8, B00111100, B01000000, B01000000, B01111100, B00000000, // u
5, 8, B00011100, B00100000, B01000000, B00100000, B00011100, // v
5, 8, B00111100, B01000000, B00111100, B01000000, B00111100, // w
5, 8, B01000100, B00101000, B00010000, B00101000, B01000100, // x
4, 8, B10011100, B10100000, B10100000, B01111100, B00000000, // y
3, 8, B01100100, B01010100, B01001100, B00000000, B00000000, // z
3, 8, B00001000, B00110110, B01000001, B00000000, B00000000, // {
1, 8, B01111111, B00000000, B00000000, B00000000, B00000000, // |
3, 8, B01000001, B00110110, B00001000, B00000000, B00000000, // }
4, 8, B00001000, B00000100, B00001000, B00000100, B00000000, // ~
};
#define PLAY_E 3
#define playTime 100

unsigned long startMillis;
unsigned long currentMillis;
const unsigned long period = 500;

const byte LATCH_PIN=6;
const byte CLOCK_PIN=5;
const byte DATA_PIN=4;
Duinotech595 duinotech595 (LATCH_PIN, DATA_PIN, CLOCK_PIN);
byte pairArray[] = {LED_PAIR_1_GREEN,
                    LED_PAIR_2_BLUE,
                    LED_PAIR_1_RED,
                    LED_PAIR_2_GREEN,
                    LED_PAIR_1_RED,
                    LED_PAIR_2_BLUE,};
                    
int data = 8;    // DIN pin of MAX7219 module
int load = 9;    // CS pin of MAX7219 module
int clock = 10;  // CLK pin of MAX7219 module

int maxInUse = 6;  //how many MAX7219 are connected

MaxMatrix m(data, load, clock, maxInUse); // define Library

byte buffer[10];

char string1[] = " Keep cool... Diamond Dogs Rule the World OK - David Bowie, 1974.      ";  // Scrolling Text


void setup(){
  m.init(); // module MAX7219
  m.setIntensity(5); // LED Intensity 0-15
  pinMode(PLAY_E,OUTPUT);
  duinotech595.init();
  startMillis = millis();
  
}

void loop(){
  currentMillis = millis;
    if (currentMillis-startMillis>=period)
    
     duinotech595.off();
      delay(500);
      
      for (int i=0; i < sizeof (pairArray); i++) 
      {
        duinotech595.updateShiftRegister(pairArray[i]);
        delay(500);
       }
   
      
  
  digitalWrite(PLAY_E, HIGH);
  delay(50);
  digitalWrite(PLAY_E,LOW);
  delay(playTime);

  byte c;
  delay(100);
  m.shiftLeft(false, true);
  printStringWithShift(string1, 100); // Send scrolling Text
 

}

// Put extracted character on Display
void printCharWithShift(char c, int shift_speed){
  if (c < 32) return;
  c -= 32;
  memcpy_P(buffer, CH + 7*c, 7);
  m.writeSprite(maxInUse*8, 0, buffer);
  m.setColumn(maxInUse*8 + buffer[0], 0);
  
  for (int i=0; i<buffer[0]+1; i++) 
  {
    delay(shift_speed);
    m.shiftLeft(false, false);
  }
}

// Extract characters from Scrolling text
void printStringWithShift(char* s, int shift_speed){
  while (*s != 0){
    printCharWithShift(*s, shift_speed);
    s++;
  }
 
  }

There is a voice recorder module in there as well, triggered by Pin3.

I have some millis statements in there which are superfluous - this code cycles from top to bottom and works, but of course the flashing LED section at the top only works on every loop of the whole program.

Use Ctrl-T to see your mismatched braces.

Thank you!

I got the message "No changes necessary for Auto Format" whatever that means!

Bealman:
However, at the moment, I have them combined into one sketch. The RGB routine is at the top of the code. So of course, when the code runs, the RGB LEDs flash and do their thing, then stop. The text message then scrolls, then the whole thing starts again.

Have a look at how the code is organized in Several Things at a Time

Note how each function runs very briefly and returns to loop() so the next one can be called. None of the functions tries to complete a task in one call. And there may be dozens of calls to a function before it is actually time for it to do anything.

...R

Get rid of the for-loop :wink: Below is provided as a guide how to approach; it’s not compiled (and obviously not tested).

Create a function (e.g. updateLeds) and put the for-loop in there

void updateLeds()
{
  for (int i = 0; i < sizeof (pairArray); i++)
  {
    duinotech595.updateShiftRegister(pairArray[i]);
    delay(500);
  }
}

Add a static local variable (e.g. called paIndex) to replace i.
Also add a variable to remember the last update time (e.g. lastUpdateTime).

Static variables will be remembered between calls to the function (like global variables) but are local to the function. The ‘beauty’ is that you can e.g. have a lastUpdateTime variable in every function that needs one and they will not interfere with each other.

void updateLeds()
{
  // pairArray index
  static byte paIndex;
  // remember last time that leds were updated
  static unsigned long lastUpdateTime;
  
  for (int i = 0; i < sizeof (pairArray); i++)
  {
    duinotech595.updateShiftRegister(pairArray[i]);
    delay(500);
  }
}

Get rid of the for-loop and replace i by paIndex.

void updateLeds()
{
  // pairArray index
  static byte paIndex;
  // remember last time that leds were updated
  static unsigned long lastUpdateTime;
  
  // update shift register  
  duinotech595.updateShiftRegister(pairArray[paIndex]);
  // increment the index
  paIndex++;
  delay(500);
}

Check if all elements of pairArray are processed

void updateLeds()
{
  // pairArray index
  static byte paIndex;
  // remember last time that leds were updated
  static unsigned long lastUpdateTime;
  
  // update shift register  
  duinotech595.updateShiftRegister(pairArray[paIndex]);
  // increment the index
  paIndex++;

  delay(500);

  // check if we iterated over all elements of pairArray
  if(paIndex > sizeof(pairArray))
  {
    paIndex = 0;
  }
}

Lastly, get rid of the delay in favour of millis()

void updateLeds()
{
  // pairArray index
  static byte paIndex;
  // remember last time that leds were updated
  static unsigned long lastUpdateTime;

  // if it's time
  if (millis() - lastUpdateTime >= 500)
  {
    // update shift register  
    duinotech595.updateShiftRegister(pairArray[paIndex]);
    // remember last time that the shift register was updated.
    lastUpdateTime = millis();
    // increment the index
    paIndex++;
  }
}

You will need to call this function repeatedly; any delays in other parts of the code might cause it to misbehave so you need to get rid of all delays and for-loops (if you still have any).

Simple example for testing above

void loop()
{
  updateLeds();
}

Thanks, folks! It's getting late here in Aus, so I'll take a look at it tomorrow.

Stay safe!

Bealman:
Thanks, folks! It's getting late here in Aus, so I'll take a look at it tomorrow.

You must be retired, going to bed this early! :grin:

Beauty sleep.... NOT!