Support rotary encoder on Shelly Dimmer

Support rotary encoder on Shelly Dimmer (#10407)
This commit is contained in:
Theo Arends 2021-01-07 17:53:48 +01:00
parent 98b529ce7b
commit d319bc8ecb
5 changed files with 36 additions and 16 deletions

View File

@ -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

View File

@ -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)

View File

@ -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 {

View File

@ -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();

View File

@ -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