diff --git a/sonoff/_changelog.ino b/sonoff/_changelog.ino index 58e0edbb2..0a96b4630 100644 --- a/sonoff/_changelog.ino +++ b/sonoff/_changelog.ino @@ -5,6 +5,7 @@ * Add extended LED power control using command LedPowerX where X is 1 to 4. Enabled when "LedLink(i)" is configured too (#5709) * Fix core 2.5.x ISR not in IRAM exception (#5837) * Add support for VL53L0x time of flight sensor. Might interfere with TSL2561 using same I2C address (#5845) + * Add command AdcParam to control ADC0 Temperature and Light formula parameters * * 6.5.0.11 20190517 * Add command SetOption64 0/1 to switch between "-" or "_" as sensor index separator impacting DS18X20, DHT, BMP and SHT3X sensor names (#5689) diff --git a/sonoff/settings.h b/sonoff/settings.h index 03529e8fa..5f6350116 100644 --- a/sonoff/settings.h +++ b/sonoff/settings.h @@ -210,8 +210,9 @@ struct SYSCFG { uint8_t webserver; // 1AB uint8_t weblog_level; // 1AC uint8_t mqtt_fingerprint[2][20]; // 1AD + uint8_t adc_param_type; // 1D5 - uint8_t free_1D5[19]; // 1D5 Free since 5.12.0e + uint8_t free_1D6[18]; // 1D6 Free since 5.12.0e uint8_t sps30_inuse_hours; // 1E8 char mqtt_host[33]; // 1E9 - Keep together with below as being copied as one chunck with reset 6 @@ -336,7 +337,10 @@ struct SYSCFG { uint8_t free_774[32]; // 774 - uint32_t drivers[3]; // 794 +// uint32_t drivers[3]; // 794 - 6.5.0.12 replaced by below three entries + uint32_t adc_param1; // 794 + uint32_t adc_param2; // 798 + int adc_param3; // 79C uint32_t monitors; // 7A0 uint32_t sensors[3]; // 7A4 uint32_t displays; // 7B0 diff --git a/sonoff/settings.ino b/sonoff/settings.ino index a8445b232..0adc1ab9e 100644 --- a/sonoff/settings.ino +++ b/sonoff/settings.ino @@ -908,7 +908,7 @@ void SettingsDefaultSet2(void) SettingsDefaultWebColor(); - memset(&Settings.drivers, 0xFF, 32); // Enable all possible monitors, displays, drivers and sensors + memset(&Settings.monitors, 0xFF, 20); // Enable all possible monitors, displays and sensors } /********************************************************************************************/ @@ -1129,7 +1129,7 @@ void SettingsDelta(void) Settings.timezone_minutes = 0; } if (Settings.version < 0x06030004) { - memset(&Settings.drivers, 0xFF, 32); // Enable all possible monitors, displays, drivers and sensors + memset(&Settings.monitors, 0xFF, 20); // Enable all possible monitors, displays and sensors } if (Settings.version < 0x0603000E) { Settings.flag2.calc_resolution = CALC_RESOLUTION; diff --git a/sonoff/xsns_02_analog.ino b/sonoff/xsns_02_analog.ino index 85560e3d3..0fe674c3a 100644 --- a/sonoff/xsns_02_analog.ino +++ b/sonoff/xsns_02_analog.ino @@ -35,21 +35,40 @@ // 3V3 --- ANALOG_NTC_BRIDGE_RESISTANCE ---v--- NTC --- Gnd // | // ADC0 -#define ANALOG_NTC_BRIDGE_RESISTANCE 32000.0 // NTC Voltage bridge resistor -#define ANALOG_NTC_RESISTANCE 10000.0 // NTC Resistance -#define ANALOG_NTC_B_COEFFICIENT 3350.0 // NTC Beta Coefficient +#define ANALOG_NTC_BRIDGE_RESISTANCE 32000 // NTC Voltage bridge resistor +#define ANALOG_NTC_RESISTANCE 10000 // NTC Resistance +#define ANALOG_NTC_B_COEFFICIENT 3350 // NTC Beta Coefficient // LDR parameters // 3V3 --- LDR ---v--- ANALOG_LDR_BRIDGE_RESISTANCE --- Gnd // | // ADC0 -#define ANALOG_LDR_BRIDGE_RESISTANCE 10000.0 // LDR Voltage bridge resistor +#define ANALOG_LDR_BRIDGE_RESISTANCE 10000 // LDR Voltage bridge resistor #define ANALOG_LDR_LUX_CALC_SCALAR 12518931 // Experimental -#define ANALOG_LDR_LUX_CALC_EXPONENT -1.405 // Experimental +#define ANALOG_LDR_LUX_CALC_EXPONENT -1.4050 // Experimental uint16_t adc_last_value = 0; float adc_temp = 0; +void AdcInit(void) +{ + if ((Settings.adc_param_type != my_adc0) || (Settings.adc_param1 > 1000000) || (Settings.adc_param1 < 100)) { + if (ADC0_TEMP == my_adc0) { + // Default Shelly 2.5 and 1PM parameters + Settings.adc_param_type = ADC0_TEMP; + Settings.adc_param1 = ANALOG_NTC_BRIDGE_RESISTANCE; + Settings.adc_param2 = ANALOG_NTC_RESISTANCE; + Settings.adc_param3 = ANALOG_NTC_B_COEFFICIENT * 10000; + } + else if (ADC0_LIGHT == my_adc0) { + Settings.adc_param_type = ADC0_LIGHT; + Settings.adc_param1 = ANALOG_LDR_BRIDGE_RESISTANCE; + Settings.adc_param2 = ANALOG_LDR_LUX_CALC_SCALAR; + Settings.adc_param3 = ANALOG_LDR_LUX_CALC_EXPONENT * 10000; + } + } +} + uint16_t AdcRead(uint8_t factor) { // factor 1 = 2 samples @@ -88,8 +107,8 @@ uint16_t AdcGetLux() // Source: https://www.allaboutcircuits.com/projects/design-a-luxmeter-using-a-light-dependent-resistor/ double resistorVoltage = ((double)adc / 1023) * ANALOG_V33; double ldrVoltage = ANALOG_V33 - resistorVoltage; - double ldrResistance = ldrVoltage / resistorVoltage * ANALOG_LDR_BRIDGE_RESISTANCE; - double ldrLux = ANALOG_LDR_LUX_CALC_SCALAR * FastPrecisePow(ldrResistance, ANALOG_LDR_LUX_CALC_EXPONENT); + double ldrResistance = ldrVoltage / resistorVoltage * (double)Settings.adc_param1; + double ldrLux = (double)Settings.adc_param2 * FastPrecisePow(ldrResistance, (double)Settings.adc_param3 / 10000); return (uint16_t)ldrLux; } @@ -99,12 +118,66 @@ void AdcEverySecond(void) if (ADC0_TEMP == my_adc0) { int adc = AdcRead(2); // Steinhart-Hart equation for thermistor as temperature sensor - double Rt = (adc * ANALOG_NTC_BRIDGE_RESISTANCE) / (1024.0 * ANALOG_V33 - (double)adc); - double T = ANALOG_NTC_B_COEFFICIENT / (ANALOG_NTC_B_COEFFICIENT / ANALOG_T0 + TaylorLog(Rt / ANALOG_NTC_RESISTANCE)); + double Rt = (adc * Settings.adc_param1) / (1024.0 * ANALOG_V33 - (double)adc); + double BC = (double)Settings.adc_param3 / 10000; + double T = BC / (BC / ANALOG_T0 + TaylorLog(Rt / (double)Settings.adc_param2)); adc_temp = ConvertTemp(TO_CELSIUS(T)); } } +/*********************************************************************************************\ + * Commands +\*********************************************************************************************/ + +#define D_CMND_ADCPARAM "AdcParam" +enum AdcCommands { CMND_ADCPARAM }; +const char kAdcCommands[] PROGMEM = D_CMND_ADCPARAM; + +bool AdcCommand(void) +{ + char command[CMDSZ]; + bool serviced = true; + + int command_code = GetCommandCode(command, sizeof(command), XdrvMailbox.topic, kAdcCommands); + if (CMND_ADCPARAM == command_code) { + if (XdrvMailbox.data_len) { + if ((ADC0_TEMP == XdrvMailbox.payload) || (ADC0_LIGHT == XdrvMailbox.payload)) { +// if ((XdrvMailbox.payload == my_adc0) && ((ADC0_TEMP == my_adc0) || (ADC0_LIGHT == my_adc0))) { + if (strstr(XdrvMailbox.data, ",") != nullptr) { // Process parameter entry + char sub_string[XdrvMailbox.data_len +1]; + // AdcParam 2, 32000, 10000, 3350 + // AdcParam 3, 10000, 12518931, -1.405 + Settings.adc_param_type = XdrvMailbox.payload; +// Settings.adc_param_type = my_adc0; + Settings.adc_param1 = strtol(subStr(sub_string, XdrvMailbox.data, ",", 2), nullptr, 10); + Settings.adc_param2 = strtol(subStr(sub_string, XdrvMailbox.data, ",", 3), nullptr, 10); + Settings.adc_param3 = (int)(CharToDouble(subStr(sub_string, XdrvMailbox.data, ",", 4)) * 10000); + } else { // Set default values based on current adc type + // AdcParam 2 + // AdcParam 3 + Settings.adc_param_type = 0; + AdcInit(); + } + } + } + + // AdcParam + int value = Settings.adc_param3; + uint8_t precision; + for (precision = 4; precision > 0; precision--) { + if (value % 10) { break; } + value /= 10; + } + char param3[33]; + dtostrfd(((double)Settings.adc_param3)/10000, precision, param3); + Response_P(PSTR("{\"" D_CMND_ADCPARAM "\":[%d,%d,%d,%s]}"), + Settings.adc_param_type, Settings.adc_param1, Settings.adc_param2, param3); + } + else serviced = false; // Unknown command + + return serviced; +} + void AdcShow(bool json) { if (ADC0_INPUT == my_adc0) { @@ -176,6 +249,12 @@ bool Xsns02(uint8_t function) case FUNC_EVERY_SECOND: AdcEverySecond(); break; + case FUNC_INIT: + AdcInit(); + break; + case FUNC_COMMAND: + result = AdcCommand(); + break; case FUNC_JSON_APPEND: AdcShow(1); break;