Dimmer problem (value changes by the sensor)

Please use template to report bugs and problems. Post here your questions when not sure where else to post
Only for bugs in the Domoticz application! other problems go in different subforums!
Forum rules
Before posting here, make sure you are on the latest Beta or Stable version.
If you have problems related to the web gui, clear your browser cache + appcache first.

Use the following template when posting here:

Version: xxxx
Platform: xxxx
Plugin/Hardware: xxxx
Description:
.....

If you are having problems with scripts/blockly, always post the script (in a spoiler or code tag) or screenshots of your blockly

If you are replying, please do not quote images/code from the first post

Please mark your topic as Solved when the problem is solved.
Post Reply
jaszczomb
Posts: 1
Joined: Tuesday 07 August 2018 23:35
Target OS: Raspberry Pi
Domoticz version:
Contact:

Dimmer problem (value changes by the sensor)

Post by jaszczomb » Tuesday 07 August 2018 23:44

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? :?

Code: Select all

// ========================================================
// 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);
}

Post Reply

Who is online

Users browsing this forum: Google [Bot], Ries and 2 guests