I am trying to make a wirelessly controlled led lamp that is controlled by an IR remote. I have a while loop that continues fading through colors until a button is pressed. To check if a button has been pressed, I have an if statement after the fade to each color. The problem I'm having is that even if the condition for the if statement is false, it doesn't fade to the next color and completely stops and waits for the next button press. If anyone could point out what I'm doing wrong, I would really appreciate it!
checkIR() is being blocked by delays and time spent in while loops. You need to develop a non-blocking alternative to your program that will allow you to make changes based on the real time signals sent to the arduino affecting the program real-time.
look at this example of a non-blocking routine that cross-fades leds as sort-of a guide to construct your code:
just attach three leds and send it an 'a' or a 'b' via serial.
//RGB pins
#define GREEN 9
#define BLUE 10
#define RED 11
struct Colors{
int pin;
char* text;
};
Colors colors[3] = {
{ 9, "Green"},
{10, "Blue"},
{11, "Red"}
};
enum FadeState {
TO_RED = 0,
TO_GREEN,
TO_BLUE
};
FadeState fadeState = TO_RED;
byte flag = false;
String voice;
void setup()
{
delay(1000);
Serial.begin(9600);
pinMode(GREEN, OUTPUT);
pinMode(BLUE, OUTPUT);
pinMode(RED, OUTPUT);
digitalWrite(GREEN, HIGH);
digitalWrite(BLUE, HIGH);
digitalWrite(RED, HIGH);
}
void loop()
{
if (flag)
{
rgb();
}
if (Serial.available())
{
char myChar = Serial.read();
switch (myChar)
{
case 'a':
flag = true;
break;
case 'b':
flag = false;
break;
default:
break;
}
}
}
void rgb()
{
if (fadeState == TO_RED)
{
if (crossFade(BLUE, RED))
{
fadeState = TO_GREEN;
}
}
else if (fadeState == TO_GREEN)
{
if (crossFade(RED, GREEN))
{
fadeState = TO_BLUE;
}
}
else if (fadeState == TO_BLUE)
{
if (crossFade(GREEN, BLUE))
{
fadeState = TO_RED;
}
}
}
bool crossFade(int fromColor, int toColor)
{
static byte lastColor = 0;
static byte fadeValue = 0;
static unsigned long lastMillis = 0;
if(toColor != lastColor)
{
fadeValue = 0;
lastColor = toColor;
for(int i = 0; i < 3; i++)
{
if (colors[i].pin == toColor) Serial.println(colors[i].text);
}
}
if(millis() - lastMillis > 19) //<<<<< less than one second cross-fade @ PWM increments of 5
{
analogWrite(fromColor, 255 - fadeValue);
analogWrite(toColor, fadeValue);
fadeValue += 5;
lastMillis = millis();
}
return fadeValue >= 255;
}
Thank you both for your responses, I really appreciate the help.
In response to BulldogLowell:
I'm not too familiar with programming the Arduino, so I'm not very familiar with millis(), struct, and enum, but I quickly looked them up on the Arduino reference and think I kinda understand them now. But because of this, I'm having some trouble understanding exactly how this example is non-blocking and how I would implement it in my code. What exactly does returning fadeValue do? And how are you keeping the leds from immediately jumping to the new color, and having it fade to them instead?
In response to Robin2:
I love how readable that program is and I'm definitely going to use that style from now on because it just looks so good. In your example, I'm still not quite understanding how the program does multiple things at the same time. For example, if it is one of your functions (lets say the servo function) and you press the button to change the led on pin 7, does it stop changing the servo to immediately change the led, then continue the servo function again? Or does it have to finish the servo function, then change the led?
In Robin's code it does have to finish the function. But look at how the functions are written. It doesn't wait to move a servo all the way to a point, it just takes one step and exits. That happen really really really fast. Then the function gets called again to take another step. The point of that example is that no function waits to complete any process, just check if it is time to take a small step and take it and get on to letting other things happen.
Delta_G:
The point of that example is that no function waits to complete any process, just check if it is time to take a small step and take it and get on to letting other things happen.