Go Down

Topic: Multiple modes and patterns (Read 2 times) previous topic - next topic

tim845

I am setting up an LED light strip and am having trouble.

Maybe I am making it too difficult.

I want a different set of patterns to go with different switches.

If you press button 1, then LED 1,3,and 5 would flash white like a strobe. while LED 2 and 4 would do a pattern through several different colors.

If you press a different button a different pattern would happen.

How to get the two different patterns to happen at the same time.

Thanks for all your help

PaulS

Quote
How to get the two different patterns to happen at the same time.

That all depends on how you get one pattern to display. Show your code.

Displaying two patterns at the same time means that you don't get to use delay().

tim845

It's just a variation of a few different setups that I found on here.  when you get to the bottom to the pattern for switch5State I left it blank because that is the one that I want the flashing patterns to be at two different speeds, at the same time, for the different leds.


/*
*  Led Setup using my Arduino Mega board
*/

int switch1Pin = 22;              // Button 1 is connected to pin 22
int switch2Pin = 23;              // Button 2 is connected to pin 23
int switch3Pin = 24;              // Button 3 is connected to pin 24
int switch4Pin = 25;              // Button 4 is connected to pin 25
int switch5Pin = 26;              // Button 5 is connected to pin 26

int led1Pin = 12;
int led2Pin = 11;
int led3Pin = 10;
int led4Pin = 9;
int led5Pin = 8;

int switch1State = 0;                        
int switch2State = 0;                      
int switch3State = 0;                
int switch4State = 0;
int switch5State = 0;              

void setup() {
 pinMode(switch1Pin, INPUT);   // Button 1
 pinMode(switch2Pin, INPUT);   // Button 2
 pinMode(switch3Pin, INPUT);   // Button 3
 pinMode(switch4Pin, INPUT);   // Button 4
 pinMode(switch5Pin, INPUT);   // Button 5
 pinMode(led1Pin, OUTPUT);
 pinMode(led2Pin, OUTPUT);
 pinMode(led3Pin, OUTPUT);
 pinMode(led4Pin, OUTPUT);
 pinMode(led5Pin, OUTPUT);
 
}

void loop(){
 switch1State = digitalRead(switch1Pin);      // read input values
 switch2State = digitalRead(switch2Pin);    
 switch3State = digitalRead(switch3Pin);
 switch4State = digitalRead(switch4Pin);
 switch5State = digitalRead(switch5Pin);

 if (switch1State == HIGH) {                 // start-up setting
   digitalWrite(led1Pin, HIGH);
   digitalWrite(led2Pin, LOW);
   digitalWrite(led3Pin, LOW);
   digitalWrite(led4Pin, LOW);
   digitalWrite(led5Pin, LOW);
   }
 else{ if (switch2State == HIGH)  {          // all-on
   digitalWrite(led1Pin, HIGH);
   digitalWrite(led2Pin, HIGH);
   digitalWrite(led3Pin, HIGH);
   digitalWrite(led4Pin, HIGH);
   digitalWrite(led5Pin, HIGH);
   }          
 else{ if (switch3State == HIGH)  {                   // blinking
   digitalWrite(led1Pin, HIGH);
   digitalWrite(led2Pin, LOW);
   digitalWrite(led3Pin, HIGH);
   digitalWrite(led4Pin, LOW);
   digitalWrite(led5Pin, HIGH);
   delay(100);
   digitalWrite(led1Pin, LOW);
   digitalWrite(led2Pin, HIGH);
   digitalWrite(led3Pin, LOW);
   digitalWrite(led4Pin, HIGH);
   digitalWrite(led5Pin, LOW);
   delay(100);
   }  
 else{ if (switch4State == HIGH)  {                     // second blinking pattern
   digitalWrite(led1Pin, HIGH);
   digitalWrite(led2Pin, HIGH);
   digitalWrite(led3Pin, HIGH);
   digitalWrite(led4Pin, HIGH);
   digitalWrite(led5Pin, HIGH);
   delay(50);
   digitalWrite(led1Pin, LOW);
   digitalWrite(led2Pin, LOW);
   digitalWrite(led3Pin, LOW);
   digitalWrite(led4Pin, LOW);
   digitalWrite(led5Pin, LOW);
   delay(50);
   }
  else{ if (switch5State == HIGH)

PaulS

Your code for button 3 being pressed turns some LEDs on, sets the alarm, goes to sleep, wakes up when the alarm clock goes off, turns some LEDs off, sets the alarm, goes to sleep, wakes up when the alarm goes off, and checks which button is pressed.

Your code for button 4 being pressed turns all the LEDs on, sets the alarm, goes to sleep, wakes up when the alarm clock goes off, turns all the LEDs off, sets the alarm, goes to sleep, wakes up when the alarm goes off, and checks which button is pressed.

If you want the code for button 3 and the code for button 4 to run at the same time, you need to stay awake.

The call to delay is equivalent to setting the alarm and going to sleep. Nothing happens until the alarm goes off.

The alternative to doing nothing while waiting for the alarm to go off is to look at your watch. Is it time to do something, like turn some LEDs on or off? If so, do it, and check your watch again. If not, check your watch again.

The Blink  Without Delay example shows how to implement the "check your watch" method of blinking LEDs.

But, before you go off getting real excited, you only have 5 LEDs. How do you intend to flash them in two recognizable patterns at the same time?

tim845

I'm trying to start small and get bigger as I go.  

The end result will be that no 2 buttons can be HIGH at the same time and that all the LEDs will be RGBs, with multiple different colors going on at different times.

I thought that I would start as basic as possible, with getting the basic effect that I am going for.

Getting the 2 distinct patterns to happen at the same time is where I am having trouble.  

tim845

Ok, I have been looking at the Blink without delay example and I'm having trouble seeing how to use it with my setup.

Maybe i'm just way over my head, but i want to learn.

PaulS

Suppose you put all the code for a pattern in a function. The function to light all the LEDs could be called AllOn. The function to turn them all off could be called AllOff.

You'd need functions with names like:
void Initial() {}
void AllOn() {}
void Alternating() {}
void Blinking() {}

Then, your code would look like this:
Code: [Select]
if(switch1State == HIGH)
  Initial();
else if(switch2State == HIGH)
  AllOn();
else if(switch3State == HIGH)
  Alternating();
else if(switch4State == HIGH)
  Blinking();
else if(switch5State == HIGH)
{
  // Call 2 of the functions here
}


The problem with this approach is still that you don't have enough LEDs (yet) to have two recognizable patterns running simultaneously.

Starting small is good. This is a good time to lean about functions, and develop a few of your own. Starting too small is not good, though. Hook up a few more LEDs so that you can have two patterns going at the same time.

Change Blinking() to control the added set of LEDs.

Then, if switch 5 is pressed, call Alternating() and Blinking(). You'll see one set of lights come on and then the next set. Then, the other group will all come on and then go off.

Then, you can create a new function, BlinkAndFlash() that blinks and flashes the LEDs in each group, as appropriate. This function will NOT be able to use delay.

tim845

Ok, I figured out how to set up the functions.

how do you tell it to show 2 different functions at the same time.  with each function only affecting different LEDS.
what would the command look like to use 2 functions when button 5 is pressed.

PaulS

Quote
how do you tell it to show 2 different functions at the same time.

Actually, you can't. But, as long as you do one then the other quickly enough, it won't matter that they are not performed simultaneously.

Quickly enough means you don't use delay(). If you are turning on and off LEDs, the time between turning one on and turning the next on will be a few clock cycles. Since there are typically 16,000,000 clock cycles per second, it's unlikely that you will see one LED come on before another.

You'd create a new function, BlinkAndAlternate() for instance, that checks the time. If it's time to blink some LEDs. That means either turning them on or off. You'll need to keep track of which state the blinking LEDs are in to do that. Then, you see if it's time to alternate some LEDs. Again, that means either turning them on or off. You'll need to keep track of which state the alternating LEDs are in to do that.

tim845

Still having trouble...

I just don't understand the whole millis idea with different functions and with the different buttons being used for different lighting patterns.

I feel like an idiot because I can't wrap my head around the blink without delay idea.

Ahhhhhhhhh!

Andrew

#10
Aug 12, 2010, 10:45 am Last Edit: Aug 12, 2010, 11:10 am by Andrew Reason: 1
Imagine you yourself want to physically ring a bell every 30 seconds. There are two ways you could do it. In the first way you ring the bell, then set an alarm clock for 30 seconds time, go to sleep, wake up when the alarm goes off, ring the bell and repeat. You are not able to do anything in that 30 seconds waiting time except wait for the alarm to go off.

The second way you would ring the bell then look at your clock and note what time it is. Then you start getting on with doing other stuff, but look at the clock periodically to see if 30 seconds has gone by yet. If not, just carry on doing other stuff and glancing at the clock. If 30 seconds has gone by, ring the bell and make a note of the new time, then carry on as before.

The first method is equivalent to to using delay() in Arduino code, the second is equivalent to using millis() to note down when you do something and wait for a time interval to pass before you do it again.

millis() tells you how many milliseconds it's been since the Arduino was powered on or reset. So you can note down what millis() returns now, do some stuff, and when you look at millis() again subtract the first reading and it will tell you how much time has gone by.

Abbreviated code snippet (won't run):

Code: [Select]
void loop() // do over and over again
{
 // Do stuff here that you want to do all the time
 ...
 // and some more stuff here
 ...

 // glance at the clock
 unsigned long currentMillis = millis();

 // has enough time gone by?
 if((currentMillis - previousMillis) > timeInterval) {
   // if yes, save the current time
   previousMillis = currentMillis;  

   // do something at a regular time interval
   // if the LED is off turn it on and vice-versa:
   if (ledState == LOW) {
     ledState = HIGH;
   }
   else {
     ledState = LOW;
   }
   // set the LED with the ledState of the variable:
   digitalWrite(ledPin, ledState);
 }
}


Once you understand how this works for doing one thing at a regular interval (here blinking an LED on or off) you can expand it to do two different things at different intervals. Instead of just recording previousMillis you have previousMillis1 and previousMillis2, one for each of the two different things you want to do, and two different time intervals timeInterval1 and timeInterval2. Then each time round loop() you check if either interval has passed and if so do the appropriate thing.

Code: [Select]
void loop()
{
 // Do stuff here that you want to do all the time
 ...

 // glance at the clock
 unsigned long currentMillis = millis();

 // has enough time gone by for red action?
 if((currentMillis - previousMillisRed) > timeIntervalRed) {
   // if yes, save the current time
   previousMillisRed = currentMillis;  

   if (redLedState == LOW) {
     redLedState = HIGH;
   }
   else {
     redLedState = LOW;
   }
   digitalWrite(redLedPin, redLedState);
 }

 // has enough time gone by for green action?
 if((currentMillis - previousMillisGreen) > timeIntervalGreen) {
   // if yes, save the current time
   previousMillisGreen = currentMillis;  

   if (greenLedState == LOW) {
     greenLedState = HIGH;
   }
   else {
     greenLedState = LOW;
   }
   digitalWrite(greenLedPin, greenLedState);
 }


}


Hope this helps.

Andrew

tim845

Ok, I got that working with one led... using millis.

how do I work millis with functions.  Do I say:

if (function1 == LOW) {
     function1 = HIGH;
   }
   else {
     function1 = LOW;
   }
   
and then put the second function right after???

I don't mean to sound like an idiot,  maybe I'm over my head...

tim845

In my function for switch 1, I have a start to the writing but I'm not sure how to tell it to flash from one pattern to the other back and forth.

unsigned long currentMillis = millis();
 
 if ((currentMillis - previousMillis) > interval1) {
   previousMillis = currentMillis;
   
   analogWrite(RHaloR, 255);
   analogWrite(RHaloG, 0);
   analogWrite(RHaloB, 0);
   analogWrite(LHaloR, 0);
   analogWrite(LHaloG, 0);
   analogWrite(LHaloB, 255);
   analogWrite(IntR, 0);
   analogWrite(IntG, 0);
   analogWrite(IntB, 255);
   analogWrite(BrakeR, 0);
   analogWrite(BrakeG, 0);
   analogWrite(BrakeB, 255);
   
to this one

   analogWrite(RHaloR, 0);
   analogWrite(RHaloG, 0);
   analogWrite(RHaloB, 255);
   analogWrite(LHaloR, 255);
   analogWrite(LHaloG, 0);
   analogWrite(LHaloB, 0);
   analogWrite(IntR, 255);
   analogWrite(IntG, 0);
   analogWrite(IntB, 0);
   analogWrite(BrakeR, 255);
   analogWrite(BrakeG, 0);
   analogWrite(BrakeB, 0);
   }

tim845

#13
Aug 17, 2010, 01:59 am Last Edit: Aug 17, 2010, 02:30 pm by tim845 Reason: 1
Ok,  This is as close as I can get...

the problem is, is that it doesn't matter what value I put for interval,  it goes the same speed.

Help!!!

Code: [Select]
long interval = 100;           // interval at which to blink (milliseconds)
long interval2 = 100;

long previousMillis = 0;
long previousMillis2 = 0;
int ledState = LOW;


void loop(){                       // intitial lighting
   Initial();
       
 switch1State = digitalRead(switch1Pin);      // read input values
 switch2State = digitalRead(switch2Pin);    
 switch3State = digitalRead(switch3Pin);
 switch4State = digitalRead(switch4Pin);
 switch5State = digitalRead(switch5Pin);
 switch6State = digitalRead(switch6Pin);
 
 if (switch1State == HIGH)                  // when the first button is pressed
   police();
  else if (switch2State == HIGH)            // when the next button is pressed
   fire();
 else if (switch3State == HIGH)             // the next button
   BlueGlow();
 else if (switch4State == HIGH)             // the next button
   RedGlow();
 else if (switch5State == HIGH)             // the next button
   ColorShiftGlow();
 else if (switch6State == HIGH)              // the next button
   Initial();
 }
     
void Initial(){                       // intitial lighting
   analogWrite(RHaloR, 255);
   analogWrite(RHaloG, 255);
   analogWrite(RHaloB, 255);
   analogWrite(LHaloR, 255);
   analogWrite(LHaloG, 255);
   analogWrite(LHaloB, 255);
   analogWrite(IntR, 255);
   analogWrite(IntG, 255);
   analogWrite(IntB, 255);
   analogWrite(BrakeR, 255);
   analogWrite(BrakeG, 0);
   analogWrite(BrakeB, 0);
   digitalWrite(FRStrobe, LOW);
   digitalWrite(FLStrobe, LOW);
   digitalWrite(BRStrobe, LOW);
   digitalWrite(BLStrobe, LOW);
   }
void BlueGlow(){                        // Blue Glow from Halos and rear emblem
   analogWrite(RHaloR, 0);
   analogWrite(RHaloG, 0);
   analogWrite(RHaloB, 255);
   analogWrite(LHaloR, 0);
   analogWrite(LHaloG, 0);
   analogWrite(LHaloB, 255);
   analogWrite(IntR, 0);
   analogWrite(IntG, 0);
   analogWrite(IntB, 255);
   analogWrite(BrakeR, 0);
   analogWrite(BrakeG, 0);
   analogWrite(BrakeB, 255);
   digitalWrite(FRStrobe, LOW);
   digitalWrite(FLStrobe, LOW);
   digitalWrite(BRStrobe, LOW);
   digitalWrite(BLStrobe, LOW);
   }
void RedGlow(){                          // Red Glow from Halos and rear emblem
   analogWrite(RHaloR, 255);
   analogWrite(RHaloG, 0);
   analogWrite(RHaloB, 0);
   analogWrite(LHaloR, 255);
   analogWrite(LHaloG, 0);
   analogWrite(LHaloB, 0);
   analogWrite(IntR, 255);
   analogWrite(IntG, 0);
   analogWrite(IntB, 0);
   analogWrite(BrakeR, 255);
   analogWrite(BrakeG, 0);
   analogWrite(BrakeB, 0);
   digitalWrite(FRStrobe, LOW);
   digitalWrite(FLStrobe, LOW);
   digitalWrite(BRStrobe, LOW);
   digitalWrite(BLStrobe, LOW);
   }
void police(){
 unsigned long currentMillis = millis();
 
 if ((currentMillis - previousMillis) > interval) {
   previousMillis = currentMillis;
   
   analogWrite(RHaloR, 255);
   analogWrite(RHaloG, 0);
   analogWrite(RHaloB, 0);
   analogWrite(LHaloR, 0);
   analogWrite(LHaloG, 0);
   analogWrite(LHaloB, 255);
   analogWrite(IntR, 0);
   analogWrite(IntG, 0);
   analogWrite(IntB, 255);
   analogWrite(BrakeR, 0);
   analogWrite(BrakeG, 0);
   analogWrite(BrakeB, 255);
   delay(100);
   analogWrite(RHaloR, 0);
   analogWrite(RHaloG, 0);
   analogWrite(RHaloB, 255);
   analogWrite(LHaloR, 255);
   analogWrite(LHaloG, 0);
   analogWrite(LHaloB, 0);
   analogWrite(IntR, 255);
   analogWrite(IntG, 0);
   analogWrite(IntB, 0);
   analogWrite(BrakeR, 255);
   analogWrite(BrakeG, 0);
   analogWrite(BrakeB, 0);
   delay(100);
 }
   if ((currentMillis - previousMillis2) > interval2) {
   previousMillis2 = currentMillis;
   if (ledState == LOW)
     ledState = HIGH;
     else
       ledState = LOW;
       
   digitalWrite(FRStrobe, ledState);
   digitalWrite(FLStrobe, ledState);
   digitalWrite(BRStrobe, ledState);
   digitalWrite(BLStrobe, ledState);
 }
}
void fire(){
 unsigned long currentMillis = millis();
 
 if ((currentMillis - previousMillis) > interval) {
   previousMillis = currentMillis;
   
   analogWrite(RHaloR, 0);
   analogWrite(RHaloG, 0);
   analogWrite(RHaloB, 255);
   analogWrite(LHaloR, 0);
   analogWrite(LHaloG, 0);
   analogWrite(LHaloB, 255);
   analogWrite(IntR, 0);
   analogWrite(IntG, 0);
   analogWrite(IntB, 255);
   analogWrite(BrakeR, 0);
   analogWrite(BrakeG, 0);
   analogWrite(BrakeB, 255);
   delay(100);
   analogWrite(RHaloR, 255);
   analogWrite(RHaloG, 255);
   analogWrite(RHaloB, 255);
   analogWrite(LHaloR, 255);
   analogWrite(LHaloG, 255);
   analogWrite(LHaloB, 255);
   analogWrite(IntR, 255);
   analogWrite(IntG, 255);
   analogWrite(IntB, 255);
   analogWrite(BrakeR, 255);
   analogWrite(BrakeG, 255);
   analogWrite(BrakeB, 255);
   delay(100);
 }
   if ((currentMillis - previousMillis2) > interval2) {
   previousMillis2 = currentMillis;
   if (ledState == LOW)
     ledState = HIGH;
     else
       ledState = LOW;
       
   digitalWrite(FRStrobe, ledState);
   digitalWrite(FLStrobe, ledState);
   digitalWrite(BRStrobe, ledState);
   digitalWrite(BLStrobe, ledState);
 }
}
void ColorShiftGlow(){                  // ColorShift Glow from Halos and rear emblem
  i += 1;      // Increment counter
 if (i < 10000) // First phase of fades
 {
   redVal   -= 1; // Red down
   greenVal += 1; // Green up
   blueVal   = 1; // Blue low
 }
 else if (i < 20000) // Second phase of fades
 {
   redVal    = 1; // Red low
   greenVal -= 1; // Green down
   blueVal  += 1; // Blue up
 }
 else if (i < 30000) // Third phase of fades
 {
   redVal  += 1; // Red up
   greenVal = 1; // Green low
   blueVal -= 1; // Blue down
 }
 else // Re-set the counter, and start the fades again
 {
   i = 1;
 }
   analogWrite(RHaloR, redVal);
   analogWrite(RHaloG, greenVal);
   analogWrite(RHaloB, blueVal);
   analogWrite(LHaloR, redVal);
   analogWrite(LHaloG, greenVal);
   analogWrite(LHaloB, blueVal);
   analogWrite(IntR, redVal);
   analogWrite(IntG, greenVal);
   analogWrite(IntB, blueVal);
   analogWrite(BrakeR, redVal);
   analogWrite(BrakeG, greenVal);
   analogWrite(BrakeB, blueVal);
   digitalWrite(FRStrobe, LOW);
   digitalWrite(FLStrobe, LOW);
   digitalWrite(BRStrobe, LOW);
   digitalWrite(BLStrobe, LOW);
       }

PaulS

Tim:
After more than a dozen posts, you really should know how to post code by now. Please modify your last post. Select all the code, and press the # button on the top row. That will add tags around the code that the forum software uses to display code in scrollable windows.

The police() and fire() functions use millis() and interval. But, let's looks at HOW.
Code: [Select]
void police()
{
 unsigned long currentMillis = millis();
 if ((currentMillis - previousMillis) > interval)
 {
   previousMillis = currentMillis;
 
   analogWrite(RHaloR, 255);
   // Turn other LEDs on and off
   delay(100); // There's that dreaded delay
   analogWrite(RHaloR, 0);
   // Turn other LEDs on and off
   delay(100);
 }
 
 if ((currentMillis - previousMillis2) > interval2)
 {
   previousMillis2 = currentMillis;
   if (ledState == LOW)
     ledState = HIGH;
   else
     ledState = LOW;
     
   digitalWrite(FRStrobe, ledState);
   digitalWrite(FLStrobe, ledState);
   digitalWrite(BRStrobe, ledState);
   digitalWrite(BLStrobe, ledState);
 }
}


The Arduino resets when you upload code to it, and starts running. The setup() function runs, and then loop() is called. In loop(), Initial() is called to turn all the LEDs on. Then, the button states are checked.

If the first button is pressed, the police() function is called. In police(), "now" is recorded. Now - then (0) is calculated, and compared to 100. Unless you are pretty quick noticing that the LEDs are all on, and hitting the button, more than one tenth of a second has elapsed since the Arduino was reset, so some LEDs are turned off (they were all on). You wait for 100 milliseconds, and turn some LEDs off and some on. Then, you wait for another 100 seconds.

Then, you see if the time when the function was called minus the last time this test was performed (0) is greater then 100. If you didn't get to the button quick enough, it is, so you turn some LEDs off, and exit the function.

If no other buttons were pressed, loop ends, and is called again. All the LEDs are turned back on (by the call to Initial()), and the state of the buttons is checked again.

Lets say that button 1 is still pressed (or its not a momentary contact switch and is latched). The police() function is called again. The current time is checked again, which will be 200+ milliseconds (those 2 delays, remember) later than last time. Since more than 100 milliseconds has elapsed (the value in interval), the same LED on/off pattern will be presented, and the same (fixed) time will be wasted. The LEDs will be toggled again, and some more (fixed) time wasted. Since 200+ seconds has elapsed since the last time previousMillis2 was recorded, the next if test will be true, so some LEDs will be turned off, and the function will end.

Nothing in your code changes the "speed" at which the LEDs "flash" in the police() function, since you have hard-coded delay times. Twice the hard-coded delay time is more than interval and interval2, so the "speed" never changes.

OK. So much for the rational explanation for the observed phenomenon. What "speed" are you attempting to influence? What exactly are you trying to use millis() and interval and interval2 for?

Why do you call Initial() at the start of loop()? It seems, just by it's name, that the Initial() function should be called in setup().

Go Up