From 2efb5cd1cd289d19bc5a36247efed3fbea26d24b Mon Sep 17 00:00:00 2001 From: arendst Date: Thu, 10 Aug 2017 09:12:18 +0200 Subject: [PATCH 01/13] Fix Sonoff Pow exception 0 where epc1=0x40107345 --- sonoff/_releasenotes.ino | 5 ++++- sonoff/sonoff.ino | 4 ++-- sonoff/xsns_hlw8012.ino | 19 ++++++++++--------- 3 files changed, 16 insertions(+), 12 deletions(-) diff --git a/sonoff/_releasenotes.ino b/sonoff/_releasenotes.ino index 79bce7b42..7eb145f9b 100644 --- a/sonoff/_releasenotes.ino +++ b/sonoff/_releasenotes.ino @@ -1,4 +1,7 @@ -/* 5.5.2 20170808 +/* 5.5.2a + * Fix intermittent exception 0 on Sonoff Pow + * + * 5.5.2 20170808 * Extent max number of WS2812 pixels from 256 to 512 (#667) * Add OTA handling if server responds with no update available (#695) * Removed undocumented command FlashMode (#696) diff --git a/sonoff/sonoff.ino b/sonoff/sonoff.ino index 30cde67fb..623c1108f 100644 --- a/sonoff/sonoff.ino +++ b/sonoff/sonoff.ino @@ -25,7 +25,7 @@ - Select IDE Tools - Flash Size: "1M (no SPIFFS)" ====================================================*/ -#define VERSION 0x05050200 // 5.5.2 +#define VERSION 0x05050201 // 5.5.2a enum log_t {LOG_LEVEL_NONE, LOG_LEVEL_ERROR, LOG_LEVEL_INFO, LOG_LEVEL_DEBUG, LOG_LEVEL_DEBUG_MORE, LOG_LEVEL_ALL}; enum week_t {Last, First, Second, Third, Fourth}; @@ -1999,7 +1999,7 @@ void every_second() } if (hlw_flg) { - hlw_mqttPresent(); + hlw_mqttPresent(1); } } } diff --git a/sonoff/xsns_hlw8012.ino b/sonoff/xsns_hlw8012.ino index a23f9a430..5340ad805 100644 --- a/sonoff/xsns_hlw8012.ino +++ b/sonoff/xsns_hlw8012.ino @@ -173,7 +173,7 @@ void hlw_savestate() sysCfg.hlw_kWhtotal = rtcMem.hlw_kWhtotal; } -boolean hlw_readEnergy(byte option, float &et, float &ed, uint16_t &e, uint16_t &w, float &u, float &i, float &c) +void hlw_readEnergy(byte option, float &et, float &ed, uint16_t &e, uint16_t &w, float &u, float &i, float &c) { unsigned long cur_kWhtoday = hlw_kWhtoday; unsigned long hlw_len; @@ -202,6 +202,9 @@ boolean hlw_readEnergy(byte option, float &et, float &ed, uint16_t &e, uint16_t } else { hlw_period = rtc_loctime() - hlw_lasttime; } + if (!hlw_period) { + hlw_period = sysCfg.tele_period; + } hlw_lasttime = rtc_loctime(); hlw_interval = 3600 / hlw_period; if (hlw_Ecntr) { @@ -241,8 +244,6 @@ boolean hlw_readEnergy(byte option, float &et, float &ed, uint16_t &e, uint16_t } else { c = 0; } - - return true; } void hlw_init() @@ -366,7 +367,7 @@ void hlw_margin_chk() if (jsonflg) { snprintf_P(svalue, sizeof(svalue), PSTR("%s}"), svalue); mqtt_publish_topic_P(2, PSTR("MARGINS"), svalue); - hlw_mqttPresent(); + hlw_mqttPresent(0); } } @@ -381,7 +382,7 @@ void hlw_margin_chk() if (!hlw_mplh_counter) { snprintf_P(svalue, sizeof(svalue), PSTR("{\"MaxPowerReached\":\"%d%s\"}"), pw, (sysCfg.flag.value_units) ? " W" : ""); mqtt_publish_topic_P(1, PSTR("WARNING"), svalue); - hlw_mqttPresent(); + hlw_mqttPresent(0); do_cmnd_power(1, 0); if (!hlw_mplr_counter) { hlw_mplr_counter = sysCfg.param[P_MAX_POWER_RETRY] +1; @@ -408,7 +409,7 @@ void hlw_margin_chk() } else { snprintf_P(svalue, sizeof(svalue), PSTR("{\"MaxPowerReachedRetry\":\"%s\"}"), getStateText(0)); mqtt_publish_topic_P(1, PSTR("WARNING"), svalue); - hlw_mqttPresent(); + hlw_mqttPresent(0); } } } @@ -429,7 +430,7 @@ void hlw_margin_chk() dtostrf(ped, 1, 3, svalue); snprintf_P(svalue, sizeof(svalue), PSTR("{\"MaxEnergyReached\":\"%s%s\"}"), svalue, (sysCfg.flag.value_units) ? " kWh" : ""); mqtt_publish_topic_P(1, PSTR("WARNING"), svalue); - hlw_mqttPresent(); + hlw_mqttPresent(0); do_cmnd_power(1, 0); } } @@ -647,13 +648,13 @@ void hlw_mqttStat(byte option, char* svalue, uint16_t ssvalue) #endif // USE_DOMOTICZ } -void hlw_mqttPresent() +void hlw_mqttPresent(byte option) { // {"Time":"2017-03-04T13:37:24", "Total":0.013, "Yesterday":0.013, "Today":0.000, "Period":0, "Power":0, "Factor":0.00, "Voltage":0, "Current":0.000} char svalue[200]; // was MESSZ snprintf_P(svalue, sizeof(svalue), PSTR("{\"Time\":\"%s\", "), getDateTime().c_str()); - hlw_mqttStat(1, svalue, sizeof(svalue)); + hlw_mqttStat(option, svalue, sizeof(svalue)); mqtt_publish_topic_P(2, PSTR("ENERGY"), svalue); } From 13ed472eb9ce8e0fca1c24de5257a5b3d8bd2812 Mon Sep 17 00:00:00 2001 From: arendst Date: Thu, 10 Aug 2017 16:21:31 +0200 Subject: [PATCH 02/13] Fix Sonoff Pow period data display --- sonoff/_releasenotes.ino | 5 ++-- sonoff/sonoff.ino | 2 +- sonoff/xsns_hlw8012.ino | 58 ++++++++++++++++++++-------------------- 3 files changed, 33 insertions(+), 32 deletions(-) diff --git a/sonoff/_releasenotes.ino b/sonoff/_releasenotes.ino index 7eb145f9b..612fb4f96 100644 --- a/sonoff/_releasenotes.ino +++ b/sonoff/_releasenotes.ino @@ -1,5 +1,6 @@ -/* 5.5.2a - * Fix intermittent exception 0 on Sonoff Pow +/* 5.5.2b + * Fix Sonoff Pow intermittent exception 0 + * Change Sonoff Pow sending Domoticz telemetry data only * * 5.5.2 20170808 * Extent max number of WS2812 pixels from 256 to 512 (#667) diff --git a/sonoff/sonoff.ino b/sonoff/sonoff.ino index 623c1108f..ad7708866 100644 --- a/sonoff/sonoff.ino +++ b/sonoff/sonoff.ino @@ -25,7 +25,7 @@ - Select IDE Tools - Flash Size: "1M (no SPIFFS)" ====================================================*/ -#define VERSION 0x05050201 // 5.5.2a +#define VERSION 0x05050202 // 5.5.2b enum log_t {LOG_LEVEL_NONE, LOG_LEVEL_ERROR, LOG_LEVEL_INFO, LOG_LEVEL_DEBUG, LOG_LEVEL_DEBUG_MORE, LOG_LEVEL_ALL}; enum week_t {Last, First, Second, Third, Fourth}; diff --git a/sonoff/xsns_hlw8012.ino b/sonoff/xsns_hlw8012.ino index 5340ad805..471b79d18 100644 --- a/sonoff/xsns_hlw8012.ino +++ b/sonoff/xsns_hlw8012.ino @@ -1,7 +1,7 @@ /* xsns_hlw8012.ino - sonoff pow HLW8012 energy sensor support for Sonoff-Tasmota - Copyright (C) 2017 Heiko Krupp and Theo Arends + Copyright (C) 2017 Theo Arends This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -175,6 +175,9 @@ void hlw_savestate() void hlw_readEnergy(byte option, float &et, float &ed, uint16_t &e, uint16_t &w, float &u, float &i, float &c) { +/* option 0 = do not calculate period energy usage + * option 1 = calculate period energy usage + */ unsigned long cur_kWhtoday = hlw_kWhtoday; unsigned long hlw_len; unsigned long hlw_temp; @@ -189,60 +192,50 @@ void hlw_readEnergy(byte option, float &et, float &ed, uint16_t &e, uint16_t &w, //addLog(LOG_LEVEL_DEBUG, log); et = (float)(rtcMem.hlw_kWhtotal + (cur_kWhtoday / 1000)) / 100000; - + ed = 0; if (cur_kWhtoday) { ed = (float)cur_kWhtoday / 100000000; - } else { - ed = 0; } - + e = 0; if (option) { if (!hlw_lasttime) { hlw_period = sysCfg.tele_period; } else { hlw_period = rtc_loctime() - hlw_lasttime; } - if (!hlw_period) { - hlw_period = sysCfg.tele_period; - } - hlw_lasttime = rtc_loctime(); - hlw_interval = 3600 / hlw_period; - if (hlw_Ecntr) { - hlw_len = hlw_period * 1000000 / hlw_Ecntr; - hlw_Ecntr = 0; - hlw_temp = ((HLW_PREF * sysCfg.hlw_pcal) / hlw_len) / hlw_interval; - e = hlw_temp / 10; - } else { - e = 0; + if (hlw_period) { + hlw_lasttime = rtc_loctime(); + hlw_interval = 3600 / hlw_period; + if (hlw_Ecntr) { + hlw_len = hlw_period * 1000000 / hlw_Ecntr; + hlw_Ecntr = 0; + hlw_temp = ((HLW_PREF * sysCfg.hlw_pcal) / hlw_len) / hlw_interval; + e = hlw_temp / 10; + } } } - + w = 0; if (hlw_cf_plen) { hlw_w = (HLW_PREF * sysCfg.hlw_pcal) / hlw_cf_plen; w = hlw_w / 10; - } else { - w = 0; } + u = 0; if (hlw_cf1u_plen && (w || (power &1))) { hlw_u = (HLW_UREF * sysCfg.hlw_ucal) / hlw_cf1u_plen; u = (float)hlw_u / 10; - } else { - u = 0; } + i = 0; if (hlw_cf1i_plen && w) { hlw_i = (HLW_IREF * sysCfg.hlw_ical) / hlw_cf1i_plen; i = (float)hlw_i / 1000; - } else { - i = 0; } + c = 0; if (hlw_i && hlw_u && hlw_w && w) { hlw_temp = (hlw_w * 100) / ((hlw_u * hlw_i) / 1000); if (hlw_temp > 100) { hlw_temp = 100; } c = (float)hlw_temp / 100; - } else { - c = 0; } } @@ -617,6 +610,9 @@ boolean hlw_command(char *type, uint16_t index, char *dataBuf, uint16_t data_len void hlw_mqttStat(byte option, char* svalue, uint16_t ssvalue) { +/* option 0 = do not show period energy usage + * option 1 = show period energy usage + */ char stemp0[10]; char stemp1[10]; char stemp2[10]; @@ -643,13 +639,18 @@ void hlw_mqttStat(byte option, char* svalue, uint16_t ssvalue) snprintf_P(svalue, ssvalue, PSTR("%s\"Total\":%s, \"Yesterday\":%s, \"Today\":%s%s, \"Power\":%d, \"Factor\":%s, \"Voltage\":%s, \"Current\":%s}"), svalue, stemp4, stemp0, stemp1, (option) ? speriod : "", pw, stemp2, stemp5, stemp3); #ifdef USE_DOMOTICZ - dtostrf(pet * 1000, 1, 1, stemp1); - domoticz_sensor4(pw, stemp1); + if (option) { // Only send if telemetry + dtostrf(pet * 1000, 1, 1, stemp1); + domoticz_sensor4(pw, stemp1); + } #endif // USE_DOMOTICZ } void hlw_mqttPresent(byte option) { +/* option 0 = do not show period energy usage + * option 1 = show period energy usage + */ // {"Time":"2017-03-04T13:37:24", "Total":0.013, "Yesterday":0.013, "Today":0.000, "Period":0, "Power":0, "Factor":0.00, "Voltage":0, "Current":0.000} char svalue[200]; // was MESSZ @@ -694,7 +695,6 @@ String hlw_webPresent() uint16_t pw; hlw_readEnergy(0, pet, ped, pe, pw, pu, pi, pc); - dtostrf(pu, 1, sysCfg.flag.voltage_resolution, stemp6); dtostrf(pi, 1, 3, stemp); dtostrf(pc, 1, 2, stemp2); From 7825bc0f0a0769e3706020e068f44d9fed119a50 Mon Sep 17 00:00:00 2001 From: arendst Date: Sat, 12 Aug 2017 17:55:20 +0200 Subject: [PATCH 03/13] Experimental Sonoff B1 support --- sonoff/_releasenotes.ino | 3 +- sonoff/sonoff.ino | 26 +-- sonoff/sonoff_template.h | 19 ++ sonoff/xdrv_snfled.ino | 429 +++++++++++++++++++++++++++++++-------- 4 files changed, 375 insertions(+), 102 deletions(-) diff --git a/sonoff/_releasenotes.ino b/sonoff/_releasenotes.ino index 612fb4f96..daa933601 100644 --- a/sonoff/_releasenotes.ino +++ b/sonoff/_releasenotes.ino @@ -1,6 +1,7 @@ -/* 5.5.2b +/* 5.5.2c * Fix Sonoff Pow intermittent exception 0 * Change Sonoff Pow sending Domoticz telemetry data only + * Add Sonoff B1 support (experimental) * * 5.5.2 20170808 * Extent max number of WS2812 pixels from 256 to 512 (#667) diff --git a/sonoff/sonoff.ino b/sonoff/sonoff.ino index ad7708866..8d99a51f3 100644 --- a/sonoff/sonoff.ino +++ b/sonoff/sonoff.ino @@ -25,7 +25,7 @@ - Select IDE Tools - Flash Size: "1M (no SPIFFS)" ====================================================*/ -#define VERSION 0x05050202 // 5.5.2b +#define VERSION 0x05050203 // 5.5.2c enum log_t {LOG_LEVEL_NONE, LOG_LEVEL_ERROR, LOG_LEVEL_INFO, LOG_LEVEL_DEBUG, LOG_LEVEL_DEBUG_MORE, LOG_LEVEL_ALL}; enum week_t {Last, First, Second, Third, Fourth}; @@ -303,7 +303,7 @@ uint8_t hlw_flg = 0; // Power monitor configured uint8_t i2c_flg = 0; // I2C configured uint8_t spi_flg = 0; // SPI configured uint8_t pwm_flg = 0; // PWM configured -uint8_t sfl_flg = 0; // Sonoff Led flag (0 = No led, 1 = BN-SZ01, 2 = Sonoff Led) +uint8_t sfl_flg = 0; // Sonoff Led flag (0 = No led, 1 = BN-SZ01, 2 = Sonoff Led, 5 = Sonoff B1) uint8_t pwm_idxoffset = 0; // Allowed PWM command offset (change for Sonoff Led) boolean mDNSbegun = false; @@ -2318,7 +2318,7 @@ void stateloop() button_handler(); switch_handler(); - if (sfl_flg) { // Sonoff BN-SZ01 or Sonoff Led + if (sfl_flg) { // Sonoff B1, led or BN-SZ01 sl_animate(); } @@ -2633,6 +2633,9 @@ void GPIO_init() else if (SONOFF_LED == sysCfg.module) { sfl_flg = 2; } + else if (SONOFF_B1 == sysCfg.module) { + sfl_flg = 5; + } else { Maxdevice = 0; for (byte i = 0; i < 4; i++) { @@ -2660,20 +2663,9 @@ void GPIO_init() } } - if (sfl_flg) { // Sonoff Led or BN-SZ01 - pwm_idxoffset = sfl_flg; // 1 for BN-SZ01, 2 for Sonoff Led - pin[GPIO_WS2812] = 99; // I do not allow both Sonoff Led AND WS2812 led - if (!my_module.gp.io[4]) { - pinMode(4, OUTPUT); // Stop floating outputs - digitalWrite(4, LOW); - } - if (!my_module.gp.io[5]) { - pinMode(5, OUTPUT); // Stop floating outputs - digitalWrite(5, LOW); - } - if (!my_module.gp.io[14]) { - pinMode(14, OUTPUT); // Stop floating outputs - digitalWrite(14, LOW); + if (sfl_flg) { // Sonoff B1, Led or BN-SZ01 + if (sfl_flg < 5) { + pwm_idxoffset = sfl_flg; // 1 for BN-SZ01, 2 for Sonoff Led } sl_init(); } diff --git a/sonoff/sonoff_template.h b/sonoff/sonoff_template.h index 1d4400bc3..7ceea9263 100644 --- a/sonoff/sonoff_template.h +++ b/sonoff/sonoff_template.h @@ -118,6 +118,8 @@ enum fpins_t { GPIO_HLW_CF, // HLW8012 CF power (Sonoff Pow) GPIO_ADC0, // ADC GPIO_USER, // User configurable + GPIO_DI, // my9231 PWM input + GPIO_DCKI, // my9231 CLK input GPIO_MAX }; /********************************************************************************************/ @@ -149,6 +151,7 @@ enum module_t { SONOFF_4CHPRO, HUAFAN_SS, SONOFF_BRIDGE, + SONOFF_B1, MAXMODULE }; /********************************************************************************************/ @@ -489,6 +492,22 @@ const mytmplt modules[MAXMODULE] PROGMEM = { 0, GPIO_LED1_INV, // GPIO13 Blue Led (0 = On, 1 = Off) 0, 0, 0, 0 + }, + { "Sonoff B1", // Sonoff B1 (ESP8285 - my9231) + GPIO_KEY1, // GPIO00 Pad + GPIO_USER, // GPIO01 Serial RXD and Optional sensor pad + GPIO_USER, // GPIO02 Optional sensor SDA pad + GPIO_USER, // GPIO03 Serial TXD and Optional sensor pad + 0, 0, + 0, 0, 0, // Flash connection + 0, 0, + 0, // Flash connection + GPIO_DI, // GPIO12 my9231 DI + 0, + GPIO_DCKI, // GPIO14 my9231 DCKI + 0, + 0, 0 } + }; diff --git a/sonoff/xdrv_snfled.ino b/sonoff/xdrv_snfled.ino index 9f5acdf0c..d44139255 100644 --- a/sonoff/xdrv_snfled.ino +++ b/sonoff/xdrv_snfled.ino @@ -18,7 +18,7 @@ */ /*********************************************************************************************\ - * Sonoff Led and BN-SZ01 + * Sonoff B1, Led and BN-SZ01 \*********************************************************************************************/ uint8_t ledTable[] = { @@ -39,9 +39,9 @@ uint8_t ledTable[] = { 184,186,189,191,193,195,197,199,201,204,206,208,210,212,215,217, 219,221,224,226,228,231,233,235,238,240,243,245,248,250,253,255 }; -uint8_t sl_dcolor[2]; -uint8_t sl_tcolor[2]; -uint8_t sl_lcolor[2]; +uint8_t sl_dcolor[5]; +uint8_t sl_tcolor[5]; +uint8_t sl_lcolor[5]; uint8_t sl_power; uint8_t sl_any; @@ -49,54 +49,201 @@ uint8_t sl_wakeupActive = 0; uint8_t sl_wakeupDimmer = 0; uint16_t sl_wakeupCntr = 0; -/********************************************************************************************/ +/*********************************************************************************************\ + * Sonoff B1 based on OpenLight https://github.com/icamgo/noduino-sdk +\*********************************************************************************************/ -void sl_setDim(uint8_t myDimmer) +uint8_t sl_last_command; + +void sl_di_pulse(byte times) { - if ((1 == sfl_flg) && (100 == myDimmer)) { - myDimmer = 99; // BN-SZ01 starts flickering at dimmer = 100 + for (byte i = 0; i < times; i++) { + digitalWrite(pin[GPIO_DI], HIGH); + digitalWrite(pin[GPIO_DI], LOW); } - float newDim = 100 / (float)myDimmer; - float fmyCld = (float)sysCfg.led_color[0] / newDim; - sl_dcolor[0] = (uint8_t)fmyCld; - float fmyWrm = (float)sysCfg.led_color[1] / newDim; - sl_dcolor[1] = (uint8_t)fmyWrm; } +void sl_dcki_pulse(byte times) +{ + for (byte i = 0; i < times; i++) { + digitalWrite(pin[GPIO_DCKI], HIGH); + digitalWrite(pin[GPIO_DCKI], LOW); + } +} + +void sl_send_command(uint8_t command) +{ + uint8_t command_data; + + sl_last_command = command; + +// ets_intr_lock(); + delayMicroseconds(12); // TStop > 12us. + // Send 12 DI pulse, after 6 pulse's falling edge store duty data, and 12 + // pulse's rising edge convert to command mode. + sl_di_pulse(12); + delayMicroseconds(12); // Delay >12us, begin send CMD data + + for (byte n = 0; n < 2; n++) { // Send CMD data + command_data = command; + + for (byte i = 0; i < 4; i++) { // Send byte + digitalWrite(pin[GPIO_DCKI], LOW); + if (command_data & 0x80) { + digitalWrite(pin[GPIO_DI], HIGH); + } else { + digitalWrite(pin[GPIO_DI], LOW); + } + +// digitalWrite(pin[GPIO_DI], (command_data & 0x80)); + + digitalWrite(pin[GPIO_DCKI], HIGH); + command_data = command_data << 1; + if (command_data & 0x80) { + digitalWrite(pin[GPIO_DI], HIGH); + } else { + digitalWrite(pin[GPIO_DI], LOW); + } + digitalWrite(pin[GPIO_DCKI], LOW); + digitalWrite(pin[GPIO_DI], LOW); + command_data = command_data << 1; + } + } + + delayMicroseconds(12); // TStart > 12us. Delay 12 us. + // Send 16 DI pulse, at 14 pulse's falling edge store CMD data, and + // at 16 pulse's falling edge convert to duty mode. + sl_di_pulse(16); + delayMicroseconds(12); // TStop > 12us. +// ets_intr_unlock(); +} + +void sl_send_duty(uint16_t duty_r, uint16_t duty_g, uint16_t duty_b, uint16_t duty_w, uint16_t duty_c) +{ + uint8_t bit_length = 8; + uint16_t duty_current = 0; + + uint16_t duty[8] = { duty_r, duty_g, duty_b, 0, duty_w, duty_c, 0, 0 }; // Definition for RGBWC channels + +// ets_intr_lock(); + delayMicroseconds(12); // TStop > 12us. + + for (byte channel = 0; channel < 8; channel++) { // RGB0WC00 8CH + duty_current = duty[channel]; // RGBWC Channel + for (byte i = 0; i < bit_length / 2; i++) { // Send 8bit/12bit/14bit/16bit Data + digitalWrite(pin[GPIO_DCKI], LOW); + if (duty_current & (0x01 << (bit_length - 1))) { + digitalWrite(pin[GPIO_DI], HIGH); + } else { + digitalWrite(pin[GPIO_DI], LOW); + } + digitalWrite(pin[GPIO_DCKI], HIGH); + duty_current = duty_current << 1; + if (duty_current & (0x01 << (bit_length - 1))) { + digitalWrite(pin[GPIO_DI], HIGH); + } else { + digitalWrite(pin[GPIO_DI], LOW); + } + digitalWrite(pin[GPIO_DCKI], LOW); + digitalWrite(pin[GPIO_DI], LOW); + duty_current = duty_current << 1; + } + } + + delayMicroseconds(12); // TStart > 12us. Ready for send DI pulse. + sl_di_pulse(8); // Send 8 DI pulse. After 8 pulse falling edge, store old data. + delayMicroseconds(12); // TStop > 12us. +// ets_intr_unlock(); +} + +/********************************************************************************************/ + void sl_init(void) { - sysCfg.pwmvalue[0] = 0; // We use dimmer / led_color - if (2 == sfl_flg) { - sysCfg.pwmvalue[1] = 0; // We use led_color + pin[GPIO_WS2812] = 99; // I do not allow both Sonoff Led AND WS2812 led + if (sfl_flg < 5) { + if (!my_module.gp.io[4]) { + pinMode(4, OUTPUT); // Stop floating outputs + digitalWrite(4, LOW); + } + if (!my_module.gp.io[5]) { + pinMode(5, OUTPUT); // Stop floating outputs + digitalWrite(5, LOW); + } + if (!my_module.gp.io[14]) { + pinMode(14, OUTPUT); // Stop floating outputs + digitalWrite(14, LOW); + } + sysCfg.pwmvalue[0] = 0; // We use dimmer / led_color + if (2 == sfl_flg) { + sysCfg.pwmvalue[1] = 0; // We use led_color + } + } else { + pinMode(pin[GPIO_DI], OUTPUT); + pinMode(pin[GPIO_DCKI], OUTPUT); + digitalWrite(pin[GPIO_DI], LOW); + digitalWrite(pin[GPIO_DCKI], LOW); + + // Clear all duty register + sl_dcki_pulse(64); + sl_send_command(0x18); // ONE_SHOT_DISABLE, REACTION_FAST, BIT_WIDTH_8, FREQUENCY_DIVIDE_1, SCATTER_APDM + + // Test + sl_send_duty(16, 0, 0, 0, 0); // Red } + sl_power = 0; sl_any = 0; sl_wakeupActive = 0; } -void sl_setColor(char* colstr) +void sl_setDim(uint8_t myDimmer) { - uint8_t my_color[2]; - char *p; - - uint16_t temp = strtol(colstr, &p, 16); - my_color[1] = temp & 0xFF; // Warm - temp >>= 8; - my_color[0] = temp & 0xFF; // Cold - if (temp < my_color[1]) { - temp = my_color[1]; + float temp; + + if ((1 == sfl_flg) && (100 == myDimmer)) { + myDimmer = 99; // BN-SZ01 starts flickering at dimmer = 100 } - float mDim = (float)temp / 2.55; + float newDim = 100 / (float)myDimmer; + for (byte i = 0; i < sfl_flg; i++) { + temp = (float)sysCfg.led_color[i] / newDim; + sl_dcolor[i] = (uint8_t)temp; + } +} + +void sl_setColor() +{ + uint8_t highest = 0; + float temp; + + for (byte i = 0; i < sfl_flg; i++) { + if (highest < sl_dcolor[i]) { + highest = sl_dcolor[i]; + } + } + float mDim = (float)highest / 2.55; sysCfg.led_dimmer[0] = (uint8_t)mDim; float newDim = 100 / mDim; - float fmyCold = (float)my_color[0] * newDim; - float fmyWarm = (float)my_color[1] * newDim; - sysCfg.led_color[0] = (uint8_t)fmyCold; - sysCfg.led_color[1] = (uint8_t)fmyWarm; + for (byte i = 0; i < sfl_flg; i++) { + temp = (float)sl_dcolor[i] * newDim; + sysCfg.led_color[i] = (uint8_t)temp; + } +} + +char* sl_getColor(char* scolor) +{ + sl_setDim(sysCfg.led_dimmer[0]); + scolor[0] = '\0'; + for (byte i = 0; i < sfl_flg; i++) { + snprintf_P(scolor, 11, PSTR("%s%02X"), scolor, sl_dcolor[i]); + } + return scolor; } void sl_prepPower(char *svalue, uint16_t ssvalue) { + char scolor[11]; + // do_cmnd_power(index, (sysCfg.led_dimmer[0]>0)); if (sysCfg.led_dimmer[0] && !(power&1)) { do_cmnd_power(1, 7); // No publishPowerState @@ -107,12 +254,9 @@ void sl_prepPower(char *svalue, uint16_t ssvalue) #ifdef USE_DOMOTICZ mqtt_publishDomoticzPowerState(1); #endif // USE_DOMOTICZ - sl_setDim(sysCfg.led_dimmer[0]); - if (2 == sfl_flg) { - uint16_t color = (uint16_t)sl_dcolor[0] << 8; - color += (uint16_t)sl_dcolor[1]; - snprintf_P(svalue, ssvalue, PSTR("{\"POWER\":\"%s\", \"Dimmer\":%d, \"Color\":\"%04X\"}"), - getStateText(power &1), sysCfg.led_dimmer[0], color); + if (sfl_flg > 1) { + snprintf_P(svalue, ssvalue, PSTR("{\"POWER\":\"%s\", \"Dimmer\":%d, \"Color\":\"%s\"}"), + getStateText(power &1), sysCfg.led_dimmer[0], sl_getColor(scolor)); } else { snprintf_P(svalue, ssvalue, PSTR("{\"POWER\":\"%s\", \"Dimmer\":%d}"), getStateText(power &1), sysCfg.led_dimmer[0]); @@ -133,40 +277,38 @@ void sl_animate() // {"Wakeup":"Done"} char svalue[32]; // was MESSZ uint8_t fadeValue; + uint8_t cur_col[5]; if (0 == sl_power) { // Power Off - sl_tcolor[0] = 0; - sl_tcolor[1] = 0; + for (byte i = 0; i < sfl_flg; i++) { + sl_tcolor[i] = 0; + } } else { if (!sl_wakeupActive) { // Power On sl_setDim(sysCfg.led_dimmer[0]); if (0 == sysCfg.led_fade) { - sl_tcolor[0] = sl_dcolor[0]; - sl_tcolor[1] = sl_dcolor[1]; - } else { - if (sl_tcolor[0] != sl_dcolor[0]) { - if (sl_tcolor[0] < sl_dcolor[0]) { - sl_tcolor[0] += ((sl_dcolor[0] - sl_tcolor[0]) >> sysCfg.led_speed) +1; - } - if (sl_tcolor[0] > sl_dcolor[0]) { - sl_tcolor[0] -= ((sl_tcolor[0] - sl_dcolor[0]) >> sysCfg.led_speed) +1; - } + for (byte i = 0; i < sfl_flg; i++) { + sl_tcolor[i] = sl_dcolor[i]; } - if ((2 == sfl_flg) && (sl_tcolor[1] != sl_dcolor[1])) { - if (sl_tcolor[1] < sl_dcolor[1]) { - sl_tcolor[1] += ((sl_dcolor[1] - sl_tcolor[1]) >> sysCfg.led_speed) +1; - } - if (sl_tcolor[1] > sl_dcolor[1]) { - sl_tcolor[1] -= ((sl_tcolor[1] - sl_dcolor[1]) >> sysCfg.led_speed) +1; + } else { + for (byte i = 0; i < sfl_flg; i++) { + if (sl_tcolor[i] != sl_dcolor[i]) { + if (sl_tcolor[i] < sl_dcolor[i]) { + sl_tcolor[i] += ((sl_dcolor[i] - sl_tcolor[i]) >> sysCfg.led_speed) +1; + } + if (sl_tcolor[i] > sl_dcolor[i]) { + sl_tcolor[i] -= ((sl_tcolor[i] - sl_dcolor[i]) >> sysCfg.led_speed) +1; + } } } } } else { // Power On using wake up duration if (2 == sl_wakeupActive) { sl_wakeupActive = 1; - sl_tcolor[0] = 0; - sl_tcolor[1] = 0; + for (byte i = 0; i < sfl_flg; i++) { + sl_tcolor[i] = 0; + } sl_wakeupCntr = 0; sl_wakeupDimmer = 0; } @@ -176,8 +318,9 @@ void sl_animate() sl_wakeupDimmer++; if (sl_wakeupDimmer <= sysCfg.led_dimmer[0]) { sl_setDim(sl_wakeupDimmer); - sl_tcolor[0] = sl_dcolor[0]; - sl_tcolor[1] = sl_dcolor[1]; + for (byte i = 0; i < sfl_flg; i++) { + sl_tcolor[i] = sl_dcolor[i]; + } } else { snprintf_P(svalue, sizeof(svalue), PSTR("{\"Wakeup\":\"Done\"}")); mqtt_publish_topic_P(2, PSTR("WAKEUP"), svalue); @@ -186,15 +329,25 @@ void sl_animate() } } } - if ((sl_lcolor[0] != sl_tcolor[0]) || (sl_lcolor[1] != sl_tcolor[1]) || sl_any) { + for (byte i = 0; i < sfl_flg; i++) { + if (sl_lcolor[i] != sl_tcolor[i]) { + sl_any = 1; + } + } + if (sl_any) { sl_any = 0; - sl_lcolor[0] = sl_tcolor[0]; - sl_lcolor[1] = sl_tcolor[1]; for (byte i = 0; i < sfl_flg; i++) { - if (pin[GPIO_PWM1 +i] < 99) { - analogWrite(pin[GPIO_PWM1 +i], ((sysCfg.led_table) ? ledTable[sl_lcolor[i]] : sl_lcolor[i]) * (PWM_RANGE / 255)); + sl_lcolor[i] = sl_tcolor[i]; + cur_col[i] = (sysCfg.led_table) ? ledTable[sl_lcolor[i]] : sl_lcolor[i]; + if (sfl_flg < 5) { + if (pin[GPIO_PWM1 +i] < 99) { + analogWrite(pin[GPIO_PWM1 +i], cur_col[i] * (PWM_RANGE / 255)); + } } } + if (5 == sfl_flg) { + sl_send_duty(cur_col[0], cur_col[1], cur_col[2], cur_col[3], cur_col[4]); + } } } @@ -202,28 +355,135 @@ void sl_animate() * Hue support \*********************************************************************************************/ +void sl_rgb2hsb(float *hue, float *sat, float *bri) +{ + sl_setDim(sysCfg.led_dimmer[0]); + + float r = (float)(sl_dcolor[0] / 255.0f); + float g = (float)(sl_dcolor[1] / 255.0f); + float b = (float)(sl_dcolor[2] / 255.0f); + + float max = fmax(fmax(r, g), b); + float min = fmin(fmin(r, g), b); + + *bri = (max + min) / 2.0f; + + if (max == min) { + *hue = *sat = 0.0f; + } else { + float d = max - min; + *sat = (*bri > 0.5f) ? d / (2.0f - max - min) : d / (max + min); + + if (r > g && r > b) { + *hue = (g - b) / d + (g < b ? 6.0f : 0.0f); + } + else if (g > b) { + *hue = (b - r) / d + 2.0f; + } + else { + *hue = (r - g) / d + 4.0f; + } + *hue /= 6.0f; + } +} + +float sl_hue2rgb(float p, float q, float t) +{ + if (t < 0.0f) { + t += 1.0f; + } + if (t > 1.0f) { + t -= 1.0f; + } + if (t < 1.0f / 6.0f) { + return p + (q - p) * 6.0f * t; + } + if (t < 1.0f / 2.0f) { + return q; + } + if (t < 2.0f / 3.0f) { + return p + (q - p) * (2.0f / 3.0f - t) * 6.0f; + } + return p; +} + +void sl_hsb2rgb(float hue, float sat, float bri) +{ + float r; + float g; + float b; + + if (sat == 0.0f) { + r = g = b = bri; + } else { + float q = bri < 0.5f ? bri * (1.0f + sat) : bri + sat - bri * sat; + float p = 2.0f * bri - q; + r = sl_hue2rgb(p, q, hue + 1.0f / 3.0f); + g = sl_hue2rgb(p, q, hue); + b = sl_hue2rgb(p, q, hue - 1.0f / 3.0f); + } + sl_dcolor[0] = (uint8_t)(r * 255 + 0.5f); + sl_dcolor[1] = (uint8_t)(g * 255 + 0.5f); + sl_dcolor[2] = (uint8_t)(b * 255 + 0.5f); + sl_setColor(); +} + +/********************************************************************************************/ + void sl_replaceHSB(String *response) { - response->replace("{h}", "0"); - response->replace("{s}", "0"); - response->replace("{b}", String((uint8_t)(2.54f * (float)sysCfg.led_dimmer[0]))); + float hue; + float sat; + float bri; + + if (5 == sfl_flg) { + sl_rgb2hsb(&hue, &sat, &bri); + response->replace("{h}", String((uint16_t)(65535.0f * hue))); + response->replace("{s}", String((uint8_t)(254.0f * sat))); + response->replace("{b}", String((uint8_t)(254.0f * bri))); + } else { + response->replace("{h}", "0"); + response->replace("{s}", "0"); + response->replace("{b}", String((uint8_t)(2.54f * (float)sysCfg.led_dimmer[0]))); + } } void sl_getHSB(float *hue, float *sat, float *bri) { - *hue = 0; - *sat = 0; - *bri = (2.54f * (float)sysCfg.led_dimmer[0]); + if (5 == sfl_flg) { + sl_rgb2hsb(hue, sat, bri); + } else { + *hue = 0; + *sat = 0; + *bri = (2.54f * (float)sysCfg.led_dimmer[0]); + } } void sl_setHSB(float hue, float sat, float bri) { char svalue[MESSZ]; - - uint8_t tmp = (uint8_t)(bri * 100); - sysCfg.led_dimmer[0] = tmp; - sl_prepPower(svalue, sizeof(svalue)); - mqtt_publish_topic_P(5, "DIMMER", svalue); + +/* + char log[LOGSZ]; + char stemp1[10]; + char stemp2[10]; + char stemp3[10]; + dtostrf(hue, 1, 3, stemp1); + dtostrf(sat, 1, 3, stemp2); + dtostrf(bri, 1, 3, stemp3); + snprintf_P(log, sizeof(log), PSTR("LED: Hue %s, Sat %s, Bri %s"), stemp1, stemp2, stemp3); + addLog(LOG_LEVEL_DEBUG, log); +*/ + if (5 == sfl_flg) { + sl_hsb2rgb(hue, sat, bri); + sl_prepPower(svalue, sizeof(svalue)); + mqtt_publish_topic_P(5, "COLOR", svalue); + } else { + uint8_t tmp = (uint8_t)(bri * 100); + sysCfg.led_dimmer[0] = tmp; + sl_prepPower(svalue, sizeof(svalue)); + mqtt_publish_topic_P(5, "DIMMER", svalue); + } } /*********************************************************************************************\ @@ -234,18 +494,19 @@ boolean sl_command(char *type, uint16_t index, char *dataBufUc, uint16_t data_le { boolean serviced = true; boolean coldim = false; + char scolor[11]; + char *p; - if ((2 == sfl_flg) && !strcmp_P(type,PSTR("COLOR"))) { - uint8_t my_color[2]; - char *p; - if (4 == data_len) { - sl_setColor(dataBufUc); + if ((sfl_flg > 1) && !strcmp_P(type,PSTR("COLOR"))) { + if ((2 * sfl_flg) == data_len) { + for (byte i = 0; i < sfl_flg; i++) { + strlcpy(scolor, dataBufUc + (i *2), 3); + sl_dcolor[i] = (uint8_t)strtol(scolor, &p, 16); + } + sl_setColor(); coldim = true; } else { - sl_setDim(sysCfg.led_dimmer[0]); - uint16_t color = (uint16_t)sl_dcolor[0] << 8; - color += (uint16_t)sl_dcolor[1]; - snprintf_P(svalue, ssvalue, PSTR("{\"Color\":\"%04X\"}"), color); + snprintf_P(svalue, ssvalue, PSTR("{\"Color\":\"%s\"}"), sl_getColor(scolor)); } } else if (!strcmp_P(type,PSTR("DIMMER"))) { From 941deba8152118074f006cbe138c1891addfb37b Mon Sep 17 00:00:00 2001 From: Theo Arends Date: Sun, 13 Aug 2017 11:19:34 +0200 Subject: [PATCH 04/13] Still testing Sonoff B1 --- sonoff/_releasenotes.ino | 2 +- sonoff/sonoff.ino | 2 +- sonoff/xdrv_snfled.ino | 120 ++++++++++++++++----------------------- 3 files changed, 52 insertions(+), 72 deletions(-) diff --git a/sonoff/_releasenotes.ino b/sonoff/_releasenotes.ino index daa933601..f85a28622 100644 --- a/sonoff/_releasenotes.ino +++ b/sonoff/_releasenotes.ino @@ -1,4 +1,4 @@ -/* 5.5.2c +/* 5.5.2d * Fix Sonoff Pow intermittent exception 0 * Change Sonoff Pow sending Domoticz telemetry data only * Add Sonoff B1 support (experimental) diff --git a/sonoff/sonoff.ino b/sonoff/sonoff.ino index 8d99a51f3..86d85ae11 100644 --- a/sonoff/sonoff.ino +++ b/sonoff/sonoff.ino @@ -25,7 +25,7 @@ - Select IDE Tools - Flash Size: "1M (no SPIFFS)" ====================================================*/ -#define VERSION 0x05050203 // 5.5.2c +#define VERSION 0x05050204 // 5.5.2d enum log_t {LOG_LEVEL_NONE, LOG_LEVEL_ERROR, LOG_LEVEL_INFO, LOG_LEVEL_DEBUG, LOG_LEVEL_DEBUG_MORE, LOG_LEVEL_ALL}; enum week_t {Last, First, Second, Third, Fourth}; diff --git a/sonoff/xdrv_snfled.ino b/sonoff/xdrv_snfled.ino index d44139255..b8d7a74a0 100644 --- a/sonoff/xdrv_snfled.ino +++ b/sonoff/xdrv_snfled.ino @@ -50,24 +50,29 @@ uint8_t sl_wakeupDimmer = 0; uint16_t sl_wakeupCntr = 0; /*********************************************************************************************\ - * Sonoff B1 based on OpenLight https://github.com/icamgo/noduino-sdk + * Sonoff B1 based on OpenLight https://github.com/icamgo/noduino-sdk (my9231 and my9291) \*********************************************************************************************/ -uint8_t sl_last_command; +extern "C" { + void os_delay_us(unsigned int); +} -void sl_di_pulse(byte times) +uint8_t sl_pdi; +uint8_t sl_pdcki; + +void sl_di_pulse(uint8_t times) { - for (byte i = 0; i < times; i++) { - digitalWrite(pin[GPIO_DI], HIGH); - digitalWrite(pin[GPIO_DI], LOW); + for (uint8_t i = 0; i < times; i++) { + digitalWrite(sl_pdi, HIGH); + digitalWrite(sl_pdi, LOW); } } -void sl_dcki_pulse(byte times) +void sl_dcki_pulse(uint8_t times) { - for (byte i = 0; i < times; i++) { - digitalWrite(pin[GPIO_DCKI], HIGH); - digitalWrite(pin[GPIO_DCKI], LOW); + for (uint8_t i = 0; i < times; i++) { + digitalWrite(sl_pdcki, HIGH); + digitalWrite(sl_pdcki, LOW); } } @@ -75,84 +80,57 @@ void sl_send_command(uint8_t command) { uint8_t command_data; - sl_last_command = command; - // ets_intr_lock(); - delayMicroseconds(12); // TStop > 12us. + os_delay_us(12); // TStop > 12us. // Send 12 DI pulse, after 6 pulse's falling edge store duty data, and 12 // pulse's rising edge convert to command mode. sl_di_pulse(12); - delayMicroseconds(12); // Delay >12us, begin send CMD data - - for (byte n = 0; n < 2; n++) { // Send CMD data + os_delay_us(12); // Delay >12us, begin send CMD data + for (uint8_t n = 0; n < 2; n++) { // Send CMD data command_data = command; - - for (byte i = 0; i < 4; i++) { // Send byte - digitalWrite(pin[GPIO_DCKI], LOW); - if (command_data & 0x80) { - digitalWrite(pin[GPIO_DI], HIGH); - } else { - digitalWrite(pin[GPIO_DI], LOW); - } - -// digitalWrite(pin[GPIO_DI], (command_data & 0x80)); - - digitalWrite(pin[GPIO_DCKI], HIGH); + for (uint8_t i = 0; i < 4; i++) { // Send byte + digitalWrite(sl_pdcki, LOW); + digitalWrite(sl_pdi, (command_data & 0x80)); + digitalWrite(sl_pdcki, HIGH); command_data = command_data << 1; - if (command_data & 0x80) { - digitalWrite(pin[GPIO_DI], HIGH); - } else { - digitalWrite(pin[GPIO_DI], LOW); - } - digitalWrite(pin[GPIO_DCKI], LOW); - digitalWrite(pin[GPIO_DI], LOW); + digitalWrite(sl_pdi, (command_data & 0x80)); + digitalWrite(sl_pdcki, LOW); + digitalWrite(sl_pdi, LOW); command_data = command_data << 1; } } - - delayMicroseconds(12); // TStart > 12us. Delay 12 us. + os_delay_us(12); // TStart > 12us. Delay 12 us. // Send 16 DI pulse, at 14 pulse's falling edge store CMD data, and // at 16 pulse's falling edge convert to duty mode. sl_di_pulse(16); - delayMicroseconds(12); // TStop > 12us. + os_delay_us(12); // TStop > 12us. // ets_intr_unlock(); } void sl_send_duty(uint16_t duty_r, uint16_t duty_g, uint16_t duty_b, uint16_t duty_w, uint16_t duty_c) { - uint8_t bit_length = 8; uint16_t duty_current = 0; - uint16_t duty[8] = { duty_r, duty_g, duty_b, 0, duty_w, duty_c, 0, 0 }; // Definition for RGBWC channels + uint16_t duty[6] = { duty_r, duty_g, duty_b, duty_w, duty_c, 0 }; // Definition for RGBWC channels // ets_intr_lock(); - delayMicroseconds(12); // TStop > 12us. - - for (byte channel = 0; channel < 8; channel++) { // RGB0WC00 8CH - duty_current = duty[channel]; // RGBWC Channel - for (byte i = 0; i < bit_length / 2; i++) { // Send 8bit/12bit/14bit/16bit Data - digitalWrite(pin[GPIO_DCKI], LOW); - if (duty_current & (0x01 << (bit_length - 1))) { - digitalWrite(pin[GPIO_DI], HIGH); - } else { - digitalWrite(pin[GPIO_DI], LOW); - } - digitalWrite(pin[GPIO_DCKI], HIGH); + os_delay_us(12); // TStop > 12us. + for (uint8_t channel = 0; channel < 6; channel++) { // RGBWC0 6CH + duty_current = duty[channel]; // RGBWC Channel + for (uint8_t i = 0; i < 4; i++) { // Send 8bit Data + digitalWrite(sl_pdcki, LOW); + digitalWrite(sl_pdi, (duty_current & 0x80)); + digitalWrite(sl_pdcki, HIGH); duty_current = duty_current << 1; - if (duty_current & (0x01 << (bit_length - 1))) { - digitalWrite(pin[GPIO_DI], HIGH); - } else { - digitalWrite(pin[GPIO_DI], LOW); - } - digitalWrite(pin[GPIO_DCKI], LOW); - digitalWrite(pin[GPIO_DI], LOW); + digitalWrite(sl_pdi, (duty_current & 0x80)); + digitalWrite(sl_pdcki, LOW); + digitalWrite(sl_pdi, LOW); duty_current = duty_current << 1; } } - - delayMicroseconds(12); // TStart > 12us. Ready for send DI pulse. - sl_di_pulse(8); // Send 8 DI pulse. After 8 pulse falling edge, store old data. - delayMicroseconds(12); // TStop > 12us. + os_delay_us(12); // TStart > 12us. Ready for send DI pulse. + sl_di_pulse(8); // Send 8 DI pulse. After 8 pulse falling edge, store old data. + os_delay_us(12); // TStop > 12us. // ets_intr_unlock(); } @@ -179,17 +157,20 @@ void sl_init(void) sysCfg.pwmvalue[1] = 0; // We use led_color } } else { - pinMode(pin[GPIO_DI], OUTPUT); - pinMode(pin[GPIO_DCKI], OUTPUT); - digitalWrite(pin[GPIO_DI], LOW); - digitalWrite(pin[GPIO_DCKI], LOW); + sl_pdi = pin[GPIO_DI]; + sl_pdcki = pin[GPIO_DCKI]; + + pinMode(sl_pdi, OUTPUT); + pinMode(sl_pdcki, OUTPUT); + digitalWrite(sl_pdi, LOW); + digitalWrite(sl_pdcki, LOW); // Clear all duty register sl_dcki_pulse(64); sl_send_command(0x18); // ONE_SHOT_DISABLE, REACTION_FAST, BIT_WIDTH_8, FREQUENCY_DIVIDE_1, SCATTER_APDM // Test - sl_send_duty(16, 0, 0, 0, 0); // Red +// sl_send_duty(16, 0, 0, 0, 0); // Red } sl_power = 0; @@ -463,7 +444,6 @@ void sl_setHSB(float hue, float sat, float bri) { char svalue[MESSZ]; -/* char log[LOGSZ]; char stemp1[10]; char stemp2[10]; @@ -473,7 +453,7 @@ void sl_setHSB(float hue, float sat, float bri) dtostrf(bri, 1, 3, stemp3); snprintf_P(log, sizeof(log), PSTR("LED: Hue %s, Sat %s, Bri %s"), stemp1, stemp2, stemp3); addLog(LOG_LEVEL_DEBUG, log); -*/ + if (5 == sfl_flg) { sl_hsb2rgb(hue, sat, bri); sl_prepPower(svalue, sizeof(svalue)); From 1377b4b171b1407183b6b58a387f063da287eda6 Mon Sep 17 00:00:00 2001 From: Theo Arends Date: Sun, 13 Aug 2017 11:23:07 +0200 Subject: [PATCH 05/13] Revert "Experimental Sonoff B1 support" This reverts commit 7825bc0f0a0769e3706020e068f44d9fed119a50. --- sonoff/_releasenotes.ino | 3 +- sonoff/sonoff.ino | 26 ++- sonoff/sonoff_template.h | 19 -- sonoff/xdrv_snfled.ino | 433 ++++++++------------------------------- 4 files changed, 104 insertions(+), 377 deletions(-) diff --git a/sonoff/_releasenotes.ino b/sonoff/_releasenotes.ino index daa933601..612fb4f96 100644 --- a/sonoff/_releasenotes.ino +++ b/sonoff/_releasenotes.ino @@ -1,7 +1,6 @@ -/* 5.5.2c +/* 5.5.2b * Fix Sonoff Pow intermittent exception 0 * Change Sonoff Pow sending Domoticz telemetry data only - * Add Sonoff B1 support (experimental) * * 5.5.2 20170808 * Extent max number of WS2812 pixels from 256 to 512 (#667) diff --git a/sonoff/sonoff.ino b/sonoff/sonoff.ino index 8d99a51f3..ad7708866 100644 --- a/sonoff/sonoff.ino +++ b/sonoff/sonoff.ino @@ -25,7 +25,7 @@ - Select IDE Tools - Flash Size: "1M (no SPIFFS)" ====================================================*/ -#define VERSION 0x05050203 // 5.5.2c +#define VERSION 0x05050202 // 5.5.2b enum log_t {LOG_LEVEL_NONE, LOG_LEVEL_ERROR, LOG_LEVEL_INFO, LOG_LEVEL_DEBUG, LOG_LEVEL_DEBUG_MORE, LOG_LEVEL_ALL}; enum week_t {Last, First, Second, Third, Fourth}; @@ -303,7 +303,7 @@ uint8_t hlw_flg = 0; // Power monitor configured uint8_t i2c_flg = 0; // I2C configured uint8_t spi_flg = 0; // SPI configured uint8_t pwm_flg = 0; // PWM configured -uint8_t sfl_flg = 0; // Sonoff Led flag (0 = No led, 1 = BN-SZ01, 2 = Sonoff Led, 5 = Sonoff B1) +uint8_t sfl_flg = 0; // Sonoff Led flag (0 = No led, 1 = BN-SZ01, 2 = Sonoff Led) uint8_t pwm_idxoffset = 0; // Allowed PWM command offset (change for Sonoff Led) boolean mDNSbegun = false; @@ -2318,7 +2318,7 @@ void stateloop() button_handler(); switch_handler(); - if (sfl_flg) { // Sonoff B1, led or BN-SZ01 + if (sfl_flg) { // Sonoff BN-SZ01 or Sonoff Led sl_animate(); } @@ -2633,9 +2633,6 @@ void GPIO_init() else if (SONOFF_LED == sysCfg.module) { sfl_flg = 2; } - else if (SONOFF_B1 == sysCfg.module) { - sfl_flg = 5; - } else { Maxdevice = 0; for (byte i = 0; i < 4; i++) { @@ -2663,9 +2660,20 @@ void GPIO_init() } } - if (sfl_flg) { // Sonoff B1, Led or BN-SZ01 - if (sfl_flg < 5) { - pwm_idxoffset = sfl_flg; // 1 for BN-SZ01, 2 for Sonoff Led + if (sfl_flg) { // Sonoff Led or BN-SZ01 + pwm_idxoffset = sfl_flg; // 1 for BN-SZ01, 2 for Sonoff Led + pin[GPIO_WS2812] = 99; // I do not allow both Sonoff Led AND WS2812 led + if (!my_module.gp.io[4]) { + pinMode(4, OUTPUT); // Stop floating outputs + digitalWrite(4, LOW); + } + if (!my_module.gp.io[5]) { + pinMode(5, OUTPUT); // Stop floating outputs + digitalWrite(5, LOW); + } + if (!my_module.gp.io[14]) { + pinMode(14, OUTPUT); // Stop floating outputs + digitalWrite(14, LOW); } sl_init(); } diff --git a/sonoff/sonoff_template.h b/sonoff/sonoff_template.h index 7ceea9263..1d4400bc3 100644 --- a/sonoff/sonoff_template.h +++ b/sonoff/sonoff_template.h @@ -118,8 +118,6 @@ enum fpins_t { GPIO_HLW_CF, // HLW8012 CF power (Sonoff Pow) GPIO_ADC0, // ADC GPIO_USER, // User configurable - GPIO_DI, // my9231 PWM input - GPIO_DCKI, // my9231 CLK input GPIO_MAX }; /********************************************************************************************/ @@ -151,7 +149,6 @@ enum module_t { SONOFF_4CHPRO, HUAFAN_SS, SONOFF_BRIDGE, - SONOFF_B1, MAXMODULE }; /********************************************************************************************/ @@ -492,22 +489,6 @@ const mytmplt modules[MAXMODULE] PROGMEM = { 0, GPIO_LED1_INV, // GPIO13 Blue Led (0 = On, 1 = Off) 0, 0, 0, 0 - }, - { "Sonoff B1", // Sonoff B1 (ESP8285 - my9231) - GPIO_KEY1, // GPIO00 Pad - GPIO_USER, // GPIO01 Serial RXD and Optional sensor pad - GPIO_USER, // GPIO02 Optional sensor SDA pad - GPIO_USER, // GPIO03 Serial TXD and Optional sensor pad - 0, 0, - 0, 0, 0, // Flash connection - 0, 0, - 0, // Flash connection - GPIO_DI, // GPIO12 my9231 DI - 0, - GPIO_DCKI, // GPIO14 my9231 DCKI - 0, - 0, 0 } - }; diff --git a/sonoff/xdrv_snfled.ino b/sonoff/xdrv_snfled.ino index d44139255..9f5acdf0c 100644 --- a/sonoff/xdrv_snfled.ino +++ b/sonoff/xdrv_snfled.ino @@ -18,7 +18,7 @@ */ /*********************************************************************************************\ - * Sonoff B1, Led and BN-SZ01 + * Sonoff Led and BN-SZ01 \*********************************************************************************************/ uint8_t ledTable[] = { @@ -39,9 +39,9 @@ uint8_t ledTable[] = { 184,186,189,191,193,195,197,199,201,204,206,208,210,212,215,217, 219,221,224,226,228,231,233,235,238,240,243,245,248,250,253,255 }; -uint8_t sl_dcolor[5]; -uint8_t sl_tcolor[5]; -uint8_t sl_lcolor[5]; +uint8_t sl_dcolor[2]; +uint8_t sl_tcolor[2]; +uint8_t sl_lcolor[2]; uint8_t sl_power; uint8_t sl_any; @@ -49,201 +49,54 @@ uint8_t sl_wakeupActive = 0; uint8_t sl_wakeupDimmer = 0; uint16_t sl_wakeupCntr = 0; -/*********************************************************************************************\ - * Sonoff B1 based on OpenLight https://github.com/icamgo/noduino-sdk -\*********************************************************************************************/ - -uint8_t sl_last_command; - -void sl_di_pulse(byte times) -{ - for (byte i = 0; i < times; i++) { - digitalWrite(pin[GPIO_DI], HIGH); - digitalWrite(pin[GPIO_DI], LOW); - } -} - -void sl_dcki_pulse(byte times) -{ - for (byte i = 0; i < times; i++) { - digitalWrite(pin[GPIO_DCKI], HIGH); - digitalWrite(pin[GPIO_DCKI], LOW); - } -} - -void sl_send_command(uint8_t command) -{ - uint8_t command_data; - - sl_last_command = command; - -// ets_intr_lock(); - delayMicroseconds(12); // TStop > 12us. - // Send 12 DI pulse, after 6 pulse's falling edge store duty data, and 12 - // pulse's rising edge convert to command mode. - sl_di_pulse(12); - delayMicroseconds(12); // Delay >12us, begin send CMD data - - for (byte n = 0; n < 2; n++) { // Send CMD data - command_data = command; - - for (byte i = 0; i < 4; i++) { // Send byte - digitalWrite(pin[GPIO_DCKI], LOW); - if (command_data & 0x80) { - digitalWrite(pin[GPIO_DI], HIGH); - } else { - digitalWrite(pin[GPIO_DI], LOW); - } - -// digitalWrite(pin[GPIO_DI], (command_data & 0x80)); - - digitalWrite(pin[GPIO_DCKI], HIGH); - command_data = command_data << 1; - if (command_data & 0x80) { - digitalWrite(pin[GPIO_DI], HIGH); - } else { - digitalWrite(pin[GPIO_DI], LOW); - } - digitalWrite(pin[GPIO_DCKI], LOW); - digitalWrite(pin[GPIO_DI], LOW); - command_data = command_data << 1; - } - } - - delayMicroseconds(12); // TStart > 12us. Delay 12 us. - // Send 16 DI pulse, at 14 pulse's falling edge store CMD data, and - // at 16 pulse's falling edge convert to duty mode. - sl_di_pulse(16); - delayMicroseconds(12); // TStop > 12us. -// ets_intr_unlock(); -} - -void sl_send_duty(uint16_t duty_r, uint16_t duty_g, uint16_t duty_b, uint16_t duty_w, uint16_t duty_c) -{ - uint8_t bit_length = 8; - uint16_t duty_current = 0; - - uint16_t duty[8] = { duty_r, duty_g, duty_b, 0, duty_w, duty_c, 0, 0 }; // Definition for RGBWC channels - -// ets_intr_lock(); - delayMicroseconds(12); // TStop > 12us. - - for (byte channel = 0; channel < 8; channel++) { // RGB0WC00 8CH - duty_current = duty[channel]; // RGBWC Channel - for (byte i = 0; i < bit_length / 2; i++) { // Send 8bit/12bit/14bit/16bit Data - digitalWrite(pin[GPIO_DCKI], LOW); - if (duty_current & (0x01 << (bit_length - 1))) { - digitalWrite(pin[GPIO_DI], HIGH); - } else { - digitalWrite(pin[GPIO_DI], LOW); - } - digitalWrite(pin[GPIO_DCKI], HIGH); - duty_current = duty_current << 1; - if (duty_current & (0x01 << (bit_length - 1))) { - digitalWrite(pin[GPIO_DI], HIGH); - } else { - digitalWrite(pin[GPIO_DI], LOW); - } - digitalWrite(pin[GPIO_DCKI], LOW); - digitalWrite(pin[GPIO_DI], LOW); - duty_current = duty_current << 1; - } - } - - delayMicroseconds(12); // TStart > 12us. Ready for send DI pulse. - sl_di_pulse(8); // Send 8 DI pulse. After 8 pulse falling edge, store old data. - delayMicroseconds(12); // TStop > 12us. -// ets_intr_unlock(); -} - /********************************************************************************************/ +void sl_setDim(uint8_t myDimmer) +{ + if ((1 == sfl_flg) && (100 == myDimmer)) { + myDimmer = 99; // BN-SZ01 starts flickering at dimmer = 100 + } + float newDim = 100 / (float)myDimmer; + float fmyCld = (float)sysCfg.led_color[0] / newDim; + sl_dcolor[0] = (uint8_t)fmyCld; + float fmyWrm = (float)sysCfg.led_color[1] / newDim; + sl_dcolor[1] = (uint8_t)fmyWrm; +} + void sl_init(void) { - pin[GPIO_WS2812] = 99; // I do not allow both Sonoff Led AND WS2812 led - if (sfl_flg < 5) { - if (!my_module.gp.io[4]) { - pinMode(4, OUTPUT); // Stop floating outputs - digitalWrite(4, LOW); - } - if (!my_module.gp.io[5]) { - pinMode(5, OUTPUT); // Stop floating outputs - digitalWrite(5, LOW); - } - if (!my_module.gp.io[14]) { - pinMode(14, OUTPUT); // Stop floating outputs - digitalWrite(14, LOW); - } - sysCfg.pwmvalue[0] = 0; // We use dimmer / led_color - if (2 == sfl_flg) { - sysCfg.pwmvalue[1] = 0; // We use led_color - } - } else { - pinMode(pin[GPIO_DI], OUTPUT); - pinMode(pin[GPIO_DCKI], OUTPUT); - digitalWrite(pin[GPIO_DI], LOW); - digitalWrite(pin[GPIO_DCKI], LOW); - - // Clear all duty register - sl_dcki_pulse(64); - sl_send_command(0x18); // ONE_SHOT_DISABLE, REACTION_FAST, BIT_WIDTH_8, FREQUENCY_DIVIDE_1, SCATTER_APDM - - // Test - sl_send_duty(16, 0, 0, 0, 0); // Red + sysCfg.pwmvalue[0] = 0; // We use dimmer / led_color + if (2 == sfl_flg) { + sysCfg.pwmvalue[1] = 0; // We use led_color } - sl_power = 0; sl_any = 0; sl_wakeupActive = 0; } -void sl_setDim(uint8_t myDimmer) +void sl_setColor(char* colstr) { - float temp; - - if ((1 == sfl_flg) && (100 == myDimmer)) { - myDimmer = 99; // BN-SZ01 starts flickering at dimmer = 100 - } - float newDim = 100 / (float)myDimmer; - for (byte i = 0; i < sfl_flg; i++) { - temp = (float)sysCfg.led_color[i] / newDim; - sl_dcolor[i] = (uint8_t)temp; - } -} + uint8_t my_color[2]; + char *p; -void sl_setColor() -{ - uint8_t highest = 0; - float temp; - - for (byte i = 0; i < sfl_flg; i++) { - if (highest < sl_dcolor[i]) { - highest = sl_dcolor[i]; - } + uint16_t temp = strtol(colstr, &p, 16); + my_color[1] = temp & 0xFF; // Warm + temp >>= 8; + my_color[0] = temp & 0xFF; // Cold + if (temp < my_color[1]) { + temp = my_color[1]; } - float mDim = (float)highest / 2.55; + float mDim = (float)temp / 2.55; sysCfg.led_dimmer[0] = (uint8_t)mDim; float newDim = 100 / mDim; - for (byte i = 0; i < sfl_flg; i++) { - temp = (float)sl_dcolor[i] * newDim; - sysCfg.led_color[i] = (uint8_t)temp; - } -} - -char* sl_getColor(char* scolor) -{ - sl_setDim(sysCfg.led_dimmer[0]); - scolor[0] = '\0'; - for (byte i = 0; i < sfl_flg; i++) { - snprintf_P(scolor, 11, PSTR("%s%02X"), scolor, sl_dcolor[i]); - } - return scolor; + float fmyCold = (float)my_color[0] * newDim; + float fmyWarm = (float)my_color[1] * newDim; + sysCfg.led_color[0] = (uint8_t)fmyCold; + sysCfg.led_color[1] = (uint8_t)fmyWarm; } void sl_prepPower(char *svalue, uint16_t ssvalue) { - char scolor[11]; - // do_cmnd_power(index, (sysCfg.led_dimmer[0]>0)); if (sysCfg.led_dimmer[0] && !(power&1)) { do_cmnd_power(1, 7); // No publishPowerState @@ -254,9 +107,12 @@ void sl_prepPower(char *svalue, uint16_t ssvalue) #ifdef USE_DOMOTICZ mqtt_publishDomoticzPowerState(1); #endif // USE_DOMOTICZ - if (sfl_flg > 1) { - snprintf_P(svalue, ssvalue, PSTR("{\"POWER\":\"%s\", \"Dimmer\":%d, \"Color\":\"%s\"}"), - getStateText(power &1), sysCfg.led_dimmer[0], sl_getColor(scolor)); + sl_setDim(sysCfg.led_dimmer[0]); + if (2 == sfl_flg) { + uint16_t color = (uint16_t)sl_dcolor[0] << 8; + color += (uint16_t)sl_dcolor[1]; + snprintf_P(svalue, ssvalue, PSTR("{\"POWER\":\"%s\", \"Dimmer\":%d, \"Color\":\"%04X\"}"), + getStateText(power &1), sysCfg.led_dimmer[0], color); } else { snprintf_P(svalue, ssvalue, PSTR("{\"POWER\":\"%s\", \"Dimmer\":%d}"), getStateText(power &1), sysCfg.led_dimmer[0]); @@ -277,38 +133,40 @@ void sl_animate() // {"Wakeup":"Done"} char svalue[32]; // was MESSZ uint8_t fadeValue; - uint8_t cur_col[5]; if (0 == sl_power) { // Power Off - for (byte i = 0; i < sfl_flg; i++) { - sl_tcolor[i] = 0; - } + sl_tcolor[0] = 0; + sl_tcolor[1] = 0; } else { if (!sl_wakeupActive) { // Power On sl_setDim(sysCfg.led_dimmer[0]); if (0 == sysCfg.led_fade) { - for (byte i = 0; i < sfl_flg; i++) { - sl_tcolor[i] = sl_dcolor[i]; - } + sl_tcolor[0] = sl_dcolor[0]; + sl_tcolor[1] = sl_dcolor[1]; } else { - for (byte i = 0; i < sfl_flg; i++) { - if (sl_tcolor[i] != sl_dcolor[i]) { - if (sl_tcolor[i] < sl_dcolor[i]) { - sl_tcolor[i] += ((sl_dcolor[i] - sl_tcolor[i]) >> sysCfg.led_speed) +1; - } - if (sl_tcolor[i] > sl_dcolor[i]) { - sl_tcolor[i] -= ((sl_tcolor[i] - sl_dcolor[i]) >> sysCfg.led_speed) +1; - } + if (sl_tcolor[0] != sl_dcolor[0]) { + if (sl_tcolor[0] < sl_dcolor[0]) { + sl_tcolor[0] += ((sl_dcolor[0] - sl_tcolor[0]) >> sysCfg.led_speed) +1; + } + if (sl_tcolor[0] > sl_dcolor[0]) { + sl_tcolor[0] -= ((sl_tcolor[0] - sl_dcolor[0]) >> sysCfg.led_speed) +1; + } + } + if ((2 == sfl_flg) && (sl_tcolor[1] != sl_dcolor[1])) { + if (sl_tcolor[1] < sl_dcolor[1]) { + sl_tcolor[1] += ((sl_dcolor[1] - sl_tcolor[1]) >> sysCfg.led_speed) +1; + } + if (sl_tcolor[1] > sl_dcolor[1]) { + sl_tcolor[1] -= ((sl_tcolor[1] - sl_dcolor[1]) >> sysCfg.led_speed) +1; } } } } else { // Power On using wake up duration if (2 == sl_wakeupActive) { sl_wakeupActive = 1; - for (byte i = 0; i < sfl_flg; i++) { - sl_tcolor[i] = 0; - } + sl_tcolor[0] = 0; + sl_tcolor[1] = 0; sl_wakeupCntr = 0; sl_wakeupDimmer = 0; } @@ -318,9 +176,8 @@ void sl_animate() sl_wakeupDimmer++; if (sl_wakeupDimmer <= sysCfg.led_dimmer[0]) { sl_setDim(sl_wakeupDimmer); - for (byte i = 0; i < sfl_flg; i++) { - sl_tcolor[i] = sl_dcolor[i]; - } + sl_tcolor[0] = sl_dcolor[0]; + sl_tcolor[1] = sl_dcolor[1]; } else { snprintf_P(svalue, sizeof(svalue), PSTR("{\"Wakeup\":\"Done\"}")); mqtt_publish_topic_P(2, PSTR("WAKEUP"), svalue); @@ -329,25 +186,15 @@ void sl_animate() } } } - for (byte i = 0; i < sfl_flg; i++) { - if (sl_lcolor[i] != sl_tcolor[i]) { - sl_any = 1; - } - } - if (sl_any) { + if ((sl_lcolor[0] != sl_tcolor[0]) || (sl_lcolor[1] != sl_tcolor[1]) || sl_any) { sl_any = 0; + sl_lcolor[0] = sl_tcolor[0]; + sl_lcolor[1] = sl_tcolor[1]; for (byte i = 0; i < sfl_flg; i++) { - sl_lcolor[i] = sl_tcolor[i]; - cur_col[i] = (sysCfg.led_table) ? ledTable[sl_lcolor[i]] : sl_lcolor[i]; - if (sfl_flg < 5) { - if (pin[GPIO_PWM1 +i] < 99) { - analogWrite(pin[GPIO_PWM1 +i], cur_col[i] * (PWM_RANGE / 255)); - } + if (pin[GPIO_PWM1 +i] < 99) { + analogWrite(pin[GPIO_PWM1 +i], ((sysCfg.led_table) ? ledTable[sl_lcolor[i]] : sl_lcolor[i]) * (PWM_RANGE / 255)); } } - if (5 == sfl_flg) { - sl_send_duty(cur_col[0], cur_col[1], cur_col[2], cur_col[3], cur_col[4]); - } } } @@ -355,135 +202,28 @@ void sl_animate() * Hue support \*********************************************************************************************/ -void sl_rgb2hsb(float *hue, float *sat, float *bri) -{ - sl_setDim(sysCfg.led_dimmer[0]); - - float r = (float)(sl_dcolor[0] / 255.0f); - float g = (float)(sl_dcolor[1] / 255.0f); - float b = (float)(sl_dcolor[2] / 255.0f); - - float max = fmax(fmax(r, g), b); - float min = fmin(fmin(r, g), b); - - *bri = (max + min) / 2.0f; - - if (max == min) { - *hue = *sat = 0.0f; - } else { - float d = max - min; - *sat = (*bri > 0.5f) ? d / (2.0f - max - min) : d / (max + min); - - if (r > g && r > b) { - *hue = (g - b) / d + (g < b ? 6.0f : 0.0f); - } - else if (g > b) { - *hue = (b - r) / d + 2.0f; - } - else { - *hue = (r - g) / d + 4.0f; - } - *hue /= 6.0f; - } -} - -float sl_hue2rgb(float p, float q, float t) -{ - if (t < 0.0f) { - t += 1.0f; - } - if (t > 1.0f) { - t -= 1.0f; - } - if (t < 1.0f / 6.0f) { - return p + (q - p) * 6.0f * t; - } - if (t < 1.0f / 2.0f) { - return q; - } - if (t < 2.0f / 3.0f) { - return p + (q - p) * (2.0f / 3.0f - t) * 6.0f; - } - return p; -} - -void sl_hsb2rgb(float hue, float sat, float bri) -{ - float r; - float g; - float b; - - if (sat == 0.0f) { - r = g = b = bri; - } else { - float q = bri < 0.5f ? bri * (1.0f + sat) : bri + sat - bri * sat; - float p = 2.0f * bri - q; - r = sl_hue2rgb(p, q, hue + 1.0f / 3.0f); - g = sl_hue2rgb(p, q, hue); - b = sl_hue2rgb(p, q, hue - 1.0f / 3.0f); - } - sl_dcolor[0] = (uint8_t)(r * 255 + 0.5f); - sl_dcolor[1] = (uint8_t)(g * 255 + 0.5f); - sl_dcolor[2] = (uint8_t)(b * 255 + 0.5f); - sl_setColor(); -} - -/********************************************************************************************/ - void sl_replaceHSB(String *response) { - float hue; - float sat; - float bri; - - if (5 == sfl_flg) { - sl_rgb2hsb(&hue, &sat, &bri); - response->replace("{h}", String((uint16_t)(65535.0f * hue))); - response->replace("{s}", String((uint8_t)(254.0f * sat))); - response->replace("{b}", String((uint8_t)(254.0f * bri))); - } else { - response->replace("{h}", "0"); - response->replace("{s}", "0"); - response->replace("{b}", String((uint8_t)(2.54f * (float)sysCfg.led_dimmer[0]))); - } + response->replace("{h}", "0"); + response->replace("{s}", "0"); + response->replace("{b}", String((uint8_t)(2.54f * (float)sysCfg.led_dimmer[0]))); } void sl_getHSB(float *hue, float *sat, float *bri) { - if (5 == sfl_flg) { - sl_rgb2hsb(hue, sat, bri); - } else { - *hue = 0; - *sat = 0; - *bri = (2.54f * (float)sysCfg.led_dimmer[0]); - } + *hue = 0; + *sat = 0; + *bri = (2.54f * (float)sysCfg.led_dimmer[0]); } void sl_setHSB(float hue, float sat, float bri) { char svalue[MESSZ]; - -/* - char log[LOGSZ]; - char stemp1[10]; - char stemp2[10]; - char stemp3[10]; - dtostrf(hue, 1, 3, stemp1); - dtostrf(sat, 1, 3, stemp2); - dtostrf(bri, 1, 3, stemp3); - snprintf_P(log, sizeof(log), PSTR("LED: Hue %s, Sat %s, Bri %s"), stemp1, stemp2, stemp3); - addLog(LOG_LEVEL_DEBUG, log); -*/ - if (5 == sfl_flg) { - sl_hsb2rgb(hue, sat, bri); - sl_prepPower(svalue, sizeof(svalue)); - mqtt_publish_topic_P(5, "COLOR", svalue); - } else { - uint8_t tmp = (uint8_t)(bri * 100); - sysCfg.led_dimmer[0] = tmp; - sl_prepPower(svalue, sizeof(svalue)); - mqtt_publish_topic_P(5, "DIMMER", svalue); - } + + uint8_t tmp = (uint8_t)(bri * 100); + sysCfg.led_dimmer[0] = tmp; + sl_prepPower(svalue, sizeof(svalue)); + mqtt_publish_topic_P(5, "DIMMER", svalue); } /*********************************************************************************************\ @@ -494,19 +234,18 @@ boolean sl_command(char *type, uint16_t index, char *dataBufUc, uint16_t data_le { boolean serviced = true; boolean coldim = false; - char scolor[11]; - char *p; - if ((sfl_flg > 1) && !strcmp_P(type,PSTR("COLOR"))) { - if ((2 * sfl_flg) == data_len) { - for (byte i = 0; i < sfl_flg; i++) { - strlcpy(scolor, dataBufUc + (i *2), 3); - sl_dcolor[i] = (uint8_t)strtol(scolor, &p, 16); - } - sl_setColor(); + if ((2 == sfl_flg) && !strcmp_P(type,PSTR("COLOR"))) { + uint8_t my_color[2]; + char *p; + if (4 == data_len) { + sl_setColor(dataBufUc); coldim = true; } else { - snprintf_P(svalue, ssvalue, PSTR("{\"Color\":\"%s\"}"), sl_getColor(scolor)); + sl_setDim(sysCfg.led_dimmer[0]); + uint16_t color = (uint16_t)sl_dcolor[0] << 8; + color += (uint16_t)sl_dcolor[1]; + snprintf_P(svalue, ssvalue, PSTR("{\"Color\":\"%04X\"}"), color); } } else if (!strcmp_P(type,PSTR("DIMMER"))) { From 700e51b0914816d0fe4277e58338122422549efa Mon Sep 17 00:00:00 2001 From: Theo Arends Date: Sun, 13 Aug 2017 13:11:44 +0200 Subject: [PATCH 06/13] Add Sonoff B1 b using different pins --- sonoff/_releasenotes.ino | 2 +- sonoff/sonoff.ino | 4 ++-- sonoff/sonoff_template.h | 18 +++++++++++++++++- 3 files changed, 20 insertions(+), 4 deletions(-) diff --git a/sonoff/_releasenotes.ino b/sonoff/_releasenotes.ino index f85a28622..3cdd9e4ec 100644 --- a/sonoff/_releasenotes.ino +++ b/sonoff/_releasenotes.ino @@ -1,4 +1,4 @@ -/* 5.5.2d +/* 5.5.2e * Fix Sonoff Pow intermittent exception 0 * Change Sonoff Pow sending Domoticz telemetry data only * Add Sonoff B1 support (experimental) diff --git a/sonoff/sonoff.ino b/sonoff/sonoff.ino index 86d85ae11..5ae0e505e 100644 --- a/sonoff/sonoff.ino +++ b/sonoff/sonoff.ino @@ -25,7 +25,7 @@ - Select IDE Tools - Flash Size: "1M (no SPIFFS)" ====================================================*/ -#define VERSION 0x05050204 // 5.5.2d +#define VERSION 0x05050205 // 5.5.2e enum log_t {LOG_LEVEL_NONE, LOG_LEVEL_ERROR, LOG_LEVEL_INFO, LOG_LEVEL_DEBUG, LOG_LEVEL_DEBUG_MORE, LOG_LEVEL_ALL}; enum week_t {Last, First, Second, Third, Fourth}; @@ -2633,7 +2633,7 @@ void GPIO_init() else if (SONOFF_LED == sysCfg.module) { sfl_flg = 2; } - else if (SONOFF_B1 == sysCfg.module) { + else if ((SONOFF_B1 == sysCfg.module) || (SONOFF_B1b == sysCfg.module)) { sfl_flg = 5; } else { diff --git a/sonoff/sonoff_template.h b/sonoff/sonoff_template.h index 7ceea9263..0c1a1a569 100644 --- a/sonoff/sonoff_template.h +++ b/sonoff/sonoff_template.h @@ -152,6 +152,7 @@ enum module_t { HUAFAN_SS, SONOFF_BRIDGE, SONOFF_B1, + SONOFF_B1b, MAXMODULE }; /********************************************************************************************/ @@ -507,7 +508,22 @@ const mytmplt modules[MAXMODULE] PROGMEM = { GPIO_DCKI, // GPIO14 my9231 DCKI 0, 0, 0 + }, + { "Sonoff B1 b", // Sonoff B1 (ESP8285 - my9231) + GPIO_KEY1, // GPIO00 Pad + GPIO_USER, // GPIO01 Serial RXD and Optional sensor pad + GPIO_USER, // GPIO02 Optional sensor SDA pad + GPIO_USER, // GPIO03 Serial TXD and Optional sensor pad + 0, 0, + 0, 0, 0, // Flash connection + 0, 0, + 0, // Flash connection + 0, + GPIO_DI, // GPIO13 my9231 DI + 0, + GPIO_DCKI, // GPIO15 my9231 DCKI + 0, 0 } - + }; From 5fdc5e890a62871c57a640d8532929e2f28368c8 Mon Sep 17 00:00:00 2001 From: arendst Date: Sun, 13 Aug 2017 15:31:49 +0200 Subject: [PATCH 07/13] Add AiLight and update Sonoff B1 (experimental) --- sonoff/_releasenotes.ino | 4 +-- sonoff/sonoff.ino | 17 +++++---- sonoff/sonoff_template.h | 11 +++--- sonoff/xdrv_snfled.ino | 75 +++++++++++++++++++++++++++++----------- 4 files changed, 71 insertions(+), 36 deletions(-) diff --git a/sonoff/_releasenotes.ino b/sonoff/_releasenotes.ino index 3cdd9e4ec..ac7a5ceb2 100644 --- a/sonoff/_releasenotes.ino +++ b/sonoff/_releasenotes.ino @@ -1,7 +1,7 @@ -/* 5.5.2e +/* 5.5.2f * Fix Sonoff Pow intermittent exception 0 * Change Sonoff Pow sending Domoticz telemetry data only - * Add Sonoff B1 support (experimental) + * Add Ai-Thinker RGBW led (AiLight) and Sonoff B1 support (experimental) * * 5.5.2 20170808 * Extent max number of WS2812 pixels from 256 to 512 (#667) diff --git a/sonoff/sonoff.ino b/sonoff/sonoff.ino index 5ae0e505e..5b559f964 100644 --- a/sonoff/sonoff.ino +++ b/sonoff/sonoff.ino @@ -25,7 +25,7 @@ - Select IDE Tools - Flash Size: "1M (no SPIFFS)" ====================================================*/ -#define VERSION 0x05050205 // 5.5.2e +#define VERSION 0x05050206 // 5.5.2f enum log_t {LOG_LEVEL_NONE, LOG_LEVEL_ERROR, LOG_LEVEL_INFO, LOG_LEVEL_DEBUG, LOG_LEVEL_DEBUG_MORE, LOG_LEVEL_ALL}; enum week_t {Last, First, Second, Third, Fourth}; @@ -2318,7 +2318,7 @@ void stateloop() button_handler(); switch_handler(); - if (sfl_flg) { // Sonoff B1, led or BN-SZ01 + if (sfl_flg) { // Sonoff B1, AiLight, Sonoff led or BN-SZ01 sl_animate(); } @@ -2627,13 +2627,16 @@ void GPIO_init() Maxdevice = 0; Baudrate = 19200; } - else if (SONOFF_BN == sysCfg.module) { + else if (SONOFF_BN == sysCfg.module) { // Single color led (White) sfl_flg = 1; } - else if (SONOFF_LED == sysCfg.module) { + else if (SONOFF_LED == sysCfg.module) { // Dual color led (White warm and cold) sfl_flg = 2; } - else if ((SONOFF_B1 == sysCfg.module) || (SONOFF_B1b == sysCfg.module)) { + else if (AILIGHT == sysCfg.module) { // RGBW led + sfl_flg = 4; + } + else if (SONOFF_B1 == sysCfg.module) { // RGBWC led sfl_flg = 5; } else { @@ -2663,8 +2666,8 @@ void GPIO_init() } } - if (sfl_flg) { // Sonoff B1, Led or BN-SZ01 - if (sfl_flg < 5) { + if (sfl_flg) { // Sonoff B1, AiLight, Sonoff Led or BN-SZ01 + if (sfl_flg < 4) { pwm_idxoffset = sfl_flg; // 1 for BN-SZ01, 2 for Sonoff Led } sl_init(); diff --git a/sonoff/sonoff_template.h b/sonoff/sonoff_template.h index 0c1a1a569..bd7e2cadc 100644 --- a/sonoff/sonoff_template.h +++ b/sonoff/sonoff_template.h @@ -152,7 +152,7 @@ enum module_t { HUAFAN_SS, SONOFF_BRIDGE, SONOFF_B1, - SONOFF_B1b, + AILIGHT, MAXMODULE }; /********************************************************************************************/ @@ -506,10 +506,9 @@ const mytmplt modules[MAXMODULE] PROGMEM = { GPIO_DI, // GPIO12 my9231 DI 0, GPIO_DCKI, // GPIO14 my9231 DCKI - 0, - 0, 0 + 0, 0, 0 }, - { "Sonoff B1 b", // Sonoff B1 (ESP8285 - my9231) + { "AiLight", // Ai-Thinker RGBW led (ESP8266 - my9291) GPIO_KEY1, // GPIO00 Pad GPIO_USER, // GPIO01 Serial RXD and Optional sensor pad GPIO_USER, // GPIO02 Optional sensor SDA pad @@ -519,9 +518,9 @@ const mytmplt modules[MAXMODULE] PROGMEM = { 0, 0, 0, // Flash connection 0, - GPIO_DI, // GPIO13 my9231 DI + GPIO_DI, // GPIO13 my9291 DI 0, - GPIO_DCKI, // GPIO15 my9231 DCKI + GPIO_DCKI, // GPIO15 my9291 DCKI 0, 0 } diff --git a/sonoff/xdrv_snfled.ino b/sonoff/xdrv_snfled.ino index b8d7a74a0..8161a077b 100644 --- a/sonoff/xdrv_snfled.ino +++ b/sonoff/xdrv_snfled.ino @@ -18,7 +18,7 @@ */ /*********************************************************************************************\ - * Sonoff B1, Led and BN-SZ01 + * Sonoff B1, AiLight, Sonoff Led and BN-SZ01 \*********************************************************************************************/ uint8_t ledTable[] = { @@ -50,7 +50,7 @@ uint8_t sl_wakeupDimmer = 0; uint16_t sl_wakeupCntr = 0; /*********************************************************************************************\ - * Sonoff B1 based on OpenLight https://github.com/icamgo/noduino-sdk (my9231 and my9291) + * Sonoff B1 (my9231) and AiLight (my9291) based on OpenLight https://github.com/icamgo/noduino-sdk \*********************************************************************************************/ extern "C" { @@ -76,7 +76,7 @@ void sl_dcki_pulse(uint8_t times) } } -void sl_send_command(uint8_t command) +void sl_my92x1_command(uint8_t chips, uint8_t command) { uint8_t command_data; @@ -85,8 +85,8 @@ void sl_send_command(uint8_t command) // Send 12 DI pulse, after 6 pulse's falling edge store duty data, and 12 // pulse's rising edge convert to command mode. sl_di_pulse(12); - os_delay_us(12); // Delay >12us, begin send CMD data - for (uint8_t n = 0; n < 2; n++) { // Send CMD data + os_delay_us(12); // Delay >12us, begin send CMD data + for (uint8_t n = 0; n < chips; n++) { // Send CMD data command_data = command; for (uint8_t i = 0; i < 4; i++) { // Send byte digitalWrite(sl_pdcki, LOW); @@ -107,7 +107,7 @@ void sl_send_command(uint8_t command) // ets_intr_unlock(); } -void sl_send_duty(uint16_t duty_r, uint16_t duty_g, uint16_t duty_b, uint16_t duty_w, uint16_t duty_c) +void sl_my9231_duty(uint16_t duty_r, uint16_t duty_g, uint16_t duty_b, uint16_t duty_w, uint16_t duty_c) { uint16_t duty_current = 0; @@ -134,12 +134,39 @@ void sl_send_duty(uint16_t duty_r, uint16_t duty_g, uint16_t duty_b, uint16_t du // ets_intr_unlock(); } +void sl_my9291_duty(uint16_t duty_r, uint16_t duty_g, uint16_t duty_b, uint16_t duty_w) +{ + uint16_t duty_current = 0; + + uint16_t duty[4] = { duty_r, duty_g, duty_b, duty_w }; // Definition for RGBW channels + +// ets_intr_lock(); + os_delay_us(12); // TStop > 12us. + for (uint8_t channel = 0; channel < 4; channel++) { // RGBW 4CH + duty_current = duty[channel]; // RGBW Channel + for (uint8_t i = 0; i < 4; i++) { // Send 8bit Data + digitalWrite(sl_pdcki, LOW); + digitalWrite(sl_pdi, (duty_current & 0x80)); + digitalWrite(sl_pdcki, HIGH); + duty_current = duty_current << 1; + digitalWrite(sl_pdi, (duty_current & 0x80)); + digitalWrite(sl_pdcki, LOW); + digitalWrite(sl_pdi, LOW); + duty_current = duty_current << 1; + } + } + os_delay_us(12); // TStart > 12us. Ready for send DI pulse. + sl_di_pulse(8); // Send 8 DI pulse. After 8 pulse falling edge, store old data. + os_delay_us(12); // TStop > 12us. +// ets_intr_unlock(); +} + /********************************************************************************************/ void sl_init(void) { pin[GPIO_WS2812] = 99; // I do not allow both Sonoff Led AND WS2812 led - if (sfl_flg < 5) { + if (sfl_flg < 4) { if (!my_module.gp.io[4]) { pinMode(4, OUTPUT); // Stop floating outputs digitalWrite(4, LOW); @@ -165,12 +192,15 @@ void sl_init(void) digitalWrite(sl_pdi, LOW); digitalWrite(sl_pdcki, LOW); - // Clear all duty register - sl_dcki_pulse(64); - sl_send_command(0x18); // ONE_SHOT_DISABLE, REACTION_FAST, BIT_WIDTH_8, FREQUENCY_DIVIDE_1, SCATTER_APDM - - // Test -// sl_send_duty(16, 0, 0, 0, 0); // Red + if (4 == sfl_flg) { + // Clear all duty register + sl_dcki_pulse(32); // 1 * 32 bits + sl_my92x1_command(1, 0x18); // ONE_SHOT_DISABLE, REACTION_FAST, BIT_WIDTH_8, FREQUENCY_DIVIDE_1, SCATTER_APDM + } else if (5 == sfl_flg) { + // Clear all duty register + sl_dcki_pulse(48); // 2 * 24 bits + sl_my92x1_command(2, 0x18); // ONE_SHOT_DISABLE, REACTION_FAST, BIT_WIDTH_8, FREQUENCY_DIVIDE_1, SCATTER_APDM + } } sl_power = 0; @@ -320,14 +350,17 @@ void sl_animate() for (byte i = 0; i < sfl_flg; i++) { sl_lcolor[i] = sl_tcolor[i]; cur_col[i] = (sysCfg.led_table) ? ledTable[sl_lcolor[i]] : sl_lcolor[i]; - if (sfl_flg < 5) { + if (sfl_flg < 4) { if (pin[GPIO_PWM1 +i] < 99) { analogWrite(pin[GPIO_PWM1 +i], cur_col[i] * (PWM_RANGE / 255)); } } } - if (5 == sfl_flg) { - sl_send_duty(cur_col[0], cur_col[1], cur_col[2], cur_col[3], cur_col[4]); + if (4 == sfl_flg) { + sl_my9291_duty(cur_col[0], cur_col[1], cur_col[2], cur_col[3]); + } + else if (5 == sfl_flg) { + sl_my9231_duty(cur_col[0], cur_col[1], cur_col[2], cur_col[3], cur_col[4]); } } } @@ -417,7 +450,7 @@ void sl_replaceHSB(String *response) float sat; float bri; - if (5 == sfl_flg) { + if (sfl_flg > 2) { sl_rgb2hsb(&hue, &sat, &bri); response->replace("{h}", String((uint16_t)(65535.0f * hue))); response->replace("{s}", String((uint8_t)(254.0f * sat))); @@ -431,7 +464,7 @@ void sl_replaceHSB(String *response) void sl_getHSB(float *hue, float *sat, float *bri) { - if (5 == sfl_flg) { + if (sfl_flg > 2) { sl_rgb2hsb(hue, sat, bri); } else { *hue = 0; @@ -443,7 +476,7 @@ void sl_getHSB(float *hue, float *sat, float *bri) void sl_setHSB(float hue, float sat, float bri) { char svalue[MESSZ]; - +/* char log[LOGSZ]; char stemp1[10]; char stemp2[10]; @@ -453,8 +486,8 @@ void sl_setHSB(float hue, float sat, float bri) dtostrf(bri, 1, 3, stemp3); snprintf_P(log, sizeof(log), PSTR("LED: Hue %s, Sat %s, Bri %s"), stemp1, stemp2, stemp3); addLog(LOG_LEVEL_DEBUG, log); - - if (5 == sfl_flg) { +*/ + if (sfl_flg > 2) { sl_hsb2rgb(hue, sat, bri); sl_prepPower(svalue, sizeof(svalue)); mqtt_publish_topic_P(5, "COLOR", svalue); From 99c9b1671c2b2625e23ba63592b34445ebb5bb78 Mon Sep 17 00:00:00 2001 From: arendst Date: Tue, 15 Aug 2017 22:09:52 +0200 Subject: [PATCH 08/13] Add Sonoff B1 Support. AiLight is experimental --- sonoff/_releasenotes.ino | 6 +- sonoff/sonoff.ino | 3 +- sonoff/sonoff_template.h | 4 +- sonoff/xdrv_snfled.ino | 155 ++++++++++++++++----------------------- sonoff/xdrv_wemohue.ino | 23 +++++- sonoff/xdrv_ws2812.ino | 68 +++++++++-------- 6 files changed, 128 insertions(+), 131 deletions(-) diff --git a/sonoff/_releasenotes.ino b/sonoff/_releasenotes.ino index ac7a5ceb2..cc9d81c0b 100644 --- a/sonoff/_releasenotes.ino +++ b/sonoff/_releasenotes.ino @@ -1,7 +1,9 @@ -/* 5.5.2f +/* 5.5.2g * Fix Sonoff Pow intermittent exception 0 * Change Sonoff Pow sending Domoticz telemetry data only - * Add Ai-Thinker RGBW led (AiLight) and Sonoff B1 support (experimental) + * Add Sonoff B1 support + * Add Ai-Thinker RGBW led (AiLight) (experimental) + * Add NeoPixelBus library to Sonoff Led for Hue support (saves 1k1 code space) * * 5.5.2 20170808 * Extent max number of WS2812 pixels from 256 to 512 (#667) diff --git a/sonoff/sonoff.ino b/sonoff/sonoff.ino index 5b559f964..97a0c15bc 100644 --- a/sonoff/sonoff.ino +++ b/sonoff/sonoff.ino @@ -25,7 +25,7 @@ - Select IDE Tools - Flash Size: "1M (no SPIFFS)" ====================================================*/ -#define VERSION 0x05050206 // 5.5.2f +#define VERSION 0x05050207 // 5.5.2g enum log_t {LOG_LEVEL_NONE, LOG_LEVEL_ERROR, LOG_LEVEL_INFO, LOG_LEVEL_DEBUG, LOG_LEVEL_DEBUG_MORE, LOG_LEVEL_ALL}; enum week_t {Last, First, Second, Third, Fourth}; @@ -172,6 +172,7 @@ enum opt_t {P_HOLD_TIME, P_MAX_POWER_RETRY, P_MAX_PARAM8}; // Index in sysCf #include // Ota #include // Webserver, Updater #include // WemoHue, IRremote, Domoticz +#include // Ws2812, Sonoff Led hue support #ifdef USE_WEBSERVER #include // WifiManager, Webserver #include // WifiManager diff --git a/sonoff/sonoff_template.h b/sonoff/sonoff_template.h index bd7e2cadc..333ed89e9 100644 --- a/sonoff/sonoff_template.h +++ b/sonoff/sonoff_template.h @@ -117,9 +117,9 @@ enum fpins_t { GPIO_HLW_CF1, // HLW8012 CF1 voltage / current (Sonoff Pow) GPIO_HLW_CF, // HLW8012 CF power (Sonoff Pow) GPIO_ADC0, // ADC + GPIO_DI, // my92x1 PWM input + GPIO_DCKI, // my92x1 CLK input GPIO_USER, // User configurable - GPIO_DI, // my9231 PWM input - GPIO_DCKI, // my9231 CLK input GPIO_MAX }; /********************************************************************************************/ diff --git a/sonoff/xdrv_snfled.ino b/sonoff/xdrv_snfled.ino index 8161a077b..525c245f4 100644 --- a/sonoff/xdrv_snfled.ino +++ b/sonoff/xdrv_snfled.ino @@ -80,7 +80,6 @@ void sl_my92x1_command(uint8_t chips, uint8_t command) { uint8_t command_data; -// ets_intr_lock(); os_delay_us(12); // TStop > 12us. // Send 12 DI pulse, after 6 pulse's falling edge store duty data, and 12 // pulse's rising edge convert to command mode. @@ -104,19 +103,17 @@ void sl_my92x1_command(uint8_t chips, uint8_t command) // at 16 pulse's falling edge convert to duty mode. sl_di_pulse(16); os_delay_us(12); // TStop > 12us. -// ets_intr_unlock(); } -void sl_my9231_duty(uint16_t duty_r, uint16_t duty_g, uint16_t duty_b, uint16_t duty_w, uint16_t duty_c) +void sl_my9231_duty(uint8_t duty_r, uint8_t duty_g, uint8_t duty_b, uint8_t duty_w, uint8_t duty_c) { - uint16_t duty_current = 0; + uint8_t duty_current = 0; - uint16_t duty[6] = { duty_r, duty_g, duty_b, duty_w, duty_c, 0 }; // Definition for RGBWC channels + uint8_t duty[6] = { duty_w, duty_c, 0, duty_g, duty_r, duty_b }; // Definition for RGBWC channels -// ets_intr_lock(); os_delay_us(12); // TStop > 12us. - for (uint8_t channel = 0; channel < 6; channel++) { // RGBWC0 6CH - duty_current = duty[channel]; // RGBWC Channel + for (uint8_t channel = 0; channel < 6; channel++) { // WC0GRB 6CH + duty_current = duty[channel]; for (uint8_t i = 0; i < 4; i++) { // Send 8bit Data digitalWrite(sl_pdcki, LOW); digitalWrite(sl_pdi, (duty_current & 0x80)); @@ -131,16 +128,14 @@ void sl_my9231_duty(uint16_t duty_r, uint16_t duty_g, uint16_t duty_b, uint16_t os_delay_us(12); // TStart > 12us. Ready for send DI pulse. sl_di_pulse(8); // Send 8 DI pulse. After 8 pulse falling edge, store old data. os_delay_us(12); // TStop > 12us. -// ets_intr_unlock(); } -void sl_my9291_duty(uint16_t duty_r, uint16_t duty_g, uint16_t duty_b, uint16_t duty_w) +void sl_my9291_duty(uint8_t duty_r, uint8_t duty_g, uint8_t duty_b, uint8_t duty_w) { - uint16_t duty_current = 0; + uint8_t duty_current = 0; - uint16_t duty[4] = { duty_r, duty_g, duty_b, duty_w }; // Definition for RGBW channels + uint8_t duty[4] = { duty_r, duty_g, duty_b, duty_w }; // Definition for RGBW channels -// ets_intr_lock(); os_delay_us(12); // TStop > 12us. for (uint8_t channel = 0; channel < 4; channel++) { // RGBW 4CH duty_current = duty[channel]; // RGBW Channel @@ -158,7 +153,6 @@ void sl_my9291_duty(uint16_t duty_r, uint16_t duty_g, uint16_t duty_b, uint16_t os_delay_us(12); // TStart > 12us. Ready for send DI pulse. sl_di_pulse(8); // Send 8 DI pulse. After 8 pulse falling edge, store old data. os_delay_us(12); // TStop > 12us. -// ets_intr_unlock(); } /********************************************************************************************/ @@ -198,7 +192,7 @@ void sl_init(void) sl_my92x1_command(1, 0x18); // ONE_SHOT_DISABLE, REACTION_FAST, BIT_WIDTH_8, FREQUENCY_DIVIDE_1, SCATTER_APDM } else if (5 == sfl_flg) { // Clear all duty register - sl_dcki_pulse(48); // 2 * 24 bits + sl_dcki_pulse(64); // 2 * 32 bits sl_my92x1_command(2, 0x18); // ONE_SHOT_DISABLE, REACTION_FAST, BIT_WIDTH_8, FREQUENCY_DIVIDE_1, SCATTER_APDM } } @@ -211,7 +205,7 @@ void sl_init(void) void sl_setDim(uint8_t myDimmer) { float temp; - + if ((1 == sfl_flg) && (100 == myDimmer)) { myDimmer = 99; // BN-SZ01 starts flickering at dimmer = 100 } @@ -371,76 +365,17 @@ void sl_animate() void sl_rgb2hsb(float *hue, float *sat, float *bri) { - sl_setDim(sysCfg.led_dimmer[0]); + RgbColor dcolor; - float r = (float)(sl_dcolor[0] / 255.0f); - float g = (float)(sl_dcolor[1] / 255.0f); - float b = (float)(sl_dcolor[2] / 255.0f); - - float max = fmax(fmax(r, g), b); - float min = fmin(fmin(r, g), b); - - *bri = (max + min) / 2.0f; - - if (max == min) { - *hue = *sat = 0.0f; - } else { - float d = max - min; - *sat = (*bri > 0.5f) ? d / (2.0f - max - min) : d / (max + min); - - if (r > g && r > b) { - *hue = (g - b) / d + (g < b ? 6.0f : 0.0f); - } - else if (g > b) { - *hue = (b - r) / d + 2.0f; - } - else { - *hue = (r - g) / d + 4.0f; - } - *hue /= 6.0f; - } -} - -float sl_hue2rgb(float p, float q, float t) -{ - if (t < 0.0f) { - t += 1.0f; - } - if (t > 1.0f) { - t -= 1.0f; - } - if (t < 1.0f / 6.0f) { - return p + (q - p) * 6.0f * t; - } - if (t < 1.0f / 2.0f) { - return q; - } - if (t < 2.0f / 3.0f) { - return p + (q - p) * (2.0f / 3.0f - t) * 6.0f; - } - return p; -} - -void sl_hsb2rgb(float hue, float sat, float bri) -{ - float r; - float g; - float b; - - if (sat == 0.0f) { - r = g = b = bri; - } else { - float q = bri < 0.5f ? bri * (1.0f + sat) : bri + sat - bri * sat; - float p = 2.0f * bri - q; - r = sl_hue2rgb(p, q, hue + 1.0f / 3.0f); - g = sl_hue2rgb(p, q, hue); - b = sl_hue2rgb(p, q, hue - 1.0f / 3.0f); - } - sl_dcolor[0] = (uint8_t)(r * 255 + 0.5f); - sl_dcolor[1] = (uint8_t)(g * 255 + 0.5f); - sl_dcolor[2] = (uint8_t)(b * 255 + 0.5f); - sl_setColor(); -} + sl_setDim(sysCfg.led_dimmer[0]); + dcolor.R = sl_dcolor[0]; + dcolor.G = sl_dcolor[1]; + dcolor.B = sl_dcolor[2]; + HsbColor hsb = HsbColor(dcolor); + *hue = hsb.H; + *sat = hsb.S; + *bri = hsb.B; +} /********************************************************************************************/ @@ -458,7 +393,8 @@ void sl_replaceHSB(String *response) } else { response->replace("{h}", "0"); response->replace("{s}", "0"); - response->replace("{b}", String((uint8_t)(2.54f * (float)sysCfg.led_dimmer[0]))); +// response->replace("{b}", String((uint8_t)(2.54f * (float)sysCfg.led_dimmer[0]))); + response->replace("{b}", String((uint8_t)(0.01f * (float)sysCfg.led_dimmer[0]))); } } @@ -469,33 +405,68 @@ void sl_getHSB(float *hue, float *sat, float *bri) } else { *hue = 0; *sat = 0; - *bri = (2.54f * (float)sysCfg.led_dimmer[0]); +// *bri = (2.54f * (float)sysCfg.led_dimmer[0]); + *bri = (0.01f * (float)sysCfg.led_dimmer[0]); } } -void sl_setHSB(float hue, float sat, float bri) +void sl_setHSB(float hue, float sat, float bri, float ct) { char svalue[MESSZ]; + HsbColor hsb; + float my_ct; + /* char log[LOGSZ]; char stemp1[10]; char stemp2[10]; char stemp3[10]; + char stemp4[10]; dtostrf(hue, 1, 3, stemp1); dtostrf(sat, 1, 3, stemp2); dtostrf(bri, 1, 3, stemp3); - snprintf_P(log, sizeof(log), PSTR("LED: Hue %s, Sat %s, Bri %s"), stemp1, stemp2, stemp3); + dtostrf(ct, 1, 3, stemp4); + snprintf_P(log, sizeof(log), PSTR("HUE: Set Hue %s, Sat %s, Bri %s, Ct %s"), stemp1, stemp2, stemp3, stemp4); addLog(LOG_LEVEL_DEBUG, log); */ + if (sfl_flg > 2) { - sl_hsb2rgb(hue, sat, bri); + hsb.H = hue; + hsb.S = sat; + hsb.B = bri; + RgbColor tmp = RgbColor(hsb); + sl_dcolor[0] = tmp.R; + sl_dcolor[1] = tmp.G; + sl_dcolor[2] = tmp.B; + sl_setColor(); sl_prepPower(svalue, sizeof(svalue)); mqtt_publish_topic_P(5, "COLOR", svalue); } else { uint8_t tmp = (uint8_t)(bri * 100); sysCfg.led_dimmer[0] = tmp; - sl_prepPower(svalue, sizeof(svalue)); - mqtt_publish_topic_P(5, "DIMMER", svalue); + if (2 == sfl_flg) { + if (ct > 0) { + my_ct = ct - 0.306; + if (my_ct > 0.694) { // >500 (Warm) + my_ct = 0.694; + } + float fcold = 367 * (0.694 - my_ct); // 0 - 255 + float fwarm = 367 * my_ct; // 0 - 255 + float fmax = (fwarm > fcold) ? fwarm : fcold; + float fbri = 100 / (fmax / 2.55); // Scale to 255 + if (bri < 1) { + bri = bri + 0.01; // Adjust for sl_setColor + } + sl_dcolor[0] = (uint8_t)(fcold * fbri * bri); // Cold + sl_dcolor[1] = (uint8_t)(fwarm * fbri * bri); // Warm + sl_setColor(); + } + sl_prepPower(svalue, sizeof(svalue)); + mqtt_publish_topic_P(5, "COLOR", svalue); + } else { + sl_prepPower(svalue, sizeof(svalue)); + mqtt_publish_topic_P(5, "DIMMER", svalue); + } } } diff --git a/sonoff/xdrv_wemohue.ino b/sonoff/xdrv_wemohue.ino index 08bcba878..3d0aa30fc 100644 --- a/sonoff/xdrv_wemohue.ino +++ b/sonoff/xdrv_wemohue.ino @@ -533,6 +533,7 @@ void hue_lights(String *path) float bri = 0; float hue = 0; float sat = 0; + float ct = 0; bool resp = false; bool on = false; bool change = false; @@ -636,9 +637,21 @@ void hue_lights(String *path) response.replace("{res}", String(tmp)); change = true; } + if (hue_json.containsKey("ct")) { // Color temperature 153 (Cold) to 500 (Warm) + tmp = hue_json["ct"]; + ct = (float)tmp / 500.0f; + if (resp) { + response += ","; + } + response += FPSTR(HUE_LIGHT_RESPONSE_JSON); + response.replace("{id}", String(device)); + response.replace("{cmd}", "ct"); + response.replace("{res}", String(tmp)); + change = true; + } if (change) { if (sfl_flg) { - sl_setHSB(hue, sat, bri); + sl_setHSB(hue, sat, bri, ct); #ifdef USE_WS2812 } else if (pin[GPIO_WS2812] < 99) { @@ -655,6 +668,9 @@ void hue_lights(String *path) else { response = FPSTR(HUE_ERROR_JSON); } + +addLog(LOG_LEVEL_DEBUG_MORE, response.c_str()); + webServer->send(200, FPSTR(HDR_CTYPE_JSON), response); } else if(path->indexOf("/lights/") >= 0) { // Got /lights/ID @@ -678,6 +694,9 @@ void hue_lights(String *path) void hue_groups(String *path) { +/* + * http://sonoff/api/username/groups?1={"name":"Woonkamer","lights":[],"type":"Room","class":"Living room"}) + */ String response = "{}"; if (path->endsWith("/0")) { @@ -721,7 +740,7 @@ void handle_hue_api(String *path) else if (path->endsWith("/")) hue_auth(path); // New HUE App setup else if (path->endsWith("/config")) hue_config(path); else if (path->indexOf("/lights") >= 0) hue_lights(path); - else if (path->indexOf("/groups") >= 0) hue_groups(path); + else if (path->indexOf("/groups") >= 0) hue_groups(path); else if (path->endsWith("/schedules")) hue_todo(path); else if (path->endsWith("/sensors")) hue_todo(path); else if (path->endsWith("/scenes")) hue_todo(path); diff --git a/sonoff/xdrv_ws2812.ino b/sonoff/xdrv_ws2812.ino index 93a6e5fe4..92fe3e349 100644 --- a/sonoff/xdrv_ws2812.ino +++ b/sonoff/xdrv_ws2812.ino @@ -22,7 +22,7 @@ * WS2812 Leds using NeopixelBus library \*********************************************************************************************/ -#include +//#include // Global defined as also used by Sonoff Led #ifdef USE_WS2812_DMA #if (USE_WS2812_CTYPE == 1) @@ -145,37 +145,6 @@ void ws2812_setColor(uint16_t led, char* colstr) } } -void ws2812_replaceHSB(String *response) -{ - ws2812_setDim(sysCfg.ws_dimmer); - HsbColor hsb = HsbColor(dcolor); - response->replace("{h}", String((uint16_t)(65535.0f * hsb.H))); - response->replace("{s}", String((uint8_t)(254.0f * hsb.S))); - response->replace("{b}", String((uint8_t)(254.0f * hsb.B))); -} - -void ws2812_getHSB(float *hue, float *sat, float *bri) -{ - ws2812_setDim(sysCfg.ws_dimmer); - HsbColor hsb = HsbColor(dcolor); - *hue = hsb.H; - *sat = hsb.S; - *bri = hsb.B; -} - -void ws2812_setHSB(float hue, float sat, float bri) -{ - char rgb[7]; - - HsbColor hsb; - hsb.H = hue; - hsb.S = sat; - hsb.B = bri; - RgbColor tmp = RgbColor(hsb); - sprintf(rgb,"%02X%02X%02X", tmp.R, tmp.G, tmp.B); - ws2812_setColor(0,rgb); -} - void ws2812_getColor(uint16_t led, char* svalue, uint16_t ssvalue) { RgbColor mcolor; @@ -504,6 +473,41 @@ void ws2812_init(uint8_t powerbit) ws2812_pixels(); } +/*********************************************************************************************\ + * Hue support +\*********************************************************************************************/ + +void ws2812_replaceHSB(String *response) +{ + ws2812_setDim(sysCfg.ws_dimmer); + HsbColor hsb = HsbColor(dcolor); + response->replace("{h}", String((uint16_t)(65535.0f * hsb.H))); + response->replace("{s}", String((uint8_t)(254.0f * hsb.S))); + response->replace("{b}", String((uint8_t)(254.0f * hsb.B))); +} + +void ws2812_getHSB(float *hue, float *sat, float *bri) +{ + ws2812_setDim(sysCfg.ws_dimmer); + HsbColor hsb = HsbColor(dcolor); + *hue = hsb.H; + *sat = hsb.S; + *bri = hsb.B; +} + +void ws2812_setHSB(float hue, float sat, float bri) +{ + char rgb[7]; + + HsbColor hsb; + hsb.H = hue; + hsb.S = sat; + hsb.B = bri; + RgbColor tmp = RgbColor(hsb); + sprintf(rgb,"%02X%02X%02X", tmp.R, tmp.G, tmp.B); + ws2812_setColor(0,rgb); +} + /*********************************************************************************************\ * Commands \*********************************************************************************************/ From ebee148be89c1c16d042ec4db59d50d946a755fd Mon Sep 17 00:00:00 2001 From: arendst Date: Wed, 16 Aug 2017 17:05:36 +0200 Subject: [PATCH 09/13] Add Sonoff B1 features --- sonoff/_releasenotes.ino | 11 +- sonoff/sonoff.ino | 2 +- sonoff/sonoff_template.h | 3 +- sonoff/webserver.ino | 21 +++- sonoff/xdrv_ir_send.ino | 2 +- sonoff/xdrv_snfled.ino | 211 ++++++++++++++++++++------------------- sonoff/xdrv_wemohue.ino | 9 +- 7 files changed, 141 insertions(+), 118 deletions(-) diff --git a/sonoff/_releasenotes.ino b/sonoff/_releasenotes.ino index cc9d81c0b..03a265ba0 100644 --- a/sonoff/_releasenotes.ino +++ b/sonoff/_releasenotes.ino @@ -1,9 +1,14 @@ -/* 5.5.2g +/* 5.5.2h * Fix Sonoff Pow intermittent exception 0 * Change Sonoff Pow sending Domoticz telemetry data only - * Add Sonoff B1 support + * Add Sonoff B1 RGBCW led support with command Color RRGGBBCCWW (#676) + * Add command CT 152..500 to Sonoff Led and Sonoff B1 to control Color Temperature + * Add Cold-Warm slider to web page for Sonoff Led and Sonoff B1 + * Add CT parameter to Hue * Add Ai-Thinker RGBW led (AiLight) (experimental) - * Add NeoPixelBus library to Sonoff Led for Hue support (saves 1k1 code space) + * Add NeoPixelBus library to Sonoff Led for Hue support (saves 1k code space) + * Add user configurable GPIO4 and GPIO5 to module Sonoff Bridge + * Fix Mitsubishi HVAC IR power controll (#740) * * 5.5.2 20170808 * Extent max number of WS2812 pixels from 256 to 512 (#667) diff --git a/sonoff/sonoff.ino b/sonoff/sonoff.ino index 97a0c15bc..f4be6a1d7 100644 --- a/sonoff/sonoff.ino +++ b/sonoff/sonoff.ino @@ -25,7 +25,7 @@ - Select IDE Tools - Flash Size: "1M (no SPIFFS)" ====================================================*/ -#define VERSION 0x05050207 // 5.5.2g +#define VERSION 0x05050208 // 5.5.2h enum log_t {LOG_LEVEL_NONE, LOG_LEVEL_ERROR, LOG_LEVEL_INFO, LOG_LEVEL_DEBUG, LOG_LEVEL_DEBUG_MORE, LOG_LEVEL_ALL}; enum week_t {Last, First, Second, Third, Fourth}; diff --git a/sonoff/sonoff_template.h b/sonoff/sonoff_template.h index 333ed89e9..409621322 100644 --- a/sonoff/sonoff_template.h +++ b/sonoff/sonoff_template.h @@ -486,7 +486,8 @@ const mytmplt modules[MAXMODULE] PROGMEM = { GPIO_TXD, // GPIO01 RF bridge control GPIO_USER, // GPIO02 Optional sensor GPIO_RXD, // GPIO03 RF bridge control - 0, 0, + GPIO_USER, // GPIO04 Optional sensor + GPIO_USER, // GPIO05 Optional sensor 0, 0, 0, // Flash connection 0, 0, 0, // Flash connection diff --git a/sonoff/webserver.ino b/sonoff/webserver.ino index 249fd51e5..a8bf0bba2 100644 --- a/sonoff/webserver.ino +++ b/sonoff/webserver.ino @@ -70,6 +70,9 @@ const char HTTP_HEAD[] PROGMEM = "function lb(p){" "la('?d='+p);" "}" + "function lc(p){" + "la('?t='+p);" + "}" "" "" "" "" - "
" + "
" "

{ha} Module

{h}

"; const char HTTP_SCRIPT_CONSOL[] PROGMEM = "var sn=0;" // Scroll position @@ -415,7 +419,7 @@ void handleRoot() if (HTTP_MANAGER == _httpflag) { handleWifi0(); } else { - char stemp[10], line[100]; + char stemp[10], line[160]; String page = FPSTR(HTTP_HEAD); page.replace(F("{v}"), F("Main menu")); page.replace(F(""), F("")); @@ -423,7 +427,12 @@ void handleRoot() page += F("
"); if (Maxdevice) { if (sfl_flg) { - snprintf_P(line, sizeof(line), PSTR(""), + if ((2 == sfl_flg) || (5 == sfl_flg)) { + snprintf_P(line, sizeof(line), PSTR("
ColdWarm
"), + sl_getColorTemp()); + page += line; + } + snprintf_P(line, sizeof(line), PSTR("
DarkBright
"), sysCfg.led_dimmer[0]); page += line; } @@ -474,6 +483,10 @@ void handleAjax2() snprintf_P(svalue, sizeof(svalue), PSTR("dimmer %s"), webServer->arg("d").c_str()); do_cmnd(svalue); } + if (strlen(webServer->arg("t").c_str())) { + snprintf_P(svalue, sizeof(svalue), PSTR("ct %s"), webServer->arg("t").c_str()); + do_cmnd(svalue); + } if (strlen(webServer->arg("k").c_str())) { snprintf_P(svalue, sizeof(svalue), PSTR("rfkey%s"), webServer->arg("k").c_str()); do_cmnd(svalue); diff --git a/sonoff/xdrv_ir_send.ino b/sonoff/xdrv_ir_send.ino index a1998f605..e25b44176 100644 --- a/sonoff/xdrv_ir_send.ino +++ b/sonoff/xdrv_ir_send.ino @@ -261,7 +261,7 @@ boolean ir_hvac_mitsubishi(const char *HVAC_Mode,const char *HVAC_FanMode, boole mode = (p - HVACMODE +1) << 3; // HOT = 0x08, DRY = 0x10, COOL = 0x18, AUTO = 0x20 mitsubir->setMode(mode); - mitsubir->setPower(~HVAC_Power); + mitsubir->setPower(HVAC_Power); if (HVAC_FanMode == NULL) { p = (char*)FANSPEED; // default FAN_SPEED_AUTO diff --git a/sonoff/xdrv_snfled.ino b/sonoff/xdrv_snfled.ino index 525c245f4..dba0e6167 100644 --- a/sonoff/xdrv_snfled.ino +++ b/sonoff/xdrv_snfled.ino @@ -19,6 +19,13 @@ /*********************************************************************************************\ * Sonoff B1, AiLight, Sonoff Led and BN-SZ01 + * + * sfl_flg Module Color ColorTemp + * 1 Sonoff BN-SZ W no + * 2 Sonoff Led CW yes + * 3 not used + * 4 AiLight RGBW no + * 5 Sonoff B1 RGBCW yes \*********************************************************************************************/ uint8_t ledTable[] = { @@ -50,7 +57,7 @@ uint8_t sl_wakeupDimmer = 0; uint16_t sl_wakeupCntr = 0; /*********************************************************************************************\ - * Sonoff B1 (my9231) and AiLight (my9291) based on OpenLight https://github.com/icamgo/noduino-sdk + * Sonoff B1 and AiLight inspired by OpenLight https://github.com/icamgo/noduino-sdk \*********************************************************************************************/ extern "C" { @@ -76,83 +83,56 @@ void sl_dcki_pulse(uint8_t times) } } -void sl_my92x1_command(uint8_t chips, uint8_t command) +void sl_my92x1_write(uint8_t data) { - uint8_t command_data; + for (uint8_t i = 0; i < 4; i++) { // Send 8bit Data + digitalWrite(sl_pdcki, LOW); + digitalWrite(sl_pdi, (data & 0x80)); + digitalWrite(sl_pdcki, HIGH); + data = data << 1; + digitalWrite(sl_pdi, (data & 0x80)); + digitalWrite(sl_pdcki, LOW); + digitalWrite(sl_pdi, LOW); + data = data << 1; + } +} - os_delay_us(12); // TStop > 12us. +void sl_my92x1_init() +{ + uint8_t chips = sfl_flg -3; // 1 (AiLight) or 2 (Sonoff B1) + + sl_dcki_pulse(chips * 32); // Clear all duty register + os_delay_us(12); // TStop > 12us. // Send 12 DI pulse, after 6 pulse's falling edge store duty data, and 12 // pulse's rising edge convert to command mode. sl_di_pulse(12); - os_delay_us(12); // Delay >12us, begin send CMD data + os_delay_us(12); // Delay >12us, begin send CMD data for (uint8_t n = 0; n < chips; n++) { // Send CMD data - command_data = command; - for (uint8_t i = 0; i < 4; i++) { // Send byte - digitalWrite(sl_pdcki, LOW); - digitalWrite(sl_pdi, (command_data & 0x80)); - digitalWrite(sl_pdcki, HIGH); - command_data = command_data << 1; - digitalWrite(sl_pdi, (command_data & 0x80)); - digitalWrite(sl_pdcki, LOW); - digitalWrite(sl_pdi, LOW); - command_data = command_data << 1; - } + sl_my92x1_write(0x18); // ONE_SHOT_DISABLE, REACTION_FAST, BIT_WIDTH_8, FREQUENCY_DIVIDE_1, SCATTER_APDM } - os_delay_us(12); // TStart > 12us. Delay 12 us. + os_delay_us(12); // TStart > 12us. Delay 12 us. // Send 16 DI pulse, at 14 pulse's falling edge store CMD data, and // at 16 pulse's falling edge convert to duty mode. sl_di_pulse(16); - os_delay_us(12); // TStop > 12us. + os_delay_us(12); // TStop > 12us. } -void sl_my9231_duty(uint8_t duty_r, uint8_t duty_g, uint8_t duty_b, uint8_t duty_w, uint8_t duty_c) +void sl_my92x1_duty(uint8_t duty_r, uint8_t duty_g, uint8_t duty_b, uint8_t duty_w, uint8_t duty_c) { - uint8_t duty_current = 0; + uint8_t channels[2] = { 4, 6 }; - uint8_t duty[6] = { duty_w, duty_c, 0, duty_g, duty_r, duty_b }; // Definition for RGBWC channels + uint8_t didx = sfl_flg -4; // 0 or 1 - os_delay_us(12); // TStop > 12us. - for (uint8_t channel = 0; channel < 6; channel++) { // WC0GRB 6CH - duty_current = duty[channel]; - for (uint8_t i = 0; i < 4; i++) { // Send 8bit Data - digitalWrite(sl_pdcki, LOW); - digitalWrite(sl_pdi, (duty_current & 0x80)); - digitalWrite(sl_pdcki, HIGH); - duty_current = duty_current << 1; - digitalWrite(sl_pdi, (duty_current & 0x80)); - digitalWrite(sl_pdcki, LOW); - digitalWrite(sl_pdi, LOW); - duty_current = duty_current << 1; - } + uint8_t duty[2][6] = {{ duty_r, duty_g, duty_b, duty_w, 0, 0 }, // Definition for RGBW channels + { duty_w, duty_c, 0, duty_g, duty_r, duty_b }}; // Definition for RGBWC channels + + os_delay_us(12); // TStop > 12us. + for (uint8_t channel = 0; channel < channels[didx]; channel++) { + sl_my92x1_write(duty[didx][channel]); // Send 8bit Data } - os_delay_us(12); // TStart > 12us. Ready for send DI pulse. - sl_di_pulse(8); // Send 8 DI pulse. After 8 pulse falling edge, store old data. - os_delay_us(12); // TStop > 12us. -} - -void sl_my9291_duty(uint8_t duty_r, uint8_t duty_g, uint8_t duty_b, uint8_t duty_w) -{ - uint8_t duty_current = 0; - - uint8_t duty[4] = { duty_r, duty_g, duty_b, duty_w }; // Definition for RGBW channels - - os_delay_us(12); // TStop > 12us. - for (uint8_t channel = 0; channel < 4; channel++) { // RGBW 4CH - duty_current = duty[channel]; // RGBW Channel - for (uint8_t i = 0; i < 4; i++) { // Send 8bit Data - digitalWrite(sl_pdcki, LOW); - digitalWrite(sl_pdi, (duty_current & 0x80)); - digitalWrite(sl_pdcki, HIGH); - duty_current = duty_current << 1; - digitalWrite(sl_pdi, (duty_current & 0x80)); - digitalWrite(sl_pdcki, LOW); - digitalWrite(sl_pdi, LOW); - duty_current = duty_current << 1; - } - } - os_delay_us(12); // TStart > 12us. Ready for send DI pulse. - sl_di_pulse(8); // Send 8 DI pulse. After 8 pulse falling edge, store old data. - os_delay_us(12); // TStop > 12us. + os_delay_us(12); // TStart > 12us. Ready for send DI pulse. + sl_di_pulse(8); // Send 8 DI pulse. After 8 pulse falling edge, store old data. + os_delay_us(12); // TStop > 12us. } /********************************************************************************************/ @@ -186,15 +166,7 @@ void sl_init(void) digitalWrite(sl_pdi, LOW); digitalWrite(sl_pdcki, LOW); - if (4 == sfl_flg) { - // Clear all duty register - sl_dcki_pulse(32); // 1 * 32 bits - sl_my92x1_command(1, 0x18); // ONE_SHOT_DISABLE, REACTION_FAST, BIT_WIDTH_8, FREQUENCY_DIVIDE_1, SCATTER_APDM - } else if (5 == sfl_flg) { - // Clear all duty register - sl_dcki_pulse(64); // 2 * 32 bits - sl_my92x1_command(2, 0x18); // ONE_SHOT_DISABLE, REACTION_FAST, BIT_WIDTH_8, FREQUENCY_DIVIDE_1, SCATTER_APDM - } + sl_my92x1_init(); } sl_power = 0; @@ -202,6 +174,46 @@ void sl_init(void) sl_wakeupActive = 0; } +void sl_setColorTemp(uint16_t ct) +{ +/* Color Temperature (https://developers.meethue.com/documentation/core-concepts) + * + * ct = 153 = 2000K = Warm = CCWW = 00FF + * ct = 500 = 6500K = Cold = CCWW = FF00 + */ + uint16_t my_ct = ct - 153; + if (my_ct > 347) { + my_ct = 347; + } + uint16_t icold = (100 * (347 - my_ct)) / 136; + uint16_t iwarm = (100 * my_ct) / 136; + if (5 == sfl_flg) { + sysCfg.led_color[0] = 0; + sysCfg.led_color[1] = 0; + sysCfg.led_color[2] = 0; + sysCfg.led_color[3] = (uint8_t)icold; + sysCfg.led_color[4] = (uint8_t)iwarm; + } else { + sysCfg.led_color[0] = (uint8_t)icold; + sysCfg.led_color[1] = (uint8_t)iwarm; + } +} + +uint16_t sl_getColorTemp() +{ + uint8_t ct_idx = 0; + if (5 == sfl_flg) { + ct_idx = 3; + } + uint16_t my_ct = sysCfg.led_color[ct_idx +1]; + if (my_ct > 0) { + return ((my_ct * 136) / 100) + 154; + } else { + my_ct = sysCfg.led_color[ct_idx]; + return 499 - ((my_ct * 136) / 100); + } +} + void sl_setDim(uint8_t myDimmer) { float temp; @@ -350,11 +362,8 @@ void sl_animate() } } } - if (4 == sfl_flg) { - sl_my9291_duty(cur_col[0], cur_col[1], cur_col[2], cur_col[3]); - } - else if (5 == sfl_flg) { - sl_my9231_duty(cur_col[0], cur_col[1], cur_col[2], cur_col[3], cur_col[4]); + if (sfl_flg > 3) { + sl_my92x1_duty(cur_col[0], cur_col[1], cur_col[2], cur_col[3], cur_col[4]); } } } @@ -410,35 +419,36 @@ void sl_getHSB(float *hue, float *sat, float *bri) } } -void sl_setHSB(float hue, float sat, float bri, float ct) +void sl_setHSB(float hue, float sat, float bri, uint16_t ct) { char svalue[MESSZ]; HsbColor hsb; - float my_ct; /* char log[LOGSZ]; char stemp1[10]; char stemp2[10]; char stemp3[10]; - char stemp4[10]; dtostrf(hue, 1, 3, stemp1); dtostrf(sat, 1, 3, stemp2); dtostrf(bri, 1, 3, stemp3); - dtostrf(ct, 1, 3, stemp4); - snprintf_P(log, sizeof(log), PSTR("HUE: Set Hue %s, Sat %s, Bri %s, Ct %s"), stemp1, stemp2, stemp3, stemp4); + snprintf_P(log, sizeof(log), PSTR("HUE: Set Hue %s, Sat %s, Bri %s, Ct %d"), stemp1, stemp2, stemp3, ct); addLog(LOG_LEVEL_DEBUG, log); */ if (sfl_flg > 2) { - hsb.H = hue; - hsb.S = sat; - hsb.B = bri; - RgbColor tmp = RgbColor(hsb); - sl_dcolor[0] = tmp.R; - sl_dcolor[1] = tmp.G; - sl_dcolor[2] = tmp.B; - sl_setColor(); + if ((5 == sfl_flg) && (ct > 0)) { + sl_setColorTemp(ct); + } else { + hsb.H = hue; + hsb.S = sat; + hsb.B = bri; + RgbColor tmp = RgbColor(hsb); + sl_dcolor[0] = tmp.R; + sl_dcolor[1] = tmp.G; + sl_dcolor[2] = tmp.B; + sl_setColor(); + } sl_prepPower(svalue, sizeof(svalue)); mqtt_publish_topic_P(5, "COLOR", svalue); } else { @@ -446,20 +456,7 @@ void sl_setHSB(float hue, float sat, float bri, float ct) sysCfg.led_dimmer[0] = tmp; if (2 == sfl_flg) { if (ct > 0) { - my_ct = ct - 0.306; - if (my_ct > 0.694) { // >500 (Warm) - my_ct = 0.694; - } - float fcold = 367 * (0.694 - my_ct); // 0 - 255 - float fwarm = 367 * my_ct; // 0 - 255 - float fmax = (fwarm > fcold) ? fwarm : fcold; - float fbri = 100 / (fmax / 2.55); // Scale to 255 - if (bri < 1) { - bri = bri + 0.01; // Adjust for sl_setColor - } - sl_dcolor[0] = (uint8_t)(fcold * fbri * bri); // Cold - sl_dcolor[1] = (uint8_t)(fwarm * fbri * bri); // Warm - sl_setColor(); + sl_setColorTemp(ct); } sl_prepPower(svalue, sizeof(svalue)); mqtt_publish_topic_P(5, "COLOR", svalue); @@ -493,6 +490,14 @@ boolean sl_command(char *type, uint16_t index, char *dataBufUc, uint16_t data_le snprintf_P(svalue, ssvalue, PSTR("{\"Color\":\"%s\"}"), sl_getColor(scolor)); } } + else if (!strcmp_P(type,PSTR("CT")) && ((2 == sfl_flg) || (5 == sfl_flg))) { // ColorTemp + if ((payload >= 153) && (payload <= 500)) { // https://developers.meethue.com/documentation/core-concepts + sl_setColorTemp(payload); + coldim = true; + } else { + snprintf_P(svalue, ssvalue, PSTR("{\"CT\":%d}"), sl_getColorTemp()); + } + } else if (!strcmp_P(type,PSTR("DIMMER"))) { if ((payload >= 0) && (payload <= 100)) { sysCfg.led_dimmer[0] = payload; diff --git a/sonoff/xdrv_wemohue.ino b/sonoff/xdrv_wemohue.ino index 3d0aa30fc..ac522167d 100644 --- a/sonoff/xdrv_wemohue.ino +++ b/sonoff/xdrv_wemohue.ino @@ -533,7 +533,7 @@ void hue_lights(String *path) float bri = 0; float hue = 0; float sat = 0; - float ct = 0; + uint16_t ct = 0; bool resp = false; bool on = false; bool change = false; @@ -638,15 +638,14 @@ void hue_lights(String *path) change = true; } if (hue_json.containsKey("ct")) { // Color temperature 153 (Cold) to 500 (Warm) - tmp = hue_json["ct"]; - ct = (float)tmp / 500.0f; + ct = hue_json["ct"]; if (resp) { response += ","; } response += FPSTR(HUE_LIGHT_RESPONSE_JSON); response.replace("{id}", String(device)); response.replace("{cmd}", "ct"); - response.replace("{res}", String(tmp)); + response.replace("{res}", String(ct)); change = true; } if (change) { @@ -669,7 +668,7 @@ void hue_lights(String *path) response = FPSTR(HUE_ERROR_JSON); } -addLog(LOG_LEVEL_DEBUG_MORE, response.c_str()); +//addLog(LOG_LEVEL_DEBUG_MORE, response.c_str()); webServer->send(200, FPSTR(HDR_CTYPE_JSON), response); } From e9f4ca930ab0ca0bd8e1cd05aacaa16e6032e1b1 Mon Sep 17 00:00:00 2001 From: arendst Date: Wed, 16 Aug 2017 17:45:23 +0200 Subject: [PATCH 10/13] v5.5.2h - Add Sonoff B1 support 5.5.2h * Fix Sonoff Pow intermittent exception 0 * Change Sonoff Pow sending Domoticz telemetry data only * Add Sonoff B1 RGBCW led support with command Color RRGGBBCCWW (#676) * Add command CT 152..500 to Sonoff Led and Sonoff B1 to control Color Temperature * Add Cold-Warm slider to web page for Sonoff Led and Sonoff B1 * Add CT parameter to Hue * Add Ai-Thinker RGBW led (AiLight) (experimental) * Add NeoPixelBus library to Sonoff Led for Hue support (saves 1k code space) * Add user configurable GPIO4 and GPIO5 to module Sonoff Bridge * Fix Mitsubishi HVAC IR power controll (#740) --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 858eca87f..fd4df1eae 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,7 @@ ## Sonoff-Tasmota Provide ESP8266 based Sonoff by [iTead Studio](https://www.itead.cc/) and ElectroDragon IoT Relay with Serial, Web and MQTT control allowing 'Over the Air' or OTA firmware updates using Arduino IDE. -Current version is **5.5.2** - See [sonoff/_releasenotes.ino](https://github.com/arendst/Sonoff-Tasmota/blob/master/sonoff/_releasenotes.ino) for change information. +Current version is **5.5.2h** - See [sonoff/_releasenotes.ino](https://github.com/arendst/Sonoff-Tasmota/blob/master/sonoff/_releasenotes.ino) for change information. ### ATTENTION All versions @@ -47,6 +47,7 @@ The following devices are supported: - [iTead Sonoff SC](http://sonoff.itead.cc/en/products/residential/sonoff-sc) - [iTead Sonoff Led](http://sonoff.itead.cc/en/products/appliances/sonoff-led) - [iTead Sonoff BN-SZ01 Ceiling Led](http://sonoff.itead.cc/en/products/appliances/bn-sz01) +- [iTead Sonoff B1](http://sonoff.itead.cc/en/products/residential/sonoff-b1) - [iTead Sonoff RF Bridge 433](http://sonoff.itead.cc/en/products/appliances/sonoff-rf-bridge-433) - [iTead Sonoff Dev](https://www.itead.cc/sonoff-dev.html) - [iTead 1 Channel Switch 5V / 12V](https://www.itead.cc/smart-home/inching-self-locking-wifi-wireless-switch.html) @@ -55,7 +56,6 @@ The following devices are supported: Planned support: - [iTead Sonoff T1](http://sonoff.itead.cc/en/products/residential/sonoff-t1) -- [iTead Sonoff B1](http://sonoff.itead.cc/en/products/residential/sonoff-b1) From 963476e68833dd6aeebff86edf0ea419c0f9c0ea Mon Sep 17 00:00:00 2001 From: arendst Date: Wed, 16 Aug 2017 22:56:32 +0200 Subject: [PATCH 11/13] v5.5.2i 5.5.2i * Fix Sonoff Pow intermittent exception 0 * Change Sonoff Pow sending Domoticz telemetry data only * Add Sonoff B1 RGBCW led support with command Color RRGGBBCCWW (#676) * Add command CT 152..500 to Sonoff Led and Sonoff B1 to control Color Temperature * Add Cold-Warm slider to web page for Sonoff Led and Sonoff B1 * Add CT parameter to Hue * Add Ai-Thinker RGBW led (AiLight) (experimental) * Add NeoPixelBus library to Sonoff Led for Hue support (saves 1k code space) * Add user configurable GPIO4 and GPIO5 to module Sonoff Bridge * Fix Mitsubishi HVAC IR power controll (#740) * Add Sonoff T1 support (#582) --- README.md | 6 ++--- sonoff/_releasenotes.ino | 3 ++- sonoff/sonoff.ino | 2 +- sonoff/sonoff_template.h | 49 +++++++++++++++++++++++++++++++++++++++- 4 files changed, 53 insertions(+), 7 deletions(-) diff --git a/README.md b/README.md index fd4df1eae..67796d1a7 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,7 @@ ## Sonoff-Tasmota Provide ESP8266 based Sonoff by [iTead Studio](https://www.itead.cc/) and ElectroDragon IoT Relay with Serial, Web and MQTT control allowing 'Over the Air' or OTA firmware updates using Arduino IDE. -Current version is **5.5.2h** - See [sonoff/_releasenotes.ino](https://github.com/arendst/Sonoff-Tasmota/blob/master/sonoff/_releasenotes.ino) for change information. +Current version is **5.5.2i** - See [sonoff/_releasenotes.ino](https://github.com/arendst/Sonoff-Tasmota/blob/master/sonoff/_releasenotes.ino) for change information. ### ATTENTION All versions @@ -44,6 +44,7 @@ The following devices are supported: - [iTead S20 Smart Socket](http://sonoff.itead.cc/en/products/residential/s20-socket) - [iTead Slampher](http://sonoff.itead.cc/en/products/residential/slampher-rf) - [iTead Sonoff Touch](http://sonoff.itead.cc/en/products/residential/sonoff-touch) +- [iTead Sonoff T1](http://sonoff.itead.cc/en/products/residential/sonoff-t1) - [iTead Sonoff SC](http://sonoff.itead.cc/en/products/residential/sonoff-sc) - [iTead Sonoff Led](http://sonoff.itead.cc/en/products/appliances/sonoff-led) - [iTead Sonoff BN-SZ01 Ceiling Led](http://sonoff.itead.cc/en/products/appliances/bn-sz01) @@ -54,8 +55,5 @@ The following devices are supported: - [iTead Motor Clockwise/Anticlockwise](https://www.itead.cc/smart-home/motor-reversing-wifi-wireless-switch.html) - [Electrodragon IoT Relay Board](http://www.electrodragon.com/product/wifi-iot-relay-board-based-esp8266/) -Planned support: -- [iTead Sonoff T1](http://sonoff.itead.cc/en/products/residential/sonoff-t1) - diff --git a/sonoff/_releasenotes.ino b/sonoff/_releasenotes.ino index 03a265ba0..d1a532236 100644 --- a/sonoff/_releasenotes.ino +++ b/sonoff/_releasenotes.ino @@ -1,4 +1,4 @@ -/* 5.5.2h +/* 5.5.2i * Fix Sonoff Pow intermittent exception 0 * Change Sonoff Pow sending Domoticz telemetry data only * Add Sonoff B1 RGBCW led support with command Color RRGGBBCCWW (#676) @@ -9,6 +9,7 @@ * Add NeoPixelBus library to Sonoff Led for Hue support (saves 1k code space) * Add user configurable GPIO4 and GPIO5 to module Sonoff Bridge * Fix Mitsubishi HVAC IR power controll (#740) + * Add Sonoff T1 support (#582) * * 5.5.2 20170808 * Extent max number of WS2812 pixels from 256 to 512 (#667) diff --git a/sonoff/sonoff.ino b/sonoff/sonoff.ino index f4be6a1d7..0a010da3e 100644 --- a/sonoff/sonoff.ino +++ b/sonoff/sonoff.ino @@ -25,7 +25,7 @@ - Select IDE Tools - Flash Size: "1M (no SPIFFS)" ====================================================*/ -#define VERSION 0x05050208 // 5.5.2h +#define VERSION 0x05050209 // 5.5.2i enum log_t {LOG_LEVEL_NONE, LOG_LEVEL_ERROR, LOG_LEVEL_INFO, LOG_LEVEL_DEBUG, LOG_LEVEL_DEBUG_MORE, LOG_LEVEL_ALL}; enum week_t {Last, First, Second, Third, Fourth}; diff --git a/sonoff/sonoff_template.h b/sonoff/sonoff_template.h index 409621322..061892623 100644 --- a/sonoff/sonoff_template.h +++ b/sonoff/sonoff_template.h @@ -153,6 +153,9 @@ enum module_t { SONOFF_BRIDGE, SONOFF_B1, AILIGHT, + SONOFF_T11, + SONOFF_T12, + SONOFF_T13, MAXMODULE }; /********************************************************************************************/ @@ -523,7 +526,51 @@ const mytmplt modules[MAXMODULE] PROGMEM = { 0, GPIO_DCKI, // GPIO15 my9291 DCKI 0, 0 + }, + { "Sonoff T1 1CH", // Sonoff T1 1CH (ESP8285) + 0, + GPIO_USER, // GPIO01 Serial RXD and Optional sensor + 0, + GPIO_USER, // GPIO03 Serial TXD and Optional sensor + 0, + GPIO_REL1, // GPIO05 Blue Led and Relay 1 (0 = Off, 1 = On) + 0, 0, 0, // Flash connection + GPIO_KEY1, // GPIO09 Button 1 + 0, + 0, // Flash connection + 0, + GPIO_LED1_INV, // GPIO13 Blue Led (0 = On, 1 = Off) + 0, 0, 0, 0 + }, + { "Sonoff T1 2CH", // Sonoff T1 2CH (ESP8285) + GPIO_KEY1, // GPIO00 Button 1 + GPIO_USER, // GPIO01 Serial RXD and Optional sensor + 0, + GPIO_USER, // GPIO03 Serial TXD and Optional sensor + GPIO_REL2, // GPIO04 Blue Led and Relay 2 (0 = Off, 1 = On) + 0, + 0, 0, 0, // Flash connection + 0, + GPIO_KEY2, // GPIO10 Button 2 + 0, // Flash connection + GPIO_REL1, // GPIO12 Blue Led and Relay 1 (0 = Off, 1 = On) + GPIO_LED1_INV, // GPIO13 Blue Led (0 = On, 1 = Off) + 0, 0, 0, 0 + }, + { "Sonoff T1 3CH", // Sonoff T1 3CH (ESP8285) + GPIO_KEY1, // GPIO00 Button 1 + GPIO_USER, // GPIO01 Serial RXD and Optional sensor + 0, + GPIO_USER, // GPIO03 Serial TXD and Optional sensor + GPIO_REL3, // GPIO04 Blue Led and Relay 3 (0 = Off, 1 = On) + GPIO_REL2, // GPIO05 Blue Led and Relay 2 (0 = Off, 1 = On) + 0, 0, 0, // Flash connection + GPIO_KEY2, // GPIO09 Button 2 + GPIO_KEY3, // GPIO10 Button 3 + 0, // Flash connection + GPIO_REL1, // GPIO12 Blue Led and Relay 1 (0 = Off, 1 = On) + GPIO_LED1_INV, // GPIO13 Blue Led (0 = On, 1 = Off) + 0, 0, 0, 0 } - }; From e0f759a31836c8a41ec3b07b11859036d754d97e Mon Sep 17 00:00:00 2001 From: arendst Date: Fri, 18 Aug 2017 10:40:21 +0200 Subject: [PATCH 12/13] Invert Sonoff T1 led state --- README.md | 2 +- sonoff/_releasenotes.ino | 3 ++- sonoff/sonoff.ino | 8 ++++++-- 3 files changed, 9 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 67796d1a7..50b5e1e03 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,7 @@ ## Sonoff-Tasmota Provide ESP8266 based Sonoff by [iTead Studio](https://www.itead.cc/) and ElectroDragon IoT Relay with Serial, Web and MQTT control allowing 'Over the Air' or OTA firmware updates using Arduino IDE. -Current version is **5.5.2i** - See [sonoff/_releasenotes.ino](https://github.com/arendst/Sonoff-Tasmota/blob/master/sonoff/_releasenotes.ino) for change information. +Current version is **5.5.2j** - See [sonoff/_releasenotes.ino](https://github.com/arendst/Sonoff-Tasmota/blob/master/sonoff/_releasenotes.ino) for change information. ### ATTENTION All versions diff --git a/sonoff/_releasenotes.ino b/sonoff/_releasenotes.ino index d1a532236..72fb41be3 100644 --- a/sonoff/_releasenotes.ino +++ b/sonoff/_releasenotes.ino @@ -1,4 +1,4 @@ -/* 5.5.2i +/* 5.5.2j * Fix Sonoff Pow intermittent exception 0 * Change Sonoff Pow sending Domoticz telemetry data only * Add Sonoff B1 RGBCW led support with command Color RRGGBBCCWW (#676) @@ -10,6 +10,7 @@ * Add user configurable GPIO4 and GPIO5 to module Sonoff Bridge * Fix Mitsubishi HVAC IR power controll (#740) * Add Sonoff T1 support (#582) + * Change Sonoff T1 command Ledstate functionality by turning led on if power is off * * 5.5.2 20170808 * Extent max number of WS2812 pixels from 256 to 512 (#667) diff --git a/sonoff/sonoff.ino b/sonoff/sonoff.ino index 0a010da3e..939eb9bfe 100644 --- a/sonoff/sonoff.ino +++ b/sonoff/sonoff.ino @@ -25,7 +25,7 @@ - Select IDE Tools - Flash Size: "1M (no SPIFFS)" ====================================================*/ -#define VERSION 0x05050209 // 5.5.2i +#define VERSION 0x0505020A // 5.5.2j enum log_t {LOG_LEVEL_NONE, LOG_LEVEL_ERROR, LOG_LEVEL_INFO, LOG_LEVEL_DEBUG, LOG_LEVEL_DEBUG_MORE, LOG_LEVEL_ALL}; enum week_t {Last, First, Second, Third, Fourth}; @@ -2351,7 +2351,11 @@ void stateloop() } } else { if (sysCfg.ledstate &0x01) { - setLed((SONOFF_TOUCH == sysCfg.module) ? (power ^1) : power); + boolean tstate = power; + if ((SONOFF_TOUCH == sysCfg.module) || (SONOFF_T11 == sysCfg.module) || (SONOFF_T12 == sysCfg.module) || (SONOFF_T13 == sysCfg.module)) { + tstate = (!power) ? 1 : 0; + } + setLed(tstate); } } } From 06d0c62dfa8fd0566b0584e18c0383476379699e Mon Sep 17 00:00:00 2001 From: arendst Date: Fri, 18 Aug 2017 12:55:08 +0200 Subject: [PATCH 13/13] Add global interlock Use command SetOption14 1 to enable interlock mode --- README.md | 2 +- sonoff/_releasenotes.ino | 3 ++- sonoff/settings.h | 2 +- sonoff/sonoff.ino | 36 ++++++++++++++++++++++++++++++++++-- 4 files changed, 38 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index 50b5e1e03..36513d374 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,7 @@ ## Sonoff-Tasmota Provide ESP8266 based Sonoff by [iTead Studio](https://www.itead.cc/) and ElectroDragon IoT Relay with Serial, Web and MQTT control allowing 'Over the Air' or OTA firmware updates using Arduino IDE. -Current version is **5.5.2j** - See [sonoff/_releasenotes.ino](https://github.com/arendst/Sonoff-Tasmota/blob/master/sonoff/_releasenotes.ino) for change information. +Current version is **5.5.2k** - See [sonoff/_releasenotes.ino](https://github.com/arendst/Sonoff-Tasmota/blob/master/sonoff/_releasenotes.ino) for change information. ### ATTENTION All versions diff --git a/sonoff/_releasenotes.ino b/sonoff/_releasenotes.ino index 72fb41be3..046deffe6 100644 --- a/sonoff/_releasenotes.ino +++ b/sonoff/_releasenotes.ino @@ -1,4 +1,4 @@ -/* 5.5.2j +/* 5.5.2k * Fix Sonoff Pow intermittent exception 0 * Change Sonoff Pow sending Domoticz telemetry data only * Add Sonoff B1 RGBCW led support with command Color RRGGBBCCWW (#676) @@ -11,6 +11,7 @@ * Fix Mitsubishi HVAC IR power controll (#740) * Add Sonoff T1 support (#582) * Change Sonoff T1 command Ledstate functionality by turning led on if power is off + * Add command SetOption14 0|1 to enable interlock mode (#719, #721) * * 5.5.2 20170808 * Extent max number of WS2812 pixels from 256 to 512 (#667) diff --git a/sonoff/settings.h b/sonoff/settings.h index 2ee62d957..c08889332 100644 --- a/sonoff/settings.h +++ b/sonoff/settings.h @@ -36,7 +36,7 @@ typedef union { // Restricted by MISRA-C Rule 18.4 bu uint32_t button_swap : 1; // bit 11 (v5.1.6) uint32_t stop_flash_rotate : 1; // bit 12 (v5.2.0) uint32_t button_single : 1; // bit 13 (v5.4.0) - uint32_t spare14 : 1; + uint32_t interlock : 1; // bit 14 (v5.5.2k) uint32_t spare15 : 1; uint32_t spare16 : 1; uint32_t spare17 : 1; diff --git a/sonoff/sonoff.ino b/sonoff/sonoff.ino index 939eb9bfe..48df04fb2 100644 --- a/sonoff/sonoff.ino +++ b/sonoff/sonoff.ino @@ -25,7 +25,7 @@ - Select IDE Tools - Flash Size: "1M (no SPIFFS)" ====================================================*/ -#define VERSION 0x0505020A // 5.5.2j +#define VERSION 0x0505020B // 5.5.2k enum log_t {LOG_LEVEL_NONE, LOG_LEVEL_ERROR, LOG_LEVEL_INFO, LOG_LEVEL_DEBUG, LOG_LEVEL_DEBUG_MORE, LOG_LEVEL_ALL}; enum week_t {Last, First, Second, Third, Fourth}; @@ -266,6 +266,7 @@ uint8_t blogidx = 0; // Command backlog index uint8_t blogptr = 0; // Command backlog pointer uint8_t blogmutex = 0; // Command backlog pending uint16_t blogdelay = 0; // Command backlog delay +uint8_t interlockmutex = 0; // Interlock power command pending #ifdef USE_MQTT_TLS WiFiClientSecure espClient; // Wifi Secure Client @@ -403,6 +404,20 @@ void setRelay(uint8_t rpower) power = (1 << Maxdevice) -1; rpower = power; } + if (sysCfg.flag.interlock) { // Allow only one or no relay set + uint8_t mask = 0x01; + uint8_t count = 0; + for (byte i = 0; i < Maxdevice; i++) { + if (rpower & mask) { + count++; + } + mask <<= 1; + } + if (count > 1) { + power = 0; + rpower = 0; + } + } if ((SONOFF_DUAL == sysCfg.module) || (CH4 == sysCfg.module)) { Serial.write(0xA0); Serial.write(0x04); @@ -1010,6 +1025,12 @@ void mqttDataCb(char* topic, byte* data, unsigned int data_len) return; } else if ((sysCfg.module != MOTOR) && !strcmp_P(type,PSTR("POWERONSTATE"))) { + /* 0 = Keep relays off after power on + * 1 = Turn relays on after power on + * 2 = Toggle relays after power on + * 3 = Set relays to last saved state after power on + * 4 = Turn relays on and disable any relay control (used for Sonoff Pow to always measure power) + */ if ((payload >= 0) && (payload <= 4)) { sysCfg.poweronstate = payload; if (4 == sysCfg.poweronstate) { @@ -1062,7 +1083,7 @@ void mqttDataCb(char* topic, byte* data, unsigned int data_len) } snprintf_P(svalue, sizeof(svalue), PSTR("{\"SaveData\":\"%s\"}"), (sysCfg.savedata > 1) ? stemp1 : getStateText(sysCfg.savedata)); } - else if (!strcmp_P(type,PSTR("SETOPTION")) && ((index >= 0) && (index <= 13)) || ((index > 31) && (index <= P_MAX_PARAM8 +31))) { + else if (!strcmp_P(type,PSTR("SETOPTION")) && ((index >= 0) && (index <= 14)) || ((index > 31) && (index <= P_MAX_PARAM8 +31))) { if (index <= 31) { ptype = 0; // SetOption0 .. 31 } else { @@ -1084,6 +1105,7 @@ void mqttDataCb(char* topic, byte* data, unsigned int data_len) case 11: // button_swap case 12: // stop_flash_rotate case 13: // button_single + case 14: // interlock bitWrite(sysCfg.flag.data, index, payload); } if (12 == index) { // stop_flash_rotate @@ -1650,6 +1672,16 @@ void do_cmnd_power(byte device, byte state) blink_mask &= (0xFF ^ mask); // Clear device mask mqtt_publishPowerBlinkState(device); } + if (sysCfg.flag.interlock && !interlockmutex) { // Clear all but masked relay + interlockmutex = 1; + for (byte i = 0; i < Maxdevice; i++) { + byte imask = 0x01 << i; + if ((power & imask) && (mask != imask)) { + do_cmnd_power(i +1, 0); + } + } + interlockmutex = 0; + } switch (state) { case 0: { // Off power &= (0xFF ^ mask);