/* * IRlicht -- a 4-channel (RGBW) controller for LED-lamps, based on Arduino and * controlled via infrared by a universal remote. * * Copyright 2014 Ronald Schaten * * This program is free software: you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the Free * Software Foundation, either version 3 of the License, or (at your option) * any later version. * * This program is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for * more details. * * You should have received a copy of the GNU General Public License along with * this program. If not, see . */ #include // pins on which the LEDs are connected #define LED_WHITE 5 #define LED_GREEN 6 #define LED_BLUE 10 #define LED_RED 9 // use examples included in IRremote-library to find the correct values for // your remote. #define IR_PIN 2 #define IR_PROTOCOL 1 #define IR_FILTER 0xF70000 #define IR_MASK 0xFF0000 #define IR_KEY_1 0xF720DF #define IR_KEY_2 0xF710EF #define IR_KEY_3 0xF730CF #define IR_KEY_4 0xF70000 // key is broken on my remote :-( #define IR_KEY_5 0xF728D7 #define IR_KEY_6 0xF7A05F #define IR_KEY_7 0xF7906F #define IR_KEY_8 0xF7B04F #define IR_KEY_9 0xF78877 #define IR_KEY_FLASH 0xF7D02F #define IR_KEY_STROBE 0xF7F00F #define IR_KEY_FADE 0xF7C837 #define IR_KEY_SMOOTH 0xF7E817 #define IR_KEY_DIM 0xF7807F #define IR_KEY_BRIGHT 0xF700FF #define IR_KEY_ALLON 0xF7C03F #define IR_KEY_ALLOFF 0xF740BF #define IR_KEY_LIGHT10 0xF7A857 #define IR_KEY_LIGHT11 0xF7609F #define IR_KEY_LIGHT12 0xF750AF #define IR_KEY_LIGHT13 0xF7708F #define IR_KEY_LIGHT14 0xF748B7 #define IR_KEY_LIGHT15 0xF76897 #define IR_KEY_LIGHT16 0xF7E01F // main modes of operation #define MODE_OFF 0x00 #define MODE_CONSTANT 0x01 #define MODE_FLASH 0x02 #define MODE_STROBE 0x03 #define MODE_FADE 0x04 #define MODE_SMOOTH 0x05 // initial brightness levels int levelRed = 0x00; // colors are off int levelGreen = 0x00; int levelBlue = 0x00; int levelWhite = 0x10; // white is on a dark level int levelTotal = 0x80; // overall, everything is dimmed to half int mode = MODE_CONSTANT; // initial mode int modestep = 0; int modeincrement = 1; int animationspeed = 5; long steplength = 0; IRrecv irrecv(IR_PIN); decode_results results; // setRGBW sets all outputs void setRGBW(int red, int green, int blue, int white) { // dim all channels according to levelTotal red = map(red, 0x00, 0xff, 0x00, levelTotal); green = map(green, 0x00, 0xff, 0x00, levelTotal); blue = map(blue, 0x00, 0xff, 0x00, levelTotal); white = map(white, 0x00, 0xff, 0x00, levelTotal); if (mode != MODE_STROBE) { // keep output at least at 0x01 if channel is not turned off // unless we're in strobe mode, which means that lights should turn off completely if (levelRed > 0) { red = constrain(red, 0x01, 0xff); } if (levelGreen > 0) { green = constrain(green, 0x01, 0xff); } if (levelBlue > 0) { blue = constrain(blue, 0x01, 0xff); } if (levelWhite > 0) { white = constrain(white, 0x01, 0xff); } } // set output analogWrite(LED_RED, red); analogWrite(LED_GREEN, green); analogWrite(LED_BLUE, blue); analogWrite(LED_WHITE, white); } void setup() { Serial.begin(9600); pinMode(LED_RED, OUTPUT); pinMode(LED_GREEN, OUTPUT); pinMode(LED_BLUE, OUTPUT); pinMode(LED_WHITE, OUTPUT); setRGBW(levelRed, levelGreen, levelBlue, levelWhite); irrecv.enableIRIn(); // Start the receiver } void loop() { if (irrecv.decode(&results)) { // we received a new keypress from IR if (results.decode_type == IR_PROTOCOL) { if (results.value != 0xFFFFFFFF) { // only react to presses //if (results.value & IR_MASK == IR_FILTER) { Serial.println(results.value); switch (results.value) { case IR_KEY_1: mode = MODE_CONSTANT; levelRed += 51; if (levelRed > 0xff) { levelRed = 0x00; } break; case IR_KEY_2: mode = MODE_CONSTANT; levelGreen += 51; if (levelGreen > 0xff) { levelGreen = 0x00; } break; case IR_KEY_3: mode = MODE_CONSTANT; levelBlue += 51; if (levelBlue > 0xff) { levelBlue = 0x00; } break; case IR_KEY_4: mode = MODE_CONSTANT; levelRed = levelBlue = levelGreen = levelWhite = 0xff; break; case IR_KEY_5: mode = MODE_CONSTANT; levelWhite += 51; if (levelWhite > 0xff) { levelWhite = 0x00; } break; case IR_KEY_6: mode = MODE_CONSTANT; levelRed = levelBlue = levelGreen = levelWhite = 0x00; break; case IR_KEY_7: mode = MODE_CONSTANT; if (levelRed == levelGreen && levelBlue == 0) { // we have the right color tone, just set brightness levelRed += 51; if (levelRed > 0xff) { levelRed = 0x00; }; levelGreen += 51; if (levelGreen > 0xff) { levelGreen = 0x00; }; } else { // select color tone levelRed = levelGreen = 51; levelBlue = 0; } break; case IR_KEY_8: mode = MODE_CONSTANT; if (levelGreen == levelBlue && levelRed == 0) { // we have the right color tone, just set brightness levelGreen += 51; if (levelGreen > 0xff) { levelGreen = 0x00; }; levelBlue += 51; if (levelBlue > 0xff) { levelBlue = 0x00; }; } else { // select color tone levelGreen = levelBlue = 51; levelRed = 0; } break; case IR_KEY_9: mode = MODE_CONSTANT; if (levelBlue == levelRed && levelGreen == 0) { // we have the right color tone, just set brightness levelBlue += 51; if (levelBlue > 0xff) { levelBlue = 0x00; }; levelRed += 51; if (levelRed > 0xff) { levelRed = 0x00; }; } else { // select color tone levelBlue = levelRed = 51; levelGreen = 0; } break; case IR_KEY_FLASH: mode == MODE_FLASH ? mode = MODE_CONSTANT : mode = MODE_FLASH; steplength = 0; break; case IR_KEY_STROBE: mode == MODE_STROBE ? mode = MODE_CONSTANT : mode = MODE_STROBE; steplength = 0; break; case IR_KEY_FADE: mode == MODE_FADE ? mode = MODE_CONSTANT : mode = MODE_FADE; steplength = 0; break; case IR_KEY_SMOOTH: mode == MODE_SMOOTH ? mode = MODE_CONSTANT : mode = MODE_SMOOTH; steplength = 0; modeincrement = 1; break; case IR_KEY_DIM: levelTotal = constrain(levelTotal-0x10, 0x01, 0xff); break; case IR_KEY_BRIGHT: levelTotal = constrain(levelTotal+0x10, 0x01, 0xff); break; case IR_KEY_ALLON: animationspeed = constrain(animationspeed+1, 1, 15); break; case IR_KEY_ALLOFF: animationspeed = constrain(animationspeed-1, 1, 15); break; default: Serial.print("proto: "); Serial.print(results.decode_type, DEC); Serial.print(" code: "); Serial.println(results.value, HEX); break; } if (mode == MODE_CONSTANT) { setRGBW(levelRed, levelGreen, levelBlue, levelWhite); } } } irrecv.resume(); // Receive the next value } switch (mode) { case MODE_CONSTANT: // do nothing, it's constant after all... break; case MODE_STROBE: // flash all active channels modestep = constrain(modestep, 0, 1); steplength--; if (steplength <= 0) { if (modestep == 1) { modestep = 0; setRGBW(levelRed, levelGreen, levelBlue, levelWhite); } else { modestep = 1; setRGBW(0x00, 0x00, 0x00, 0x00); } steplength = animationspeed * 10000L; } break; case MODE_FLASH: // flash between all colors modestep = constrain(modestep, 0, 5); steplength--; if (steplength <= 0) { switch (modestep) { case 0: levelRed = 0xff; levelGreen = 0x00; levelBlue = 0x00; modestep = 1; break; case 1: levelRed = 0xff; levelGreen = 0xff; levelBlue = 0x00; modestep = 2; break; case 2: levelRed = 0x00; levelGreen = 0xff; levelBlue = 0x00; modestep = 3; break; case 3: levelRed = 0x00; levelGreen = 0xff; levelBlue = 0xff; modestep = 4; break; case 4: levelRed = 0x00; levelGreen = 0x00; levelBlue = 0xff; modestep = 5; break; case 5: levelRed = 0xff; levelGreen = 0x00; levelBlue = 0xff; modestep = 0; break; } setRGBW(levelRed, levelGreen, levelBlue, levelWhite); steplength = animationspeed * 10000L; } break; case MODE_FADE: // fade between all colors modestep = constrain(modestep, 0x00, 6 * 0xff); steplength--; if (steplength <= 0) { if (modestep < 1 * 0xff) { // red on, increment green levelRed = 0xff; levelGreen = modestep % 0xff; levelBlue = 0x00; } else if (modestep < 2 * 0xff) { // green on, decrement red levelRed = 0xff - modestep % 0xff; levelGreen = 0xff; levelBlue = 0x00; } else if (modestep < 3 * 0xff) { // green on, increment blue levelRed = 0x00; levelGreen = 0xff; levelBlue = modestep % 0xff; } else if (modestep < 4 * 0xff) { // blue on, decrement green levelRed = 0x00; levelGreen = 0xff - modestep % 0xff; levelBlue = 0xff; } else if (modestep < 5 * 0xff) { // blue on, increment red levelRed = modestep % 0xff; levelGreen = 0x00; levelBlue = 0xff; } else { // red on, decrement blue levelRed = 0xff; levelGreen = 0x00; levelBlue = 0xff - modestep % 0xff; } setRGBW(levelRed, levelGreen, levelBlue, levelWhite); steplength = animationspeed * 10000L / 0xff; modestep++; if (modestep >= 6 * 0xff) { modestep = 0; } } break; case MODE_SMOOTH: // smooth fading of all active channels modestep = constrain(modestep, 0x00, 0xff); steplength--; if (steplength <= 0) { int red = map(levelRed, 0x00, 0xff, 0x00, modestep); int green = map(levelGreen, 0x00, 0xff, 0x00, modestep); int blue = map(levelBlue, 0x00, 0xff, 0x00, modestep); int white = map(levelWhite, 0x00, 0xff, 0x00, modestep); setRGBW(red, green, blue, white); steplength = animationspeed * 10000L / 0xff; modestep += modeincrement; if (modestep <= 0x00 || modestep >= 0xff) { modeincrement = -modeincrement; } } break; } } // vim:filetype=c:ts=2