diff --git a/platformio.ini b/platformio.ini index 297145fd1..ea01492f8 100755 --- a/platformio.ini +++ b/platformio.ini @@ -114,9 +114,8 @@ build_flags = -D NDEBUG -Wl,-Map,firmware.map [core_2_6_1] -; *** Esp8266 core for Arduino version 2.6.1 (for Windows, most Linux variants and Mac) -; *** custom setup until the core 2.6.1 version is official released from PlatformIO crew -platform = https://github.com/Jason2866/platform-espressif8266.git#core_2_6_1 +; *** Esp8266 core for Arduino version 2.6.1 +platform = https://github.com/platformio/platform-espressif8266.git#develop build_flags = ${esp82xx_defaults.build_flags} -Wl,-Teagle.flash.1m.ld -DBEARSSL_SSL_BASIC diff --git a/tasmota/my_user_config.h b/tasmota/my_user_config.h index aa98f3e82..7ef154d53 100644 --- a/tasmota/my_user_config.h +++ b/tasmota/my_user_config.h @@ -218,7 +218,8 @@ // (POWER_ALL_OFF, POWER_ALL_ON, POWER_ALL_SAVED_TOGGLE, POWER_ALL_SAVED, POWER_ALL_ALWAYS_ON, POWER_ALL_OFF_PULSETIME_ON) #define APP_BLINKTIME 10 // [BlinkTime] Time in 0.1 Sec to blink/toggle power for relay 1 #define APP_BLINKCOUNT 10 // [BlinkCount] Number of blinks (0 = 32000) -#define APP_SLEEP 0 // [Sleep] Sleep time to lower energy consumption (0 = Off, 1 - 250 mSec) +#define APP_SLEEP 0 // [Sleep] Sleep time to lower energy consumption (0 = Off, 1 - 250 mSec), +#define PWM_MAX_SLEEP 10 // Sleep will be lowered to this value when light is on, to avoid flickering #define KEY_DEBOUNCE_TIME 50 // [ButtonDebounce] Number of mSeconds button press debounce time #define KEY_HOLD_TIME 40 // [SetOption32] Number of 0.1 seconds to hold Button or external Pushbutton before sending HOLD message @@ -289,7 +290,8 @@ // -- MQTT - TLS - AWS IoT ------------------------ // Using TLS starting with version v6.5.0.16 compilation will only work using Core 2.4.2 and 2.5.2. No longer supported: 2.3.0 //#define USE_MQTT_TLS // Use TLS for MQTT connection (+34.5k code, +7.0k mem and +4.8k additional during connection handshake) -// #define USE_MQTT_TLS_CA_CERT // Force full CA validation instead of fingerprints, slower, but simpler to use (+2.2k code, +1.9k mem during connection handshake) +// #define USE_MQTT_TLS_CA_CERT // Force full CA validation instead of fingerprints, slower, but simpler to use. (+2.2k code, +1.9k mem during connection handshake) + // This includes the LetsEncrypt CA in tasmota_ca.ino for verifying server certificates // #define USE_MQTT_TLS_FORCE_EC_CIPHER // Force Elliptic Curve cipher (higher security) required by some servers (automatically enabled with USE_MQTT_AWS_IOT) (+11.4k code, +0.4k mem) // #define USE_MQTT_AWS_IOT // Enable MQTT for AWS IoT - requires a private key (+11.9k code, +0.4k mem) // Note: you need to generate a private key + certificate per device and update 'tasmota/tasmota_aws_iot.cpp' diff --git a/tasmota/xdrv_01_webserver.ino b/tasmota/xdrv_01_webserver.ino index 193f8fcf3..141543b5c 100644 --- a/tasmota/xdrv_01_webserver.ino +++ b/tasmota/xdrv_01_webserver.ino @@ -152,21 +152,13 @@ const char HTTP_SCRIPT_ROOT[] PROGMEM = "}" #endif // USE_SCRIPT_WEB_DISPLAY -#ifdef USE_JAVASCRIPT_ES6 - "lb=(v,p)=>la(`&${v}=${p}`);" - "lc=(v,i,p)=>la(`&${v}${i}=${p}`);" -#else - "function lb(v,p){" - "la('&'+v+'='+p);" - "}" "function lc(v,i,p){" + "if(v=='h'||v=='d'){" // Hue or Brightness changed so change Saturation colors too + "var sl=eb('sl4').value;" + "eb('s').style.background='linear-gradient(to right,rgb('+sl+'%%,'+sl+'%%,'+sl+'%%),hsl('+eb('sl2').value+',100%%,50%%))';" + "}" "la('&'+v+i+'='+p);" "}" -#endif // USE_JAVASCRIPT_ES6 - "function ld(v,p){" - "eb('s').style.background='linear-gradient(to right,#fff,hsl('+p+',100%%,50%%))';" - "la('&'+v+'='+p);" - "}" "wl(la);"; @@ -379,12 +371,9 @@ const char HTTP_HEAD_STYLE3[] PROGMEM = "

%s

"; const char HTTP_MSG_SLIDER_GRADIENT[] PROGMEM = - "
"; -const char HTTP_MSG_SLIDER_HUE[] PROGMEM = - "
" - "
"; -const char HTTP_MSG_SLIDER_CHANNEL[] PROGMEM = - "
"; + "
" + "" + "
"; const char HTTP_MSG_SLIDER_SHUTTER[] PROGMEM = "
" D_CLOSE "" D_OPEN "
" "
"; @@ -962,8 +951,6 @@ void HandleWifiLogin(void) WSContentStop(); } - - void HandleRoot(void) { if (CaptivePortal()) { return; } // If captive portal redirect instead of displaying the page. @@ -1012,26 +999,64 @@ void HandleRoot(void) uint8_t light_subtype = light_type &7; if (!Settings.flag3.pwm_multi_channels) { // SetOption68 0 - Enable multi-channels PWM instead of Color PWM if ((LST_COLDWARM == light_subtype) || (LST_RGBWC == light_subtype)) { - // Cold - Warm &t related to lb("t", value) and WebGetArg("t", tmp, sizeof(tmp)); - WSContentSend_P(HTTP_MSG_SLIDER_GRADIENT, "a", "#fff", "#ff0", 153, 500, LightGetColorTemp(), 't'); // White to Yellow + + WSContentSend_P(HTTP_MSG_SLIDER_GRADIENT, // Cold Warm + "a", // a - Unique HTML id + "#fff", "#ff0", // White to Yellow + 1, // sl1 + 153, 500, // Range color temperature + LightGetColorTemp(), + 't', 0); // t0 - Value id releated to lc("t0", value) and WebGetArg("t0", tmp, sizeof(tmp)); } if (light_subtype > 2) { uint16_t hue; uint8_t sat; - uint8_t bri; - LightGetHSB(&hue, &sat, &bri); - WSContentSend_P(HTTP_MSG_SLIDER_HUE, hue); // Hue - snprintf_P(stemp, sizeof(stemp), PSTR("#%02X%02X%02X"), Settings.light_color[0], Settings.light_color[1], Settings.light_color[2]); - // Saturation "s" related to eb('s').style.background='linear-gradient(to right,#fff,hsl('+p+',100%%,50%%))'; - WSContentSend_P(HTTP_MSG_SLIDER_GRADIENT, "s", "#fff", stemp, 1, 100, changeUIntScale(sat, 0, 255, 0, 100), 'n'); + LightGetHSB(&hue, &sat, nullptr); + + WSContentSend_P(HTTP_MSG_SLIDER_GRADIENT, // Hue + "b", // b - Unique HTML id + "#800", "#f00 5%,#ff0 20%,#0f0 35%,#0ff 50%,#00f 65%,#f0f 80%,#f00 95%,#800", // Hue colors + 2, // sl2 - Unique range HTML id - Used as source for Saturation end color + 1, 359, // Range valid Hue + hue, + 'h', 0); // h0 - Value id + + uint8_t dcolor = changeUIntScale(Settings.light_dimmer, 0, 100, 0, 255); + char scolor[8]; + snprintf_P(scolor, sizeof(scolor), PSTR("#%02X%02X%02X"), dcolor, dcolor, dcolor); // Saturation start color from Black to White + uint8_t red, green, blue; + LightHsToRgb(hue, 255, &red, &green, &blue); + snprintf_P(stemp, sizeof(stemp), PSTR("#%02X%02X%02X"), red, green, blue); // Saturation end color + + WSContentSend_P(HTTP_MSG_SLIDER_GRADIENT, // Saturation + "s", // s - Unique HTML id related to eb('s').style.background='linear-gradient(to right,rgb('+sl+'%%,'+sl+'%%,'+sl+'%%),hsl('+eb('sl2').value+',100%%,50%%))'; + scolor, stemp, // Brightness to max current color + 3, // sl3 - Unique range HTML id - Not used + 1, 100, // Range 1 to 100% + changeUIntScale(sat, 0, 255, 0, 100), + 'n', 0); // n0 - Value id } - // Dark - Bright &d related to lb("d", value) and WebGetArg("d", tmp, sizeof(tmp)); - WSContentSend_P(HTTP_MSG_SLIDER_GRADIENT, "b", "#000", "#fff", 1, 100, Settings.light_dimmer, 'd'); // Black to White + + WSContentSend_P(HTTP_MSG_SLIDER_GRADIENT, // Brightness - Black to White + "c", // c - Unique HTML id + "#000", "#fff", // Black to White + 4, // sl4 - Unique range HTML id - Used as source for Saturation begin color + 1, 100, // Range 1 to 100% + Settings.light_dimmer, + 'd', 0); // d0 - Value id is related to lc("d0", value) and WebGetArg("d0", tmp, sizeof(tmp)); } else { // Settings.flag3.pwm_multi_channels - SetOption68 1 - Enable multi-channels PWM instead of Color PWM uint32_t pwm_channels = light_subtype > LST_MAX ? LST_MAX : light_subtype; + stemp[0] = 'd'; stemp[1] = '0'; stemp[2] = '\0'; // d0 for (uint32_t i = 0; i < pwm_channels; i++) { - uint8_t index = (pwm_channels < 3) ? i +3 : i; - WSContentSend_P(HTTP_MSG_SLIDER_CHANNEL, "#fff", changeUIntScale(Settings.light_color[i], 0, 255, 0, 100), i+1); // Dark to Light + stemp[1]++; // d1 to d5 - Make unique ids + + WSContentSend_P(HTTP_MSG_SLIDER_GRADIENT, // Channel brightness - Black to White + stemp, // d1 to d5 - Unique HTML id + "#000", "#fff", // Black to White + i+1, // sl1 to sl5 - Unique range HTML id - Not used + 1, 100, // Range 1 to 100% + changeUIntScale(Settings.light_color[i], 0, 255, 0, 100), + 'd', i+1); // d1 to d5 - Value id } } // Settings.flag3.pwm_multi_channels } @@ -1136,7 +1161,7 @@ bool HandleRootStatusRefresh(void) } #endif // USE_SONOFF_IFAN } - WebGetArg("d", tmp, sizeof(tmp)); // 0 - 100 Dimmer value + WebGetArg("d0", tmp, sizeof(tmp)); // 0 - 100 Dimmer value if (strlen(tmp)) { snprintf_P(svalue, sizeof(svalue), PSTR(D_CMND_DIMMER " %s"), tmp); ExecuteWebCommand(svalue, SRC_WEBGUI); @@ -1150,17 +1175,17 @@ bool HandleRootStatusRefresh(void) ExecuteWebCommand(svalue, SRC_WEBGUI); } } - WebGetArg("t", tmp, sizeof(tmp)); // 153 - 500 Color temperature + WebGetArg("t0", tmp, sizeof(tmp)); // 153 - 500 Color temperature if (strlen(tmp)) { snprintf_P(svalue, sizeof(svalue), PSTR(D_CMND_COLORTEMPERATURE " %s"), tmp); ExecuteWebCommand(svalue, SRC_WEBGUI); } - WebGetArg("u", tmp, sizeof(tmp)); // 0 - 359 Hue value + WebGetArg("h0", tmp, sizeof(tmp)); // 0 - 359 Hue value if (strlen(tmp)) { snprintf_P(svalue, sizeof(svalue), PSTR(D_CMND_HSBCOLOR "1 %s"), tmp); ExecuteWebCommand(svalue, SRC_WEBGUI); } - WebGetArg("n", tmp, sizeof(tmp)); // 0 - 99 Saturation value + WebGetArg("n0", tmp, sizeof(tmp)); // 0 - 99 Saturation value if (strlen(tmp)) { snprintf_P(svalue, sizeof(svalue), PSTR(D_CMND_HSBCOLOR "2 %s"), tmp); ExecuteWebCommand(svalue, SRC_WEBGUI); diff --git a/tasmota/xdrv_04_light.ino b/tasmota/xdrv_04_light.ino index ab15dbbf0..3e06446ec 100644 --- a/tasmota/xdrv_04_light.ino +++ b/tasmota/xdrv_04_light.ino @@ -1173,7 +1173,7 @@ void LightInit(void) light_controller.setCTRGBLinked(ct_rgb_linked); } - if ((LST_SINGLE < Light.subtype) && Light.pwm_multi_channels) { + if ((LST_SINGLE <= Light.subtype) && Light.pwm_multi_channels) { // we treat each PWM channel as an independant one, hence we switch to light_controller.setPWMMultiChannel(true); Light.device = devices_present - Light.subtype + 1; // adjust if we also have relays @@ -1257,6 +1257,10 @@ uint32_t LightGetHSB(uint16_t *hue,uint8_t *sat, uint8_t *bri) { light_state.getHSB(hue, sat, bri); } +void LightHsToRgb(uint16_t hue, uint8_t sat, uint8_t *r_r, uint8_t *r_g, uint8_t *r_b) { + light_state.HsToRgb(hue, sat, r_r, r_g, r_b); +} + // If SetOption68 is set, get the brightness for a specific device uint8_t LightGetBri(uint8_t device) { uint8_t bri = 254; // default value if relay @@ -1363,6 +1367,7 @@ void LightState(uint8_t append) { char scolor[LIGHT_COLOR_SIZE]; char scommand[33]; + bool unlinked = !light_controller.isCTRGBLinked() && (Light.subtype >= LST_RGBW); // there are 2 power and dimmers for RGB and White if (append) { ResponseAppend_P(PSTR(",")); @@ -1370,8 +1375,18 @@ void LightState(uint8_t append) Response_P(PSTR("{")); } if (!Light.pwm_multi_channels) { - GetPowerDevice(scommand, Light.device, sizeof(scommand), Settings.flag.device_index_enable); // SetOption26 - Switch between POWER or POWER1 - ResponseAppend_P(PSTR("\"%s\":\"%s\",\"" D_CMND_DIMMER "\":%d"), scommand, GetStateText(Light.power), light_state.getDimmer()); + if (unlinked) { + // RGB and W are unlinked, we display the second Power/Dimmer + ResponseAppend_P(PSTR("\"" D_RSLT_POWER "%d\":\"%s\",\"" D_CMND_DIMMER "%d\":%d" + ",\"" D_RSLT_POWER "%d\":\"%s\",\"" D_CMND_DIMMER "%d\":%d"), + Light.device, GetStateText(Light.power & 1), Light.device, light_state.getDimmer(1), + Light.device + 1, GetStateText(Light.power & 2 ? 1 : 0), Light.device + 1, light_state.getDimmer(2)); + } else { + GetPowerDevice(scommand, Light.device, sizeof(scommand), Settings.flag.device_index_enable); // SetOption26 - Switch between POWER or POWER1 + ResponseAppend_P(PSTR("\"%s\":\"%s\",\"" D_CMND_DIMMER "\":%d"), scommand, GetStateText(Light.power & 1), + light_state.getDimmer()); + } + if (Light.subtype > LST_SINGLE) { ResponseAppend_P(PSTR(",\"" D_CMND_COLOR "\":\"%s\""), LightGetColor(scolor)); @@ -1423,8 +1438,7 @@ void LightState(uint8_t append) } } -void LightPreparePower(void) -{ +void LightPreparePower(power_t channels = 0xFFFFFFFF) { // 1 = only RGB, 2 = only CT, 3 = both RGB and CT #ifdef DEBUG_LIGHT AddLog_P2(LOG_LEVEL_DEBUG, "LightPreparePower power=%d Light.power=%d", power, Light.power); #endif @@ -1462,20 +1476,24 @@ void LightPreparePower(void) } } else { // RGB - if (light_state.getBriRGB() && !(Light.power & 1)) { - if (!Settings.flag.not_power_linked) { // SetOption20 - Control power in relation to Dimmer/Color/Ct changes - ExecuteCommandPower(Light.device, POWER_ON_NO_STATE, SRC_LIGHT); + if (channels & 1) { + if (light_state.getBriRGB() && !(Light.power & 1)) { + if (!Settings.flag.not_power_linked) { // SetOption20 - Control power in relation to Dimmer/Color/Ct changes + ExecuteCommandPower(Light.device, POWER_ON_NO_STATE, SRC_LIGHT); + } + } else if (!light_state.getBriRGB() && (Light.power & 1)) { + ExecuteCommandPower(Light.device, POWER_OFF_NO_STATE, SRC_LIGHT); } - } else if (!light_state.getBri() && (Light.power & 1)) { - ExecuteCommandPower(Light.device, POWER_OFF_NO_STATE, SRC_LIGHT); } // White CT - if (light_state.getBriCT() && !(Light.power & 2)) { - if (!Settings.flag.not_power_linked) { // SetOption20 - Control power in relation to Dimmer/Color/Ct changes - ExecuteCommandPower(Light.device + 1, POWER_ON_NO_STATE, SRC_LIGHT); + if (channels & 2) { + if (light_state.getBriCT() && !(Light.power & 2)) { + if (!Settings.flag.not_power_linked) { // SetOption20 - Control power in relation to Dimmer/Color/Ct changes + ExecuteCommandPower(Light.device + 1, POWER_ON_NO_STATE, SRC_LIGHT); + } + } else if (!light_state.getBriCT() && (Light.power & 2)) { + ExecuteCommandPower(Light.device + 1, POWER_OFF_NO_STATE, SRC_LIGHT); } - } else if (!light_state.getBri() && (Light.power & 2)) { - ExecuteCommandPower(Light.device + 1, POWER_OFF_NO_STATE, SRC_LIGHT); } } #ifdef USE_DOMOTICZ @@ -1594,11 +1612,11 @@ void LightAnimate(void) sleep = Settings.sleep; } } else { -#ifdef PWM_LIGHTSCHEME0_IGNORE_SLEEP - sleep = (LS_POWER == Settings.light_scheme) && (!Light.fade_running) ? Settings.sleep : 0; // If no animation then use sleep as is -#else - sleep = 0; -#endif // PWM_LIGHTSCHEME0_IGNORE_SLEEP + if (Settings.sleep > PWM_MAX_SLEEP) { + sleep = PWM_MAX_SLEEP; // set a maxumum value of 50 milliseconds to ensure that animations are smooth + } else { + sleep = Settings.sleep; // or keep the current sleep if it's lower than 50 + } switch (Settings.light_scheme) { case LS_POWER: light_controller.calcLevels(Light.new_color); @@ -1650,8 +1668,8 @@ void LightAnimate(void) LightApplyPower(Light.new_color, Light.power); // AddLog_P2(LOG_LEVEL_INFO, PSTR("last_color (%02X%02X%02X%02X%02X) new_color (%02X%02X%02X%02X%02X) power %d"), - // Light.last_color[0], Light.last_color[1], Light.last_color[2], Light.last_color[3], Light.last_color[4], - // Light.new_color[0], Light.new_color[1], Light.new_color[2], Light.new_color[3], Light.new_color[4], + // Light.last_color[0], Light.last_color[1], Light.last_color[2], Light.last_color[3], Light.last_color[4], + // Light.new_color[0], Light.new_color[1], Light.new_color[2], Light.new_color[3], Light.new_color[4], // Light.power // ); @@ -1983,7 +2001,7 @@ bool LightColorEntry(char *buffer, uint32_t buffer_length) memset(&Light.entry_color, 0x00, sizeof(Light.entry_color)); // erase all channels except if the last character is '=', #6799 while ((buffer_length > 0) && ('=' == buffer[buffer_length - 1])) { - buffer_length--; // remove all trailing '=' + buffer_length--; // remove all trailing '=' memcpy(&Light.entry_color, &Light.current_color, sizeof(Light.entry_color)); } if (strstr(buffer, ",") != nullptr) { // Decimal entry @@ -2071,7 +2089,7 @@ void CmndSupportColor(void) ResponseCmndIdxChar(scolor); } if (coldim) { - LightPreparePower(); + LightPreparePower(); // no parameter, recalculate Power for all channels } } @@ -2102,11 +2120,12 @@ void CmndWhite(void) void CmndChannel(void) { if ((XdrvMailbox.index >= Light.device) && (XdrvMailbox.index < Light.device + Light.subtype )) { - bool coldim = false; + uint32_t light_index = XdrvMailbox.index - Light.device; + power_t coldim = 0; // bit flag to update // Handle +/- special command if (1 == XdrvMailbox.data_len) { - uint8_t channel = changeUIntScale(Light.current_color[XdrvMailbox.index - Light.device],0,255,0,100); + uint8_t channel = changeUIntScale(Light.current_color[light_index],0,255,0,100); if ('+' == XdrvMailbox.data[0]) { XdrvMailbox.payload = (channel > 89) ? 100 : channel + 10; } else if ('-' == XdrvMailbox.data[0]) { @@ -2116,23 +2135,28 @@ void CmndChannel(void) // Set "Channel" directly - this allows Color and Direct PWM control to coexist if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload <= 100)) { - Light.current_color[XdrvMailbox.index - Light.device] = changeUIntScale(XdrvMailbox.payload,0,100,0,255); + Light.current_color[light_index] = changeUIntScale(XdrvMailbox.payload,0,100,0,255); if (Light.pwm_multi_channels) { - // if (!Settings.flag.not_power_linked) { // SetOption20 - Control power in relation to Dimmer/Color/Ct changes - // Light.power = Light.power | (1 << (XdrvMailbox.index - Light.device)); // ask to turn on channel - // } + coldim = 1 << light_index; // change the specified channel } else { - // if we change channels 1,2,3 then turn off CT mode (unless non-linked) - if ((XdrvMailbox.index <= 3) && (light_controller.isCTRGBLinked())) { - Light.current_color[3] = Light.current_color[4] = 0; + if (light_controller.isCTRGBLinked()) { + // if we change channels 1,2,3 then turn off CT mode (unless non-linked) + if ((light_index < 3) && (light_controller.isCTRGBLinked())) { + Light.current_color[3] = Light.current_color[4] = 0; + } else { + Light.current_color[0] = Light.current_color[1] = Light.current_color[2] = 0; + } + coldim = 1; + } else { + if (light_index < 3) { coldim = 1; } // RGB + else { coldim = 2; } // CT } } light_controller.changeChannels(Light.current_color); - coldim = true; } - ResponseCmndIdxNumber(changeUIntScale(Light.current_color[XdrvMailbox.index -1],0,255,0,100)); + ResponseCmndIdxNumber(changeUIntScale(Light.current_color[light_index],0,255,0,100)); if (coldim) { - LightPreparePower(); + LightPreparePower(coldim); } } } @@ -2179,7 +2203,7 @@ void CmndHsbColor(void) } if (validHSB) { light_controller.changeHSB(HSB[0], HSB[1], HSB[2]); - LightPreparePower(); + LightPreparePower(1); MqttPublishPrefixTopic_P(RESULT_OR_STAT, PSTR(D_CMND_COLOR)); } } else { @@ -2242,7 +2266,7 @@ void CmndColorTemperature(void) } if ((XdrvMailbox.payload >= 153) && (XdrvMailbox.payload <= 500)) { // https://developers.meethue.com/documentation/core-concepts light_controller.changeCTB(XdrvMailbox.payload, light_state.getBri()); - LightPreparePower(); + LightPreparePower(2); } else { ResponseCmndNumber(ct); } @@ -2272,17 +2296,19 @@ void CmndDimmer(void) if (light_controller.isCTRGBLinked()) { // normal state, linked RGB and CW light_controller.changeDimmer(XdrvMailbox.payload); + LightPreparePower(); } else { if (0 != XdrvMailbox.index) { light_controller.changeDimmer(XdrvMailbox.payload, XdrvMailbox.index); + LightPreparePower(1 << (XdrvMailbox.index - 1)); // recalculate only the target dimmer } else { // change both dimmers light_controller.changeDimmer(XdrvMailbox.payload, 1); light_controller.changeDimmer(XdrvMailbox.payload, 2); + LightPreparePower(); } } Light.update = true; - LightPreparePower(); } else { ResponseCmndNumber(dimmer); } diff --git a/tasmota/xsns_26_lm75ad.ino b/tasmota/xsns_26_lm75ad.ino index d1dd7bb3b..78a85ad2b 100644 --- a/tasmota/xsns_26_lm75ad.ino +++ b/tasmota/xsns_26_lm75ad.ino @@ -53,7 +53,11 @@ void LM75ADDetect(void) { for (uint32_t i = 0; i < sizeof(lm75ad_addresses); i++) { lm75ad_address = lm75ad_addresses[i]; - if (I2cActive(lm75ad_address)) { continue; } + if (I2cActive(lm75ad_address)) { + continue; } + if (!I2cSetDevice(lm75ad_address)) { + break; // do not make the next step without a confirmed device on the bus + } uint16_t buffer; if (I2cValidRead16(&buffer, lm75ad_address, LM75_THYST_REGISTER)) { if (buffer == 0x4B00) { diff --git a/tasmota/xsns_46_MLX90614.ino b/tasmota/xsns_46_MLX90614.ino index 3cc304f1f..dc5850789 100644 --- a/tasmota/xsns_46_MLX90614.ino +++ b/tasmota/xsns_46_MLX90614.ino @@ -31,58 +31,37 @@ #define MLX90614_TOBJ1 0x07 #define MLX90614_TOBJ2 0x08 -bool mlx_ready = false; -float obj_temp; -float amb_temp; +struct { + union { + uint16_t value; + uint32_t i2c_buf; + }; + float obj_temp; + float amb_temp; + bool ready = false; +} mlx90614; void MLX90614_Init(void) { if (!I2cSetDevice(I2_ADR_IRT)) { return; } - I2cSetActiveFound(I2_ADR_IRT, "MLX90614"); - mlx_ready = true; - - // not needed on tasmota - //Wire.begin(); - //delay(500); -} - -// return ir temp -// 0 = chip, 1 = object temperature -// * 0.02 - 273.15 -uint16_t read_irtmp(uint8_t flag) -{ - Wire.beginTransmission(I2_ADR_IRT); - if (!flag) { - Wire.write(MLX90614_TA); - } else { - Wire.write(MLX90614_TOBJ1); - } - Wire.endTransmission(false); - - Wire.requestFrom(I2_ADR_IRT, 3); - uint8_t low = Wire.read(); - uint8_t hig = Wire.read(); - Wire.read(); - - uint16_t val = ((uint16_t)hig << 8) | low; - return val; + mlx90614.ready = true; } void MLX90614_Every_Second(void) { - uint16_t uval = read_irtmp(1); - if (uval & 0x8000) { - obj_temp = -999; - } else { - obj_temp = ((float)uval * 0.02) - 273.15; - } - uval = read_irtmp(0); - if (uval & 0x8000) { - amb_temp = -999; - } else { - amb_temp = ((float)uval * 0.02) - 273.15; - } + mlx90614.i2c_buf = I2cRead24(I2_ADR_IRT, MLX90614_TOBJ1); + if (mlx90614.value & 0x8000) { + mlx90614.obj_temp = -999; + } else { + mlx90614.obj_temp = ((float)mlx90614.value * 0.02) - 273.15; + } + mlx90614.i2c_buf = I2cRead24(I2_ADR_IRT,MLX90614_TA); + if (mlx90614.value & 0x8000) { + mlx90614.amb_temp = -999; + } else { + mlx90614.amb_temp = ((float)mlx90614.value * 0.02) - 273.15; + } } #ifdef USE_WEBSERVER @@ -94,9 +73,9 @@ void MLX90614_Every_Second(void) void MLX90614_Show(uint8_t json) { char obj_tstr[16]; - dtostrfd(obj_temp, Settings.flag2.temperature_resolution, obj_tstr); + dtostrfd(mlx90614.obj_temp, Settings.flag2.temperature_resolution, obj_tstr); char amb_tstr[16]; - dtostrfd(amb_temp, Settings.flag2.temperature_resolution, amb_tstr); + dtostrfd(mlx90614.amb_temp, Settings.flag2.temperature_resolution, amb_tstr); if (json) { ResponseAppend_P(PSTR(",\"MLX90614\":{\"OBJTMP\":%s,\"AMBTMP\":%s}"), obj_tstr, amb_tstr); @@ -120,7 +99,7 @@ bool Xsns46(byte function) if (FUNC_INIT == function) { MLX90614_Init(); } - else if (mlx_ready) { + else if (mlx90614.ready) { switch (function) { case FUNC_EVERY_SECOND: MLX90614_Every_Second();