I'm trying to control a series of LEDs using an IR remote. I have a problem when I try to play a sequence with the LEDs where they all light up in a line and turn off accordingly. I loop through the sequence and I am trying to make it so the instant I press a button on the remote it breaks out of that sequence. The issue lies in the Flash(); function, I think. What can I do?
#include <boarddefs.h>
#include <IRremote.h>
#include <IRremoteInt.h>
#include <ir_Lego_PF_BitStreamEncoder.h>
int recvPin = 11;
IRrecv irrecv(recvPin);
decode_results results;
#define BUTTON_ON 0xF076C13B // codes for different buttons on the remote
#define BUTTON_OFF 0xFF9186B7
#define BUTTON_R 0xE5CFBD7F
#define BUTTON_G 0x8C22657B
#define BUTTON_B 0x2A89195F
#define BUTTON_FLASH 0x35A9425F
int rLED = 5;
int gLED = 4;
int bLED = 3;
int stR = LOW; // intital state of red LED
int stG = LOW; // intital state of green LED
int stB = LOW; // initial state of blue LED
int flash = false;
void setup() {
Serial.begin(9600); // Status message will be sent to PC at 9600 baud
pinMode(rLED, OUTPUT);
pinMode(gLED, OUTPUT);
pinMode(bLED, OUTPUT);
irrecv.enableIRIn();
}
void Flash() { // flashing function
while (flash == false) {
digitalWrite(rLED, LOW);
digitalWrite(gLED, LOW);
digitalWrite(bLED, LOW);
digitalWrite(rLED, HIGH);
delay(75);
digitalWrite(gLED, HIGH);
delay(75);
digitalWrite(bLED, HIGH);
delay(75);
digitalWrite(rLED, LOW);
delay(75);
digitalWrite(gLED, LOW);
delay(75);
digitalWrite(bLED, LOW);
delay(75);
stR = LOW;
stG = LOW;
stB = LOW;
if (results.value == BUTTON_OFF) // attempting to make it so when i press the OFF button on the remote,
{ // the loop breaks/stops and I can go back to pressing any button on
break; // the remote
}
}
}
void loop() {
if (irrecv.decode(&results))
{
if (results.value == BUTTON_ON)
{
digitalWrite(rLED, HIGH);
digitalWrite(gLED, HIGH);
digitalWrite(bLED, HIGH);
stR = HIGH;
stG = HIGH;
stB = HIGH;
}
if (results.value == BUTTON_OFF)
{
digitalWrite(rLED, LOW);
digitalWrite(gLED, LOW);
digitalWrite(bLED, LOW);
stR = LOW;
stG = LOW;
stB = LOW;
}
if (results.value == BUTTON_R)
{
digitalWrite(rLED, !stR);
stR = !stR;
}
if (results.value == BUTTON_G)
{
digitalWrite(gLED, !stG);
stG = !stG;
}
if (results.value == BUTTON_B)
{
digitalWrite(bLED, !stB);
stB = !stB;
}
if (results.value == BUTTON_FLASH)
{
Flash(); // calling flash func
}
irrecv.resume();
}
}
1 Answer 1
Replace delay with millis in Flash()
.
You do this by making every delay it's own state and give each state a number. Then inside flash
you check which state you are in to set the LEDs and how long you have been in it to trigger the next state.
boolean flashing = false;
int flashingState = -1;
long nextFlashingState = 0;
void Flash() { // flashing function
if(!flashing ){
flashingState =-1;
return;
}
long ms = millis();
switch(flashingState ){
case -1:
flashingState =0;
nextflashingState = ms+75; //init "timer"
//fallthrough
case 0:
digitalWrite(rLED, LOW);
digitalWrite(gLED, LOW);
digitalWrite(bLED, LOW);
digitalWrite(rLED, HIGH);
if(nextflashingState < ms){
flashingState =1;
nextflashingState +=75;
}
break;
case 1:
digitalWrite(gLED, HIGH);
if(nextflashingState < ms){
flashingState = 2;
nextflashingState +=75;
}
break;
case 2:
digitalWrite(bLED, HIGH);
if(nextflashingState < ms){
flashingState = 3;
nextflashingState +=75;
}
break;
case 3:
digitalWrite(rLED, LOW);
if(nextflashingState < ms){
flashingState = 4;
nextflashingState +=75;
}
break;
case 4:
digitalWrite(gLED, LOW);
if(nextflashingState < ms){
flashingState = 5;
nextflashingState +=75;
}
break;
case 5:
digitalWrite(bLED, LOW);
if(nextflashingState < ms){
flashingState = 0;
nextflashingState +=75;
}
break;
}
}
I used state -1
as the init state to start the timer, the case block will fall through to the next case. The millis()
function returns the number of milliseconds since the arduino booted up (it overflows every ~1.5 months). So when I start a timer I set the the nextFlashingState
to the time when it should start the next state.
Then in loop you call it every time.
void loop() {
if (irrecv.decode(&results))
{
if (results.value == BUTTON_ON)
{
digitalWrite(rLED, HIGH);
digitalWrite(gLED, HIGH);
digitalWrite(bLED, HIGH);
stR = HIGH;
stG = HIGH;
stB = HIGH;
}
if (results.value == BUTTON_OFF)
{
flashing =false;
digitalWrite(rLED, LOW);
digitalWrite(gLED, LOW);
digitalWrite(bLED, LOW);
stR = LOW;
stG = LOW;
stB = LOW;
}
if (results.value == BUTTON_R)
{
digitalWrite(rLED, !stR);
stR = !stR;
}
if (results.value == BUTTON_G)
{
digitalWrite(gLED, !stG);
stG = !stG;
}
if (results.value == BUTTON_B)
{
digitalWrite(bLED, !stB);
stB = !stB;
}
if (results.value == BUTTON_FLASH)
{
flashing =true;
}
irrecv.resume();
}
Flash();
}
-
1Thanks for the answer! I don't really understand your code, however, I uploaded it and it doesn't seem to do what I wanted it to do. When I press the flash button on the remote, it still flashes endlessly, but now when I press something on the remote the lights do kinda respond to it but keep flashing endlessly.EdD– EdD2017年09月05日 14:50:19 +00:00Commented Sep 5, 2017 at 14:50
-
1it will stop flashing when you press off. If you add
flashing =false;
to the other if blocks then flashing will stop when that button is pressedratchet freak– ratchet freak2017年09月05日 14:52:20 +00:00Commented Sep 5, 2017 at 14:52 -
1Alright, thanks, it works! I wonder how I will make it work with more complicated sequences but for now I do wanna understand what you did there in the
void Flash()
function and anything else you added cause I am a beginner and if you could possibly refer me to some website where I can learn more about this I would greatly appreciate it :)EdD– EdD2017年09月05日 16:19:45 +00:00Commented Sep 5, 2017 at 16:19 -
1@EdD I edited my answer to explain a bit how you would go about replacing delay with millisratchet freak– ratchet freak2017年09月05日 17:20:43 +00:00Commented Sep 5, 2017 at 17:20