diff --git a/CHANGELOG.md b/CHANGELOG.md index 83a0ff3cd..5fdc845de 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,7 @@ All notable changes to this project will be documented in this file. ## [9.2.0.3] ### Added - Support for time proportioned (``#define USE_TIMEPROP``) and optional PID (``#define USE_PID``) relay control (#10412) +- Support rotary encoder on Shelly Dimmer (#10407) ### Breaking Changed - ESP32 switch from default SPIFFS to default LittleFS file system loosing current (zigbee) files diff --git a/RELEASENOTES.md b/RELEASENOTES.md index 17f7a24b1..134186e64 100644 --- a/RELEASENOTES.md +++ b/RELEASENOTES.md @@ -76,6 +76,7 @@ The attached binaries can also be downloaded from http://ota.tasmota.com/tasmota - Support for disabling 38kHz IR modulation using ``#define IR_SEND_USE_MODULATION false`` [#10301](https://github.com/arendst/Tasmota/issues/10301) - Support for SPI display driver for ST7789 TFT by Gerhard Mutz [#9037](https://github.com/arendst/Tasmota/issues/9037) - Support for time proportioned (``#define USE_TIMEPROP``) and optional PID (``#define USE_PID``) relay control [#10412](https://github.com/arendst/Tasmota/issues/10412) +- Support rotary encoder on Shelly Dimmer [#10407](https://github.com/arendst/Tasmota/issues/10407) - Basic support for ESP32 Odroid Go 16MB binary tasmota32-odroidgo.bin [#8630](https://github.com/arendst/Tasmota/issues/8630) - SPI display driver SSD1331 Color oled by Jeroen Vermeulen [#10376](https://github.com/arendst/Tasmota/issues/10376) diff --git a/tasmota/support_command.ino b/tasmota/support_command.ino index 4b3e2436b..7faef10d5 100644 --- a/tasmota/support_command.ino +++ b/tasmota/support_command.ino @@ -884,7 +884,12 @@ void CmndSetoption(void) #endif #if (defined(USE_IR_REMOTE) && defined(USE_IR_RECEIVE)) || defined(USE_IR_REMOTE_FULL) if (P_IR_UNKNOW_THRESHOLD == pindex) { - IrReceiveUpdateThreshold(); + IrReceiveUpdateThreshold(); // SetOption38 + } +#endif +#ifdef ROTARY_V1 + if (P_ROTARY_MAX_STEP == pindex) { + RotaryInitMaxSteps(); // SetOption43 } #endif } else { diff --git a/tasmota/support_rotary.ino b/tasmota/support_rotary.ino index 538aeff2f..f4461d0c0 100644 --- a/tasmota/support_rotary.ino +++ b/tasmota/support_rotary.ino @@ -46,17 +46,15 @@ #define ROTARY_DEBOUNCE 10 // Debounce time in milliseconds #endif -// (0) = Mi Desk lamp (1) = Normal rotary -// ---------------------------- ---------------------- -const uint8_t rotary_dimmer_increment[2] = { 100 / (ROTARY_MAX_STEPS * 3), 100 / ROTARY_MAX_STEPS }; // Dimmer 1..100 = 100 -const uint8_t rotary_ct_increment[2] = { 350 / (ROTARY_MAX_STEPS * 3), 350 / ROTARY_MAX_STEPS }; // Ct 153..500 = 347 -const uint8_t rotary_color_increment[2] = { 360 / (ROTARY_MAX_STEPS * 3), 360 / ROTARY_MAX_STEPS }; // Hue 0..359 = 360 const uint8_t rotary_offset = 128; const int8_t rotary_state_pos[16] = { 0, 1, -1, 2, -1, 0, -2, 1, 1, -2, 0, -1, 2, -1, 1, 0 }; struct ROTARY { uint8_t no_pullup_mask_a = 0; // Rotary A pull-up bitmask flags uint8_t no_pullup_mask_b = 0; // Rotary B pull-up bitmask flags + uint8_t dimmer_increment; + uint8_t ct_increment; + uint8_t color_increment; uint8_t model; bool present; } Rotary; @@ -132,14 +130,29 @@ void ICACHE_RAM_ATTR RotaryIsrArg(void *arg) { } } +void RotaryInitMaxSteps(void) { + if ((0 == Settings.param[P_ROTARY_MAX_STEP]) || (Settings.param[P_ROTARY_MAX_STEP] > 100)) { + Settings.param[P_ROTARY_MAX_STEP] = ROTARY_MAX_STEPS; // SetOption43 + } + uint8_t max_steps = Settings.param[P_ROTARY_MAX_STEP]; + if (!Rotary.model) { max_steps *= 3; } + Rotary.dimmer_increment = 100 / max_steps; // Dimmer 1..100 = 100 + Rotary.ct_increment = 350 / max_steps; // Ct 153..500 = 347 + Rotary.color_increment = 360 / max_steps; // Hue 0..359 = 360 +} + void RotaryInit(void) { Rotary.present = false; + Rotary.model = 1; #ifdef ESP8266 if (MI_DESK_LAMP == TasmotaGlobal.module_type) { Rotary.model = 0; } #endif // ESP8266 + + RotaryInitMaxSteps(); + for (uint32_t index = 0; index < MAX_ROTARIES; index++) { Encoder[index].pinb = -1; if (PinUsed(GPIO_ROT1A, index) && PinUsed(GPIO_ROT1B, index)) { @@ -196,7 +209,7 @@ void RotaryHandler(void) { bool button_pressed = (Button.hold_timer[index]); // Button is pressed: set color temperature if (button_pressed) { Encoder[index].changed = true; } -// AddLog_P(LOG_LEVEL_DEBUG, PSTR("ROT: Button1 %d, Position %d"), button_pressed, rotary_position); + AddLog_P(LOG_LEVEL_DEBUG, PSTR("ROT: Button1 %d, Position %d"), button_pressed, rotary_position); #ifdef USE_LIGHT if (!Settings.flag4.rotary_uses_rules) { // SetOption98 - Use rules instead of light control @@ -204,16 +217,16 @@ void RotaryHandler(void) { if (0 == index) { // Rotary1 if (button_pressed) { if (second_rotary) { // Color RGB - LightColorOffset(rotary_position * rotary_color_increment[Rotary.model]); + LightColorOffset(rotary_position * Rotary.color_increment); } else { // Color Temperature or Color RGB - if (!LightColorTempOffset(rotary_position * rotary_ct_increment[Rotary.model])) { - LightColorOffset(rotary_position * rotary_color_increment[Rotary.model]); + if (!LightColorTempOffset(rotary_position * Rotary.ct_increment)) { + LightColorOffset(rotary_position * Rotary.color_increment); } } } else { // Dimmer RGBCW or RGB only if second rotary uint32_t dimmer_index = second_rotary ? 1 : 0; if (!Settings.flag4.rotary_poweron_dimlow || TasmotaGlobal.power) { // SetOption113 - On rotary dial after power off set dimmer low - LightDimmerOffset(dimmer_index, rotary_position * rotary_dimmer_increment[Rotary.model]); + LightDimmerOffset(dimmer_index, rotary_position * Rotary.dimmer_increment); } else { if (rotary_position > 0) { // Only power on if rotary increase LightDimmerOffset(dimmer_index, -LightGetDimmer(dimmer_index) + ROTARY_START_DIM); @@ -222,9 +235,9 @@ void RotaryHandler(void) { } } else { // Rotary2 if (button_pressed) { // Color Temperature - LightColorTempOffset(rotary_position * rotary_ct_increment[Rotary.model]); + LightColorTempOffset(rotary_position * Rotary.ct_increment); } else { // Dimmer CW - LightDimmerOffset(2, rotary_position * rotary_dimmer_increment[Rotary.model]); + LightDimmerOffset(2, rotary_position * Rotary.dimmer_increment); } } } else { @@ -233,8 +246,8 @@ void RotaryHandler(void) { if (Encoder[index].abs_position[button_pressed] < 0) { Encoder[index].abs_position[button_pressed] = 0; } - if (Encoder[index].abs_position[button_pressed] > ROTARY_MAX_STEPS) { - Encoder[index].abs_position[button_pressed] = ROTARY_MAX_STEPS; + if (Encoder[index].abs_position[button_pressed] > Settings.param[P_ROTARY_MAX_STEP]) { // SetOption43 - Rotary steps + Encoder[index].abs_position[button_pressed] = Settings.param[P_ROTARY_MAX_STEP]; // SetOption43 - Rotary steps } Response_P(PSTR("{\"Rotary%d\":{\"Pos1\":%d,\"Pos2\":%d}}"), index +1, Encoder[index].abs_position[0], Encoder[index].abs_position[1]); XdrvRulesProcess(); diff --git a/tasmota/tasmota.h b/tasmota/tasmota.h index 9cd4e2d3d..49b3789b1 100644 --- a/tasmota/tasmota.h +++ b/tasmota/tasmota.h @@ -254,7 +254,7 @@ enum Shortcuts { SC_CLEAR, SC_DEFAULT, SC_USER }; enum SettingsParamIndex { P_HOLD_TIME, P_MAX_POWER_RETRY, P_BACKLOG_DELAY, P_MDNS_DELAYED_START, P_BOOT_LOOP_OFFSET, P_RGB_REMAP, P_IR_UNKNOW_THRESHOLD, // SetOption32 .. SetOption38 P_CSE7766_INVALID_POWER, P_HOLD_IGNORE, P_ARP_GRATUITOUS, P_OVER_TEMP, // SetOption39 .. SetOption42 - P_ex_DIMMER_MAX, P_ex_TUYA_VOLTAGE_ID, P_ex_TUYA_CURRENT_ID, P_ex_TUYA_POWER_ID, // SetOption43 .. SetOption46 + P_ROTARY_MAX_STEP, P_ex_TUYA_VOLTAGE_ID, P_ex_TUYA_CURRENT_ID, P_ex_TUYA_POWER_ID, // SetOption43 .. SetOption46 P_ex_ENERGY_TARIFF1, P_ex_ENERGY_TARIFF2, // SetOption47 .. SetOption48 P_MAX_PARAM8 }; // Max is PARAM8_SIZE (18) - SetOption32 until SetOption49