diff --git a/README.md b/README.md index c2e18f479..676b3fdd7 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.8.0e** - See [sonoff/_releasenotes.ino](https://github.com/arendst/Sonoff-Tasmota/blob/development/sonoff/_releasenotes.ino) for change information. +Current version is **5.8.0f** - See [sonoff/_releasenotes.ino](https://github.com/arendst/Sonoff-Tasmota/blob/development/sonoff/_releasenotes.ino) for change information. ### ATTENTION All versions diff --git a/sonoff/_releasenotes.ino b/sonoff/_releasenotes.ino index b7710deab..f63faf5d3 100644 --- a/sonoff/_releasenotes.ino +++ b/sonoff/_releasenotes.ino @@ -1,4 +1,9 @@ -/* 5.8.0e +/* 5.8.0f + * Set all saved power settings to Off when SetOption0 (SaveState) = 0 (#955) + * Allow PWM initialization after restart (#955) + * Add support for inverted PWM (#960) + * + * 5.8.0e * Add Domoticz counter sensor to Sonoff Bridge representing Received RF code (#943) * Add support for Luani HVIO board (https://luani.de/projekte/esp8266-hvio/) (#953) * diff --git a/sonoff/settings.h b/sonoff/settings.h index e9809eea3..e50c0acd8 100644 --- a/sonoff/settings.h +++ b/sonoff/settings.h @@ -166,7 +166,9 @@ struct SYSCFG { uint16_t led_pixels; uint8_t led_color[5]; uint8_t led_table; - uint8_t led_dimmer[3]; + uint8_t led_dimmer; + uint8_t ex_led_dimmer1; // Never used + uint8_t ex_led_dimmer2; // Never used uint8_t led_fade; uint8_t led_speed; uint8_t led_scheme; diff --git a/sonoff/settings.ino b/sonoff/settings.ino index c3f607a88..c3479336b 100644 --- a/sonoff/settings.ino +++ b/sonoff/settings.ino @@ -544,9 +544,7 @@ void CFG_DefaultSet_3_9_3() sysCfg.led_color[i] = 255; } sysCfg.led_table = 0; - for (byte i = 0; i < 3; i++){ - sysCfg.led_dimmer[i] = 10; - } + sysCfg.led_dimmer = 10; sysCfg.led_fade = 0; sysCfg.led_speed = 1; sysCfg.led_scheme = 0; @@ -726,7 +724,7 @@ void CFG_Delta() sysCfg.led_color[0] = sysCfg.ws_red; sysCfg.led_color[1] = sysCfg.ws_green; sysCfg.led_color[2] = sysCfg.ws_blue; - sysCfg.led_dimmer[0] = sysCfg.ws_dimmer; + sysCfg.led_dimmer = sysCfg.ws_dimmer; sysCfg.led_table = sysCfg.ws_ledtable; sysCfg.led_fade = sysCfg.ws_fade; sysCfg.led_speed = sysCfg.ws_speed; diff --git a/sonoff/sonoff.ino b/sonoff/sonoff.ino index 628cb1f27..f7f436074 100644 --- a/sonoff/sonoff.ino +++ b/sonoff/sonoff.ino @@ -25,7 +25,7 @@ - Select IDE Tools - Flash Size: "1M (no SPIFFS)" ====================================================*/ -#define VERSION 0x05080005 // 5.8.0e +#define VERSION 0x05080006 // 5.8.0f enum week_t {Last, First, Second, Third, Fourth}; enum dow_t {Sun=1, Mon, Tue, Wed, Thu, Fri, Sat}; @@ -285,6 +285,7 @@ mytmplt my_module; // Active copy of GPIOs uint8_t pin[GPIO_MAX]; // Possible pin configurations uint8_t rel_inverted[4] = { 0 }; // Relay inverted flag (1 = (0 = On, 1 = Off)) uint8_t led_inverted[4] = { 0 }; // LED inverted flag (1 = (0 = On, 1 = Off)) +uint8_t pwm_inverted[5] = { 0 }; // PWM inverted flag (1 = inverted) uint8_t dht_flg = 0; // DHT configured uint8_t hlw_flg = 0; // Power monitor configured uint8_t i2c_flg = 0; // I2C configured @@ -1253,7 +1254,7 @@ void mqttDataCb(char* topic, byte* data, unsigned int data_len) else if (!strcasecmp_P(type, PSTR(D_CMND_PWM)) && (index > pwm_idxoffset) && (index <= 5)) { if ((payload >= 0) && (payload <= PWM_RANGE) && (pin[GPIO_PWM1 + index -1] < 99)) { sysCfg.pwmvalue[index -1] = payload; - analogWrite(pin[GPIO_PWM1 + index -1], payload); + analogWrite(pin[GPIO_PWM1 + index -1], pwm_inverted[index -1] ? PWM_RANGE - payload : payload); } snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"" D_CMND_PWM "\":{")); bool first = true; @@ -2421,6 +2422,8 @@ void stateloop() if (!((sysCfg.power &mask) == (power &mask))) { sysCfg.power = power; } + } else { + sysCfg.power = 0; } CFG_Save(0); savedatacounter = sysCfg.savedata; @@ -2438,6 +2441,8 @@ void stateloop() } if (sysCfg.flag.savestate) { sysCfg.power = power; + } else { + sysCfg.power = 0; } if (hlw_flg) { hlw_savestate(); @@ -2597,6 +2602,10 @@ void GPIO_init() led_inverted[mpin - GPIO_LED1_INV] = 1; mpin -= 4; } + else if ((mpin >= GPIO_PWM1_INV) && (mpin <= GPIO_PWM5_INV)) { + pwm_inverted[mpin - GPIO_PWM1_INV] = 1; + mpin -= 5; + } #ifdef USE_DHT else if ((mpin >= GPIO_DHT11) && (mpin <= GPIO_DHT22)) { if (dht_setup(i, mpin)) { @@ -2704,7 +2713,7 @@ void GPIO_init() if (pin[GPIO_PWM1 +i] < 99) { pwm_flg = 1; pinMode(pin[GPIO_PWM1 +i], OUTPUT); - analogWrite(pin[GPIO_PWM1 +i], sysCfg.pwmvalue[i]); + analogWrite(pin[GPIO_PWM1 +i], pwm_inverted[i] ? PWM_RANGE - sysCfg.pwmvalue[i] : sysCfg.pwmvalue[i]); } } diff --git a/sonoff/sonoff_template.h b/sonoff/sonoff_template.h index ef9e870fd..6dd84a626 100644 --- a/sonoff/sonoff_template.h +++ b/sonoff/sonoff_template.h @@ -61,6 +61,11 @@ enum upins_t { GPIO_CNTR2, GPIO_CNTR3, GPIO_CNTR4, + GPIO_PWM1_INV, // RGB Red or C Cold White + GPIO_PWM2_INV, // RGB Green or CW Warm White + GPIO_PWM3_INV, // RGB Blue + GPIO_PWM4_INV, // RGBW (Cold) White + GPIO_PWM5_INV, // RGBCW Warm White GPIO_SENSOR_END }; // Text in webpage Module Parameters and commands GPIOS and GPIO @@ -106,7 +111,12 @@ const char sensors[GPIO_SENSOR_END][9] PROGMEM = { D_SENSOR_COUNTER "1", D_SENSOR_COUNTER "2", D_SENSOR_COUNTER "3", - D_SENSOR_COUNTER "4" + D_SENSOR_COUNTER "4", + D_SENSOR_PWM "1I", + D_SENSOR_PWM "2I", + D_SENSOR_PWM "3I", + D_SENSOR_PWM "4I", + D_SENSOR_PWM "5I" }; // Programmer selectable GPIO functionality offset by user selectable GPIOs diff --git a/sonoff/webserver.ino b/sonoff/webserver.ino index eab7b3f35..755e824f2 100644 --- a/sonoff/webserver.ino +++ b/sonoff/webserver.ino @@ -447,7 +447,7 @@ void handleRoot() snprintf_P(line, sizeof(line), HTTP_MSG_SLIDER1, sl_getColorTemp()); page += line; } - snprintf_P(line, sizeof(line), HTTP_MSG_SLIDER2, sysCfg.led_dimmer[0]); + snprintf_P(line, sizeof(line), HTTP_MSG_SLIDER2, sysCfg.led_dimmer); page += line; } page += FPSTR(HTTP_TABLE100); @@ -572,7 +572,7 @@ void handleAjax2() * Will interrupt user action when selected if (sfl_flg) { snprintf_P(line, sizeof(line), PSTR(""), - sysCfg.led_dimmer[0]); + sysCfg.led_dimmer); page += line; } */ diff --git a/sonoff/xdrv_domoticz.ino b/sonoff/xdrv_domoticz.ino index 98a64f0eb..bcf330861 100644 --- a/sonoff/xdrv_domoticz.ino +++ b/sonoff/xdrv_domoticz.ino @@ -71,7 +71,7 @@ void mqtt_publishDomoticzPowerState(byte device) if (sysCfg.flag.mqtt_enabled && sysCfg.domoticz_relay_idx[device -1]) { if (sfl_flg) { snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"idx\":%d,\"nvalue\":2,\"svalue\":\"%d\"}"), - sysCfg.domoticz_relay_idx[device -1], sysCfg.led_dimmer[device -1]); + sysCfg.domoticz_relay_idx[device -1], sysCfg.led_dimmer); mqtt_publish(domoticz_in_topic); } snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"idx\":%d,\"nvalue\":%d,\"svalue\":\"\"}"), @@ -175,11 +175,11 @@ boolean domoticz_mqttData(char *topicBuf, uint16_t stopicBuf, char *dataBuf, uin snprintf_P(stemp1, sizeof(stemp1), PSTR("%d"), i +1); if (2 == nvalue) { nvalue = domoticz["svalue1"]; -// if (sfl_flg && (sysCfg.led_dimmer[i] == nvalue) && ((power >> i) &1)) { // Unable to power off using webpage due to Domoticz re-sends dimmer state - if (sfl_flg && (sysCfg.led_dimmer[i] == nvalue)) { +// if (sfl_flg && (sysCfg.led_dimmer == nvalue) && ((power >> i) &1)) { // Unable to power off using webpage due to Domoticz re-sends dimmer state + if (sfl_flg && (sysCfg.led_dimmer == nvalue)) { return 1; } - snprintf_P(topicBuf, stopicBuf, PSTR("/" D_CMND_DIMMER "%s"), (Maxdevice > 1) ? stemp1 : ""); + snprintf_P(topicBuf, stopicBuf, PSTR("/" D_CMND_DIMMER)); snprintf_P(dataBuf, sdataBuf, PSTR("%d"), nvalue); found = 1; } else { diff --git a/sonoff/xdrv_snfled.ino b/sonoff/xdrv_snfled.ino index adba344df..1b59dfea6 100644 --- a/sonoff/xdrv_snfled.ino +++ b/sonoff/xdrv_snfled.ino @@ -69,7 +69,7 @@ uint8_t sl_tcolor[5]; uint8_t sl_lcolor[5]; uint8_t sl_power = 0; -uint8_t sl_any = 0; +uint8_t sl_any = 1; uint8_t sl_wakeupActive = 0; uint8_t sl_wakeupDimmer = 0; uint16_t sl_wakeupCntr = 0; @@ -201,7 +201,7 @@ void sl_init(void) } sl_power = 0; - sl_any = 0; + sl_any = 1; sl_wakeupActive = 0; } @@ -270,7 +270,7 @@ void sl_setColor() } } float mDim = (float)highest / 2.55; - sysCfg.led_dimmer[0] = (uint8_t)mDim; + sysCfg.led_dimmer = (uint8_t)mDim; float newDim = 100 / mDim; for (byte i = 0; i < (sfl_flg &7); i++) { temp = (float)sl_dcolor[i] * newDim; @@ -280,7 +280,7 @@ void sl_setColor() char* sl_getColor(char* scolor) { - sl_setDim(sysCfg.led_dimmer[0]); + sl_setDim(sysCfg.led_dimmer); scolor[0] = '\0'; for (byte i = 0; i < (sfl_flg &7); i++) { snprintf_P(scolor, 11, PSTR("%s%02X"), scolor, sl_dcolor[i]); @@ -292,11 +292,10 @@ void sl_prepPower() { char scolor[11]; -// do_cmnd_power(index, (sysCfg.led_dimmer[0]>0)); - if (sysCfg.led_dimmer[0] && !(sl_power)) { + if (sysCfg.led_dimmer && !(sl_power)) { do_cmnd_power(Maxdevice, 7); // No publishPowerState } - else if (!sysCfg.led_dimmer[0] && sl_power) { + else if (!sysCfg.led_dimmer && sl_power) { do_cmnd_power(Maxdevice, 6); // No publishPowerState } #ifdef USE_DOMOTICZ @@ -305,10 +304,10 @@ void sl_prepPower() #endif // USE_DOMOTICZ if ((sfl_flg &7) > 1) { snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"" D_RSLT_POWER "\":\"%s\", \"" D_CMND_DIMMER "\":%d, \"" D_CMND_COLOR "\":\"%s\"}"), - getStateText(sl_power), sysCfg.led_dimmer[0], sl_getColor(scolor)); + getStateText(sl_power), sysCfg.led_dimmer, sl_getColor(scolor)); } else { snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"" D_RSLT_POWER "\":\"%s\", \"" D_CMND_DIMMER "\":%d}"), - getStateText(sl_power), sysCfg.led_dimmer[0]); + getStateText(sl_power), sysCfg.led_dimmer); } } @@ -342,7 +341,7 @@ void sl_animate() sleep = 0; switch (sysCfg.led_scheme) { case 0: // Power On - sl_setDim(sysCfg.led_dimmer[0]); // Power On + sl_setDim(sysCfg.led_dimmer); // Power On if (0 == sysCfg.led_fade) { for (byte i = 0; i < (sfl_flg &7); i++) { sl_tcolor[i] = sl_dcolor[i]; @@ -370,10 +369,10 @@ void sl_animate() sl_wakeupDimmer = 0; } sl_wakeupCntr++; - if (sl_wakeupCntr > ((sysCfg.led_wakeup * STATES) / sysCfg.led_dimmer[0])) { + if (sl_wakeupCntr > ((sysCfg.led_wakeup * STATES) / sysCfg.led_dimmer)) { sl_wakeupCntr = 0; sl_wakeupDimmer++; - if (sl_wakeupDimmer <= sysCfg.led_dimmer[0]) { + if (sl_wakeupDimmer <= sysCfg.led_dimmer) { sl_setDim(sl_wakeupDimmer); for (byte i = 0; i < (sfl_flg &7); i++) { sl_tcolor[i] = sl_dcolor[i]; @@ -408,7 +407,8 @@ void sl_animate() cur_col[i] = (sysCfg.led_table) ? ledTable[sl_lcolor[i]] : sl_lcolor[i]; if (sfl_flg < 6) { if (pin[GPIO_PWM1 +i] < 99) { - analogWrite(pin[GPIO_PWM1 +i], cur_col[i] * (PWM_RANGE / 255)); + uint16_t curcol = cur_col[i] * (PWM_RANGE / 255); + analogWrite(pin[GPIO_PWM1 +i], pwm_inverted[i] ? PWM_RANGE - curcol : curcol); } } } @@ -434,7 +434,7 @@ float sl_Bri = 0.0; void sl_rgb2hsb() { - sl_setDim(sysCfg.led_dimmer[0]); + sl_setDim(sysCfg.led_dimmer); // convert colors to float between (0.0 - 1.0) float r = sl_dcolor[0] / 255.0f; @@ -539,8 +539,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)(0.01f * (float)sysCfg.led_dimmer[0]))); +// response->replace("{b}", String((uint8_t)(2.54f * (float)sysCfg.led_dimmer))); + response->replace("{b}", String((uint8_t)(0.01f * (float)sysCfg.led_dimmer))); } } @@ -554,8 +554,8 @@ void sl_getHSB(float *hue, float *sat, float *bri) } else { *hue = 0; *sat = 0; -// *bri = (2.54f * (float)sysCfg.led_dimmer[0]); - *bri = (0.01f * (float)sysCfg.led_dimmer[0]); +// *bri = (2.54f * (float)sysCfg.led_dimmer); + *bri = (0.01f * (float)sysCfg.led_dimmer); } } @@ -586,7 +586,7 @@ void sl_setHSB(float hue, float sat, float bri, uint16_t ct) mqtt_publish_topic_P(5, PSTR(D_CMND_COLOR)); } else { uint8_t tmp = (uint8_t)(bri * 100); - sysCfg.led_dimmer[0] = tmp; + sysCfg.led_dimmer = tmp; if (2 == (sfl_flg &7)) { if (ct > 0) { sl_setColorTemp(ct); @@ -671,7 +671,7 @@ boolean sl_command(char *type, uint16_t index, char *dataBuf, uint16_t data_len, #endif // USE_WS2812 ************************************************************************ else if (!strcasecmp_P(type, PSTR(D_CMND_WAKEUP))) { if ((payload >= 0) && (payload <= 100)) { - sysCfg.led_dimmer[0] = payload; + sysCfg.led_dimmer = payload; } sl_wakeupActive = 3; sysCfg.led_scheme = 1; @@ -688,10 +688,10 @@ boolean sl_command(char *type, uint16_t index, char *dataBuf, uint16_t data_len, } else if (!strcasecmp_P(type, PSTR(D_CMND_DIMMER))) { if ((payload >= 0) && (payload <= 100)) { - sysCfg.led_dimmer[0] = payload; + sysCfg.led_dimmer = payload; coldim = true; } else { - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"" D_CMND_DIMMER "\":%d}"), sysCfg.led_dimmer[0]); + snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"" D_CMND_DIMMER "\":%d}"), sysCfg.led_dimmer); } } else if (!strcasecmp_P(type, PSTR(D_CMND_LEDTABLE))) { diff --git a/sonoff/xdrv_ws2812.ino b/sonoff/xdrv_ws2812.ino index 5e59f8114..a8cad8073 100644 --- a/sonoff/xdrv_ws2812.ino +++ b/sonoff/xdrv_ws2812.ino @@ -118,7 +118,7 @@ void ws2812_clock() RgbColor c; strip->ClearTo(0); // Reset strip - float newDim = 100 / (float)sysCfg.led_dimmer[0]; + float newDim = 100 / (float)sysCfg.led_dimmer; float f1 = 255 / newDim; uint8_t i1 = (uint8_t)f1; float f2 = 127 / newDim; @@ -135,7 +135,6 @@ void ws2812_clock() c = strip->GetPixelColor(mod(i -1, j)); c.G = i3; strip->SetPixelColor(mod(i -1, j), c); c = strip->GetPixelColor(mod(i, j)); c.G = i1; strip->SetPixelColor(mod(i, j), c); c = strip->GetPixelColor(mod(i +1, j)); c.G = i3; strip->SetPixelColor(mod(i +1, j), c); -// i = (rtcTime.Hour % 12) * (50 / clksize); i = (rtcTime.Hour % 12 * 5 + rtcTime.Minute / 12 ) * 10 / clksize; c = strip->GetPixelColor(mod(i -2, j)); c.R = i3; strip->SetPixelColor(mod(i -2, j), c); c = strip->GetPixelColor(mod(i -1, j)); c.R = i2; strip->SetPixelColor(mod(i -1, j), c); @@ -161,7 +160,7 @@ void ws2812_gradientColor(uint8_t schemenr, struct wsColor* mColor, uint16_t ran start = (scheme.count -1) - start; end = (scheme.count -1) - end; } - float newDim = 100 / (float)sysCfg.led_dimmer[0]; + float newDim = 100 / (float)sysCfg.led_dimmer; float fmyRed = (float)map(rangeIndex % gradRange, 0, gradRange, scheme.colors[start].red, scheme.colors[end].red) / newDim; float fmyGrn = (float)map(rangeIndex % gradRange, 0, gradRange, scheme.colors[start].green, scheme.colors[end].green) / newDim; float fmyBlu = (float)map(rangeIndex % gradRange, 0, gradRange, scheme.colors[start].blue, scheme.colors[end].blue) / newDim; @@ -235,7 +234,7 @@ void ws2812_bars(uint8_t schemenr) wsColor mcolor[scheme.count]; memcpy(mcolor, scheme.colors, sizeof(mcolor)); - float newDim = 100 / (float)sysCfg.led_dimmer[0]; + float newDim = 100 / (float)sysCfg.led_dimmer; for (i = 0; i < scheme.count; i++) { float fmyRed = (float)mcolor[i].red / newDim; float fmyGrn = (float)mcolor[i].green / newDim;