v5.8.0f - Add inverted PWM support

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)
This commit is contained in:
arendst 2017-10-04 17:29:49 +02:00
parent 12af1af01b
commit c82fe7f46e
10 changed files with 66 additions and 43 deletions

View File

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

View File

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

View File

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

View File

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

View File

@ -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]);
}
}

View File

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

View File

@ -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("<input type='range' min='1' max='100' value='%d' onchange='lb(value)'>"),
sysCfg.led_dimmer[0]);
sysCfg.led_dimmer);
page += line;
}
*/

View File

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

View File

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

View File

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