Dimmer problem (value changes by the sensor)



  • Hi
    I have a problem with Dimmer updated by “sensor” rotary encoder from Mysensors gateway.

    Project:
    The Rotary encoder updates the dimmer by a value in the domoticz, then by the script or group other dimmers are updated with the same value (rotary encoder).

    What works:
    Dimmer is successfully updated by (sensor) mysensors gateway, I see visually that value bar is moving and setup on correct value, but…

    Does not works:
    ...that's it, nothing changes on other dimmers, like rotary was set up with value but not trigger, no actions are made. In the dimmer log tab, I can see when dimmer from the dashboard is setup (set up: specific value ) and linked dimmers are updated too, but when the main dimmer is updated by rotary encoder there is only “ON’ word and linked dimmers do not receive any data.

    This is a bug? Wrong Arduino script? Or do I have to do additional actions in domoticz? :?

    // ========================================================
    // INCLUDES
    // ========================================================
    #define MY_GATEWAY_SERIAL
    #define MY_DEBUG
    // for display
    #include <Arduino.h>
    #include <Wire.h>
    #include <U8g2lib.h>
    #include <MySensors.h>
    // for timer
    #include <TimerOne.h>
    // for rotary encoder
    #include <Rotary.h>
    
    // ========================================================
    // DEBUG
    // ========================================================
    
    
    //=========================================================
    //sciemniacz
    //=======================================================
    #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 2"
    #define SV "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];
    #define LED_PIN 7           // Arduino pin attached to MOSFET Gate pin
    MyMessage dimmer_msg(1, V_PERCENTAGE);
    MyMessage light_msg(1, V_STATUS);
    MyMessage dimmerinp(8, V_PERCENTAGE);
    MyMessage lightinp(8, V_STATUS);
    static int16_t currentLevel = 0;  // Current dim level...
    #define LIGHT_OFF 0
    #define LIGHT_ON 1
    int16_t last_state = LIGHT_ON;
    int16_t last_dim = 100;
    int16_t dupa = 10;
    // ========================================================
    // DEFAULTS
    // ========================================================
    
    #define VERSION_TITLE "OLED MENU PAGES"
    #define VERSION_HW "Corridor 2 Rev. B"
    #define VERSION_SUBTITLE "by @schlueri 2017"
    #define VERSION "0.32B"
    
    // Status LED
    #define STATUS_LED_PIN 9
    bool statusLedOn = false;
    
    // Timer
    #define TIMER 1000
    
    // Display and menu stuff
    int displayCurrentPage = 0;
    bool setNeedsDisplay = false;
    
    // Main menu fixed to 3 items, left, center, right...
    #define MENU_SELECTED_TIMEOUT 4000
    #define MENU_POS_Y 62
    #define MENU_POS_Y_HIDDEN 76
    #define MENU_ANIMATION_PIXEL_STEP 2
    String menuItems[3] = {"MAIN", "NETWORK", "SETUP"};
    int menuActive = 1;             // left active
    int menuSelected = menuActive;  // selected
    bool menuPageMode = true;      // true => rotary encoder control page and not menu
    
    // Menu animation
    bool menuAnimationRunning = true;
    int menuPosY = MENU_POS_Y;
    
    // Rotary encoder with switch
    #define ROTARY_SWITCH 5  // A1
    #define ROTARY_PIN1 2
    #define ROTARY_PIN2 3
    #define ROTARY_ACCEL_OFFSET1 20
    #define ROTARY_ACCEL_OFFSET2 50
    #define ROTARY_ACCEL_OFFSET3 70
    unsigned long rotaryLastMove;
    bool rotaryButtonPressed = false;
    
    
    // Test slider
    int sliderPosX = 64;
    
    // Logic
    long int heartbeat = 0;
    #define HEARTBEAT_TRIGGER 1000
    #define HEARTBEAT_TRIGGER_TIME 50
    
    // ========================================================
    // PAGES STUFF
    // ========================================================
    
    #define SETUP_MENU_ITEMS 8
    String setupMenuItems[SETUP_MENU_ITEMS] = {"EXIT", "LDR LEVEL", "LDR THRESHOLD", "PIR SENSOR", "LED COLOR", "LED ANIMATION", "LED OUT TEST", "VERSION & INFO"};
    int setupMenuSelected = 0;
    
    // ========================================================
    // INITS
    // ========================================================
    
    // Display
    U8G2_SH1106_128X64_NONAME_F_HW_I2C u8g2(U8G2_R0, /* reset=*/ U8X8_PIN_NONE);
    // Rotary Encoder
    Rotary rotary = Rotary(ROTARY_PIN1, ROTARY_PIN2);
    
    // ========================================================
    // SETUP
    // ========================================================
     
    void setup()
    {
      // put your setup code here, to run once:
    
      // Status LED
      pinMode(STATUS_LED_PIN, OUTPUT);
      digitalWrite(STATUS_LED_PIN, HIGH);
    
    #ifdef DEBUG
      Serial.begin(DEBUG_BAUD);
      Serial.println("DEBUG MODE");
      Serial.print("Version ");
      Serial.print(VERSION);
      Serial.print("\n\n");
    #endif
    
      // Menu Button
      pinMode(ROTARY_SWITCH, INPUT);
      digitalWrite(ROTARY_SWITCH, INPUT_PULLUP);
    
    #ifdef BUTTON1_PIN
      pinMode(BUTTON1_PIN, INPUT);
      digitalWrite(BUTTON1_PIN, INPUT_PULLUP);
    #endif
    
      // OLED Display
      u8g2.begin(/* menu_select_pin= */ 5, /* menu_next_pin= */ 0, /* menu_prev_pin= */ 0, /* menu_home_pin= */ 0);
    
      setNeedsDisplay = true;
    
      Timer1.initialize(TIMER);
      Timer1.attachInterrupt(timerEvent);
    
    =======================================
    
     fadeTo = dimValue = 0;
    
      update_light();
    }
    
    // ========================================================
    // LOOP
    // ========================================================
    
    void loop() {
      // put your main code here, to run repeatedly:
    
      digitalWrite(STATUS_LED_PIN, statusLedOn);
    
      if (menuAnimationRunning) {
        if (menuPageMode && menuPosY < MENU_POS_Y_HIDDEN) {
          // do animation
          menuPosY = menuPosY + MENU_ANIMATION_PIXEL_STEP;
          setNeedsDisplay = true;
        }
        if (!menuPageMode && menuPosY > MENU_POS_Y) {
          // do animation
          menuPosY = menuPosY - MENU_ANIMATION_PIXEL_STEP;
          setNeedsDisplay = true;
        }
      }
      if (menuAnimationRunning && (menuPosY == MENU_POS_Y || menuPosY == MENU_POS_Y_HIDDEN)) {
        // looks like animation is done
        menuAnimationRunning = false;
      }
    
      if (setNeedsDisplay) {
       
        displayRenderCurrentPage();
        setNeedsDisplay = false;
      }
      
    checkRotaryEncoder();
    
     {
      //In MySensors2.x, first message must come from within loop()
      static bool first_message_sent = false;
      if ( first_message_sent == false ) {
        Serial.println( "Sending initial state..." );
        send_dimmer_message();
        send_status_message();
        first_message_sent = true;
      }
    }
    }
    // ========================================================
    // TIMER
    // ========================================================
    
    void timerEvent() {
      // Heartbeat
      if (heartbeat > HEARTBEAT_TRIGGER) {
        statusLedOn = true;
      }
      if (heartbeat > HEARTBEAT_TRIGGER + HEARTBEAT_TRIGGER_TIME) {
        statusLedOn = false;
        heartbeat = 0;
      }
      heartbeat++;
    
      // Menu logic
      unsigned long timeOffset = millis() - rotaryLastMove;
      if (timeOffset > MENU_SELECTED_TIMEOUT) {
        // deselect menu
        menuSelected = menuActive;
        rotaryLastMove = millis();
        setNeedsDisplay = true;
      }
      
      // Rotary Encoder
      unsigned char result = rotary.process();
      if (result) {
    
        if (!menuPageMode) {
          if (result == DIR_CW) {
            // right
            if (menuSelected < 3) {
              menuSelected++;
            }
          } else {
            // left
            if (menuSelected > 1) {
              menuSelected--;
            }
          }
          setNeedsDisplay = true;
        } else {
    
          // Acceleration
          byte acceleration = 1;
          unsigned long timeOffset = millis() - rotaryLastMove;
          
          //Serial.println(timeOffset);
    
          if (displayCurrentPage == 0 || displayCurrentPage == 1) {
            if (timeOffset < ROTARY_ACCEL_OFFSET1) {
              acceleration = 16;
            } else if (timeOffset < ROTARY_ACCEL_OFFSET2) {
              acceleration = 4;
            } else if (timeOffset < ROTARY_ACCEL_OFFSET3) {
              acceleration = 2;
            }
          
            // Development test => control slider
            if (result == DIR_CW) {
              // right
              if (sliderPosX < 128) {
                sliderPosX = sliderPosX + acceleration;
              }
            } else {
              // left
              if (sliderPosX > 0) {
                sliderPosX = sliderPosX - acceleration;
              }
            }
            setNeedsDisplay = true;
          }
    
          if (displayCurrentPage == 2) {
            if (result == DIR_CW) {
              // right
              setupMenuSelected++;
            } else {
              // left
              setupMenuSelected--;
            }
            if (setupMenuSelected > SETUP_MENU_ITEMS - 1) {
              setupMenuSelected = SETUP_MENU_ITEMS - 1;
            }
            if (setupMenuSelected < 1) {
              setupMenuSelected = 0;
            }
            setNeedsDisplay = true;
          }
    
        }
    
        rotaryLastMove = millis();
        
      }
    
      // Rotary button
      if (buttonEvent()) {
        rotaryLastMove = millis();
        if (menuActive == menuSelected) {
          if (!menuPageMode) {
            // give controls to page (button press on selected page)
            menuPageMode = true;
            menuAnimationRunning = true;
            
            sliderPosX = 64;
            
            setNeedsDisplay = true;
            
            #ifdef DEBUG
            Serial.println("PAGE MODE ON");
            #endif
          } else {
            menuPageMode = false;   
            menuAnimationRunning = true;
            setNeedsDisplay = true;
            sliderPosX = 64;
    
            setupMenuSelected = 0;
            
            #ifdef DEBUG
            Serial.println("PAGE MODE OFF"); 
            #endif
          }
        }
        if (!menuPageMode) {
          menuActive = menuSelected;
          if (menuActive == 1) {
            displayCurrentPage = 0;
          }
          if (menuActive == 2) {
            displayCurrentPage = 1;
          }
          if (menuActive == 3) {
            displayCurrentPage = 2;
          }
          setNeedsDisplay = true;
        }
      }
    
      // Action button => reset page mode during development
    #ifdef BUTTON1_PIN
      if (digitalRead(BUTTON1_PIN) == 0 && menuPageMode) {
        menuPageMode = false;   
        menuAnimationRunning = true;
        setNeedsDisplay = true;
       // sliderPosX = 64;
        #ifdef DEBUG
        Serial.println("PAGE MODE OFF"); 
        #endif
      }
    #endif
      
    }
    
    // ========================================================
    // MENU BUTTON
    // ========================================================
    
    bool buttonEvent() {
      bool result = false;
      bool menuButton = false;
      if (digitalRead(ROTARY_SWITCH) == 1) {
        menuButton = true;
      }
      if (menuButton && !rotaryButtonPressed) {
        rotaryButtonPressed = true;
      } else if (!menuButton && rotaryButtonPressed) {
        rotaryButtonPressed = false;
        result = true;
        // FIXME: debounce for try, check if it's really needed
        //delay(4);
      }
      return result;
    }
    
    // ========================================================
    // DISPLAY - Screen Drawing
    // ========================================================
    
    void displayRenderCurrentPage() {
      // OLED Display update
      u8g2.firstPage();
      do {
    
        if (displayCurrentPage == 0) {
          u8g2.setFont(u8g2_font_8x13B_tr);
          u8g2.drawStr(0, 12, "Main Page");
        }
    
        if (displayCurrentPage == 1) {
          u8g2.setFont(u8g2_font_8x13B_tr);
          u8g2.drawStr(0, 12, "Network Page");
        }
    
        if (displayCurrentPage == 2) {
          if (!menuPageMode) {
            u8g2.setFont(u8g2_font_8x13B_tr);
            u8g2.drawStr(0, 10, "Setup Page");
            u8g2.setFont(u8g2_font_5x7_tr);
            u8g2.drawStr(0, 28, "PRESS BUTTON FOR SUBMENU");
          } else {
            drawPageMenu();
    
            if (setupMenuSelected == 0) {
              u8g2.setFont(u8g2_font_5x7_tr);
              u8g2.drawStr(0, 28, "DEMO MODE");
              u8g2.drawStr(0, 38, "PRESS BUTTON TO EXIT");
            }
    
            if (setupMenuSelected == 7) {
              // Version & Info
              u8g2.setFont(u8g2_font_5x7_tr);
              u8g2.setCursor(0, 28);
              u8g2.print(VERSION_TITLE);
              u8g2.print(" ");
              u8g2.print(VERSION);
    
              u8g2.setCursor(0, 38);
              u8g2.print(VERSION_SUBTITLE);
    
              u8g2.setCursor(0, 56);
              u8g2.print("HW: ");
              u8g2.print(VERSION_HW);
              
    
            }
          }
        }
    
        if (displayCurrentPage == 0 || displayCurrentPage == 1) {
          u8g2.setFont(u8g2_font_5x7_tr);
          if (menuPageMode) { 
            u8g2.drawStr(0, 28, "ROTARY CONTROL ON PAGE");
            u8g2.setCursor(0, 46);
            u8g2.print("VALUE ");
            u8g2.print(sliderPosX);
          } else {
            u8g2.drawStr(0, 28, "ROTARY CONTROL ON MENU");
          }
          drawSlider(31);
        }
    
        drawMenuBar();
        
      } while ( u8g2.nextPage() );
    }
    
    void drawPageMenu() {
      u8g2.setFont(u8g2_font_6x12_tr);
      if (displayCurrentPage == 2) {
        String text = setupMenuItems[setupMenuSelected];
        // center text
        int textWidth = u8g2.getStrWidth(text.c_str());
        int textX = (128 - textWidth) / 2;
        int textXPadding = 4;
        u8g2.drawRBox(textX - textXPadding, 0, textWidth + textXPadding + textXPadding, 11, 2);
        u8g2.setDrawColor(0);
        u8g2.setCursor(textX, 11 - 2);
        u8g2.print(text);
        u8g2.setDrawColor(1);
    
        bool drawLeftTriangle = false;
        bool drawRightTriangle = false;
    
        if (setupMenuSelected < SETUP_MENU_ITEMS - 1) {
          drawRightTriangle = true;
        }
        if (setupMenuSelected > 0) {
          drawLeftTriangle = true;
        }
    
        if (drawLeftTriangle) {
          // Triangle left
          u8g2.drawTriangle(4, 1, 4, 9, 0, 5);
        }
        if (drawRightTriangle) {
          // Triangle right
          u8g2.drawTriangle(128 - 5, 1, 128 - 5, 9, 127, 5);
        }
        u8g2.drawHLine(0, 14, 128);
      }
      
    }
    
    void drawSlider(int yPos) {
      u8g2.drawFrame(0, yPos, 100, 6);
      if (sliderPosX < 1) {
        sliderPosX = 0;
      }
      if (sliderPosX > 100) {
        sliderPosX = 100;
      }
      u8g2.drawVLine(sliderPosX, yPos, 6);
    }
    
    void drawMenuBar() {
      int textX = 0;
      int textY = menuPosY;
      int textWidth = 0;
      int textXPadding = 4;
      
      u8g2.setFont(u8g2_font_6x12_tr);
      u8g2.setDrawColor(1);
    
      u8g2.drawHLine(0, textY - 11 - 2, 128);
    
      if (textY < MENU_POS_Y_HIDDEN) {
        // center menu
        String text = menuItems[1];
        textWidth = u8g2.getStrWidth(text.c_str());
        textX = (128 - textWidth) / 2;
        if (menuActive == 2) {
          u8g2.drawRBox(textX - textXPadding, textY + 2 - 11, textWidth + textXPadding + textXPadding, 11, 2);
          u8g2.setDrawColor(0);
        } 
        if (menuActive != menuSelected && menuSelected == 2) {
          u8g2.drawRFrame(textX - textXPadding, textY + 2 - 11, textWidth + textXPadding + textXPadding, 11, 2);
          u8g2.setDrawColor(1);
        }
      
        u8g2.setCursor(textX, textY);
        u8g2.print(text);
        u8g2.setDrawColor(1);
      
        // left menu
        text = menuItems[0];
        textX = textXPadding;
        textWidth = u8g2.getStrWidth(text.c_str());
        if (menuActive == 1) {
          u8g2.drawRBox(textX - textXPadding, textY + 2 - 11, textWidth + textXPadding + textXPadding, 11, 2);
          u8g2.setDrawColor(0);
        } 
        if (menuActive != menuSelected && menuSelected == 1) {
          u8g2.drawRFrame(textX - textXPadding, textY + 2 - 11, textWidth + textXPadding + textXPadding, 11, 2);
          u8g2.setDrawColor(1);
        }
        u8g2.setCursor(textX, textY);
        u8g2.print(text);
        u8g2.setDrawColor(1);
      
        // right menu
        text = menuItems[2];
        textWidth = u8g2.getStrWidth(text.c_str());
        textX = 128 - textWidth - textXPadding;
        if (menuActive == 3) {
          u8g2.drawRBox(textX - textXPadding, textY + 2 - 11, textWidth + textXPadding + textXPadding, 11, 2);
          u8g2.setDrawColor(0);
        }
        if (menuActive != menuSelected && menuSelected == 3) {
          u8g2.drawRFrame(textX - textXPadding, textY + 2 - 11, textWidth + textXPadding + textXPadding, 11, 2);
          u8g2.setDrawColor(1);
        }
        u8g2.setCursor(textX, textY);
        u8g2.print(text);
        u8g2.setDrawColor(1);
      }
      
    }
    
    void presentation() {
      sendSketchInfo(SN, SV);
      // led
      present(1, S_DIMMER, 1);
         // rotary
        present( 8, S_DIMMER, 1 );
    
        
    }
    
    void receive(const MyMessage &message)
    
    {
      //When receiving a V_STATUS command, switch the light between OFF
      //and the last received dimmer value  
      
     if (message.sensor == 1){
        if (message.type == V_STATUS) 
      {
        Serial.println( "V_STATUS command received..." );
    
        int lstate = message.getInt();
        if (( lstate < 0 ) || ( lstate > 1 )) {
          Serial.println( "V_STATUS data invalid (should be 0/1)" );
          return;
        }
        last_state = lstate;
    
        //If last dimmer state is zero, set dimmer to 100
        if (( last_state == LIGHT_ON ) && ( last_dim == 0 )) {
          last_dim=10;
        }
    
        //Update constroller status
        send_status_message();
    
      } else if (message.type == V_PERCENTAGE)
      {
        Serial.println( "V_PERCENTAGE command received..." );
        int dim_value = constrain( message.getInt(), 0, 100 );
        if ( dim_value == 0 ) {
          last_state = LIGHT_OFF;
    
          //Update constroller with dimmer value & status
          send_dimmer_message();
          send_status_message();      
        } else {
          last_state = LIGHT_ON;
          last_dim = dim_value;
    
          //Update constroller with dimmer value
          send_dimmer_message();
        }
    
      } else {
        Serial.println( "Invalid command received..." );
        return;
      }
    
      //Here you set the actual light state/level
      update_light();
    }
    }   
    
    
    void update_light()
    {
      //For this example, just print the light status to console.
      if ( last_state == LIGHT_OFF ) {
        Serial.println( "Light state: OFF" );
      } else {
        Serial.print( "Light state: ON, Level: " );
        Serial.println( last_dim );
       analogWrite( LED_PIN, (last_dim) );
      }
    }
    
    void send_dimmer_message()
    {
      send( dimmer_msg.set( last_dim ) );
    }
    
    void send_status_message()
    {
      if ( last_state == LIGHT_OFF ) {
        send( light_msg.set( (int16_t)0) );
      } else {
        send( light_msg.set( (int16_t)1) );
      }
    }
    
    void checkRotaryEncoder() {
    
      if (sliderPosX > 100) {
        sliderPosX = 100;
      } else if (sliderPosX < 0) {
        sliderPosX = 0;
      }
      if (sliderPosX != dupa) { 
        dupa = sliderPosX;
        changedByKnob = true;
      send_dimmer_message_rottary();
      }
    }
    
    
    void send_dimmer_message_rottary()
    {
     send(dimmerinp.set(dupa),1);
    }```

 

343
Online

7.9k
Users

8.7k
Topics

93.6k
Posts