Add command AdcParam

Add command AdcParam to control ADC0 Temperature and Light formula parameters
This commit is contained in:
Theo Arends 2019-05-24 12:28:09 +02:00
parent a8dc742f4e
commit 56615dce4e
4 changed files with 97 additions and 13 deletions

View File

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

View File

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

View File

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

View File

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