URGENT:  LED sequencing using millus(). HELP!

Hi guys, look I have been trying to sequence a red, a green and a blue LED, in that order, when I activate a push button. I have a SampleAndSend function sampling LDR input but the problem is that when I use the delay() function in the cycling routine it shuts the SampleAndSend() function off while it activates the RGB LED cycle.

I understand that by using the millis() function as a timer I can sequence the same routine without affecting SampleAndSend() but I'm really stuck at using millus to accomplish the same task (I'm a novice). Could somebody please help me?

Here's my original code using the delay() function, is there an equivalent method using millus():

#define SAMPLE_PERIOD 10 // Sample Period in Milliseconds
// N.B. The arduino can sample all pins
int setPins[] = {1, 1, 1, 1, 1, 1};

//=======================================================================
//** Variables for data polling
//**
int analogPin, digitalPin; // Counters for poll loop
int analogData; // outgoing ADC value
byte x = 0; //byte to store digital status
byte y = 0; //same as above to store remaining digital pins status
//======================================================================

const int LED_RED = 2; // LED connected to digital pin 2
const int LED_GREEN = 3; // LED connected to digital pin 2
const int LED_BLUE= 4; // LED connected to digital pin 2
const int button_Pin = 5; //Sample button pushed sets the program to run once

// variables will change:
int button_State = 0; // variable for reading the pushbutton status

// The setup() method runs once, when the sketch starts
//=======================================================================

void setup() {
//setup serial baudrate for USB connection
Serial.begin(57600);

// initialize the digital pins as an output:
pinMode(LED_RED, OUTPUT);
pinMode(LED_GREEN, OUTPUT);
pinMode(LED_BLUE, OUTPUT);
pinMode(button_Pin,INPUT);

//enable digital pullups. All digital pins are set high
//and will only output change when connected to ground
for(digitalPin=6;digitalPin<14;++digitalPin)
{
pinMode(digitalPin, INPUT); //Setpin up for input
digitalWrite(digitalPin, HIGH); //enable internal pullups
}
}

//***********************************************************************
//** period has passed and its time to sample again.
void loop() {

long periodCheck = millis()%SAMPLE_PERIOD;

if (periodCheck == 0)
{
SampleAndSend();
}
//--------------------------------------------------------------------------------------------------

// read the state of the pushbutton value:
const int button_Pin = 5; //Sample button pushed sets the program to run once

button_State = digitalRead(button_Pin);

// check if the pushbutton is pressed.
// if it is, the buttonState is HIGH:
if (button_State == LOW) {

digitalWrite(LED_RED, HIGH); // set the LED on
delay(1000); // wait for a second
digitalWrite(LED_RED, LOW); // set the LED off
delay(1000); // wait for a second

digitalWrite(LED_GREEN, HIGH); // set the LED on
delay(1000); // wait for a second
digitalWrite(LED_GREEN, LOW); // set the LED off
delay(1000);

digitalWrite(LED_BLUE, HIGH); // set the LED on
delay(1000); // wait for a second
digitalWrite(LED_BLUE, LOW); // set the LED off
delay(1000);
}

else {
// turn LEDs off:
digitalWrite(LED_RED, LOW);
digitalWrite(LED_GREEN, LOW);
digitalWrite(LED_BLUE, LOW);
}

}

//*********************************************************************// SampleAndSend

void SampleAndSend()
{
x = PIND >> 7; // Shift digital pin port D by 2 to avoid TX and RX pins

Serial.print(x, BYTE);
y = PINB; // Read remaining digital pins
Serial.print(y, BYTE);

for(analogPin=0; analogPin<6; analogPin++) {
if(setPins[analogPin]==1)
{
analogData = analogRead(analogPin); // Read current analog pin value
Serial.print(analogData >> 7, BYTE); // shift high bits into output byte
Serial.print(analogData % 128, BYTE); // mod by 128 for the small byte
}
else
{
Serial.print(0, BYTE); // Send 0 to output
Serial.print(0, BYTE); //
}
}

Serial.print(255, BYTE); // end of packet signifier

/* This bit of code was used for checking how long a full read takes
Serial.println(millis());
*/
}

Thanks again for your time! :slight_smile:

Have you looked at Blink Without Delay...

Yes I have looked at it and tried to employ variations of code to achieve the same affect but to little avail.

Your problem is relatively simple, in that all you have to do is eliminate the "delay" calls (which, luckily all have the same duration) for which the Blink without delay example will help, and then implement a state-machine.
Every time one second has elapsed, the state machine advances a step. Each step consist of an LED being switched on or off.
A "switch/case" statement is a good way of implementing the machine, and an "enum" is a useful way of defining the states.

Please, when posting code, use the "#" button on the editor toolbar.

BTW You have two "button_Pin" declared - whilst they're currently both the same value, it may well bite you on the derriere in the future - get rid of the second one would be my advice.

Cheers thanks for the advice I was able to use the following code to get the RGB LED's to loop infintely:

int counter = 0;
int counter_Max =5;// These both go in the constants
section at the top of the script

//================the following goes within the main void loop()

if (millis()%1000==0)
{
if (counter<counter_max)
counter++;
else
counter=0;
Serial.print("counter = " );
Serial.print(counter);

// Then you can turn on or off the lights depending on the value of the counter, using a switch statement.

switch (counter) {
case 0: digitalWrite(LED_RED,HIGH);
break;
case 1: digitalWrite(LED_RED,LOW);
break;
case 2: digitalWrite(LED_GREEN,HIGH);
break;
case 3: digitalWrite(LED_GREEN,LOW);
break;
case 4: digitalWrite(LED_BLUE,HIGH);
break;
case 5: digitalWrite(LED_BLUE,LOW);
break;

}
}

Now the only problem is getting the button to activate the loop at the same point in the sequence ie RED LED on for one second, off once second etc when I activate the push button, which is a push to make incidently.

if (millis()%1000==0)

This is not really a good idea. Have you printed out the values that millis returns?

Depending on what is going on between the calls to millis, you might get numbers like 995, 996, 997, 998, 1000, 1001, 1002... or you might get numbers like 995, 998, 1001, 1004, 1006...

Relying on millis being evenly divisible by 1000 might mean missing a lot of times when a change should occur.

Better would be to do like the Blink Without Delay example does and record when a change has occurred, and see if it has been more than some period of time since then. 1000 (from the 1st sequence of values) would then trigger the next change (and recording of when). So would 1001 (from the 2nd sequence of values).

Well, seems to work well on it's own, but I've tried to get the sampling routine to run simultaneously at 10ms periods and there seems to be irregularity in the time periods during which the LED's are on and off: They will stay on for a second then off for two seconds (Frustrating, :o).