Go Down

Topic: Color change timer (Read 1 time) previous topic - next topic

eclipsemints

Oct 03, 2008, 08:52 am Last Edit: Oct 03, 2008, 08:56 am by eclipsemints Reason: 1
Hi, all

I am new to C and new to the arduino.
I basically don't have any background of C and electronics....

I'm currently making a color change timer by using tri-color (RGB) LED.
My initial idea is that I just want to change the color from green, blue to red within 10 seconds, but I don't want to use "delay".
I used a light sensor(Photocell) as a switch. I also used "MsTimer2.h" in the sketch.

I'll show my sketch below. It doesn't work properly, because of my lack of programming skill... Tri-color LED flashes with "purple" and "green" with this sketch. I don't know why...
Please help me!!

Here is my sketch. Please modify it.-----
If I can't complete my idea with this sketch, please give me any idea.
Thanks heaps!!

Code: [Select]
#include <MsTimer2.h>

int ledPinG=10; //Green LED
int ledPinB=11; //BLUE LED
int ledPinR=12; //RED LED
int switchPin=2;  //Light sensor
int val;// Switch connected to digital pin 2


void setup() {
 Serial.begin(9600);           // set up Serial library at 9600 bps
 pinMode(switchPin, INPUT);  // Light sensor as a switch
 pinMode(ledPinG,OUTPUT);  // sets the digital pin as input to read switch
 pinMode(ledPinB,OUTPUT);  // sets the digital pin as input to read switch
 pinMode(ledPinR,OUTPUT);  // sets the digital pin as input to read switch

 MsTimer2::set(1000, flash); // 1000ms period
 MsTimer2::start();
}
void flash() {
static boolean output = HIGH;
  if (digitalRead(switchPin) ==LOW) //if the light sensor is uncovered
  {
     digitalWrite(ledPinB, output); //blink Blue LED
     output = !output;
     digitalWrite(ledPinG, output);  //blink Greene LED
     output = !output;
     digitalWrite(ledPinR, output);  //blink Red LED
     output = !output;

  }
}

void loop() {
   val = digitalRead(switchPin);   // read input value and store it in val
   if (val == HIGH) {              // if the light sensor is covered
   digitalWrite(ledPinG, LOW);    // turn LED off
   digitalWrite(ledPinB, LOW);    // turn LED off
   digitalWrite(ledPinR, LOW);    // turn LED off
 }

}

Syvwlch

Quote

     digitalWrite(ledPinB, output); //blink Blue LED
     output = !output;
     digitalWrite(ledPinG, output);  //blink Greene LED
     output = !output;
     digitalWrite(ledPinR, output);  //blink Red LED
     output = !output;


If you enter that sequence with output HIGH then blue is high, green is low and red is high and you exit with output LOW.

If you enter it with output LOW (e.g. looping around a second time), then blue is low, green is high and red is low, and you exit with output HIGH.

In other words, you always have either green on alone, or blue and red on together: green and purple.

If you want to cycle thru three states (blue, red and green) you need a state variable (e.g. output) that can hold three values, so not a boolean. For flexibility, you might want three booleans, one per LED.
----------
Mathieu

eclipsemints

Thanks Mathieu!
But, I still can't get it...

If it possible, could someone tell me how I can change the sketch?
(what variable should I add & which part shuould I change?)

mem

I wonder if you are unnecessarily making things difficult for yourself. Why not try it using delay instead of the timer. That way you can sequence through each of the colors you want. Once you have that code running it will be easier to see how you can modify it for use with a timer if you really need to do that.

eclipsemints

Thanks for your suggention!

I tried color timer setting with "delay" function, but I can't turn off the "color changing" immediately during the loop . It always stops after the RED LED blink.
When I cover the light sensor, I want to turn off it immediately.
How should I change the sketch?

Here is the sketch.
Code: [Select]

int ledPinG=10; //Green LED
int ledPinB=11; //BLUE LED
int ledPinR=12; //RED LED
int switchPin=2;  //Light sensor
int val;// Switch connected to digital pin 2

void setup() {
 Serial.begin(9600);           // set up Serial library at 9600 bps
 pinMode(switchPin,INPUT);  // Light sensor as a switch
 pinMode(ledPinG,OUTPUT);  // sets the digital pin as input to read switch
 pinMode(ledPinB,OUTPUT);  // sets the digital pin as input to read switch
 pinMode(ledPinR,OUTPUT);  // sets the digital pin as input to read switch
}

void loop() {
    val = digitalRead(switchPin);   // read input value and store it in val
     if (val == LOW) {              // the light sensor is uncovered by a hand
     digitalWrite(ledPinG, HIGH);  //blink Greene LED
     digitalWrite(ledPinB, HIGH); //blink Blue LED
     digitalWrite(ledPinR, HIGH);  //blink Red LED
     delay(2000);
     digitalWrite(ledPinG, HIGH);  //blink Greene LED
     digitalWrite(ledPinB, LOW); //
     digitalWrite(ledPinR, LOW);  /
     delay(2000);
     digitalWrite(ledPinG, HIGH);  //blink Greene LED
     digitalWrite(ledPinB, HIGH); //blink Blue LED
     digitalWrite(ledPinR, LOW);  //
     delay(2000);
     digitalWrite(ledPinG, LOW);  //
     digitalWrite(ledPinB, HIGH); //blink Blue LED
     digitalWrite(ledPinR, LOW);  //
     delay(2000);
     digitalWrite(ledPinG, LOW);  //
     digitalWrite(ledPinB, HIGH); //blink Blue LED
     digitalWrite(ledPinR, HIGH);  //blink Red LED
     delay(2000);
     digitalWrite(ledPinG, LOW);  /
     digitalWrite(ledPinB, LOW); //
     digitalWrite(ledPinR, HIGH);  //blink Red LED
     delay(2000);
     }
   
   val = digitalRead(switchPin);   // read input value and store it in val
   if (val == HIGH) {              // if the light sensor is covered by a hand
   digitalWrite(ledPinG, LOW);    // turn LED off
   digitalWrite(ledPinB, LOW);    // turn LED off
   digitalWrite(ledPinR, LOW);    // turn LED off
 }
}

mem

#5
Oct 03, 2008, 03:38 pm Last Edit: Oct 03, 2008, 03:39 pm by mem Reason: 1
This may give you some ideas of how to proceed. Its not tested so may need some work but I hope points you in the right direction. After you get it going, you can improve it by using an array to define your colors and looping through the array elements in for loop. This would let you replace those repeated checks for sensor state with a single check at the top of the loop.

Have fun!

Code: [Select]

int ledPinG=10; //Green LED
int ledPinB=11; //BLUE LED
int ledPinR=12; //RED LED
int switchPin=2;  //Light sensor
int val;// Switch connected to digital pin 2

void setup() {
 Serial.begin(9600);           // set up Serial library at 9600 bps
 pinMode(switchPin,INPUT);  // Light sensor as a switch
 pinMode(ledPinG,OUTPUT);  // sets the digital pin as input to read switch
 pinMode(ledPinB,OUTPUT);  // sets the digital pin as input to read switch
 pinMode(ledPinR,OUTPUT);  // sets the digital pin as input to read switch
}

void loop() {
 if( digitalRead(switchPin) == LOW)
   setColor(1,1,1,2000);        
 if( digitalRead(switchPin) == LOW)
   setColor(0,1,0,2000);  
 if( digitalRead(switchPin) == LOW)        
   // do your other colors ....


 if( digitalRead(switchPin) == HIGH)
    setColor(0,0,0,0);  // turn LEDs off
}


void setColor(int R, int G, int B, int delayMs){
 // set the LED colors and delay for the given number of milliseconds
 // but return if sensor is covered
 digitalWrite(ledPinG, R);
 digitalWrite(ledPinB, G);
 digitalWrite(ledPinR, B);
 while(delayMs--){
   // this loop checks the sensor every millisecond
   delay(1);
   if( digitalRead(switchPin) == HIGH)
     return; // exit the while loop if sensor is covered
 }  
}

eclipsemints

Thanks for your quick reply, mem!!
It works perfectly!!

I'll try to add more functions and develop this color timer.
Thanks a lot!!

eclipsemints

Hi, all

I added some codes to create "10 seconds color timer", below.
This timer changes its color every 2 seconds.
sec.
0~1: white
2~3: green
4~5: light blue
6~7: blue
8~9: purple
10:   red

Now, I want to add another function that
"when timer is over 10 seconds, it blinks quickly with red color till the light sensor is covered by a hand".
Is there any way to do that? Please, help me!!
Thanks!!

Code: [Select]

int ledPinG=10; //Green LED
int ledPinB=11; //BLUE LED
int ledPinR=12; //RED LED
int switchPin=2;  //Light sensor
int val;// Switch connected to digital pin 2

void setup() {
 Serial.begin(9600);           // set up Serial library at 9600 bps
 pinMode(switchPin,INPUT);  // Light sensor as a switch
 pinMode(ledPinG,OUTPUT);  // sets the digital pin as input to read switch
 pinMode(ledPinB,OUTPUT);  // sets the digital pin as input to read switch
 pinMode(ledPinR,OUTPUT);  // sets the digital pin as input to read switch
}

void loop() {
 if( digitalRead(switchPin) == LOW)
   setColor(1,1,1,2000);
 if( digitalRead(switchPin) == LOW)
   setColor(1,0,0,2000);    
 if( digitalRead(switchPin) == LOW)
   setColor(1,1,0,2000);  
 if( digitalRead(switchPin) == LOW)
   setColor(0,1,0,2000);
 if( digitalRead(switchPin) == LOW)
   setColor(0,1,1,2000);    
 if( digitalRead(switchPin) == LOW)
   setColor(0,0,1,2000);    
   // do your other colors ....
   
 if( digitalRead(switchPin) == HIGH)
    setColor(0,0,0,0);  // turn LEDs off
}

void setColor(int R, int G, int B, int delayMs){
 // set the LED colors and delay for the given number of milliseconds
 // but return if sensor is covered
 digitalWrite(ledPinG, R);
 digitalWrite(ledPinB, G);
 digitalWrite(ledPinR, B);
 while(delayMs--){
   // this loop checks the sensor every millisecond
   delay(1);
   if( digitalRead(switchPin) == HIGH)
     return; // exit the while loop if sensor is covered
 }
}

mem

#8
Oct 04, 2008, 06:14 am Last Edit: Oct 04, 2008, 06:18 am by mem Reason: 1
There are many ways you can do that. Why not add some code in loop to keep track of time and check if more then ten seconds have elapsed.

You can use the millis function to get the time (in milliseconds) since the sketch started and if you save the value in a variable each time the timer is restarted you can calculate the elapsed time  (elapsed time is the current time minus the start time).

Another way. Because the time for each color change is hard coded in your sketch, you would know its time to flash after the color goes to red (i.e. after ten seconds). For this to work you need to restart the color sequence from the first color when the sensor is covered.

eclipsemints

I checked about :Millis" function.
I'm a Newbie, so I did't understand how I can use it in my sketch :'(
Should I make "void redBlink..." or something??
Can I use "mills" directly into the loop?

Thank you for your help many times!!

mem


The reference page for millis is here: http://www.arduino.cc/en/Reference/Millis

And there are a few tutorials with examples of how to use it to determine elapsed time, here is one: http://www.arduino.cc/en/Tutorial/BlinkWithoutDelay

Try either of  both of those examples and when you see how it works you can think about adding to your sketch.

Have fun

eclipsemints

Thanks for your information!

I added a function of RED LED blink after RGB color changing.
Firstly, I tried Red LED blink code separately and it was working.
However when I added this sketch into the color timer sketch,
it doesn't work.... Could you help me to modify this sketch?

Code: [Select]

int ledPinG=10; //Green LED
int ledPinB=11; //BLUE LED
int ledPinR=12; //RED LED
int switchPin=2;  //Light sensor
int val;// Switch connected to digital pin 2
int value = LOW;                // previous value of the LED
long previousMillis = 0;        // will store last time LED was updated
long interval = 250;           // interval at which to blink (milliseconds)


void setup() {
 Serial.begin(9600);           // set up Serial library at 9600 bps
 pinMode(switchPin,INPUT);  // Light sensor as a switch
 pinMode(ledPinG,OUTPUT);  // sets the digital pin as input to read switch
 pinMode(ledPinB,OUTPUT);  // sets the digital pin as input to read switch
 pinMode(ledPinR,OUTPUT);  // sets the digital pin as input to read switch
}

void loop() { // G, B, R color change
 if( digitalRead(switchPin) == LOW) // light blue
   setColor(1,1,0,2000);
 if( digitalRead(switchPin) == LOW) // blue
   setColor(0,1,0,2000);    
 if( digitalRead(switchPin) == LOW) //green
   setColor(1,0,0,2000);  
 if( digitalRead(switchPin) == LOW) //yellow
   setColor(1,0,1,2000);
 if( digitalRead(switchPin) == LOW) //purple
   setColor(0,1,1,2000);    
 if( digitalRead(switchPin) == LOW) //red
   setColor(0,0,1,2000);    
 // add more colors--------------
 
 // Red LED blinks
  if ( (millis() - previousMillis > interval) ) {
        previousMillis = millis();                         // remember the last time - blinked the LED
        // if the LED is off turn it on and vice-versa.
        if (value == LOW)
           value = HIGH;
        else
           value = LOW;
        digitalWrite(ledPinR, value);
  }
 
  // turn LEDs off
  if( digitalRead(switchPin) == HIGH)
  setColor(0,0,0,0);

}

void setColor(int R, int G, int B, int delayMs){
 // set the LED colors and delay for the given number of milliseconds
 // but return if sensor is covered
 digitalWrite(ledPinG, R);
 digitalWrite(ledPinB, G);
 digitalWrite(ledPinR, B);
 while(delayMs--){
   // this loop checks the sensor every millisecond
   delay(1);
   if(digitalRead(switchPin) == HIGH)
     return; // exit the while loop if sensor is covered  
       }
}


mikalhart

Eclipse,

I believe your problem stems from this little snippet of code:

Code: [Select]
 if ( (millis() - previousMillis > interval) ) {
        previousMillis = millis();                         // remember the last time - blinked the LED
        // if the LED is off turn it on and vice-versa.
        if (value == LOW)
           value = HIGH;
        else
           value = LOW;
        digitalWrite(ledPinR, value);
  }
 
  // turn LEDs off
  if( digitalRead(switchPin) == HIGH)
  setColor(0,0,0,0);


In the first {} clause, you correctly flip the value of the red LED every 250ms.  However in the very next line, you turn ALL the LEDs off, per the comment.  If you turn an LED on and immediately turn it off, you won't be able to see it.

Mikal

eclipsemints

Thanks for your feedback, mikalhart.

I tried to use "millis" function, but I couldn't manage "RGB color changing" part with this "RED LED blinks" part in my sketch...
Sorry, I'm new to programming...  If it possible, could someone modify it?
Thanks so much!

Syvwlch

#14
Oct 05, 2008, 08:24 am Last Edit: Oct 05, 2008, 08:27 am by Syvwlch Reason: 1
Hi Eclipsemints,

When you tried the red blink code by itself, it was the only thing in the main loop of the sketch... that is, inside void loop(). Anything inside void loop() will repeat forever, so in that case, the red link blinked.

When you moved it into your original code, it no longer repeats, because only the entire void loop() repeats. So you flash the various leds, toggle the red led once, and then immediately, either turn everything off if switchpin is high, and restart the loop or go straight to restarting the loop and if switchpin is low, start with cyan (light blue) in which the red led is off.

What you need to do is put the red blink code into its own loop, for example a while loop, which will continue looping as long as (i.e. while) switchpin is low.

Here is the reference for the while loop, see if you can change your code to put the red blink inside one, with the stay-in-loop-while-this-is-true condition (switchpin == low).

Good luck!  ;)
----------
Mathieu

Go Up