Skip to content
  • MySensors
  • OpenHardware.io
  • Categories
  • Recent
  • Tags
  • Popular
Skins
  • Light
  • Brite
  • Cerulean
  • Cosmo
  • Flatly
  • Journal
  • Litera
  • Lumen
  • Lux
  • Materia
  • Minty
  • Morph
  • Pulse
  • Sandstone
  • Simplex
  • Sketchy
  • Spacelab
  • United
  • Yeti
  • Zephyr
  • Dark
  • Cyborg
  • Darkly
  • Quartz
  • Slate
  • Solar
  • Superhero
  • Vapor

  • Default (No Skin)
  • No Skin
Collapse
Brand Logo
  1. Home
  2. Development
  3. Dimmable led actuator sketch enhancement

Dimmable led actuator sketch enhancement

Scheduled Pinned Locked Moved Development
6 Posts 3 Posters 2.6k Views 1 Watching
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • ferpandoF Offline
    ferpandoF Offline
    ferpando
    Hero Member
    wrote on last edited by ferpando
    #1

    Hello,

    I've been working on a simple mod of the dimmable led actuator available in the examples folder.

    I needed a few things that were not included, like the ability to set a more precise fade level, make longer fades and also being able to change those fade times dynamically.

    Also, as a result of longer dafe times, I had to modify the sketch so the node is still able to send/receive messages during fade time.

    You could send messages from VERA this way:

    luup.call_action("urn:upnp-arduino-cc:serviceId:arduino1", "SendCommand", {radioId="6;100", variableId="DIMMER", value="100,25"}, 130)
    

    This message is sent to node id 6, with parent node id 130, and tells the node to fade to 100% in 25 seconds.
    You could choose any number (0-100) to fade to, instead of the 10% increment Vera offers. Also the old functionality remains working as before.

    Here's the sketch in case someone is interested:

    /***
     * This program is free software; you can redistribute it and/or
     * modify it under the terms of the GNU General Public License
     * version 2 as published by the Free Software Foundation.
     * 
     * DESCRIPTION
     * This sketch provides a Dimmable LED Light using PWM and based Henrik Ekblad 
     * <henrik.ekblad@gmail.com> Vera Arduino Sensor project.  
     * Developed by Bruce Lacey, inspired by Hek's MySensor's example sketches.
     * 
     * The circuit uses a MOSFET for Pulse-Wave-Modulation to dim the attached LED or LED strip.  
     * The MOSFET Gate pin is connected to Arduino pin 3 (LED_PIN), the MOSFET Drain pin is connected
     * to the LED negative terminal and the MOSFET Source pin is connected to ground.  
     *
     * This sketch is extensible to support more than one MOSFET/PWM dimmer per circuit.
     *
     * REVISION HISTORY
     * Version 1.0 - February 15, 2014 - Bruce Lacey
     * Version 1.1 - August 13, 2014 - Converted to 1.4 (hek) 
     * Version 1.2 - April 13, 2015 - Added long dynamic and precise fade, also made fade non exclusive (ferpando)
     ***/
     
     #include <Time.h> 
     
    #define SN "DimmableLED"
    #define SV "1.2"
    
    #include <MySensor.h> 
    #include <SPI.h>
    
    #define LED_PIN 5      // Arduino pin attached to MOSFET Gate pin
    
    MySensor gw(9,10);
    
    static int currentLevel = 0;  // Current dim level...
    static int requestedLevel = 0;
    
    MyMessage dimmerMsg(0, V_DIMMER);
    MyMessage lightMsg(0, V_LIGHT);
    
    int FADE_DELAY;   // Delay in ms for each percentage fade up/down (10ms = 1s full-range dim)
    
    /***
     * Dimmable LED initialization method
     */
    void setup()  
    { 
      Serial.println( SN ); 
      gw.begin( incomingMessage );
      
      // Register the LED Dimmable Light with the gateway
      gw.present( 0, S_DIMMER );
      
      gw.sendSketchInfo(SN, SV);
      // Pull the gateway's current dim level - restore light level upon sendor node power-up
      gw.request( 0, V_DIMMER );
    
    }
    
    /***
     *  Dimmable LED main processing loop 
     */
    void loop() 
    {
      gw.process();
      fadeToLevel();
      // if delay is too long, it might stop the node from receiving/sending more messages for a long time.
      //doing it this way, the node can keep functioning regardless fade completition.
    }
    
    void incomingMessage(const MyMessage &message) {
      if (message.type == V_LIGHT || message.type == V_DIMMER) {
        
        if(message.sensor == 100 ){ //fade special, addressed to node 100
          // Message payload: value to fade to, seconds to fade     example: "20,10"
          
          int commaIndex = msg.indexOf(',');
    
          String firstValue = msg.substring(0, commaIndex);
          String secondValue = msg.substring(commaIndex+1);
    
          requestedLevel=firstValue.toInt();
          int steps=abs(currentLevel-requestedLevel);
    
          if(commaIndex == -1){
             FADE_DELAY=10;
          }else { 
             FADE_DELAY = 1000* secondValue.toInt() / steps;
          }
        }else { //fade normal
        
              FADE_DELAY=10;
              //  Retrieve the power or dim level from the incoming request message
              requestedLevel = atoi( message.data );
              
              // Adjust incoming level if this is a V_LIGHT variable update [0 == off, 1 == on]
              requestedLevel *= ( message.type == V_LIGHT ? 100 : 1 );
              
              // Clip incoming level to valid range of 0 to 100
              requestedLevel = requestedLevel > 100 ? 100 : requestedLevel;
              requestedLevel = requestedLevel < 0   ? 0   : requestedLevel;
              
              }
           
          Serial.print( "Changing level to " );
          Serial.print( requestedLevel );
          Serial.print( ", from " ); 
          Serial.println( currentLevel ); 
           
             
          // Inform the gateway of the current DimmableLED's SwitchPower1 and LoadLevelStatus value...
          gw.send(lightMsg.set(currentLevel > 0 ? 1 : 0));
      
          // hek comment: Is this really nessesary?
          gw.send( dimmerMsg.set(currentLevel) );
        
        }
    }
    
    /***
     *  This method provides a graceful fade up/down effect
     */
    void fadeToLevel() {
    
      if ( currentLevel != requestedLevel ) {
        int delta = ( requestedLevel - currentLevel ) < 0 ? -1 : 1;
      
        currentLevel += delta;
        Serial.print( "analog write: " );
        Serial.println( currentLevel / 100. * 255 );
        analogWrite( LED_PIN, (int)(currentLevel / 100. * 255) );
        delay( FADE_DELAY );
      }
      
    }
    
    1 Reply Last reply
    1
    • ferpandoF Offline
      ferpandoF Offline
      ferpando
      Hero Member
      wrote on last edited by ferpando
      #2

      A few bug fixes and also this sends back to gateway the value of 'requestedValue' instead of 'currentValue' as I think it should be.
      Delays and precise setpoint are now correct.

      /***
       * This program is free software; you can redistribute it and/or
       * modify it under the terms of the GNU General Public License
       * version 2 as published by the Free Software Foundation.
       * 
       * DESCRIPTION
       * This sketch provides a Dimmable LED Light using PWM and based Henrik Ekblad 
       * <henrik.ekblad@gmail.com> Vera Arduino Sensor project.  
       * Developed by Bruce Lacey, inspired by Hek's MySensor's example sketches.
       * 
       * The circuit uses a MOSFET for Pulse-Wave-Modulation to dim the attached LED or LED strip.  
       * The MOSFET Gate pin is connected to Arduino pin 3 (LED_PIN), the MOSFET Drain pin is connected
       * to the LED negative terminal and the MOSFET Source pin is connected to ground.  
       *
       * This sketch is extensible to support more than one MOSFET/PWM dimmer per circuit.
       *
       * REVISION HISTORY
       * Version 1.0 - February 15, 2014 - Bruce Lacey
       * Version 1.1 - August 13, 2014 - Converted to 1.4 (hek) 
       * Version 1.2 - April 13, 2015 - Added long dynamic and precise fade, also made fade non exclusive (ferpando)
       ***/
       
       #include <Time.h> 
       
      #define SN "DimmableLED"
      #define SV "1.2"
      
      #include <MySensor.h> 
      #include <SPI.h>
      
      #define LED_PIN 5      // Arduino pin attached to MOSFET Gate pin
      
      MySensor gw(9,10);
      
      static int currentLevel = 0;  // Current dim level...
      static int requestedLevel = 0;
      boolean preciseFade = false;
      
      MyMessage dimmerMsg(0, V_DIMMER);
      MyMessage lightMsg(0, V_LIGHT);
      
      int FADE_DELAY;   // Delay in ms for each percentage fade up/down (10ms = 1s full-range dim)
      
      /***
       * Dimmable LED initialization method
       */
      void setup()  
      { 
        Serial.println( SN ); 
        gw.begin( incomingMessage );
        
        // Register the LED Dimmable Light with the gateway
        gw.present( 0, S_DIMMER );
        
        gw.sendSketchInfo(SN, SV);
        // Pull the gateway's current dim level - restore light level upon sendor node power-up
        gw.request( 0, V_DIMMER );
      
      }
      
      /***
       *  Dimmable LED main processing loop 
       */
      void loop() 
      {
        gw.process();
        fadeToLevel();
        // if delay is too long, it might stop the node from receiving/sending more messages for a long time.
        //doing it this way, the node can keep functioning regardless fade completition.
      }
      
      void incomingMessage(const MyMessage &message) {
        if (message.type == V_LIGHT || message.type == V_DIMMER) {
          int steps;
          int multiplier;
          if(message.sensor == 100 ){ //fade special, addressed to node 100
            // Message payload: value to fade to, seconds to fade     example: "20,10"
            preciseFade = true;
            String msg=message.getString();
            
            int commaIndex = msg.indexOf(',');
      
            String firstValue = msg.substring(0, commaIndex);
            String secondValue = msg.substring(commaIndex+1);
      
            requestedLevel=firstValue.toInt();
            steps = currentLevel-requestedLevel;
            multiplier = abs(1000 / steps);
            if(commaIndex == -1){
               FADE_DELAY=multiplier * 10;
            }else { 
               FADE_DELAY = multiplier * secondValue.toInt();
            }
          }else { //fade normal
                preciseFade = false;
                steps = currentLevel-requestedLevel;
                multiplier = abs(1000 / steps);
                FADE_DELAY=multiplier * 10;
                //  Retrieve the power or dim level from the incoming request message
                requestedLevel = atoi( message.data );
                
                // Adjust incoming level if this is a V_LIGHT variable update [0 == off, 1 == on]
                requestedLevel *= ( message.type == V_LIGHT ? 100 : 1 );
                
                // Clip incoming level to valid range of 0 to 100
                requestedLevel = requestedLevel > 100 ? 100 : requestedLevel;
                requestedLevel = requestedLevel < 0   ? 0   : requestedLevel;
                
                }
                
          Serial.print( "Changing level to " );
          Serial.print( requestedLevel );
          Serial.print( ", from " ); 
          Serial.println( currentLevel ); 
           
          // Inform the gateway of the current DimmableLED's SwitchPower1 and LoadLevelStatus value...
          gw.send(lightMsg.set(requestedLevel > 0 ? 1 : 0));
      
          // hek comment: Is this really nessesary?
          gw.send( dimmerMsg.set(requestedLevel) );
          
          }
      }
      
      /***
       *  This method provides a graceful fade up/down effect
       */
      void fadeToLevel() {
        
        if ( currentLevel != requestedLevel ) {
          int pwmLevel;
          int delta = ( requestedLevel - currentLevel ) < 0 ? -1 : 1;
          currentLevel += delta;
          Serial.print( "analog write: " );
          if(preciseFade){ //set to specific number
              pwmLevel = (int)currentLevel;
              }else  { //set to 10% increment level
                 pwmLevel=(int)(currentLevel / 100. * 255);
                 }
        Serial.println( pwmLevel );
        analogWrite( LED_PIN, pwmLevel );
        delay( FADE_DELAY );
        }
      }
      
      AWIA 1 Reply Last reply
      0
      • D Offline
        D Offline
        Drcashman
        wrote on last edited by
        #3

        Can this be expanded to include 2-3 more outputs?

        ferpandoF 1 Reply Last reply
        0
        • ferpandoF ferpando

          A few bug fixes and also this sends back to gateway the value of 'requestedValue' instead of 'currentValue' as I think it should be.
          Delays and precise setpoint are now correct.

          /***
           * This program is free software; you can redistribute it and/or
           * modify it under the terms of the GNU General Public License
           * version 2 as published by the Free Software Foundation.
           * 
           * DESCRIPTION
           * This sketch provides a Dimmable LED Light using PWM and based Henrik Ekblad 
           * <henrik.ekblad@gmail.com> Vera Arduino Sensor project.  
           * Developed by Bruce Lacey, inspired by Hek's MySensor's example sketches.
           * 
           * The circuit uses a MOSFET for Pulse-Wave-Modulation to dim the attached LED or LED strip.  
           * The MOSFET Gate pin is connected to Arduino pin 3 (LED_PIN), the MOSFET Drain pin is connected
           * to the LED negative terminal and the MOSFET Source pin is connected to ground.  
           *
           * This sketch is extensible to support more than one MOSFET/PWM dimmer per circuit.
           *
           * REVISION HISTORY
           * Version 1.0 - February 15, 2014 - Bruce Lacey
           * Version 1.1 - August 13, 2014 - Converted to 1.4 (hek) 
           * Version 1.2 - April 13, 2015 - Added long dynamic and precise fade, also made fade non exclusive (ferpando)
           ***/
           
           #include <Time.h> 
           
          #define SN "DimmableLED"
          #define SV "1.2"
          
          #include <MySensor.h> 
          #include <SPI.h>
          
          #define LED_PIN 5      // Arduino pin attached to MOSFET Gate pin
          
          MySensor gw(9,10);
          
          static int currentLevel = 0;  // Current dim level...
          static int requestedLevel = 0;
          boolean preciseFade = false;
          
          MyMessage dimmerMsg(0, V_DIMMER);
          MyMessage lightMsg(0, V_LIGHT);
          
          int FADE_DELAY;   // Delay in ms for each percentage fade up/down (10ms = 1s full-range dim)
          
          /***
           * Dimmable LED initialization method
           */
          void setup()  
          { 
            Serial.println( SN ); 
            gw.begin( incomingMessage );
            
            // Register the LED Dimmable Light with the gateway
            gw.present( 0, S_DIMMER );
            
            gw.sendSketchInfo(SN, SV);
            // Pull the gateway's current dim level - restore light level upon sendor node power-up
            gw.request( 0, V_DIMMER );
          
          }
          
          /***
           *  Dimmable LED main processing loop 
           */
          void loop() 
          {
            gw.process();
            fadeToLevel();
            // if delay is too long, it might stop the node from receiving/sending more messages for a long time.
            //doing it this way, the node can keep functioning regardless fade completition.
          }
          
          void incomingMessage(const MyMessage &message) {
            if (message.type == V_LIGHT || message.type == V_DIMMER) {
              int steps;
              int multiplier;
              if(message.sensor == 100 ){ //fade special, addressed to node 100
                // Message payload: value to fade to, seconds to fade     example: "20,10"
                preciseFade = true;
                String msg=message.getString();
                
                int commaIndex = msg.indexOf(',');
          
                String firstValue = msg.substring(0, commaIndex);
                String secondValue = msg.substring(commaIndex+1);
          
                requestedLevel=firstValue.toInt();
                steps = currentLevel-requestedLevel;
                multiplier = abs(1000 / steps);
                if(commaIndex == -1){
                   FADE_DELAY=multiplier * 10;
                }else { 
                   FADE_DELAY = multiplier * secondValue.toInt();
                }
              }else { //fade normal
                    preciseFade = false;
                    steps = currentLevel-requestedLevel;
                    multiplier = abs(1000 / steps);
                    FADE_DELAY=multiplier * 10;
                    //  Retrieve the power or dim level from the incoming request message
                    requestedLevel = atoi( message.data );
                    
                    // Adjust incoming level if this is a V_LIGHT variable update [0 == off, 1 == on]
                    requestedLevel *= ( message.type == V_LIGHT ? 100 : 1 );
                    
                    // Clip incoming level to valid range of 0 to 100
                    requestedLevel = requestedLevel > 100 ? 100 : requestedLevel;
                    requestedLevel = requestedLevel < 0   ? 0   : requestedLevel;
                    
                    }
                    
              Serial.print( "Changing level to " );
              Serial.print( requestedLevel );
              Serial.print( ", from " ); 
              Serial.println( currentLevel ); 
               
              // Inform the gateway of the current DimmableLED's SwitchPower1 and LoadLevelStatus value...
              gw.send(lightMsg.set(requestedLevel > 0 ? 1 : 0));
          
              // hek comment: Is this really nessesary?
              gw.send( dimmerMsg.set(requestedLevel) );
              
              }
          }
          
          /***
           *  This method provides a graceful fade up/down effect
           */
          void fadeToLevel() {
            
            if ( currentLevel != requestedLevel ) {
              int pwmLevel;
              int delta = ( requestedLevel - currentLevel ) < 0 ? -1 : 1;
              currentLevel += delta;
              Serial.print( "analog write: " );
              if(preciseFade){ //set to specific number
                  pwmLevel = (int)currentLevel;
                  }else  { //set to 10% increment level
                     pwmLevel=(int)(currentLevel / 100. * 255);
                     }
            Serial.println( pwmLevel );
            analogWrite( LED_PIN, pwmLevel );
            delay( FADE_DELAY );
            }
          }
          
          AWIA Offline
          AWIA Offline
          AWI
          Hero Member
          wrote on last edited by
          #4

          @ferpando I maybe misinterpreting things but for me it looks like the "fadeToLevel" is still blocking with respect to the receipt of messages for a time as long as FADE_DELAY. would suggest making it non-blocking by means of a time counter.

          like

          // timer value for "once in a while" events
              unsigned long now = millis();
              gw.process() ;								// process MySensors messages (needed for repeater)
              // Read/update every "delay" (60) seconds
              if (now-lastUpdate > 60000) {
          		read_sensors();
          		lastUpdate = now;
              }
          
          ferpandoF 1 Reply Last reply
          0
          • AWIA AWI

            @ferpando I maybe misinterpreting things but for me it looks like the "fadeToLevel" is still blocking with respect to the receipt of messages for a time as long as FADE_DELAY. would suggest making it non-blocking by means of a time counter.

            like

            // timer value for "once in a while" events
                unsigned long now = millis();
                gw.process() ;								// process MySensors messages (needed for repeater)
                // Read/update every "delay" (60) seconds
                if (now-lastUpdate > 60000) {
            		read_sensors();
            		lastUpdate = now;
                }
            
            ferpandoF Offline
            ferpandoF Offline
            ferpando
            Hero Member
            wrote on last edited by
            #5

            @AWI
            You are right but now the blocking is just a few milliseconds instead of the whole fade time.
            I think messages are still received because the are interrupt driven, so in the next cycle message will arrive.
            You will be just delaying a few millis sending new messages.

            Your solutions is indeed an improvement to be considered.
            In my case I don't need that much control.

            1 Reply Last reply
            0
            • D Drcashman

              Can this be expanded to include 2-3 more outputs?

              ferpandoF Offline
              ferpandoF Offline
              ferpando
              Hero Member
              wrote on last edited by
              #6

              @Drcashman
              by outputs you mean to control 2-3 light fades?
              I guess it wouldn't be too difficult. Just add counters for current and requested values for each fade to keep them independent

              1 Reply Last reply
              0
              Reply
              • Reply as topic
              Log in to reply
              • Oldest to Newest
              • Newest to Oldest
              • Most Votes


              19

              Online

              11.7k

              Users

              11.2k

              Topics

              113.0k

              Posts


              Copyright 2019 TBD   |   Forum Guidelines   |   Privacy Policy   |   Terms of Service
              • Login

              • Don't have an account? Register

              • Login or register to search.
              • First post
                Last post
              0
              • MySensors
              • OpenHardware.io
              • Categories
              • Recent
              • Tags
              • Popular