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); }```