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!!
#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
}
}
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.
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.
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.
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
}
}
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!
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
}
}
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!!
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
}
}
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.
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?
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?
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
}
}
I believe your problem stems from this little snippet of code:
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.
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!
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).
It may help you to see what is happening if you familiarize yourself with millis by playing around with a simpler sketch.
Perhaps try a sketch that just turns on an LED after a few seconds using millis.
Then try adding code some millis code to turn the led off a few seconds after its turned on.
Although using delay would be a more natural choice in this exercise, doing this using millis should give you insight as to how to apply it in your timer application.
Thanks so much everyone!! and
thanks, mem for your "millis" information again!!
I used "while" function into the loop in the last part, like below.
while ( digitalRead(switchPin) == LOW){
digitalWrite(ledPinR,HIGH);
delay(250);
digitalWrite(ledPinR,LOW);
delay(250);
if( digitalRead(switchPin) == HIGH)
setColor(0,0,0,0); // turn LEDs off
}
if( digitalRead(switchPin) == HIGH)
setColor(0,0,0,0); // turn LEDs off
It probably looks a strange sketch for you guys (professionals),
but the timer is somehow working well that what I want to do.
Mills function is still diffucult for me at this stage
But I will keep learn more about the program!!
Thanks again You guys helped me a lot!!
(But I will ask another question sometime in new topic. c u then!)
Using delay instead of millis is cheating
It's a good thing programming is one of the few places where cheating is not only acceptable, its often highly desirable.
Delay works because you don't need to do anything during the delay period. But if you enhance your application and do need to do something like flash LEDs within the delay period then you may want to reconsider using millis.
Think of that millis code as if it was like telling time using a clock. You look at the clock (call millis) to get the current time and save it in a variable. You can then always tell how much time has elapsed by looking at the clock again (calling millis) and taking the difference between the current time and the time you saved. You will know the desired time has elapsed when the difference between the current time and the start time is at least as big as your desired elapsed time.
Mem's commentary is right on, eclipse. As soon as you decide you want to make just the tiniest extension to your program's function, you're going to facing some complicated surgery.
Any but the most trivial of my Arduino programs usually end up looking something like this:
static unsigned long old_millis = 0;
... // other state variables
void loop()
{
unsigned long new_millis() = millis();
Based on new_millis, old_millis, input pins and the state variables
{
do some stuff and modify the state variables
}
old_millis = new_millis;
}
And as Mathieu said, keep at it! This can be really fun.