Wall mounted 'mood light'
-
(there is a sketch for MySensors v2 available)
I received my 110v-230v AC to Mysensors PCB board last week en spent a few hours this weekend making 2 wall mounted mood lights.
I looks a little cheap from the backside but very luxurious on the wall ( < €20 total) and fully "MySensored".
I did not use the relais on the board (and discarded some of the safety measures ). Very basic: a cut WS2812b strip, a few wires.
Case is 12 mm MDF Board painted with Chalk paint (no primer needed, ready in half an hour ;-))Basic sketch with FastLED library (or Adafruit) with V_RBG.
-
Love your project and good use of the wall mount PCB. You showed me that I really need to order a couple of those I'm tired of all the phone charger cables
I couldn't really see it well on the photo's. But did you paint the back of light as well, the MDF part I mean? If not I would do it, because MDF has the tendency to bend when painted on one side only. That's why I use plywood or solid wood for almost all of my projects. Learned it the hard way, I made a cover for my radiator once out of MDF and painted only the outside. In just a day or two the cover started to bend. Which was really not funny after spending two weekends making it.
If you decide to paint the back side as well I'd use a white paint, that reflects the light coming from the ledstrip better. Other colors tend to absorp the light more.
I'm also really curious about how you mounted the MDF to the wall. It looks really great.
-
Could you please post your Arduino sketch, as I want to build something similar?
Thank you.
-
@TheoL Thank you for the tips. I painted the board on all sides. I would prefer real wood but MDF is really easy to model and I had a few sq meter left. I hate the dust though. For mounting i used a hook which fits in hole.
-
@gloob I will post the sketch after cleaning it up. I need to add on/off/ scene button functionality.
I allways try to make my nodes as autonomous as possible. That way i'm not fully controller dependent and it's more safe.
-
@AWI said:
...and discarded some of the safety measures ...
I see you've got something soldered where the fuse should be, but for the rest I can't see what you've left out. Could you tell us which components you eventually ended up using? (or not using, whatever you prefer :))
-
@mvdarend I have not used the SSR, the varistors and the fuse on the low voltage side...
-
I have updated the sketch to allow for independent operation and added a few light effects. The sketch can be used for any "Neopixel" (WS2812(B)) LED strip/ stick/ circle. Uses V_RBG and/ or V_STATUS and separate actuators (or the push button with long push) to switch the Pattern and Alarm. A few examples:
"Alarm"
Wall Light fireplace – 00:06
— Ad Imhoff"Fireplace"
Wall Light Alarm – 00:04
— Ad Imhoff"Candle light" and "Rainbow" mostly non blocking code. If somebody want to add please do so.
The sketch, heavily commented. Can always be improved
/* PROJECT: MySensors / RGB light NEOPIXEL PROGRAMMER: AWI DATE: october 10, 2015/ last update: october 14, 2015 FILE: AWI_RGB.ino LICENSE: Public domain Hardware: Nano and MySensors 1.5, Wall light 16 WS2812B leds (neopixel) Special: uses Fastled library with NeoPixel (great & fast RBG/HSV universal library) https://github.com/FastLED/FastLED SUMMARY: Different patterns and brightness settings Button switches on/off and cycles through all Color patterns on long press Remarks: Fixed node-id */ #include <MySensor.h> #include <SPI.h> #include <FastLED.h> // https://github.com/FastLED/FastLED #include <Button.h> // https://github.com/JChristensen/Button const int stripPin = 5 ; // pin where 2812 LED strip is connected const int buttonPin = 4 ; // push button const int numPixel = 16 ; // set to number of pixels (x top / y bottom) const int NODE_ID = 62 ; // fixed MySensors node id const int RGB_LightChild = 0 ; // Child Id's, standard light child on/off/ dim const int RGB_RGBChild = 1 ; // RGB light child (on/off/dim/color, if controller supports V_RBG)) const int RGB_SolidColorChild = 2 ; // when set, node reads Color text from ColorTextChild const int RGB_TextColorChild = 3 ; // Holds Text value for color (custom colors from controller) const int RGB_AlarmPatternChild = 4 ; // Switches to alarm status const int RGB_NextPatternChild = 5 ; // Move to next pattern when set CRGB leds[numPixel]; // Kelving colors: Light & daylight (in Fastled reference only) /// 1900 Kelvin Candle=0xFF9329 /* 1900 K, 255, 147, 41 */, /// 2600 Kelvin Tungsten40W=0xFFC58F /* 2600 K, 255, 197, 143 */, /// 2850 Kelvin Tungsten100W=0xFFD6AA /* 2850 K, 255, 214, 170 */, /// 3200 Kelvin Halogen=0xFFF1E0 /* 3200 K, 255, 241, 224 */, /// 5200 Kelvin CarbonArc=0xFFFAF4 /* 5200 K, 255, 250, 244 */, /// 5400 Kelvin HighNoonSun=0xFFFFFB /* 5400 K, 255, 255, 251 */, /// 6000 Kelvin DirectSunlight=0xFFFFFF /* 6000 K, 255, 255, 255 */, /// 7000 Kelvin OvercastSky=0xC9E2FF /* 7000 K, 201, 226, 255 */, /// 20000 Kelvin ClearBlueSky=0x409CFF /* 20000 K, 64, 156, 255 */ char controllerRGBvalue[] = "FFDEAD"; // Controller sent RGB value, default uint16_t curBrightness, actualBrightness, controllerRGBbrightness = 0x7F ; // Brightness globals unsigned long updateBrightnessDelay, lastBrightnessUpdate ; // Brightness timers int RGBonoff ; // OnOff flag enum { pSolid, pOff, pAlarm, pFire, pFire2, pCandle, pRainbow} ; // Pattern globals (stored in int for convenience) const int lastPatternIdx = pRainbow + 1 ; // use last pattern for patterncount int curPattern ; // current pattern unsigned long updatePatternDelay, lastPatternUpdate ; // Pattern timers unsigned long idleTimer = millis() ; // return to idle timer int idleTime = 10000 ; // return to idle after 10 secs // initialize MySensors (MySensors 1.5 style) MyTransportNRF24 transport(9, 10); // Ceech board, 3.3v (7,8) (pin default 9,10) MySensor gw(transport); MyMessage lightRGBMsg(RGB_LightChild, V_RGB); // standard messages, light MyMessage lightdimmerMsG(RGB_LightChild ,V_DIMMER); MyMessage lightOnOffMessage(RGB_LightChild, V_STATUS); Button myBtn(buttonPin, true, true, 20); //Declare the button (pin, pull_up, invert, debounce_ms) // Simple state machine for button state enum {sIdle, sBrightness, sPattern} ; // simple state machine for button press int State ; void setup() { FastLED.addLeds<NEOPIXEL, stripPin >(leds, numPixel) ; // initialize led strip .setCorrection(TypicalLEDStrip); gw.begin(incomingMessage, NODE_ID, false); // initialize MySensors gw.sendSketchInfo("AWI RGB Wall 0", "1.0"); gw.present(RGB_RGBChild, S_RGB_LIGHT, "RGB Wall RGB 0");// present to controller gw.present(RGB_LightChild, S_LIGHT, "RGB Wall Light 0"); gw.present(RGB_SolidColorChild, S_LIGHT, "RGB Set Solid color (text) 0"); gw.present(RGB_TextColorChild, S_INFO, "RGB Wall textcolor 0"); gw.present(RGB_AlarmPatternChild, S_BINARY, "RGB Wall Alarm 0"); gw.present(RGB_NextPatternChild, S_BINARY, "RGB Wall Pattern 0"); // initialize strip with color and show (strip expects long, so convert from String) for(int i = 0 ; i < 6 ; i++) { // get color value from EEPROM (6 char) controllerRGBvalue[i] = gw.loadState(i) ; } setLightPattern(pSolid, NULL) ; // default controller Solid FastLED.show(); State = sIdle ; // Initial state //randomSeed(analogRead(0)); } // read button and act accordingly // short press: on/off // longer press: set patterns with following short press // long press: set brightness increase void loop() { gw.process(); // wait for incoming messages myBtn.read(); //Read the button (only read) unsigned long now = millis(); // loop timer reference switch (State) { case sIdle: // default state, browse through patterns if (myBtn.wasReleased()){ // light on/ off in idle RGBonoff = !RGBonoff ; // invert light state setLightPattern((RGBonoff == 1)?pOff:pSolid, 100); gw.send(lightOnOffMessage.set(RGBonoff)); // and update controller } else if (myBtn.pressedFor(500)){ // move to Pattern update state with long press idleTimer = now ; // return to idle after ... State = sPattern ; } break ; case sPattern: // entered after long press if (myBtn.pressedFor(2000)){ // when press even longer move to Brightness update State = sBrightness ; } else if (myBtn.wasPressed()){ setLightPattern((curPattern + 1) % lastPatternIdx, 500 ); // increase pattern and wrap idleTimer = now ; } else if ( now > idleTime + idleTimer ){ // return to idle after ... State = sIdle ; } break ; case sBrightness: // entered after looong press if (myBtn.wasPressed()){ // if pressed again increase brightness setLightBrightness((curBrightness+1) % 0xFF, 0) ; // increase brightness and wrap (0..0xFF) idleTimer = now ; } else if ( now > idleTime + idleTimer ){ // return to idle after ... State = sIdle ; } break ; default : State = sIdle ; break ; } updateLightBrightness(); // update Brightness if time updateLightPattern(); // update Pattern if time } // Sets the light brightness, takes value and time (ms) as input void setLightBrightness(int newBrightness, unsigned long updateTime){ // global: curBrightness, actualBrightness, updateBrightnessDelay updateBrightnessDelay = updateTime / 0xFF ; // delay = time / max steps actualBrightness = curBrightness ; // assume curBrightness is actual curBrightness = newBrightness ; // set curBrightness to new value, rest is done in update } // Update the light brightness if time void updateLightBrightness(){ // global: curBrightness, actualBrightness, updateBrightnessDelay, lastBrightnessUpdate ; unsigned long now = millis() ; if (now > lastBrightnessUpdate + updateBrightnessDelay){// check if time for update if ( actualBrightness > curBrightness) { FastLED.setBrightness( actualBrightness-- ); FastLED.show(); } else if ( actualBrightness < curBrightness){ FastLED.setBrightness( actualBrightness++ ); FastLED.show(); } lastBrightnessUpdate = now ; } } // **** Pattern routines ***** // Sets and initializes the light pattern if nescessary void setLightPattern( int newPattern, unsigned long updateDelay){ // global: curPattern, updatePatternDelay curPattern = newPattern ; updatePatternDelay = updateDelay ; // delay for next pattern update, can be changed in pattern switch(curPattern){ case pSolid: // solid is controller value in all pixels for(int i = 0 ; i < numPixel ; i++) leds[i] = strtol( controllerRGBvalue, NULL, 16); FastLED.show(); break ; case pOff: // off state all pixels off for(int i = 0 ; i < numPixel ; i++) leds[i] = 0 ; FastLED.show(); break ; default : break ; } } // Update the light pattern when time for it void updateLightPattern(){ // global: curPattern, updatePatternDelay, lastPatternUpdate unsigned long now = millis() ; if (now > lastPatternUpdate + updatePatternDelay){ // check if time for update switch (curPattern) { case pAlarm: // flash light patternAlarm(); break ; case pFire: // wild fire patternFire(); break ; case pFire2: // cosy fire patternFire2(); break ; case pCandle: // flame patternCandle(); break ; case pRainbow: // rotating rainbow patternRainbow(); break ; case pSolid: // do nothing fall through case pOff: default : // def break ; } lastPatternUpdate = now ; } } // Define the different patterns // Alarm - intermittent white and red color, full intensity, intermittent top & bottom half void patternAlarm() { static boolean topBot ; // indicates direction for next entry const CRGB colorTop = CRGB(0xFF, 0, 0 ); // red color const CRGB colorBottom = CRGB(0xFF, 0xFF, 0xFF ); // white color FastLED.setBrightness(0xFF); // set the strip brightness for(int i=0; i <= (numPixel / 2 - 1) ; i++) { // for half of strip size leds[i] = topBot?colorTop:colorBottom ; leds[i+ (numPixel/2)] = topBot?colorBottom:colorTop ; } topBot = !topBot ; // switch direction FastLED.show(); } // Simulate fire with red color, varying number of leds intensity & tempo void patternFire() { byte numberLeds = random(0,numPixel); // start number and end of led's for flickering byte lum = random(100,255); // set brightness CRGB color = CRGB(200, 50+random(1,180),0 ); // get red color with varying green for(int i=0; i <= numberLeds; i++) { leds[i] = color ; FastLED.setBrightness(lum); // set the strip brightness FastLED.show(); gw.wait(random(0,10)); } updatePatternDelay = 100 ; } // Simulate fire with red color and varying intensity & tempo void patternFire2() { CRGB color = CRGB(200, random(100,150),0); // get red color with varying green for (byte p=0; p < numPixel; p++) { leds[p] = color; } FastLED.setBrightness(random(50,255)); FastLED.show(); updatePatternDelay = random(20,300); // variable delay } // Simulate candle based on fire with red color, varying number of leds intensity & tempo void patternCandle() { byte numberLeds = random(0,numPixel); // start number and end of led's for flickering byte lum = random(60, 80); // set brightness CRGB color = CRGB(200, 50+random(40,100),0 ); // get red color with varying green for(int i=0; i <= numberLeds; i++) { leds[i] = color ; FastLED.setBrightness(lum); // set the strip brightness FastLED.show(); gw.wait(random(5,10)); } updatePatternDelay = 100 ; } void patternRainbow() { static uint16_t hue ; // starting color FastLED.clear(); // for(hue=10; hue<255*3; hue++) { hue = (hue+1) % 0xFF ; // incerease hue and wrap fill_rainbow( leds, numPixel , hue /*static hue value */, 5);// set a rainbow from hue to last in stepsize 5 FastLED.show(); updatePatternDelay = 100 ; } // Incoming messages from MySensors void incomingMessage(const MyMessage &message) { int ID = message.sensor; Serial.print("Sensor: "); Serial.println(ID); switch (ID){ case RGB_LightChild: // same behaviour as RGB child/ fall through case RGB_RGBChild: // if controller can handle V_RGB if (message.type == V_RGB) { // check for RGB type strcpy(controllerRGBvalue, message.getString());// get the payload setLightPattern(pSolid, NULL); // and set solid pattern } else if (message.type == V_DIMMER) { // if DIMMER type, adjust brightness controllerRGBbrightness = map(message.getLong(), 0, 100, 0, 255); setLightBrightness(controllerRGBbrightness, 2000) ; } else if (message.type == V_STATUS) { // if on/off type, toggle brightness RGBonoff = message.getInt(); setLightBrightness((RGBonoff == 1)?controllerRGBbrightness:0, 2000); } break ; case RGB_SolidColorChild: // request color from controller if (message.type == V_STATUS) { // if get color from text child gw.request(RGB_TextColorChild, V_TEXT); setLightPattern(pSolid, NULL); // and set solid pattern (if not alre) } break ; case RGB_TextColorChild: // Text color from controller if (message.type == V_TEXT) { // if get color from text child gw.request(RGB_TextColorChild, V_TEXT); strcpy(controllerRGBvalue, message.getString());// get the payload for(int i = 0 ; i < 6 ; i++) { // save color value to EEPROM (6 char) gw.saveState(i, controllerRGBvalue[i]) ;}// Save to EEPROM } break ; case RGB_AlarmPatternChild: // set Alarm pattern if (message.type == V_STATUS) { // if get color from text child if (message.getInt() == 1){ setLightPattern(pAlarm, 500); // set slow alarm pattern } else { setLightPattern(pSolid, NULL); // and set solid pattern FastLED.setBrightness(curBrightness); } } break ; case RGB_NextPatternChild: // next pattern if (message.type == V_STATUS) { // if get color from text child if (message.getInt() == 1 ) { setLightPattern((curPattern + 1) % lastPatternIdx, 500 ); // increase pattern and wrap } } break ; } FastLED.show(); dispRGBstat(); } // debug // display the status of all RGB: controller, requested, real void dispRGBstat(void){ Serial.print(" Color: "); Serial.print(controllerRGBvalue); Serial.print(" Brightness: "); Serial.println(controllerRGBbrightness); } ```
-
hello,
i've problem with the sketch :+1 :sketch_dec08a.ino: In function 'void setup()': sketch_dec08a:89: error: 'S_INFO' was not declared in this scope gw.present(RGB_TextColorChild, S_INFO, "RGB Wall textcolor 0"); ^ sketch_dec08a.ino: In function 'void incomingMessage(const MyMessage&)': sketch_dec08a:308: error: 'V_TEXT' was not declared in this scope gw.request(RGB_TextColorChild, V_TEXT); ^ sketch_dec08a:313: error: 'V_TEXT' was not declared in this scope if (message.type == V_TEXT) { // if get color from text child ^ exit status 1 'S_INFO' was not declared in this scope
-
S_INFO inly exist in the dev branch.
That also means you have to convert the 1.5 sketch. Convert instructions here:
https://docs.google.com/document/d/1NKq5uuNdnxF5jWnum7VT32mbKLjuvqlx2A5D1qQ-H3Q/edit#
-
@mickaelr30 , did you ever get this working with 1.5?
i've got the upgrade instructions, but struggling to reverse it so it works with my current setup. Don't think i'm quite ready to upgrade all my nodes to dev quite yet.
-
@Adam-McCartney add these lines in the header and you will have it working with the production version...
// V_TEXT & V_INFO when not using the DEVELOPMENT version const byte V_TEXT = 47 ; // values taken from development edition MyMessage.h const byte S_INFO = 36 ;
-
@AWI said:
// V_TEXT & V_INFO when not using the DEVELOPMENT version
const byte V_TEXT = 47 ; // values taken from development edition MyMessage.h
const byte S_INFO = 36 ;awesome, thanks!
I'm more of a butcher than a surgeon. I can quite happily take things apart, but fixing things usually goes right over my head!!
-
I really love this project.
May I can include it in all of my sensors (doorbell, thermostat, alarm,...).Really sounds great, thanks
-
Is there a way to get your wiring schema ?
-
@Mehdi-HAMIDA There is nothing to it. A standard MySensors node (5v) with the strip connected to D5 and a button between ground and D4.
const int stripPin = 5 ; // pin where 2812 LED strip is connected const int buttonPin = 4 ; // push button
-
@AWI OK, just ordered the PCB
thx
-
@AWI: Won't this part of your sketch create sort of an endless loop?
case RGB_TextColorChild: // Text color from controller if (message.type == V_TEXT) { // if get color from text child gw.request(RGB_TextColorChild, V_TEXT);
-
@mfalkvidd Good observation. Probably the the result of an 'efficient' copy/paste
The line
gw.request(RGB_TextColorChild, V_TEXT);
I there with no reason, can be deleted...
-
Im building the same light, but i use 12v LED strips controlled with mosfets. Is it possible to use the same scetch?
-
@Tore-André-Rosander If you use standard 12v strips it won't work as such. The ws2812/11 chips in the strip used make it possible to address the individual led's.
-
@AWI Is this code for version 1.5?
Im trying to compile it for the dev (v2) but i get a lot of errors.
Mostly alot of code that "was not declared in this scope".EDIT: Just found your link to the "Conversion guide", will have look at it!
-
A version for MySensors 2 is available at https://forum.mysensors.org/topic/4934/wall-mounted-mood-light-v2
Suggested Topics
-
Welcome
Announcements • • hek