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. Problem with dimmable LED actuator with encoder

Problem with dimmable LED actuator with encoder

Scheduled Pinned Locked Moved Development
17 Posts 7 Posters 2.7k Views 7 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.
  • vladimirV Offline
    vladimirV Offline
    vladimir
    wrote on last edited by
    #1

    Hi all!

    I'm using OpenHAB 2, and I have some problems with the sketch code "DimmableLightWithRotaryEncoderButton".

    When the encoder button is pressed, the switch in OpenHAB does not respond.
    When turn the encoder knob one step, the value changes in two steps.
    Maybe you have encountered such a problem? Or maybe you can share a more modern sketch?

    /**
     * The MySensors Arduino library handles the wireless radio link and protocol
     * between your home built sensors/actuators and HA controller of choice.
     * The sensors forms a self healing radio network with optional repeaters. Each
     * repeater and gateway builds a routing tables in EEPROM which keeps track of the
     * network topology allowing messages to be routed to nodes.
     *
     * Created by Henrik Ekblad <henrik.ekblad@mysensors.org>
     * Copyright (C) 2013-2015 Sensnology AB
     * Full contributor list: https://github.com/mysensors/Arduino/graphs/contributors
     *
     * Documentation: http://www.mysensors.org
     * Support Forum: http://forum.mysensors.org
     *
     * 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.
     *
     *******************************
     *
     * REVISION HISTORY
     * Version 1.0 - Developed by Bruce Lacey and GizMoCuz (Domoticz)
     * Version 1.1 - Modified by hek to incorporate a rotary encode to adjust 
     *                                light level locally at node
     * 
     * DESCRIPTION
     * This sketch provides an example how to implement a dimmable led light node with a rotary 
     * encoder connected for adjusting light level. 
     * The encoder has a click button which turns on/off the light (and remembers last dim-level) 
     * The sketch fades the light (non-blocking) to the desired level. 
     *
     * Default MOSFET pin is 3
     * 
     *  Arduino      Encoder module
     *  ---------------------------
     *  5V           5V (+)  
     *  GND          GND (-)
     *  4            CLK (or putput 1)
     *  5            DT  (or output 1) 
     *  6            SW (Switch/Click)  
     */
    
    
    // Enable debug prints
    #define MY_DEBUG
    
    // Enable and select radio type attached
    #define MY_RADIO_NRF24
    //#define MY_RADIO_RFM69
    
    #include <SPI.h>
    #include <MySensors.h>  
    #include <Bounce2.h>
    #include <Encoder.h>
    
    #define LED_PIN 3           // Arduino pin attached to MOSFET Gate pin
    #define KNOB_ENC_PIN_1 4    // Rotary encoder input pin 1
    #define KNOB_ENC_PIN_2 5    // Rotary encoder input pin 2
    #define KNOB_BUTTON_PIN 6   // Rotary encoder button pin 
    #define FADE_DELAY 10       // Delay in ms for each percentage fade up/down (10ms = 1s full-range dim)
    #define SEND_THROTTLE_DELAY 400 // Number of milliseconds before sending after user stops turning knob
    #define SN "DimmableLED /w button"
    #define SV "1.2"
    
    #define CHILD_ID_LIGHT 1
    
    #define EEPROM_DIM_LEVEL_LAST 1
    #define EEPROM_DIM_LEVEL_SAVE 2
    
    #define LIGHT_OFF 0
    #define LIGHT_ON 1
    
    int dimValue;
    int fadeTo;
    int fadeDelta;
    byte oldButtonVal;
    bool changedByKnob=false;
    bool sendDimValue=false;
    unsigned long lastFadeStep;
    unsigned long sendDimTimeout;
    char convBuffer[10];
    
    MyMessage dimmerMsg(CHILD_ID_LIGHT, V_DIMMER);
    Encoder knob(KNOB_ENC_PIN_1, KNOB_ENC_PIN_2);  
    Bounce debouncer = Bounce(); 
    
    void setup()  
    { 
      // Set knob button pin as input (with debounce)
      pinMode(KNOB_BUTTON_PIN, INPUT);
      digitalWrite(KNOB_BUTTON_PIN, HIGH);
      debouncer.attach(KNOB_BUTTON_PIN);
      debouncer.interval(5);
      oldButtonVal = debouncer.read();
    
      // Set analog led pin to off
      analogWrite( LED_PIN, 0);
    
      // Retreive our last dim levels from the eprom
      fadeTo = dimValue = 0;
      byte oldLevel = loadLevelState(EEPROM_DIM_LEVEL_LAST);
      Serial.print("Sending in last known light level to controller: ");
      Serial.println(oldLevel);  
      send(dimmerMsg.set(oldLevel), true);   
    
      Serial.println("Ready to receive messages...");  
    }
    
    void presentation() {
      // Send the Sketch Version Information to the Gateway
      present(CHILD_ID_LIGHT, S_DIMMER);
      sendSketchInfo(SN, SV);
    }
    
    void loop()      
    {
      // Check if someone turned the rotary encode
      checkRotaryEncoder();
    
      // Check if someone has pressed the knob button
      checkButtonClick();
    
      // Fade light to new dim value
      fadeStep();
    }
    
    void receive(const MyMessage &message)
    {
      if (message.type == V_LIGHT) {
        // Incoming on/off command sent from controller ("1" or "0")
        int lightState = message.getString()[0] == '1';
        int newLevel = 0;
        if (lightState==LIGHT_ON) {
          // Pick up last saved dimmer level from the eeprom
          newLevel = loadLevelState(EEPROM_DIM_LEVEL_SAVE);
        } 
        // Send dimmer level back to controller with ack enabled
        send(dimmerMsg.set(newLevel), true);
        // We do not change any levels here until ack comes back from gateway 
        return;
      } else if (message.type == S_DIMMER) {
        // Incoming dim-level command sent from controller (or ack message)
        fadeTo = atoi(message.getString(convBuffer));
        // Save received dim value to eeprom (unless turned off). Will be
        // retreived when a on command comes in
        if (fadeTo != 0)
          saveLevelState(EEPROM_DIM_LEVEL_SAVE, fadeTo);
      }
      saveLevelState(EEPROM_DIM_LEVEL_LAST, fadeTo);
    
      Serial.print("New light level received: ");
      Serial.println(fadeTo);
    
      if (!changedByKnob) 
        knob.write(fadeTo); 
    
      // Cancel send if user turns knob while message comes in
      changedByKnob = false;
      sendDimValue = false;
    
      // Stard fading to new light level
      startFade();
    }
    
    
    
    void checkRotaryEncoder() {
      long encoderValue = knob.read();
    
      if (encoderValue > 100) {
        encoderValue = 100;
        knob.write(100);
      } else if (encoderValue < 0) {
        encoderValue = 0;
        knob.write(0);
      }
    
      if (encoderValue != fadeTo) { 
        fadeTo = encoderValue;
        changedByKnob = true;
        startFade();
      }
    }
    
    void checkButtonClick() {
      debouncer.update();
      byte buttonVal = debouncer.read();
      byte newLevel = 0;
      if (buttonVal != oldButtonVal && buttonVal == LOW) {
        if (dimValue==0) {
          // Turn on light. Set the level to last saved dim value
          int saved = loadLevelState(EEPROM_DIM_LEVEL_SAVE);
          newLevel = saved > 0 ? saved : 100;
        }
        send(dimmerMsg.set(newLevel),true);
      }
      oldButtonVal = buttonVal;
    }
    
    void startFade() {
      fadeDelta = ( fadeTo - dimValue ) < 0 ? -1 : 1;
      lastFadeStep = millis();
    }
    
    // This method provides a graceful none-blocking fade up/down effect
    void fadeStep() {
      unsigned long currentTime  = millis();
      if ( dimValue != fadeTo && currentTime > lastFadeStep + FADE_DELAY) {
        dimValue += fadeDelta;
        analogWrite( LED_PIN, (int)(dimValue / 100. * 255) );
        lastFadeStep = currentTime;
    
        Serial.print("Fading level: ");
        Serial.println(dimValue);
    
        if (fadeTo == dimValue && changedByKnob) {
          sendDimValue = true;
          sendDimTimeout = currentTime;
        }
      } 
      // Wait a few millisecs before sending in new value (if user still turns the knob)
      if (sendDimValue && currentTime > sendDimTimeout + SEND_THROTTLE_DELAY)  {
         // We're done fading.. send in new dim-value to controller.
         // Send in new dim value with ack (will be picked up in incomingMessage) 
        send(dimmerMsg.set(dimValue), true); // Send new dimmer value and request ack back
        sendDimValue = false;
      }
    }
    
    // Make sure only to store/fetch values in the range 0-100 from eeprom
    int loadLevelState(byte pos) {
      return min(max(loadState(pos),0),100);
    }
    void saveLevelState(byte pos, byte data) {
      saveState(pos,min(max(data,0),100));
    }```
    H 1 Reply Last reply
    0
    • I Offline
      I Offline
      itbeyond
      wrote on last edited by itbeyond
      #2

      @vladimir I really think you need to look at this in the serial monitor and add some serial.print lines in the associated places in the code to see what is going on.

      vladimirV 1 Reply Last reply
      0
      • I itbeyond

        @vladimir I really think you need to look at this in the serial monitor and add some serial.print lines in the associated places in the code to see what is going on.

        vladimirV Offline
        vladimirV Offline
        vladimir
        wrote on last edited by
        #3

        @itbeyond said in Problem with dimmable LED actuator with encoder:

        @vladimir I really think you need to look at this in the serial monitor and add some serial.print lines in the associated places in the code to see what is going on.

        Can you tell me where exactly to add?

        1 Reply Last reply
        0
        • vladimirV vladimir

          Hi all!

          I'm using OpenHAB 2, and I have some problems with the sketch code "DimmableLightWithRotaryEncoderButton".

          When the encoder button is pressed, the switch in OpenHAB does not respond.
          When turn the encoder knob one step, the value changes in two steps.
          Maybe you have encountered such a problem? Or maybe you can share a more modern sketch?

          /**
           * The MySensors Arduino library handles the wireless radio link and protocol
           * between your home built sensors/actuators and HA controller of choice.
           * The sensors forms a self healing radio network with optional repeaters. Each
           * repeater and gateway builds a routing tables in EEPROM which keeps track of the
           * network topology allowing messages to be routed to nodes.
           *
           * Created by Henrik Ekblad <henrik.ekblad@mysensors.org>
           * Copyright (C) 2013-2015 Sensnology AB
           * Full contributor list: https://github.com/mysensors/Arduino/graphs/contributors
           *
           * Documentation: http://www.mysensors.org
           * Support Forum: http://forum.mysensors.org
           *
           * 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.
           *
           *******************************
           *
           * REVISION HISTORY
           * Version 1.0 - Developed by Bruce Lacey and GizMoCuz (Domoticz)
           * Version 1.1 - Modified by hek to incorporate a rotary encode to adjust 
           *                                light level locally at node
           * 
           * DESCRIPTION
           * This sketch provides an example how to implement a dimmable led light node with a rotary 
           * encoder connected for adjusting light level. 
           * The encoder has a click button which turns on/off the light (and remembers last dim-level) 
           * The sketch fades the light (non-blocking) to the desired level. 
           *
           * Default MOSFET pin is 3
           * 
           *  Arduino      Encoder module
           *  ---------------------------
           *  5V           5V (+)  
           *  GND          GND (-)
           *  4            CLK (or putput 1)
           *  5            DT  (or output 1) 
           *  6            SW (Switch/Click)  
           */
          
          
          // Enable debug prints
          #define MY_DEBUG
          
          // Enable and select radio type attached
          #define MY_RADIO_NRF24
          //#define MY_RADIO_RFM69
          
          #include <SPI.h>
          #include <MySensors.h>  
          #include <Bounce2.h>
          #include <Encoder.h>
          
          #define LED_PIN 3           // Arduino pin attached to MOSFET Gate pin
          #define KNOB_ENC_PIN_1 4    // Rotary encoder input pin 1
          #define KNOB_ENC_PIN_2 5    // Rotary encoder input pin 2
          #define KNOB_BUTTON_PIN 6   // Rotary encoder button pin 
          #define FADE_DELAY 10       // Delay in ms for each percentage fade up/down (10ms = 1s full-range dim)
          #define SEND_THROTTLE_DELAY 400 // Number of milliseconds before sending after user stops turning knob
          #define SN "DimmableLED /w button"
          #define SV "1.2"
          
          #define CHILD_ID_LIGHT 1
          
          #define EEPROM_DIM_LEVEL_LAST 1
          #define EEPROM_DIM_LEVEL_SAVE 2
          
          #define LIGHT_OFF 0
          #define LIGHT_ON 1
          
          int dimValue;
          int fadeTo;
          int fadeDelta;
          byte oldButtonVal;
          bool changedByKnob=false;
          bool sendDimValue=false;
          unsigned long lastFadeStep;
          unsigned long sendDimTimeout;
          char convBuffer[10];
          
          MyMessage dimmerMsg(CHILD_ID_LIGHT, V_DIMMER);
          Encoder knob(KNOB_ENC_PIN_1, KNOB_ENC_PIN_2);  
          Bounce debouncer = Bounce(); 
          
          void setup()  
          { 
            // Set knob button pin as input (with debounce)
            pinMode(KNOB_BUTTON_PIN, INPUT);
            digitalWrite(KNOB_BUTTON_PIN, HIGH);
            debouncer.attach(KNOB_BUTTON_PIN);
            debouncer.interval(5);
            oldButtonVal = debouncer.read();
          
            // Set analog led pin to off
            analogWrite( LED_PIN, 0);
          
            // Retreive our last dim levels from the eprom
            fadeTo = dimValue = 0;
            byte oldLevel = loadLevelState(EEPROM_DIM_LEVEL_LAST);
            Serial.print("Sending in last known light level to controller: ");
            Serial.println(oldLevel);  
            send(dimmerMsg.set(oldLevel), true);   
          
            Serial.println("Ready to receive messages...");  
          }
          
          void presentation() {
            // Send the Sketch Version Information to the Gateway
            present(CHILD_ID_LIGHT, S_DIMMER);
            sendSketchInfo(SN, SV);
          }
          
          void loop()      
          {
            // Check if someone turned the rotary encode
            checkRotaryEncoder();
          
            // Check if someone has pressed the knob button
            checkButtonClick();
          
            // Fade light to new dim value
            fadeStep();
          }
          
          void receive(const MyMessage &message)
          {
            if (message.type == V_LIGHT) {
              // Incoming on/off command sent from controller ("1" or "0")
              int lightState = message.getString()[0] == '1';
              int newLevel = 0;
              if (lightState==LIGHT_ON) {
                // Pick up last saved dimmer level from the eeprom
                newLevel = loadLevelState(EEPROM_DIM_LEVEL_SAVE);
              } 
              // Send dimmer level back to controller with ack enabled
              send(dimmerMsg.set(newLevel), true);
              // We do not change any levels here until ack comes back from gateway 
              return;
            } else if (message.type == S_DIMMER) {
              // Incoming dim-level command sent from controller (or ack message)
              fadeTo = atoi(message.getString(convBuffer));
              // Save received dim value to eeprom (unless turned off). Will be
              // retreived when a on command comes in
              if (fadeTo != 0)
                saveLevelState(EEPROM_DIM_LEVEL_SAVE, fadeTo);
            }
            saveLevelState(EEPROM_DIM_LEVEL_LAST, fadeTo);
          
            Serial.print("New light level received: ");
            Serial.println(fadeTo);
          
            if (!changedByKnob) 
              knob.write(fadeTo); 
          
            // Cancel send if user turns knob while message comes in
            changedByKnob = false;
            sendDimValue = false;
          
            // Stard fading to new light level
            startFade();
          }
          
          
          
          void checkRotaryEncoder() {
            long encoderValue = knob.read();
          
            if (encoderValue > 100) {
              encoderValue = 100;
              knob.write(100);
            } else if (encoderValue < 0) {
              encoderValue = 0;
              knob.write(0);
            }
          
            if (encoderValue != fadeTo) { 
              fadeTo = encoderValue;
              changedByKnob = true;
              startFade();
            }
          }
          
          void checkButtonClick() {
            debouncer.update();
            byte buttonVal = debouncer.read();
            byte newLevel = 0;
            if (buttonVal != oldButtonVal && buttonVal == LOW) {
              if (dimValue==0) {
                // Turn on light. Set the level to last saved dim value
                int saved = loadLevelState(EEPROM_DIM_LEVEL_SAVE);
                newLevel = saved > 0 ? saved : 100;
              }
              send(dimmerMsg.set(newLevel),true);
            }
            oldButtonVal = buttonVal;
          }
          
          void startFade() {
            fadeDelta = ( fadeTo - dimValue ) < 0 ? -1 : 1;
            lastFadeStep = millis();
          }
          
          // This method provides a graceful none-blocking fade up/down effect
          void fadeStep() {
            unsigned long currentTime  = millis();
            if ( dimValue != fadeTo && currentTime > lastFadeStep + FADE_DELAY) {
              dimValue += fadeDelta;
              analogWrite( LED_PIN, (int)(dimValue / 100. * 255) );
              lastFadeStep = currentTime;
          
              Serial.print("Fading level: ");
              Serial.println(dimValue);
          
              if (fadeTo == dimValue && changedByKnob) {
                sendDimValue = true;
                sendDimTimeout = currentTime;
              }
            } 
            // Wait a few millisecs before sending in new value (if user still turns the knob)
            if (sendDimValue && currentTime > sendDimTimeout + SEND_THROTTLE_DELAY)  {
               // We're done fading.. send in new dim-value to controller.
               // Send in new dim value with ack (will be picked up in incomingMessage) 
              send(dimmerMsg.set(dimValue), true); // Send new dimmer value and request ack back
              sendDimValue = false;
            }
          }
          
          // Make sure only to store/fetch values in the range 0-100 from eeprom
          int loadLevelState(byte pos) {
            return min(max(loadState(pos),0),100);
          }
          void saveLevelState(byte pos, byte data) {
            saveState(pos,min(max(data,0),100));
          }```
          H Offline
          H Offline
          hard-shovel
          wrote on last edited by
          #4

          @vladimir
          To deal with the encoder giving two pulses per indent change the following two lines in checkRotaryEncoder:

          //-------------------------------------------------------
          void checkRotaryEncoder() {
            long encoderValue = knob.read()>>1 ;      //### Divide by 2 (using shift right) 
          
            if (encoderValue > 100) {   
              encoderValue = 100;       
              knob.write(200);                        //### max value now 200 due to divide by 2
            } else if (encoderValue < 0) {
              encoderValue = 0;
              knob.write(0);
            }
          
            if (encoderValue != fadeTo) {    
              fadeTo = encoderValue;                   
              changedByKnob = true;
              startFade();
            }
          }
          

          and the receive function change one line

           if (!changedByKnob) 
              knob.write(fadeTo<<1);             //### need to multiply by two (using Shift left)
          

          If you use a different encoder you may have to change back these settings to the original

          For the switch Pushbutton problem change the two lines in the receive function section

            if (message.type == V_STATUS) {  //## change from V_LIGHT
          
          
             } else if (message.type == V_PERCENTAGE) {    //## change from V_DIMMER
          
          vladimirV 1 Reply Last reply
          1
          • H hard-shovel

            @vladimir
            To deal with the encoder giving two pulses per indent change the following two lines in checkRotaryEncoder:

            //-------------------------------------------------------
            void checkRotaryEncoder() {
              long encoderValue = knob.read()>>1 ;      //### Divide by 2 (using shift right) 
            
              if (encoderValue > 100) {   
                encoderValue = 100;       
                knob.write(200);                        //### max value now 200 due to divide by 2
              } else if (encoderValue < 0) {
                encoderValue = 0;
                knob.write(0);
              }
            
              if (encoderValue != fadeTo) {    
                fadeTo = encoderValue;                   
                changedByKnob = true;
                startFade();
              }
            }
            

            and the receive function change one line

             if (!changedByKnob) 
                knob.write(fadeTo<<1);             //### need to multiply by two (using Shift left)
            

            If you use a different encoder you may have to change back these settings to the original

            For the switch Pushbutton problem change the two lines in the receive function section

              if (message.type == V_STATUS) {  //## change from V_LIGHT
            
            
               } else if (message.type == V_PERCENTAGE) {    //## change from V_DIMMER
            
            vladimirV Offline
            vladimirV Offline
            vladimir
            wrote on last edited by
            #5

            @hard-shovel thanks for the answer!
            The encoder started working as it should! There was only a problem with the switch in OpenHAB. It does not switch when you press a button on the device. The feeling that OpenHAB does not get the status of this switch. The device works well.
            In this video, I clearly demonstrated the problem: https://cloud.mail.ru/public/4fee/HiVX5ZSxh

            Maybe you know what the problem is? I made all the changes you wrote to me in the previous message. Here is the updated device code:

            /**
             * The MySensors Arduino library handles the wireless radio link and protocol
             * between your home built sensors/actuators and HA controller of choice.
             * The sensors forms a self healing radio network with optional repeaters. Each
             * repeater and gateway builds a routing tables in EEPROM which keeps track of the
             * network topology allowing messages to be routed to nodes.
             *
             * Created by Henrik Ekblad <henrik.ekblad@mysensors.org>
             * Copyright (C) 2013-2015 Sensnology AB
             * Full contributor list: https://github.com/mysensors/Arduino/graphs/contributors
             *
             * Documentation: http://www.mysensors.org
             * Support Forum: http://forum.mysensors.org
             *
             * 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.
             *
             *******************************
             *
             * REVISION HISTORY
             * Version 1.0 - Developed by Bruce Lacey and GizMoCuz (Domoticz)
             * Version 1.1 - Modified by hek to incorporate a rotary encode to adjust 
             *                                light level locally at node
             * 
             * DESCRIPTION
             * This sketch provides an example how to implement a dimmable led light node with a rotary 
             * encoder connected for adjusting light level. 
             * The encoder has a click button which turns on/off the light (and remembers last dim-level) 
             * The sketch fades the light (non-blocking) to the desired level. 
             *
             * Default MOSFET pin is 3
             * 
             *  Arduino      Encoder module
             *  ---------------------------
             *  5V           5V (+)  
             *  GND          GND (-)
             *  4            CLK (or putput 1)
             *  5            DT  (or output 1) 
             *  6            SW (Switch/Click)  
             */
            
             
            // Enable debug prints
            #define MY_DEBUG
            
            // Enable and select radio type attached
            #define MY_RADIO_NRF24
            //#define MY_RADIO_RFM69
            
            #include <SPI.h>
            #include <MySensors.h>  
            #include <Bounce2.h>
            #include <Encoder.h>
            
            #define LED_PIN 3           // Arduino pin attached to MOSFET Gate pin
            #define KNOB_ENC_PIN_1 4    // Rotary encoder input pin 1
            #define KNOB_ENC_PIN_2 5    // Rotary encoder input pin 2
            #define KNOB_BUTTON_PIN 6   // Rotary encoder button pin 
            #define FADE_DELAY 10       // Delay in ms for each percentage fade up/down (10ms = 1s full-range dim)
            #define SEND_THROTTLE_DELAY 400 // Number of milliseconds before sending after user stops turning knob
            #define SN "DimmableLED /w button"
            #define SV "1.2"
            
            #define CHILD_ID_LIGHT 1
            
            #define EEPROM_DIM_LEVEL_LAST 1
            #define EEPROM_DIM_LEVEL_SAVE 2
            
            #define LIGHT_OFF 0
            #define LIGHT_ON 1
            
            int dimValue;
            int fadeTo;
            int fadeDelta;
            byte oldButtonVal;
            bool changedByKnob=false;
            bool sendDimValue=false;
            unsigned long lastFadeStep;
            unsigned long sendDimTimeout;
            char convBuffer[10];
            
            MyMessage dimmerMsg(CHILD_ID_LIGHT, V_DIMMER);
            Encoder knob(KNOB_ENC_PIN_1, KNOB_ENC_PIN_2);  
            Bounce debouncer = Bounce(); 
            
            void setup()  
            { 
              // Set knob button pin as input (with debounce)
              pinMode(KNOB_BUTTON_PIN, INPUT);
              digitalWrite(KNOB_BUTTON_PIN, HIGH);
              debouncer.attach(KNOB_BUTTON_PIN);
              debouncer.interval(5);
              oldButtonVal = debouncer.read();
            
              // Set analog led pin to off
              analogWrite( LED_PIN, 0);
            
              // Retreive our last dim levels from the eprom
              fadeTo = dimValue = 0;
              byte oldLevel = loadLevelState(EEPROM_DIM_LEVEL_LAST);
              Serial.print("Sending in last known light level to controller: ");
              Serial.println(oldLevel);  
              send(dimmerMsg.set(oldLevel), true);   
            
              Serial.println("Ready to receive messages...");  
            }
            
            void presentation() {
              // Send the Sketch Version Information to the Gateway
              present(CHILD_ID_LIGHT, S_DIMMER);
              sendSketchInfo(SN, SV);
            }
            
            void loop()      
            {
              // Check if someone turned the rotary encode
              checkRotaryEncoder();
              
              // Check if someone has pressed the knob button
              checkButtonClick();
              
              // Fade light to new dim value
              fadeStep();
            }
            
            void receive(const MyMessage &message)
            {
              if (message.type == V_STATUS) {
                // Incoming on/off command sent from controller ("1" or "0")
                int lightState = message.getString()[0] == '1';
                int newLevel = 0;
                if (lightState==LIGHT_ON) {
                  // Pick up last saved dimmer level from the eeprom
                  newLevel = loadLevelState(EEPROM_DIM_LEVEL_SAVE);
                } 
                // Send dimmer level back to controller with ack enabled
                send(dimmerMsg.set(newLevel), true);
                // We do not change any levels here until ack comes back from gateway 
                return;
              } else if (message.type == V_PERCENTAGE) {
                // Incoming dim-level command sent from controller (or ack message)
                fadeTo = atoi(message.getString(convBuffer));
                // Save received dim value to eeprom (unless turned off). Will be
                // retreived when a on command comes in
                if (fadeTo != 0)
                  saveLevelState(EEPROM_DIM_LEVEL_SAVE, fadeTo);
              }
              saveLevelState(EEPROM_DIM_LEVEL_LAST, fadeTo);
              
              Serial.print("New light level received: ");
              Serial.println(fadeTo);
            
              if (!changedByKnob) 
                knob.write(fadeTo<<1);             //### need to multiply by two (using Shift left)
                
              // Cancel send if user turns knob while message comes in
              changedByKnob = false;
              sendDimValue = false;
            
              // Stard fading to new light level
              startFade();
            }
            
            
            
            void checkRotaryEncoder() {
              long encoderValue = knob.read()>>1 ;      //### Divide by 2 (using shift right) 
            
              if (encoderValue > 100) {   
                encoderValue = 100;       
                knob.write(200);                        //### max value now 200 due to divide by 2
              } else if (encoderValue < 0) {
                encoderValue = 0;
                knob.write(0);
              }
            
              if (encoderValue != fadeTo) {    
                fadeTo = encoderValue;                   
                changedByKnob = true;
                startFade();
              }
            }
            
            void checkButtonClick() {
              debouncer.update();
              byte buttonVal = debouncer.read();
              byte newLevel = 0;
              if (buttonVal != oldButtonVal && buttonVal == LOW) {
                if (dimValue==0) {
                  // Turn on light. Set the level to last saved dim value
                  int saved = loadLevelState(EEPROM_DIM_LEVEL_SAVE);
                  newLevel = saved > 0 ? saved : 100;
                }
                send(dimmerMsg.set(newLevel),true);
              }
              oldButtonVal = buttonVal;
            }
            
            void startFade() {
              fadeDelta = ( fadeTo - dimValue ) < 0 ? -1 : 1;
              lastFadeStep = millis();
            }
            
            // This method provides a graceful none-blocking fade up/down effect
            void fadeStep() {
              unsigned long currentTime  = millis();
              if ( dimValue != fadeTo && currentTime > lastFadeStep + FADE_DELAY) {
                dimValue += fadeDelta;
                analogWrite( LED_PIN, (int)(dimValue / 100. * 255) );
                lastFadeStep = currentTime;
                
                Serial.print("Fading level: ");
                Serial.println(dimValue);
            
                if (fadeTo == dimValue && changedByKnob) {
                  sendDimValue = true;
                  sendDimTimeout = currentTime;
                }
              } 
              // Wait a few millisecs before sending in new value (if user still turns the knob)
              if (sendDimValue && currentTime > sendDimTimeout + SEND_THROTTLE_DELAY)  {
                 // We're done fading.. send in new dim-value to controller.
                 // Send in new dim value with ack (will be picked up in incomingMessage) 
                send(dimmerMsg.set(dimValue), true); // Send new dimmer value and request ack back
                sendDimValue = false;
              }
            }
            
            // Make sure only to store/fetch values in the range 0-100 from eeprom
            int loadLevelState(byte pos) {
              return min(max(loadState(pos),0),100);
            }
            void saveLevelState(byte pos, byte data) {
              saveState(pos,min(max(data,0),100));
            }
            
            H 1 Reply Last reply
            1
            • vladimirV vladimir

              @hard-shovel thanks for the answer!
              The encoder started working as it should! There was only a problem with the switch in OpenHAB. It does not switch when you press a button on the device. The feeling that OpenHAB does not get the status of this switch. The device works well.
              In this video, I clearly demonstrated the problem: https://cloud.mail.ru/public/4fee/HiVX5ZSxh

              Maybe you know what the problem is? I made all the changes you wrote to me in the previous message. Here is the updated device code:

              /**
               * The MySensors Arduino library handles the wireless radio link and protocol
               * between your home built sensors/actuators and HA controller of choice.
               * The sensors forms a self healing radio network with optional repeaters. Each
               * repeater and gateway builds a routing tables in EEPROM which keeps track of the
               * network topology allowing messages to be routed to nodes.
               *
               * Created by Henrik Ekblad <henrik.ekblad@mysensors.org>
               * Copyright (C) 2013-2015 Sensnology AB
               * Full contributor list: https://github.com/mysensors/Arduino/graphs/contributors
               *
               * Documentation: http://www.mysensors.org
               * Support Forum: http://forum.mysensors.org
               *
               * 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.
               *
               *******************************
               *
               * REVISION HISTORY
               * Version 1.0 - Developed by Bruce Lacey and GizMoCuz (Domoticz)
               * Version 1.1 - Modified by hek to incorporate a rotary encode to adjust 
               *                                light level locally at node
               * 
               * DESCRIPTION
               * This sketch provides an example how to implement a dimmable led light node with a rotary 
               * encoder connected for adjusting light level. 
               * The encoder has a click button which turns on/off the light (and remembers last dim-level) 
               * The sketch fades the light (non-blocking) to the desired level. 
               *
               * Default MOSFET pin is 3
               * 
               *  Arduino      Encoder module
               *  ---------------------------
               *  5V           5V (+)  
               *  GND          GND (-)
               *  4            CLK (or putput 1)
               *  5            DT  (or output 1) 
               *  6            SW (Switch/Click)  
               */
              
               
              // Enable debug prints
              #define MY_DEBUG
              
              // Enable and select radio type attached
              #define MY_RADIO_NRF24
              //#define MY_RADIO_RFM69
              
              #include <SPI.h>
              #include <MySensors.h>  
              #include <Bounce2.h>
              #include <Encoder.h>
              
              #define LED_PIN 3           // Arduino pin attached to MOSFET Gate pin
              #define KNOB_ENC_PIN_1 4    // Rotary encoder input pin 1
              #define KNOB_ENC_PIN_2 5    // Rotary encoder input pin 2
              #define KNOB_BUTTON_PIN 6   // Rotary encoder button pin 
              #define FADE_DELAY 10       // Delay in ms for each percentage fade up/down (10ms = 1s full-range dim)
              #define SEND_THROTTLE_DELAY 400 // Number of milliseconds before sending after user stops turning knob
              #define SN "DimmableLED /w button"
              #define SV "1.2"
              
              #define CHILD_ID_LIGHT 1
              
              #define EEPROM_DIM_LEVEL_LAST 1
              #define EEPROM_DIM_LEVEL_SAVE 2
              
              #define LIGHT_OFF 0
              #define LIGHT_ON 1
              
              int dimValue;
              int fadeTo;
              int fadeDelta;
              byte oldButtonVal;
              bool changedByKnob=false;
              bool sendDimValue=false;
              unsigned long lastFadeStep;
              unsigned long sendDimTimeout;
              char convBuffer[10];
              
              MyMessage dimmerMsg(CHILD_ID_LIGHT, V_DIMMER);
              Encoder knob(KNOB_ENC_PIN_1, KNOB_ENC_PIN_2);  
              Bounce debouncer = Bounce(); 
              
              void setup()  
              { 
                // Set knob button pin as input (with debounce)
                pinMode(KNOB_BUTTON_PIN, INPUT);
                digitalWrite(KNOB_BUTTON_PIN, HIGH);
                debouncer.attach(KNOB_BUTTON_PIN);
                debouncer.interval(5);
                oldButtonVal = debouncer.read();
              
                // Set analog led pin to off
                analogWrite( LED_PIN, 0);
              
                // Retreive our last dim levels from the eprom
                fadeTo = dimValue = 0;
                byte oldLevel = loadLevelState(EEPROM_DIM_LEVEL_LAST);
                Serial.print("Sending in last known light level to controller: ");
                Serial.println(oldLevel);  
                send(dimmerMsg.set(oldLevel), true);   
              
                Serial.println("Ready to receive messages...");  
              }
              
              void presentation() {
                // Send the Sketch Version Information to the Gateway
                present(CHILD_ID_LIGHT, S_DIMMER);
                sendSketchInfo(SN, SV);
              }
              
              void loop()      
              {
                // Check if someone turned the rotary encode
                checkRotaryEncoder();
                
                // Check if someone has pressed the knob button
                checkButtonClick();
                
                // Fade light to new dim value
                fadeStep();
              }
              
              void receive(const MyMessage &message)
              {
                if (message.type == V_STATUS) {
                  // Incoming on/off command sent from controller ("1" or "0")
                  int lightState = message.getString()[0] == '1';
                  int newLevel = 0;
                  if (lightState==LIGHT_ON) {
                    // Pick up last saved dimmer level from the eeprom
                    newLevel = loadLevelState(EEPROM_DIM_LEVEL_SAVE);
                  } 
                  // Send dimmer level back to controller with ack enabled
                  send(dimmerMsg.set(newLevel), true);
                  // We do not change any levels here until ack comes back from gateway 
                  return;
                } else if (message.type == V_PERCENTAGE) {
                  // Incoming dim-level command sent from controller (or ack message)
                  fadeTo = atoi(message.getString(convBuffer));
                  // Save received dim value to eeprom (unless turned off). Will be
                  // retreived when a on command comes in
                  if (fadeTo != 0)
                    saveLevelState(EEPROM_DIM_LEVEL_SAVE, fadeTo);
                }
                saveLevelState(EEPROM_DIM_LEVEL_LAST, fadeTo);
                
                Serial.print("New light level received: ");
                Serial.println(fadeTo);
              
                if (!changedByKnob) 
                  knob.write(fadeTo<<1);             //### need to multiply by two (using Shift left)
                  
                // Cancel send if user turns knob while message comes in
                changedByKnob = false;
                sendDimValue = false;
              
                // Stard fading to new light level
                startFade();
              }
              
              
              
              void checkRotaryEncoder() {
                long encoderValue = knob.read()>>1 ;      //### Divide by 2 (using shift right) 
              
                if (encoderValue > 100) {   
                  encoderValue = 100;       
                  knob.write(200);                        //### max value now 200 due to divide by 2
                } else if (encoderValue < 0) {
                  encoderValue = 0;
                  knob.write(0);
                }
              
                if (encoderValue != fadeTo) {    
                  fadeTo = encoderValue;                   
                  changedByKnob = true;
                  startFade();
                }
              }
              
              void checkButtonClick() {
                debouncer.update();
                byte buttonVal = debouncer.read();
                byte newLevel = 0;
                if (buttonVal != oldButtonVal && buttonVal == LOW) {
                  if (dimValue==0) {
                    // Turn on light. Set the level to last saved dim value
                    int saved = loadLevelState(EEPROM_DIM_LEVEL_SAVE);
                    newLevel = saved > 0 ? saved : 100;
                  }
                  send(dimmerMsg.set(newLevel),true);
                }
                oldButtonVal = buttonVal;
              }
              
              void startFade() {
                fadeDelta = ( fadeTo - dimValue ) < 0 ? -1 : 1;
                lastFadeStep = millis();
              }
              
              // This method provides a graceful none-blocking fade up/down effect
              void fadeStep() {
                unsigned long currentTime  = millis();
                if ( dimValue != fadeTo && currentTime > lastFadeStep + FADE_DELAY) {
                  dimValue += fadeDelta;
                  analogWrite( LED_PIN, (int)(dimValue / 100. * 255) );
                  lastFadeStep = currentTime;
                  
                  Serial.print("Fading level: ");
                  Serial.println(dimValue);
              
                  if (fadeTo == dimValue && changedByKnob) {
                    sendDimValue = true;
                    sendDimTimeout = currentTime;
                  }
                } 
                // Wait a few millisecs before sending in new value (if user still turns the knob)
                if (sendDimValue && currentTime > sendDimTimeout + SEND_THROTTLE_DELAY)  {
                   // We're done fading.. send in new dim-value to controller.
                   // Send in new dim value with ack (will be picked up in incomingMessage) 
                  send(dimmerMsg.set(dimValue), true); // Send new dimmer value and request ack back
                  sendDimValue = false;
                }
              }
              
              // Make sure only to store/fetch values in the range 0-100 from eeprom
              int loadLevelState(byte pos) {
                return min(max(loadState(pos),0),100);
              }
              void saveLevelState(byte pos, byte data) {
                saveState(pos,min(max(data,0),100));
              }
              
              H Offline
              H Offline
              hard-shovel
              wrote on last edited by
              #6

              @vladimir
              I see the problem now
              When operating from Node, if you switch on or off the Switch indicator (Status) does not update.

              Try this method:
              Add the additional message line

              MyMessage statusMsg(CHILD_ID_LIGHT, V_STATUS);    // Addition for Status update to OpenHAB Controller
              

              and this in the check button function

                  send(statusMsg.set(newLevel>0 ? "1" : "0"),true); // Addition for Status update to OpenHAB Controller
              

              so complete code:

               * The sketch fades the light (non-blocking) to the desired level. 
               *
               * Default MOSFET pin is 3
               * 
               *  Arduino      Encoder module
               *  ---------------------------
               *  5V           5V (+)  
               *  GND          GND (-)
               *  4            CLK (or putput 1)
               *  5            DT  (or output 1) 
               *  6            SW (Switch/Click)  
               */
              
               
              // Enable debug prints
              #define MY_DEBUG
              
              // Enable and select radio type attached
              #define MY_RADIO_NRF24
              //#define MY_RADIO_RFM69
              
              #include <SPI.h>
              #include <MySensors.h>  
              #include <Bounce2.h>
              #include <Encoder.h>
              
              #define LED_PIN 3           // Arduino pin attached to MOSFET Gate pin
              #define KNOB_ENC_PIN_1 4    // Rotary encoder input pin 1
              #define KNOB_ENC_PIN_2 5    // Rotary encoder input pin 2
              #define KNOB_BUTTON_PIN 6   // Rotary encoder button pin 
              #define FADE_DELAY 10       // Delay in ms for each percentage fade up/down (10ms = 1s full-range dim)
              #define SEND_THROTTLE_DELAY 400 // Number of milliseconds before sending after user stops turning knob
              #define SN "DimmableLED /w button"
              #define SV "1.2"
              
              #define CHILD_ID_LIGHT 1
              
              #define EEPROM_DIM_LEVEL_LAST 1
              #define EEPROM_DIM_LEVEL_SAVE 2
              
              #define LIGHT_OFF 0
              #define LIGHT_ON 1
              
              int dimValue;
              int fadeTo;
              int fadeDelta;
              byte oldButtonVal;
              bool changedByKnob=false;
              bool sendDimValue=false;
              unsigned long lastFadeStep;
              unsigned long sendDimTimeout;
              char convBuffer[10];
              
              MyMessage dimmerMsg(CHILD_ID_LIGHT, V_DIMMER);
              MyMessage statusMsg(CHILD_ID_LIGHT, V_STATUS);    // Addition for Status update to OpenHAB Controller
              Encoder knob(KNOB_ENC_PIN_1, KNOB_ENC_PIN_2);  
              Bounce debouncer = Bounce(); 
              
              void setup()  
              { 
                // Set knob button pin as input (with debounce)
                pinMode(KNOB_BUTTON_PIN, INPUT);
                digitalWrite(KNOB_BUTTON_PIN, HIGH);
                debouncer.attach(KNOB_BUTTON_PIN);
                debouncer.interval(5);
                oldButtonVal = debouncer.read();
              
                // Set analog led pin to off
                analogWrite( LED_PIN, 0);
              
                // Retreive our last dim levels from the eprom
                fadeTo = dimValue = 0;
                byte oldLevel = loadLevelState(EEPROM_DIM_LEVEL_LAST);
                Serial.print("Sending in last known light level to controller: ");
                Serial.println(oldLevel);  
                send(dimmerMsg.set(oldLevel), true);   
                send(statusMsg.set(newLevel>0 ? "1" : "0"),true); // Addition for Status update to OpenHAB Controller
                Serial.println("Ready to receive messages...");  
              }
              
              void presentation() {
                // Send the Sketch Version Information to the Gateway
                present(CHILD_ID_LIGHT, S_DIMMER);
                sendSketchInfo(SN, SV);
              }
              
              void loop()      
              {
                // Check if someone turned the rotary encode
                checkRotaryEncoder();
                
                // Check if someone has pressed the knob button
                checkButtonClick();
                
                // Fade light to new dim value
                fadeStep();
              }
              
              void receive(const MyMessage &message)
              {
                if (message.type == V_STATUS) {
                  // Incoming on/off command sent from controller ("1" or "0")
                  int lightState = message.getString()[0] == '1';
                  int newLevel = 0;
                  if (lightState==LIGHT_ON) {
                    // Pick up last saved dimmer level from the eeprom
                    newLevel = loadLevelState(EEPROM_DIM_LEVEL_SAVE);
                  } 
                  // Send dimmer level back to controller with ack enabled
                  send(dimmerMsg.set(newLevel), true);
                  // We do not change any levels here until ack comes back from gateway 
                  return;
                } else if (message.type == V_PERCENTAGE) {
                  // Incoming dim-level command sent from controller (or ack message)
                  fadeTo = atoi(message.getString(convBuffer));
                  // Save received dim value to eeprom (unless turned off). Will be
                  // retreived when a on command comes in
                  if (fadeTo != 0)
                    saveLevelState(EEPROM_DIM_LEVEL_SAVE, fadeTo);
                }
                saveLevelState(EEPROM_DIM_LEVEL_LAST, fadeTo);
                
                Serial.print("New light level received: ");
                Serial.println(fadeTo);
              
                if (!changedByKnob) 
                  knob.write(fadeTo<<1);             //### need to multiply by two (using Shift left)
                  
                // Cancel send if user turns knob while message comes in
                changedByKnob = false;
                sendDimValue = false;
              
                // Stard fading to new light level
                startFade();
              }
              
              
              
              void checkRotaryEncoder() {
                long encoderValue = knob.read()>>1 ;      //### Divide by 2 (using shift right) 
              
                if (encoderValue > 100) {   
                  encoderValue = 100;       
                  knob.write(200);                        //### max value now 200 due to divide by 2
                } else if (encoderValue < 0) {
                  encoderValue = 0;
                  knob.write(0);
                }
              
                if (encoderValue != fadeTo) {    
                  fadeTo = encoderValue;                   
                  changedByKnob = true;
                  startFade();
                }
              }
              
              void checkButtonClick() {
                debouncer.update();
                byte buttonVal = debouncer.read();
                byte newLevel = 0;
                if (buttonVal != oldButtonVal && buttonVal == LOW) {
                  if (dimValue==0) {
                    // Turn on light. Set the level to last saved dim value
                    int saved = loadLevelState(EEPROM_DIM_LEVEL_SAVE);
                    newLevel = saved > 0 ? saved : 100;
                  }
                  send(dimmerMsg.set(newLevel),true);
                  send(statusMsg.set(newLevel>0 ? "1" : "0"),true); // Addition for Status update to OpenHAB Controller
                }
                oldButtonVal = buttonVal;
              }
              
              void startFade() {
                fadeDelta = ( fadeTo - dimValue ) < 0 ? -1 : 1;
                lastFadeStep = millis();
              }
              
              // This method provides a graceful none-blocking fade up/down effect
              void fadeStep() {
                unsigned long currentTime  = millis();
                if ( dimValue != fadeTo && currentTime > lastFadeStep + FADE_DELAY) {
                  dimValue += fadeDelta;
                  analogWrite( LED_PIN, (int)(dimValue / 100. * 255) );
                  lastFadeStep = currentTime;
                  
                  Serial.print("Fading level: ");
                  Serial.println(dimValue);
              
                  if (fadeTo == dimValue && changedByKnob) {
                    sendDimValue = true;
                    sendDimTimeout = currentTime;
                  }
                } 
                // Wait a few millisecs before sending in new value (if user still turns the knob)
                if (sendDimValue && currentTime > sendDimTimeout + SEND_THROTTLE_DELAY)  {
                   // We're done fading.. send in new dim-value to controller.
                   // Send in new dim value with ack (will be picked up in incomingMessage) 
                  send(dimmerMsg.set(dimValue), true); // Send new dimmer value and request ack back
                  sendDimValue = false;
                }
              }
              
              // Make sure only to store/fetch values in the range 0-100 from eeprom
              int loadLevelState(byte pos) {
                return min(max(loadState(pos),0),100);
              }
              void saveLevelState(byte pos, byte data) {
                saveState(pos,min(max(data,0),100));
              }
              
              vladimirV 1 Reply Last reply
              0
              • H hard-shovel

                @vladimir
                I see the problem now
                When operating from Node, if you switch on or off the Switch indicator (Status) does not update.

                Try this method:
                Add the additional message line

                MyMessage statusMsg(CHILD_ID_LIGHT, V_STATUS);    // Addition for Status update to OpenHAB Controller
                

                and this in the check button function

                    send(statusMsg.set(newLevel>0 ? "1" : "0"),true); // Addition for Status update to OpenHAB Controller
                

                so complete code:

                 * The sketch fades the light (non-blocking) to the desired level. 
                 *
                 * Default MOSFET pin is 3
                 * 
                 *  Arduino      Encoder module
                 *  ---------------------------
                 *  5V           5V (+)  
                 *  GND          GND (-)
                 *  4            CLK (or putput 1)
                 *  5            DT  (or output 1) 
                 *  6            SW (Switch/Click)  
                 */
                
                 
                // Enable debug prints
                #define MY_DEBUG
                
                // Enable and select radio type attached
                #define MY_RADIO_NRF24
                //#define MY_RADIO_RFM69
                
                #include <SPI.h>
                #include <MySensors.h>  
                #include <Bounce2.h>
                #include <Encoder.h>
                
                #define LED_PIN 3           // Arduino pin attached to MOSFET Gate pin
                #define KNOB_ENC_PIN_1 4    // Rotary encoder input pin 1
                #define KNOB_ENC_PIN_2 5    // Rotary encoder input pin 2
                #define KNOB_BUTTON_PIN 6   // Rotary encoder button pin 
                #define FADE_DELAY 10       // Delay in ms for each percentage fade up/down (10ms = 1s full-range dim)
                #define SEND_THROTTLE_DELAY 400 // Number of milliseconds before sending after user stops turning knob
                #define SN "DimmableLED /w button"
                #define SV "1.2"
                
                #define CHILD_ID_LIGHT 1
                
                #define EEPROM_DIM_LEVEL_LAST 1
                #define EEPROM_DIM_LEVEL_SAVE 2
                
                #define LIGHT_OFF 0
                #define LIGHT_ON 1
                
                int dimValue;
                int fadeTo;
                int fadeDelta;
                byte oldButtonVal;
                bool changedByKnob=false;
                bool sendDimValue=false;
                unsigned long lastFadeStep;
                unsigned long sendDimTimeout;
                char convBuffer[10];
                
                MyMessage dimmerMsg(CHILD_ID_LIGHT, V_DIMMER);
                MyMessage statusMsg(CHILD_ID_LIGHT, V_STATUS);    // Addition for Status update to OpenHAB Controller
                Encoder knob(KNOB_ENC_PIN_1, KNOB_ENC_PIN_2);  
                Bounce debouncer = Bounce(); 
                
                void setup()  
                { 
                  // Set knob button pin as input (with debounce)
                  pinMode(KNOB_BUTTON_PIN, INPUT);
                  digitalWrite(KNOB_BUTTON_PIN, HIGH);
                  debouncer.attach(KNOB_BUTTON_PIN);
                  debouncer.interval(5);
                  oldButtonVal = debouncer.read();
                
                  // Set analog led pin to off
                  analogWrite( LED_PIN, 0);
                
                  // Retreive our last dim levels from the eprom
                  fadeTo = dimValue = 0;
                  byte oldLevel = loadLevelState(EEPROM_DIM_LEVEL_LAST);
                  Serial.print("Sending in last known light level to controller: ");
                  Serial.println(oldLevel);  
                  send(dimmerMsg.set(oldLevel), true);   
                  send(statusMsg.set(newLevel>0 ? "1" : "0"),true); // Addition for Status update to OpenHAB Controller
                  Serial.println("Ready to receive messages...");  
                }
                
                void presentation() {
                  // Send the Sketch Version Information to the Gateway
                  present(CHILD_ID_LIGHT, S_DIMMER);
                  sendSketchInfo(SN, SV);
                }
                
                void loop()      
                {
                  // Check if someone turned the rotary encode
                  checkRotaryEncoder();
                  
                  // Check if someone has pressed the knob button
                  checkButtonClick();
                  
                  // Fade light to new dim value
                  fadeStep();
                }
                
                void receive(const MyMessage &message)
                {
                  if (message.type == V_STATUS) {
                    // Incoming on/off command sent from controller ("1" or "0")
                    int lightState = message.getString()[0] == '1';
                    int newLevel = 0;
                    if (lightState==LIGHT_ON) {
                      // Pick up last saved dimmer level from the eeprom
                      newLevel = loadLevelState(EEPROM_DIM_LEVEL_SAVE);
                    } 
                    // Send dimmer level back to controller with ack enabled
                    send(dimmerMsg.set(newLevel), true);
                    // We do not change any levels here until ack comes back from gateway 
                    return;
                  } else if (message.type == V_PERCENTAGE) {
                    // Incoming dim-level command sent from controller (or ack message)
                    fadeTo = atoi(message.getString(convBuffer));
                    // Save received dim value to eeprom (unless turned off). Will be
                    // retreived when a on command comes in
                    if (fadeTo != 0)
                      saveLevelState(EEPROM_DIM_LEVEL_SAVE, fadeTo);
                  }
                  saveLevelState(EEPROM_DIM_LEVEL_LAST, fadeTo);
                  
                  Serial.print("New light level received: ");
                  Serial.println(fadeTo);
                
                  if (!changedByKnob) 
                    knob.write(fadeTo<<1);             //### need to multiply by two (using Shift left)
                    
                  // Cancel send if user turns knob while message comes in
                  changedByKnob = false;
                  sendDimValue = false;
                
                  // Stard fading to new light level
                  startFade();
                }
                
                
                
                void checkRotaryEncoder() {
                  long encoderValue = knob.read()>>1 ;      //### Divide by 2 (using shift right) 
                
                  if (encoderValue > 100) {   
                    encoderValue = 100;       
                    knob.write(200);                        //### max value now 200 due to divide by 2
                  } else if (encoderValue < 0) {
                    encoderValue = 0;
                    knob.write(0);
                  }
                
                  if (encoderValue != fadeTo) {    
                    fadeTo = encoderValue;                   
                    changedByKnob = true;
                    startFade();
                  }
                }
                
                void checkButtonClick() {
                  debouncer.update();
                  byte buttonVal = debouncer.read();
                  byte newLevel = 0;
                  if (buttonVal != oldButtonVal && buttonVal == LOW) {
                    if (dimValue==0) {
                      // Turn on light. Set the level to last saved dim value
                      int saved = loadLevelState(EEPROM_DIM_LEVEL_SAVE);
                      newLevel = saved > 0 ? saved : 100;
                    }
                    send(dimmerMsg.set(newLevel),true);
                    send(statusMsg.set(newLevel>0 ? "1" : "0"),true); // Addition for Status update to OpenHAB Controller
                  }
                  oldButtonVal = buttonVal;
                }
                
                void startFade() {
                  fadeDelta = ( fadeTo - dimValue ) < 0 ? -1 : 1;
                  lastFadeStep = millis();
                }
                
                // This method provides a graceful none-blocking fade up/down effect
                void fadeStep() {
                  unsigned long currentTime  = millis();
                  if ( dimValue != fadeTo && currentTime > lastFadeStep + FADE_DELAY) {
                    dimValue += fadeDelta;
                    analogWrite( LED_PIN, (int)(dimValue / 100. * 255) );
                    lastFadeStep = currentTime;
                    
                    Serial.print("Fading level: ");
                    Serial.println(dimValue);
                
                    if (fadeTo == dimValue && changedByKnob) {
                      sendDimValue = true;
                      sendDimTimeout = currentTime;
                    }
                  } 
                  // Wait a few millisecs before sending in new value (if user still turns the knob)
                  if (sendDimValue && currentTime > sendDimTimeout + SEND_THROTTLE_DELAY)  {
                     // We're done fading.. send in new dim-value to controller.
                     // Send in new dim value with ack (will be picked up in incomingMessage) 
                    send(dimmerMsg.set(dimValue), true); // Send new dimmer value and request ack back
                    sendDimValue = false;
                  }
                }
                
                // Make sure only to store/fetch values in the range 0-100 from eeprom
                int loadLevelState(byte pos) {
                  return min(max(loadState(pos),0),100);
                }
                void saveLevelState(byte pos, byte data) {
                  saveState(pos,min(max(data,0),100));
                }
                
                vladimirV Offline
                vladimirV Offline
                vladimir
                wrote on last edited by
                #7

                @hard-shovel at compilation produces an error of the following content:

                /Users/vladimirpetrov/Documents/Arduino/Dimmer/Dimmer.ino: In function 'void setup()':
                Dimmer:106: error: 'newLevel' was not declared in this scope
                   send(statusMsg.set(newLevel > 0 ? "1" : "0"),true); // Addition for Status update to OpenHAB Controller
                                      ^
                exit status 1
                'newLevel' was not declared in this scope
                
                H 1 Reply Last reply
                0
                • vladimirV vladimir

                  @hard-shovel at compilation produces an error of the following content:

                  /Users/vladimirpetrov/Documents/Arduino/Dimmer/Dimmer.ino: In function 'void setup()':
                  Dimmer:106: error: 'newLevel' was not declared in this scope
                     send(statusMsg.set(newLevel > 0 ? "1" : "0"),true); // Addition for Status update to OpenHAB Controller
                                        ^
                  exit status 1
                  'newLevel' was not declared in this scope
                  
                  H Offline
                  H Offline
                  hard-shovel
                  wrote on last edited by
                  #8

                  @vladimir
                  Sorry about that it should be the following in the setup function

                    send(statusMsg.set(oldLevel>0 ? "1" : "0"),true); // Addition for Status update to OpenHAB Controller
                  

                  This sends the status of the lamp ON or OFF on startup biased on the dimmer value stored in the eeprom, if you do not want this then just delete this line, or fix the value 1 or 0.

                  vladimirV 1 Reply Last reply
                  0
                  • H hard-shovel

                    @vladimir
                    Sorry about that it should be the following in the setup function

                      send(statusMsg.set(oldLevel>0 ? "1" : "0"),true); // Addition for Status update to OpenHAB Controller
                    

                    This sends the status of the lamp ON or OFF on startup biased on the dimmer value stored in the eeprom, if you do not want this then just delete this line, or fix the value 1 or 0.

                    vladimirV Offline
                    vladimirV Offline
                    vladimir
                    wrote on last edited by
                    #9

                    @hard-shovel switch is working, thanks! Only while he behaves a little unpredictably: video 1, video 2

                    H 1 Reply Last reply
                    0
                    • vladimirV vladimir

                      @hard-shovel switch is working, thanks! Only while he behaves a little unpredictably: video 1, video 2

                      H Offline
                      H Offline
                      hard-shovel
                      wrote on last edited by
                      #10

                      @vladimir
                      I am unsure what you problems is from the video clips.
                      However i do see that you have several NAKS due to radio problems.

                      try this code snippet

                      //-------------------------------------------------------
                      void checkButtonClick() {
                        debouncer.update();
                        byte buttonVal = debouncer.read();
                        byte newLevel = 0;
                        if (buttonVal != oldButtonVal && buttonVal == LOW) {
                          if (dimValue==0) {
                            // Turn on light. Set the level to last saved dim value
                            int saved = loadLevelState(EEPROM_DIM_LEVEL_SAVE);
                            newLevel = saved > 1 ? saved : 100;           // newLevel = saved > 0 ? saved : 100;     
                          } 
                          send(dimmerMsg.set(newLevel),true);
                          send(statusMsg.set(newLevel>0 ? "1" : "0")); // Addition for Status update to OpenHAB Controller,   No Echo
                        }
                        oldButtonVal = buttonVal;
                      }
                      
                      vladimirV 1 Reply Last reply
                      0
                      • H hard-shovel

                        @vladimir
                        I am unsure what you problems is from the video clips.
                        However i do see that you have several NAKS due to radio problems.

                        try this code snippet

                        //-------------------------------------------------------
                        void checkButtonClick() {
                          debouncer.update();
                          byte buttonVal = debouncer.read();
                          byte newLevel = 0;
                          if (buttonVal != oldButtonVal && buttonVal == LOW) {
                            if (dimValue==0) {
                              // Turn on light. Set the level to last saved dim value
                              int saved = loadLevelState(EEPROM_DIM_LEVEL_SAVE);
                              newLevel = saved > 1 ? saved : 100;           // newLevel = saved > 0 ? saved : 100;     
                            } 
                            send(dimmerMsg.set(newLevel),true);
                            send(statusMsg.set(newLevel>0 ? "1" : "0")); // Addition for Status update to OpenHAB Controller,   No Echo
                          }
                          oldButtonVal = buttonVal;
                        }
                        
                        vladimirV Offline
                        vladimirV Offline
                        vladimir
                        wrote on last edited by vladimir
                        #11

                        @hard-shovel thank you very much!:raised_hands: Now everything works!
                        I will give here a full sketch. I'm sure it will be useful to many.

                        /**
                         * The MySensors Arduino library handles the wireless radio link and protocol
                         * between your home built sensors/actuators and HA controller of choice.
                         * The sensors forms a self healing radio network with optional repeaters. Each
                         * repeater and gateway builds a routing tables in EEPROM which keeps track of the
                         * network topology allowing messages to be routed to nodes.
                         *
                         * Created by Henrik Ekblad <henrik.ekblad@mysensors.org>
                         * Copyright (C) 2013-2015 Sensnology AB
                         * Full contributor list: https://github.com/mysensors/Arduino/graphs/contributors
                         *
                         * Documentation: http://www.mysensors.org
                         * Support Forum: http://forum.mysensors.org
                         *
                         * 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 an example how to implement a dimmable led light node with a rotary 
                         * encoder connected for adjusting light level. 
                         * The encoder has a click button which turns on/off the light (and remembers last dim-level) 
                         * The sketch fades the light (non-blocking) to the desired level. 
                         *
                         * Default MOSFET pin is 3
                         * 
                         *  Arduino      Encoder module
                         *  ---------------------------
                         *  5V           5V (+)  
                         *  GND          GND (-)
                         *  4            CLK (or putput 1)
                         *  5            DT  (or output 1) 
                         *  6            SW (Switch/Click)  
                         */
                        
                         
                        // Enable debug prints
                        #define MY_DEBUG
                        
                        // Enable and select radio type attached
                        #define MY_RADIO_NRF24
                        //#define MY_RADIO_RFM69
                        
                        #include <SPI.h>
                        #include <MySensors.h>  
                        #include <Bounce2.h>
                        #include <Encoder.h>
                        
                        #define LED_PIN 3           // Arduino pin attached to MOSFET Gate pin
                        #define KNOB_ENC_PIN_1 4    // Rotary encoder input pin 1
                        #define KNOB_ENC_PIN_2 5    // Rotary encoder input pin 2
                        #define KNOB_BUTTON_PIN 6   // Rotary encoder button pin 
                        #define FADE_DELAY 10       // Delay in ms for each percentage fade up/down (10ms = 1s full-range dim)
                        #define SEND_THROTTLE_DELAY 400 // Number of milliseconds before sending after user stops turning knob
                        #define SN "DimmableLED /w button"
                        #define SV "1.3"
                        
                        #define CHILD_ID_LIGHT 1
                        
                        #define EEPROM_DIM_LEVEL_LAST 1
                        #define EEPROM_DIM_LEVEL_SAVE 2
                        
                        #define LIGHT_OFF 0
                        #define LIGHT_ON 1
                        
                        int dimValue;
                        int fadeTo;
                        int fadeDelta;
                        byte oldButtonVal;
                        bool changedByKnob=false;
                        bool sendDimValue=false;
                        unsigned long lastFadeStep;
                        unsigned long sendDimTimeout;
                        char convBuffer[10];
                        
                        MyMessage dimmerMsg(CHILD_ID_LIGHT, V_DIMMER);
                        MyMessage statusMsg(CHILD_ID_LIGHT, V_STATUS);    // Addition for Status update to OpenHAB Controller
                        Encoder knob(KNOB_ENC_PIN_1, KNOB_ENC_PIN_2);  
                        Bounce debouncer = Bounce(); 
                        
                        void setup()  
                        { 
                          // Set knob button pin as input (with debounce)
                          pinMode(KNOB_BUTTON_PIN, INPUT);
                          digitalWrite(KNOB_BUTTON_PIN, HIGH);
                          debouncer.attach(KNOB_BUTTON_PIN);
                          debouncer.interval(5);
                          oldButtonVal = debouncer.read();
                        
                          // Set analog led pin to off
                          analogWrite( LED_PIN, 0);
                        
                          // Retreive our last dim levels from the eprom
                          fadeTo = dimValue = 0;
                          byte oldLevel = loadLevelState(EEPROM_DIM_LEVEL_LAST);
                          Serial.print("Sending in last known light level to controller: ");
                          Serial.println(oldLevel);  
                          send(dimmerMsg.set(oldLevel), true);
                          Serial.println("Ready to receive messages...");  
                        }
                        
                        void presentation() {
                          // Send the Sketch Version Information to the Gateway
                          present(CHILD_ID_LIGHT, S_DIMMER);
                          sendSketchInfo(SN, SV);
                        }
                        
                        void loop()      
                        {
                          // Check if someone turned the rotary encode
                          checkRotaryEncoder();
                          
                          // Check if someone has pressed the knob button
                          checkButtonClick();
                          
                          // Fade light to new dim value
                          fadeStep();
                        }
                        
                        void receive(const MyMessage &message)
                        {
                          if (message.type == V_STATUS) {
                            // Incoming on/off command sent from controller ("1" or "0")
                            int lightState = message.getString()[0] == '1';
                            int newLevel = 0;
                            if (lightState==LIGHT_ON) {
                              // Pick up last saved dimmer level from the eeprom
                              newLevel = loadLevelState(EEPROM_DIM_LEVEL_SAVE);
                            } 
                            // Send dimmer level back to controller with ack enabled
                            send(dimmerMsg.set(newLevel), true);
                            // We do not change any levels here until ack comes back from gateway 
                            return;
                          } else if (message.type == V_PERCENTAGE) {
                            // Incoming dim-level command sent from controller (or ack message)
                            fadeTo = atoi(message.getString(convBuffer));
                            // Save received dim value to eeprom (unless turned off). Will be
                            // retreived when a on command comes in
                            if (fadeTo != 0)
                              saveLevelState(EEPROM_DIM_LEVEL_SAVE, fadeTo);
                          }
                          saveLevelState(EEPROM_DIM_LEVEL_LAST, fadeTo);
                          
                          Serial.print("New light level received: ");
                          Serial.println(fadeTo);
                        
                          if (!changedByKnob) 
                            knob.write(fadeTo<<1);             //### need to multiply by two (using Shift left)
                            
                          // Cancel send if user turns knob while message comes in
                          changedByKnob = false;
                          sendDimValue = false;
                        
                          // Stard fading to new light level
                          startFade();
                        }
                        
                        
                        
                        void checkRotaryEncoder() {
                          long encoderValue = knob.read()>>1 ;      //### Divide by 2 (using shift right) 
                        
                          if (encoderValue > 100) {   
                            encoderValue = 100;       
                            knob.write(200);                        //### max value now 200 due to divide by 2
                          } else if (encoderValue < 0) {
                            encoderValue = 0;
                            knob.write(0);
                          }
                        
                          if (encoderValue != fadeTo) {    
                            fadeTo = encoderValue;                   
                            changedByKnob = true;
                            startFade();
                          }
                        }
                        
                        void checkButtonClick() {
                          debouncer.update();
                          byte buttonVal = debouncer.read();
                          byte newLevel = 0;
                          if (buttonVal != oldButtonVal && buttonVal == LOW) {
                            if (dimValue==0) {
                              // Turn on light. Set the level to last saved dim value
                              int saved = loadLevelState(EEPROM_DIM_LEVEL_SAVE);
                              newLevel = saved > 1 ? saved : 100;           // newLevel = saved > 0 ? saved : 100;     
                            } 
                            send(dimmerMsg.set(newLevel),true);
                            send(statusMsg.set(newLevel>0 ? "1" : "0")); // Addition for Status update to OpenHAB Controller,   No Echo
                          }
                          oldButtonVal = buttonVal;
                        }
                        
                        void startFade() {
                          fadeDelta = ( fadeTo - dimValue ) < 0 ? -1 : 1;
                          lastFadeStep = millis();
                        }
                        
                        // This method provides a graceful none-blocking fade up/down effect
                        void fadeStep() {
                          unsigned long currentTime  = millis();
                          if ( dimValue != fadeTo && currentTime > lastFadeStep + FADE_DELAY) {
                            dimValue += fadeDelta;
                            analogWrite( LED_PIN, (int)(dimValue / 100. * 255) );
                            lastFadeStep = currentTime;
                            
                            Serial.print("Fading level: ");
                            Serial.println(dimValue);
                        
                            if (fadeTo == dimValue && changedByKnob) {
                              sendDimValue = true;
                              sendDimTimeout = currentTime;
                            }
                          } 
                          // Wait a few millisecs before sending in new value (if user still turns the knob)
                          if (sendDimValue && currentTime > sendDimTimeout + SEND_THROTTLE_DELAY)  {
                             // We're done fading.. send in new dim-value to controller.
                             // Send in new dim value with ack (will be picked up in incomingMessage) 
                            send(dimmerMsg.set(dimValue), true); // Send new dimmer value and request ack back
                            sendDimValue = false;
                          }
                        }
                        
                        // Make sure only to store/fetch values in the range 0-100 from eeprom
                        int loadLevelState(byte pos) {
                          return min(max(loadState(pos),0),100);
                        }
                        void saveLevelState(byte pos, byte data) {
                          saveState(pos,min(max(data,0),100));
                        }
                        
                        1 Reply Last reply
                        2
                        • Y Offline
                          Y Offline
                          yoshida
                          wrote on last edited by
                          #12

                          Thanks Guys, finally a sketch which compiled for me :) I will try it in Domoticz later on.

                          1 Reply Last reply
                          1
                          • M Offline
                            M Offline
                            mateos78
                            wrote on last edited by
                            #13

                            Does anybody use the corrected "Example with Rotary Encoder" sketch with DOMOTICZ? I'm trying to force the sketch to work, but for time being without any result:(

                            T 1 Reply Last reply
                            0
                            • M mateos78

                              Does anybody use the corrected "Example with Rotary Encoder" sketch with DOMOTICZ? I'm trying to force the sketch to work, but for time being without any result:(

                              T Offline
                              T Offline
                              tsjoender
                              wrote on last edited by
                              #14

                              @mateos78
                              What are the symptoms you're experiencing? When changing the dim value using the encoder. Does Domoticz pick up that change? When changing the dim value on the Domoticz end. Does the node change as well?

                              I have two of these dimmer nodes with rotary encoders based on the examples and working with Domoticz. What I did find out when building them is that the radio communication needs to be working well otherwise the dimmer seems (sometimes) unresponsive to the rotary encoder. After fixing radio communication (proper module and capacitors for powering it) these sketches worked like a charm. When using message signing the importance of good communication with the gateway becomes even more important as the messages become larger.

                              1 Reply Last reply
                              0
                              • M Offline
                                M Offline
                                mateos78
                                wrote on last edited by
                                #15

                                hi tsjoender,

                                I've got connection between raspberry and arduino via USB.
                                Unfortunatelly phisical button dosn't work (no switch on / off) and there is no feedbeck from domoticz to Arduino to set level of dim.

                                I also find that when i change the led dimmer from the encoder the led changes quickly, but it take about ten seconds before the dormoticz web page updates to show each new slider position.

                                here https://www.mysensors.org/build/dimmer I've also described the problem.

                                T 1 Reply Last reply
                                0
                                • M mateos78

                                  hi tsjoender,

                                  I've got connection between raspberry and arduino via USB.
                                  Unfortunatelly phisical button dosn't work (no switch on / off) and there is no feedbeck from domoticz to Arduino to set level of dim.

                                  I also find that when i change the led dimmer from the encoder the led changes quickly, but it take about ten seconds before the dormoticz web page updates to show each new slider position.

                                  here https://www.mysensors.org/build/dimmer I've also described the problem.

                                  T Offline
                                  T Offline
                                  tsjoender
                                  wrote on last edited by
                                  #16

                                  @mateos78 The Domoticz ui gets refreshed every 10 seconds or so. I too see that updates to sensors or switches can be a bit lagging. The logs update pretty much realtime, so you can use that to confirm that Domoticz picks up the differences instantly.

                                  1 Reply Last reply
                                  0
                                  • I Offline
                                    I Offline
                                    iguaan
                                    wrote on last edited by
                                    #17

                                    Hi,
                                    i have similar problem with domoticz and mysensors.
                                    Firstly, i can't get current dim level from domoticz on startup.
                                    Secondly if i start arduino and controll it over domoticz only, dimming and on/off works. If i turn the rotary knob, domoticz commands won't work.
                                    In serial monitor i see that new dim value has been received:

                                        Serial.print("Fading level: ");
                                        Serial.println(dimValue);
                                    

                                    but output doesn't change. If i turn knob on rotary, value in domoticz changes.
                                    I removed eeprom writes and rotary button. Only dims to off/on or domoticz commands off/on.
                                    Domoticz 4.10171, Mysensors 2.3.1, ide 1.8.10

                                    
                                    // Enable debug prints to serial monitor
                                    #define MY_DEBUG
                                    #define MY_RADIO_RF24
                                    #define MY_NODE_ID 10
                                    #define MY_REPEATER_FEATURE
                                    #define MY_TRANSPORT_WAIT_READY_MS 10      //ajaviide ms, kuni läheb tööle ilma serverita
                                    
                                    
                                    #include <MySensors.h>
                                    
                                    #include <Encoder.h>
                                    #define KNOB_ENC_PIN_1 5    // Rotary encoder input pin 1
                                    #define KNOB_ENC_PIN_2 4    // Rotary encoder input pin 2
                                    #define SEND_THROTTLE_DELAY 500 // Number of milliseconds before sending after user stops turning knob
                                    
                                    #define CHILD_ID_Light 1
                                    #define SN "DimmableLED"
                                    #define SV "1.1"
                                    #define LED_PIN 3      // Arduino pin attached to MOSFET Gate pin
                                    #define FADE_DELAY 10  // Delay in ms for each percentage fade up/down (10ms = 1s full-range dim)
                                    
                                    int dimValue;
                                    int fadeTo;
                                    int fadeDelta;
                                    bool changedByKnob = false;
                                    bool sendDimValue = false;
                                    unsigned long lastFadeStep;
                                    unsigned long sendDimTimeout;
                                    
                                    //char convBuffer[10];
                                    
                                    
                                    static int16_t currentLevel ;  // Current dim level...
                                    MyMessage dimmerMsg(CHILD_ID_Light, V_DIMMER);
                                    MyMessage lightMsg(CHILD_ID_Light, V_LIGHT);
                                    
                                    Encoder knob(KNOB_ENC_PIN_1, KNOB_ENC_PIN_2);
                                    
                                    /***
                                       Dimmable LED initialization method
                                    */
                                    void setup()
                                    {
                                      // Pull the gateway's current dim level - restore light level upon node power-up
                                      request( CHILD_ID_Light, V_DIMMER);
                                      // wait(3000);
                                    
                                    }
                                    
                                    void presentation()
                                    {
                                      // Register the LED Dimmable Light with the gateway
                                      present(CHILD_ID_Light, S_DIMMER );
                                    
                                      sendSketchInfo(SN, SV);
                                    }
                                    
                                    /***
                                        Dimmable LED main processing loop
                                    */
                                    void loop()
                                    {
                                      // Check if someone turned the rotary encode
                                      checkRotaryEncoder();
                                    
                                    
                                      // Fade light to new dim value
                                      fadeStep();
                                    }
                                    
                                    void receive(const MyMessage &message)
                                    {
                                      if (message.type == V_STATUS || message.type == V_PERCENTAGE) {
                                    
                                        //  Retrieve the power or dim level from the incoming request message
                                        fadeTo = atoi( message.data );
                                    
                                        // Adjust incoming level if this is a V_LIGHT variable update [0 == off, 1 == on]
                                        fadeTo *= ( message.type == V_LIGHT ? 100 : 1 );
                                    
                                        // Clip incoming level to valid range of 0 to 100
                                        fadeTo = fadeTo > 100 ? 100 : fadeTo;
                                        fadeTo = fadeTo < 0   ? 0   : fadeTo;
                                        //startFade();
                                        Serial.print("New light level received: ");
                                        Serial.println(fadeTo);
                                    
                                        if (!changedByKnob)
                                          knob.write(fadeTo << 1);           //### need to multiply by two (using Shift left)
                                    
                                        // Cancel send if user turns knob while message comes in
                                        changedByKnob = false;
                                        sendDimValue = false;
                                    
                                        // Stard fading to new light level
                                        startFade();
                                    
                                        //		// Inform the gateway of the current DimmableLED's SwitchPower1 and LoadLevelStatus value...
                                        //		send(lightMsg.set(dimValue > 0));
                                        //
                                        //		// hek comment: Is this really nessesary?
                                        //		send( dimmerMsg.set(dimValue) );
                                    
                                    
                                      }
                                    }
                                    
                                    void checkRotaryEncoder() {
                                      long encoderValue = knob.read() >> 1 ;    //### Divide by 2 (using shift right)
                                    
                                      if (encoderValue > 100) {
                                        encoderValue = 100;
                                        knob.write(200);                        //### max value now 200 due to divide by 2
                                      } else if (encoderValue < 0) {
                                        encoderValue = 0;
                                        knob.write(0);
                                      }
                                    
                                      if (encoderValue != fadeTo) {
                                        fadeTo = encoderValue;
                                        changedByKnob = true;
                                        startFade();
                                      }
                                    }
                                    
                                    void startFade() {
                                      fadeDelta = ( fadeTo - dimValue ) < 0 ? -1 : 1;
                                      lastFadeStep = millis();
                                    }
                                    
                                    // This method provides a graceful none-blocking fade up/down effect
                                    void fadeStep() {
                                      unsigned long currentTime  = millis();
                                      if ( dimValue != fadeTo && currentTime > lastFadeStep + FADE_DELAY) {
                                        dimValue += fadeDelta;
                                        analogWrite( LED_PIN, (int)(dimValue / 100. * 255 ) );
                                        lastFadeStep = currentTime;
                                    
                                        Serial.print("Fading level: ");
                                        Serial.println(dimValue);
                                    
                                        if (fadeTo == dimValue && changedByKnob) {
                                          sendDimValue = true;
                                          sendDimTimeout = currentTime;
                                        }
                                      }
                                      // Wait a few millisecs before sending in new value (if user still turns the knob)
                                      if (sendDimValue && currentTime > sendDimTimeout + SEND_THROTTLE_DELAY)  {
                                        // We're done fading.. send in new dim-value to controller.
                                        // Send in new dim value with ack (will be picked up in incomingMessage)
                                        send(dimmerMsg.set(dimValue)); // Send new dimmer value and request ack back
                                        sendDimValue = false;
                                      }
                                    }```
                                    1 Reply Last reply
                                    0
                                    Reply
                                    • Reply as topic
                                    Log in to reply
                                    • Oldest to Newest
                                    • Newest to Oldest
                                    • Most Votes


                                    12

                                    Online

                                    11.7k

                                    Users

                                    11.2k

                                    Topics

                                    113.1k

                                    Posts


                                    Copyright 2025 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