IR Switch for Luminara Candle Automation (repost with video, photos and final sketch)


  • Admin

    So, my wife loves her Luminara candles that she can turn on and off with a Luminara remote control so heck, why not tie them into the HA system so they come on at sunset and go off when we go to bed each evening? I built a high-power IR blaster, ginned up a small circuit to decode the Luminara remote control codes using the IRSensor sketch MySensors example provided by @hek, configured the on/off IR codes in the actuator sketch and voila - our Vera 3 is able to control my wife's candles! Video, photos and the sketch are provided below.

    IR Switch Video

    Completed IR Switch Actuator
    FinalIRSwitch.jpg

    IR Switch Actuator Circuit (top)
    IRSwitchActuatorTop.jpg

    IR Switch Actuator Circuit (bottom) - should probably invest in the convenience boards that others have created to avoid excessive wire-wrapping and soldering πŸ˜‰
    IRSwitchActuatorBottom.jpg

    Assembling the IR Blaster - parallel circuit, no forward current resistors to maximize radiant luminance.
    IRBlasterAssemblyTop.jpg

    Assembled IR Blaster (top)
    IRBlasterTop.jpg

    Assembled IR Blaster (bottom)
    IRBlasterBottom.jpg

    IR Switch Sketch

    This was a fun project with a very positive wife factor and I hope others find this useful.

    Cheers.

    UPDATE (2015-MAY-13) I have started a new thread here to flesh out the design of an official IR Blaster -


  • Admin

    Cool, added your "blaster module" here:
    http://www.mysensors.org/store/#light



  • Happy wife, happy life. Well done.


  • Admin

    Nice video Bruce!


  • Admin

    @blacey Awesome! I don't know how I missed this before but I love it. Adding this to the list of things to do...

    Just curious, how long to the batteries last in the candles?


  • Admin

    They use two C-size batteries so they last a very long time. With them on the automation system, I expect them to last at least a year because my wife won't leave them running 24/7 anymore πŸ˜‰ In fact, they may last even longer because the candles will be on less per day as we approach summer because the trigger is tied to sunset... My wife has had the candles just under six months without automation and is still on her first set of batteries.


  • Admin

    @blacey awesome, thanks!


  • Hero Member

    anyone know if you can buy these in europe?



  • @korttoma just bought these yesterday on ebay:

    http://www.ebay.com/itm/Remote-Control-Electronic-LED-Candle-Romantic-Gift-3pcs-LED-Wax-Candles-DX-/251766554387?pt=LH_DefaultDomain_0&hash=item3a9e74bf13

    I have no idea if this is something useful

    Worth a try for 8 dollar?


  • Hero Member

    I just received a couple of these:

    http://www.ebay.com/itm/301578035483?_trksid=p2057872.m2749.l2649&ssPageName=STRK%3AMEBIDX%3AIT

    Looks like they are the same candles as Luminara but cheaper, time to build the IR Blaster and find out if I can use the sketch @blacey provided straight of.


  • Hero Member

    @blacey would you mind sharing how you connected the IR-Transmitters to the arduino? Is this what the Transistor is for?


  • Admin

    @korttoma, yes the transistor is used to drive the IR LEDs. It is a standard NPN transistor (NTE123AP) capable of delivering 600mA of current through the collector.

    The transistor base lead is connected to the Arduino PWM pin 3 per IRLib, the transistor emitter lead is connected to GND and the transistor collector lead is connected to the IR LED emitters wired in parallel (cathode). It is best practice to place a forward current limiting resistor between IR LEDs anode and VCC but the IRLib drives the LEDs for such short intervals, that you can avoid adding the forward current limiting resistors as I mentioned in the video.


  • Hero Member

    Thanks @blacey for the clarification. I sort of overlooked the fact that there was a video, sorry. My consirns was about the current limiting resistor but if you say the IR LEDs can take it I believe you. Thanks again for this project πŸ˜‰


  • Admin

    @korttoma - sorry you missed the video πŸ˜‰ I have it on my to-do list to draw a proper schematic for the IR blaster board and the actuator but I just haven't had time yet. I would like to post one in this thread to make it easier for people to build their own IR actuator. Maybe you will get there first πŸ˜‰



  • @blacey what program are you using to capture the IR codes from the remote ?


  • Admin

    @jeylites I used the IRSensor sketch in the MySensors examples.



  • @blacey Nice. I'm using IR Recorder from the library. I asked because you had a fancy setup in the video πŸ™‚ Very neat setup!



  • Hello @blacey , I got a question... If I'm going to add another IR into the sketch, how do I go about doing this? So two independent sensors into one. This is what I have done so far. Correct me if I'm wrong. Should I be changing something in IRsend irsend ....?

    And is your IR LED connected to Pin 1 or Pin3?

    /***
     * Binary IR Switch sketch that controls Luminara Candles
     *
     * Sketch inspired by, and a derivative work of, Hek's IR Sensor example sketch
     */
    
    #include <MySensor.h>
    #include <SPI.h>
    #include <IRLib.h>
    
    int RECV_PIN =  8;
    #define CHILD1  3 // Arduino Pin 3
    #define CHILD2  4 // Arduino Pin 4
    
    
    MySensor gw;
    MyMessage switchMsg1(CHILD1, V_VAR1);
    MyMessage switchMsg2(CHILD2, V_VAR1);
    
    // IR LED must be connexted to Arduino PWM pin 3
    IRsend irsend;                    
    #define switchOnIRcode  0x00ff629d  // Luminara On  IR code
    #define switchOffIRcode 0x00ffa857  // Luminara Off IR code
    
    void setup()  
    {  
      gw.begin(incomingMessage);
    
      // Send the sketch version information to the gateway and Controller
      gw.sendSketchInfo("IR Switch", "1.0");
    
      // Register a sensors to gw. Use binary light for test purposes.
      gw.present(CHILD1, S_LIGHT);
      gw.present(CHILD2, S_LIGHT);
      
      // Sync switch state to gateway state upon reset / power-up
      gw.request(CHILD1, V_LIGHT);
      gw.request(CHILD2, V_LIGHT);
    }
    
    void loop() 
    {
      gw.process();
    }
    
    void incomingMessage(const MyMessage &message) {
      
      // We only expect one type of message from controller. But we better check anyway.
      if (message.type==V_LIGHT) {
         int incomingRelayStatus = message.getInt();
         
         // Emit the IR ON/OFF code
         irsend.send(NEC, (incomingRelayStatus == 1 ? switchOnIRcode : switchOffIRcode), 32);
         
         // Sync gateway of the light switch state
         gw.send(switchMsg1.set(incomingRelayStatus));
         gw.send(switchMsg2.set(incomingRelayStatus));
      }
    }
    
    

  • Admin

    @jeylites My IR LEDs are connected to Pin 3 because that is what IR Lib requires. Your sketch looks close but you will need to define separate switchOnIRcode and switchOffIRcode codes for your respective lights. Then in the incomingMessage loop, send the appropriate code based upon the child ID. If you plan to have a large number of child IDs, I would create an array indexed by child ID to hold the on/off IR codes and then simply invoke ir.send() passing the onOffCode[childID] to it. Does that make sense?

    Also, I just started another thread for an official IR Blaster board that you might want to review. I plan to provide multiple device support out of the box...



  • @blacey I think I get what you're saying on #define but don't know how to associate child id with ir code. Do you have a sample or something ?

    IR blaster - you working on looks great. Next project is to use that to control my AV system.

    Thank you!


  • Admin

    @jeylites Here is a quick and dirty example for two switch IR devices... Hope this helps you get started. I will give multi-device more thoughts/elegance for the final IR Blaster.

    #include <MySensor.h>
    #include <SPI.h>
    #include <IRLib.h>
    
    #define NumChildDevices 2
    
    typedef struct IRCode {
      IRTYPES brand;
      unsigned long on;
      unsigned long off;
      unsigned int bits;
    } ir;
      
    ir childIR[NumChildDevices];
    IRsend iremitter;
    
    MySensor gw;
    MyMessage child1Msg(1, V_VAR1);
    MyMessage child2Msg(2, V_VAR2);
    
    void setup() {
      
      gw.begin();
      gw.sendSketchInfo("Multi IR", "0.1");
      
      // Initialize children devices  
      // 1. Candles (Switch)
      gw.present(1, S_LIGHT);
      childIR[1] = {NEC, 0x00ff629d, 0x00ffa857, 32};
      
      // 2. TV
      gw.present(2, S_LIGHT);
      childIR[2] = {SONY, 0x0062ff8d, 0x00aff578, 32};
      
    }
    
    void loop() {
      gw.process();
    }
    
    void incomingMessage(const MyMessage &message) {
      
      //Determine the child device
      uint8_t child = message.sensor;
      
      //Get the relay status for the child device
      int incomingRelayStatus = message.getInt();
      
      //Emit the appropriate IR code to the child device
      iremitter.send( childIR[child].brand, incomingRelayStatus == 1 ? childIR[child].on : childIR[child].off, childIR[child].bits);
    }
    


  • @blacey Thank you sir! Will test it out over the weekend.


  • Hero Member

    I just wanted to confirm that the cheep ebay Luminara "style" candles does work with blaceys sketch "out of the box".


  • Admin

    @korttoma

    do you have a link to some of the cheap ones on ebay?


  • Admin


  • Admin

    @hek

    Hmm by cheap, I thought it was below 15$ πŸ™‚


  • Hero Member

    @tbowmo said:

    @hek

    Hmm by cheap, I thought it was below 15$ πŸ™‚

    They are cheep compared to the Genuine Luminara products + I could not find a good suppler for the real thing sending to Europe

    Maybe the once @betonishard mentioned earlier in the thread would be something more in your prize range? Would be nice to know if they also work with blaceys sketch though.



  • @korttoma, didn't had time to make the ir blaster yet. So quite frankly I don't know. I am using the remote delivered in the package. It still works by the way, which was surprising for that price. The flicker of the candles is kind of fast, like there is a firm wind in my livingroom.


  • Contest Winner

    Wow this is an old topic!

    But... I was working on a project and thought that anyone who was looking for a NeoPixel candle example that isn't blocking, well this would be the place. It flickers and flutters like a real candle. The only thing is that the flame isn't illuminated like these nice Luminaras, but I'm too cheap to buy them!

    Keep in mind that my example here uses GRB LEDs, but you merely need to reorder the variables in order to get this working for RGB. Plus the Time Library is not Arduino, so you will have to play with that too for a good randomSeed().

    It looks pretty realistic with even a single neoPixel in a sheet of A4 paper rolled into a cylinder. I'll post a video when I can.

    Have fun with it:

    #include "neopixel.h"
    
    enum CandleStates{
      BURN_CANDLE,
      FLICKER_CANDLE,
      FLUTTER_CANDLE,
      MODES_MAX_CANDLE
    };
    
    enum PixelSelect{
      EVERY_PIXEL,
      SINGLE_PIXEL,
    };
    
    class Candle : public Adafruit_NeoPixel
    {
      public:
        Candle(uint16_t count, uint8_t pin, uint8_t type);
        Candle(uint16_t count, uint8_t pin, uint8_t type, PixelSelect pixel, uint32_t pixNum = 0);
        ~Candle(){};
        void update();
    
      private:
        bool fire(uint8_t greenDropValue, uint32_t cycleTime);
    
        PixelSelect _pixelMode = EVERY_PIXEL;
        uint32_t _pixNum = 0;
        CandleStates _mode;
        uint32_t _lastModeChange;
        uint32_t _modeDuration;
    
        uint8_t _redPx = 255;
        uint8_t _bluePx = 10; //10 for 5v, 15 for 3.3v
        uint8_t _grnHigh = 100; //110-120 for 5v, 135 for 3.3v
        uint8_t _grnPx = 100;
    
        uint32_t _lastBurnUpdate = 0;
        int _direction = 1;
    };
    
    Candle::Candle(uint16_t count, uint8_t pin, uint8_t type) : Adafruit_NeoPixel(count, pin, type)
    {
      randomSeed(Time.now() + micros());
      _mode = BURN_CANDLE;
    }
    
    Candle::Candle(uint16_t count, uint8_t pin, uint8_t type, PixelSelect pixel, uint32_t pixNum) : Adafruit_NeoPixel(count, pin, type)
    {
      _pixelMode = pixel;
      _pixNum = pixNum;
    }
    
    void Candle::update()
    {
      if(millis() - _lastModeChange > _modeDuration)
      {
        _mode = static_cast<CandleStates>(random(MODES_MAX_CANDLE));
        _modeDuration = random(1000, 8000);
        _lastModeChange = millis();
        //Serial.printlnf("New state: %d\tTime: %d", static_cast<int>(_mode), _modeDuration);
      }
      switch(_mode)
      {
        case BURN_CANDLE:
          this->fire(10, 120);
          break;
        case FLICKER_CANDLE:
          this->fire(15, 120);
          break;
        case FLUTTER_CANDLE:
          this->fire(30, 120);
          break;
      };
    }
    
    bool Candle::fire(uint8_t greenDropValue, uint32_t cycleTime)
    {
      int currentMillis = millis();
      if(currentMillis - _lastBurnUpdate > (cycleTime / greenDropValue / 2))
      {
        _grnPx = constrain(_grnPx += _direction, _grnHigh - greenDropValue, _grnHigh);
        if(_grnPx == _grnHigh - greenDropValue or _grnPx == _grnHigh)
        {
          _direction *= -1;
        }
        switch (_pixelMode)
        {
          case EVERY_PIXEL:
            for(int i = 0; i < this->numPixels(); i++)
            {
              this->setPixelColor(i, _grnPx, _redPx, _bluePx);
            }
            break;
          case SINGLE_PIXEL:
            this->setPixelColor(_pixNum, _grnPx, _redPx, _bluePx);
            break;
        }
        this->show();
        _lastBurnUpdate = currentMillis;
      }
    }
    
    #define PIXEL_COUNT 2
    #define PIXEL_PIN D2
    #define PIXEL_TYPE WS2812B    // I'M USING GRB WS2821B's here
    
    Candle candle = Candle(PIXEL_COUNT, PIXEL_PIN, PIXEL_TYPE, SINGLE_PIXEL);
    
    void setup(void)
    {
      Serial.begin(115200);
      pinMode(13, OUTPUT);
      candle.begin();
      candle.show();
      Serial.println("Started program");
    }
    
    void loop(void)
    {
      candle.update();
      static uint32_t lastFlashMillis = 0;
      if(millis() - lastFlashMillis > 250)
      {
        digitalWrite(13, !digitalRead(13));
        lastFlashMillis = millis();
      }
    }
    

Log in to reply
 

Suggested Topics

  • 5
  • 17
  • 8
  • 2
  • 44
  • 5

5
Online

11.4k
Users

11.1k
Topics

112.7k
Posts