Concurrent Actions

I am running the following code on my project (simple chaser sequence):

int delayTime = 0;

void setup()
{
//declare A0-A3 as outputs
pinMode(A0, OUTPUT);
pinMode(A1, OUTPUT);
pinMode(A2, OUTPUT);
pinMode(A3, OUTPUT);
pinMode(A8, OUTPUT);
pinMode(A5, OUTPUT);
}
void loop()
//the loop will repeat over and over again
{
delayTime = analogRead(0);
//We are now setting our delay TIme from 0 to the number being read on A0 which is the position of the rotory shaft on the pot. digital
digitalWrite(A0, LOW); delay(750); digitalWrite(A0, HIGH); delay(500);
digitalWrite(A1, LOW); delay(750); digitalWrite(A1, HIGH); delay(500);
digitalWrite(A2, LOW); delay(750); digitalWrite(A2, HIGH); delay(500);
digitalWrite(A3, LOW); delay(750); digitalWrite(A3, HIGH); delay(500);
}

I want to add a rapidly blinking light that I can control with a push button. I added

digitalWrite(A5, LOW); delay(10); digitalWrite(A5, HIGH); delay(10);

but that just adds it to the above chaser sequence. How do I get them to run concurrently?

By not using any delay(), but a timing based on millis().

See the BlinkWithoutDelay example.

You should only use comments that have a meaning, yours are superfluous or plain wrong.

I think your blinking (50 times a second) is to fast to be seen as blinking.

You code could look like this

const unsigned long lowTime = 750;
const unsigned long highTime = 500;
const unsigned long blinkTime = 10;

unsigned long chaseTime;
unsigned long lastBlink;

byte chaseLed;

void setup()
{
  pinMode(A0, OUTPUT);
  pinMode(A1, OUTPUT);
  pinMode(A2, OUTPUT);
  pinMode(A3, OUTPUT);
  pinMode(A5, OUTPUT);
}

void loop() {
  unsigned long topLoop = millis();

  if (chaseLed & 1) {
    if (topLoop  - chaseTime >= highTime)  {
      digitalWrite(A0 + (chaseLed >> 1), LOW);
      if (++chaseLed > 7) {
        chaseLed = 0;
      }
      chaseTime = topLoop;
    }
  } else if (topLoop - chaseTime >= lowTime) {
    digitalWrite(A0 + (chaseLed >> 1), HIGH);
    if (++chaseLed > 7) {
      chaseLed = 0;
    }
    chaseTime = topLoop;
  }
  if (topLoop - lastBlink >= blinkTime) {
    digitalWrite(A5, !digitalRead(A5));
    lastBlink = topLoop;
  }
}

You are awesome! I read your reply and went looking....getting more frustrated by the minute. The code you sent was perfect.

Oh, the comments were remnants from a previous code that I edited to work, I just ignored them.

ajdeployed12:
Oh, the comments were remnants from a previous code that I edited to work, I just ignored them.

Get into the habit to remove or adjust them. :wink:

Here you have a version with some comments.

For the chase there is a byte (phase) that increments form 0 to 7.
phase 0 and 1 manipulate led 0, phase 2 and 3 manipulate led 1, ...

So the phase can be seen as led-index * 2 + !led-state.

const unsigned long lowTime = 750;
const unsigned long highTime = 500;
const unsigned long blinkTime = 100;

unsigned long chaseTime;  // last change for chase
unsigned long lastBlink;  // last change for blink

byte phase;  // keep track on the phase of the chase
// 0 0b000 1. led on
// 1 0b001 1. led off
// 2 0b010 2. led on
// 3 0b011 2. led off
// 4 0b100 3. led on
// 5 0b101 3. led off
// 6 0b110 4. led on
// 7 0b111 5. led off
//   0bxxs xx -> led, s -> !state (because you start with high)

void setup()
{
  pinMode(A0, OUTPUT);
  pinMode(A1, OUTPUT);
  pinMode(A2, OUTPUT);
  pinMode(A3, OUTPUT);
  pinMode(A5, OUTPUT);
}

void loop() {
  unsigned long topLoop = millis(); // one timestamp for all timings
  // is next phase the low phase?
  if (phase & 1) {
    // if high duration is over
    if (topLoop  - chaseTime >= highTime)  {
      digitalWrite(A0 + (phase >> 1), LOW);  // two top bits of the phase select the led
      if (++phase > 7) { // next phase with wrap
        phase = 0;
      }
      chaseTime = topLoop; // remember when
    }
  } else { // next phase is high phase
    // if low duration is over
    if (topLoop - chaseTime >= lowTime) {
      digitalWrite(A0 + (phase >> 1), HIGH);
      if (++phase > 7) { // next phase with wrap
        phase = 0;
      }
      chaseTime = topLoop; // remember when
    }
  }
  // if blink duration is over
  if (topLoop - lastBlink >= blinkTime) {
    // change state of led by setting it to its complement
    digitalWrite(A5, !digitalRead(A5));
    lastBlink = topLoop;  // remember when
  }
}

Tried to send you a private message, not sure if it went through. Can you provide a link that explains the code you gave me? While I am super appreciative, I still need to add some more functions and would like to understand why the functions act like they do.

There is no link for a description, I wrote the code after reading your post.

You will have to live with the above 'documentation'.

If I did not make that clear enough, you can ask for further clarification.

Since I am only about a week into this, it looks like gibberish to me. I will reread the code and look up the specific functions individually to try to make sense of it and expand as needed.

There's an Automaton example that does exactly this. Chasing leds with speed controlled by a potmeter.

Code fragment:

  app.component( 
    sweep.begin( 4, 5, 6, 7, 8, 9 )
      .trigger( sweep.EVT_START )
  );

  app.component( 
    pot.begin( A0 )
      .range( 10, 200 )
      .onChange( []( int idx, int v, int up ) {
        sweep.speed( v );
      })
  );

Alright, I tried to expand on the code you provided (see below) but I got this error message:

exit status 1
Error compiling for board Arduino/Genuino Mega or Mega 2560.

So obviously I screwed something up.

My Goal:

1 4 LED Chaser Circuit (A12-A15)

1 8 Section Bar Graph Chaser (26-40) with two sections always on (22, 24)

1 Pin always ON controlling a relay switch (A8)

1 Pin controlling an LED on slow blink (A11)

1 Pin always ON controlling an LED (31)

1 Pin controlling a set of LEDs on rapid blink (currently A9) {Want to link this with ONE of the sound triggers using a momentary switch-sound and lights stop when not pressed)

2 MP3 Tracks using SparkFun MP3 Player Shield - DEV-12660 - SparkFun Electronics (0, 1, 5, 10, and A0-A4. A5)
-1 with lights and sound (see above)
-1 with just sound set to a momentary on button that plays the entire file unless the other sound trigger is pressed.

[reference: MP3 Player Shield Hookup Guide V15 - SparkFun Learn v15#example-sketch-mp3-trigger ]

CODE IS BELOW:

const unsigned long lowTime = 750;
const unsigned long highTime = 500;
const unsigned long blinkTime = 100;
const unsigned long blinkTime2 = 1000;

unsigned long chaseTime;
unsigned long lastBlink;

byte chaseLed;

*/

#include <SPI.h>           // SPI library
#include <SdFat.h>         // SDFat Library
#include <SdFatUtil.h>     // SDFat Util Library
#include <SFEMP3Shield.h>  // Mp3 Shield Library

SdFat sd; // Create object to handle SD functions

SFEMP3Shield MP3player; // Create Mp3 library object
// These variables are used in the MP3 initialization to set up
// some stereo options:
const uint8_t volume = 0; // MP3 Player volume 0=max, 255=lowest (off)
const uint16_t monoMode = 1;  // Mono setting 0=off, 3=max

/* Pin setup */
#define TRIGGER_COUNT 9
int triggerPins[TRIGGER_COUNT] = {0, 1, 5, 10, A0, A1, A2, A3, A4};
int stopPin = A5; // This pin triggers a track stop.
int lastTrigger = 0; // This variable keeps track of which tune is playing

void setup()
{
  pinMode(A12, OUTPUT);
  pinMode(A13, OUTPUT);
  pinMode(A14, OUTPUT);
  pinMode(A15, OUTPUT);
  pinMode(A9, OUTPUT);
  pinMode(A8, OUTPUT);
  pinMode(A11, OUTPUT);
  pinMode(22, OUTPUT);//Bar Graph ON
  pinMode(24, OUTPUT);//Bar Graph ON
  pinMode(26, OUTPUT);//Bar Graph Chaser
  pinMode(28, OUTPUT);//Bar Graph Chaser
  pinMode(30, OUTPUT);//Bar Graph Chaser
  pinMode(32, OUTPUT);//Bar Graph Chaser
  pinMode(34, OUTPUT);//Bar Graph Chaser
  pinMode(36, OUTPUT);//Bar Graph Chaser
  pinMode(38, OUTPUT);//Bar Graph Chaser
  pinMode(40, OUTPUT);//Bar Graph Chaser
  pinMode(31, OUTPUT);//Particle Thrower Blue Lights
  
}

void loop() {
  unsigned long topLoop = millis();


  if (chaseLed & 1) {
    if (topLoop  - chaseTime >= highTime)  {
      digitalWrite(A12 + (chaseLed >> 1), LOW);
      if (++chaseLed > 15) {
        chaseLed = 0;
      }
      chaseTime = topLoop;
    }
  } else if (topLoop - chaseTime >= lowTime) {
    digitalWrite(A12 + (chaseLed >> 1), HIGH);
    if (++chaseLed > 15) {
      chaseLed = 0;
    }

    if (chaseLed & 1) {
    if (topLoop  - chaseTime >= highTime)  {
      digitalWrite(26 + (chaseLed >> 1), LOW);
      if (++chaseLed > 40) {
        chaseLed = 0;
      }
      chaseTime = topLoop;
    }
  } else if (topLoop - chaseTime >= lowTime) {
    digitalWrite(26 + (chaseLed >> 1), HIGH);
    if (++chaseLed > 40) {
      chaseLed = 0;
    }
    chaseTime = topLoop;
  }

  if (topLoop - lastBlink >= blinkTime) {
    digitalWrite(A9, !digitalRead(A9));
    lastBlink = topLoop;
  }
    }
  if (topLoop - lastBlink >= blinkTime2) {
    digitalWrite(A11, !digitalRead(A11));
    lastBlink = topLoop;
  }
{
  /* Set up all trigger pins as inputs, with pull-ups activated: */
  for (int i=0; i<TRIGGER_COUNT; i++)
  {
    pinMode(triggerPins[i], INPUT_PULLUP);
  }
  pinMode(stopPin, INPUT_PULLUP);

  initSD();  // Initialize the SD card
  initMP3Player(); // Initialize the MP3 Shield
}

// All the loop does is continuously step through the trigger
//  pins to see if one is pulled low. If it is, it'll stop any
//  currently playing track, and start playing a new one.
void loop()
{
  for (int i=0; i<TRIGGER_COUNT; i++)
  {
    if ((digitalRead(triggerPins[i]) == LOW) && ((i+1) != lastTrigger))
    {
      lastTrigger = i+1; // Update lastTrigger variable to current trigger
      /* If another track is playing, stop it: */
      if (MP3player.isPlaying())
        MP3player.stopTrack();

      /* Use the playTrack function to play a numbered track: */
      uint8_t result = MP3player.playTrack(lastTrigger);
      // An alternative here would be to use the
      //  playMP3(fileName) function, as long as you mapped
      //  the file names to trigger pins.

      if (result == 0)  // playTrack() returns 0 on success
      {
        // Success
      }
      else // Otherwise there's an error, check the code
      {
        // Print error code somehow, someway
      }
    }
  }
  // After looping through and checking trigger pins, check to
  //  see if the stopPin (A5) is triggered.
  if (digitalRead(stopPin) == LOW)
  {
    lastTrigger = 0; // Reset lastTrigger
    // If another track is playing, stop it.
    if (MP3player.isPlaying())
      MP3player.stopTrack();
  }
}

// initSD() initializes the SD card and checks for an error.
void initSD()
{
  //Initialize the SdCard.
  if(!sd.begin(SD_SEL, SPI_HALF_SPEED)) 
    sd.initErrorHalt();
  if(!sd.chdir("/")) 
    sd.errorHalt("sd.chdir");
}

// initMP3Player() sets up all of the initialization for the
// MP3 Player Shield. It runs the begin() function, checks
// for errors, applies a patch if found, and sets the volume/
// stero mode.
void initMP3Player()
{
  uint8_t result = MP3player.begin(); // init the mp3 player shield
  if(result != 0) // check result, see readme for error codes.
  {
    // Error checking can go here!
  }
  MP3player.setVolume(volume, volume);
  MP3player.setMonoMode(monoMode);
}

And that's why we ask you to use code tags

AWOL:
And that's why we ask you to use code tags

What is a code tag?

The things that stop your code turning to italics.

Here, I've got a pair I'm not using [code][/code] - you can have them

AWOL:
The things that stop your code turning to italics.

Here, I've got a pair I'm not using [code][/code] - you can have them

Nice, thank you. The check is in the mail.

CODE IS BELOW:

Which has some issues.

*/

That closes a multiline comment that was never opened. You can't just copy and paste some code.

When I try to use Tools + Auto Format to properly indent your code, since you couldn't be bothered, that fails, because the number of open and close curly braces doesn't. YOU must fix that.

ajdeployed12:
CODE IS BELOW:

At line 56, you have the defined 'loop()'; inside 'loop()' you have another 'loop()' function defined (line 114). You can not define a function inside a function.

And function names need to be unique; you can not have

void setup()
{
}

void loop()
{
}


void loop()
{
}

And (from your code) you can also not have

void setup()
{
}

void loop()
{
  void loop()
  {
  }
}