Fix Analog MQ exception

Fix Analog MQ exception (#17271)
This commit is contained in:
Theo Arends 2022-12-12 10:57:21 +01:00
parent d83119897e
commit 630987302a
3 changed files with 44 additions and 39 deletions

View File

@ -19,6 +19,7 @@ All notable changes to this project will be documented in this file.
- TasmotaSerial ``read(buffer, size)`` regression from v9.3.0
- RCSwitch exception 0/6 on some protocols (#17285)
- ESP32 exception 28 when RtcNtpServer is enabled on restart (#17338)
- Analog MQ exception 28 on restart (#17271)
### Removed

View File

@ -164,6 +164,7 @@ The latter links can be used for OTA upgrades too like ``OtaUrl http://ota.tasmo
- ModbusBridge buffer overflow [#16979](https://github.com/arendst/Tasmota/issues/16979)
- ModbusBridge baudrates over 76500 baud [#17106](https://github.com/arendst/Tasmota/issues/17106)
- SenseAir S8 module detection [#17033](https://github.com/arendst/Tasmota/issues/17033)
- Analog MQ exception 28 on restart [#17271](https://github.com/arendst/Tasmota/issues/17271)
- RCSwitch exception 0/6 on some protocols [#17285](https://github.com/arendst/Tasmota/issues/17285)
- ESP32 exception 28 when RtcNtpServer is enabled on restart [#17338](https://github.com/arendst/Tasmota/issues/17338)

View File

@ -386,46 +386,55 @@ uint16_t AdcGetLux(uint32_t idx) {
}
void AddSampleMq(uint32_t idx){
AddLog(LOG_LEVEL_DEBUG, PSTR(D_LOG_APPLICATION "Adding sample for mq-sensor"));
// AddLog(LOG_LEVEL_DEBUG, PSTR("ADC: Adding sample for mq-sensor"));
int _adc = AdcRead(Adc[idx].pin, 2);
// init af array at same value
if (Adc[idx].indexOfPointer==-1)
{
AddLog(LOG_LEVEL_DEBUG, PSTR(D_LOG_APPLICATION "Init samples for mq-sensor"));
for (int i = 0; i < ANALOG_MQ_SAMPLES; i ++)
if (Adc[idx].indexOfPointer==-1) {
// AddLog(LOG_LEVEL_DEBUG, PSTR("ADC: Init samples for mq-sensor"));
for (int i = 0; i < ANALOG_MQ_SAMPLES; i ++) {
Adc[idx].mq_samples[i] = _adc;
}
else
}
} else {
Adc[idx].mq_samples[Adc[idx].indexOfPointer] = _adc;
}
Adc[idx].indexOfPointer++;
if (Adc[idx].indexOfPointer==ANALOG_MQ_SAMPLES)
if (Adc[idx].indexOfPointer==ANALOG_MQ_SAMPLES) {
Adc[idx].indexOfPointer=0;
}
}
float AdcGetMq(uint32_t idx) {
AddLog(LOG_LEVEL_DEBUG, PSTR(D_LOG_APPLICATION "Getting value for mq-sensor"));
// AddLog(LOG_LEVEL_DEBUG, PSTR("ADC: Getting value for mq-sensor"));
float avg = 0.0;
float _RL = 10; //Value in KiloOhms
float _R0 = 10;
for (int i = 0; i < ANALOG_MQ_SAMPLES; i ++)
for (int i = 0; i < ANALOG_MQ_SAMPLES; i ++) {
avg += Adc[idx].mq_samples[i];
}
float voltage = (avg / ANALOG_MQ_SAMPLES) * ANALOG_V33 / ANALOG_RANGE;
float _RS_Calc = ((ANALOG_V33 * _RL) / voltage) -_RL; //Get value of RS in a gas
if (_RS_Calc < 0) _RS_Calc = 0; //No negative values accepted.
float _ratio = _RS_Calc / _R0; // Get ratio RS_gas/RS_air
float ppm= Adc[idx].param2/ANALOG_MQ_DECIMAL_MULTIPLIER*FastPrecisePow(_ratio, Adc[idx].param3/ANALOG_MQ_DECIMAL_MULTIPLIER); // <- Source excel analisis https://github.com/miguel5612/MQSensorsLib_Docs/tree/master/Internal_design_documents
if(ppm < 0) ppm = 0; //No negative values accepted or upper datasheet recomendation.
char ppm_chr[6];
dtostrfd(ppm, 2, ppm_chr);
AddLog(LOG_LEVEL_DEBUG, PSTR(D_LOG_APPLICATION "Ppm read. ADC-RAW: %2_f, ppm: %s,"), &voltage, ppm_chr);
float _RL = 10; // Value in KiloOhms
float _RS_Calc = ((ANALOG_V33 * _RL) / voltage) -_RL; // Get value of RS in a gas
if (_RS_Calc < 0) {
_RS_Calc = 0; // No negative values accepted.
}
float _R0 = 10;
float _ratio = _RS_Calc / _R0; // Get ratio RS_gas/RS_air
float ppm = Adc[idx].param2 / ANALOG_MQ_DECIMAL_MULTIPLIER * FastPrecisePow(_ratio, Adc[idx].param3 / ANALOG_MQ_DECIMAL_MULTIPLIER); // Source excel analisis https://github.com/miguel5612/MQSensorsLib_Docs/tree/master/Internal_design_documents
if (ppm < 0) { ppm = 0; } // No negative values accepted or upper datasheet recomendation.
if (ppm > 100000) { ppm = 100000; }
// AddLog(LOG_LEVEL_DEBUG, PSTR("ADC: Ppm read. ADC-RAW: %2_f, ppm: %2_f"), &voltage, &ppm);
return ppm;
}
float AdcGetPh(uint32_t idx) {
int adc = AdcRead(Adc[idx].pin, 2);
float y1 = (float)Adc[idx].param1 / ANALOG_PH_DECIMAL_MULTIPLIER;
int32_t x1 = Adc[idx].param2;
float y2 = (float)Adc[idx].param3 / ANALOG_PH_DECIMAL_MULTIPLIER;
@ -434,12 +443,7 @@ float AdcGetPh(uint32_t idx) {
float m = (y2 - y1) / (float)(x2 - x1);
float ph = m * (float)(adc - x1) + y1;
char phLow_chr[6];
char phHigh_chr[6];
dtostrfd(y1, 2, phLow_chr);
dtostrfd(y2, 2, phHigh_chr);
AddLog(LOG_LEVEL_DEBUG, PSTR(D_LOG_APPLICATION "Analog pH read. ADC-RAW: %d, cal-low(pH=ADC): %s=%d, cal-high(pH=ADC): %s=%d"), adc, phLow_chr, x1, phHigh_chr,x2);
// AddLog(LOG_LEVEL_DEBUG, PSTR("ADC: Analog pH read. ADC-RAW: %d, cal-low(pH=ADC): %2_f = %d, cal-high(pH=ADC): %2_f = %d"), adc, &y1, x1, &y2, x2);
return ph;
}
@ -666,10 +670,9 @@ void AdcShow(bool json) {
}
case ADC_PH: {
float ph = AdcGetPh(idx);
char ph_chr[6];
char ph_chr[FLOATSZ];
dtostrfd(ph, 2, ph_chr);
if (json) {
AdcShowContinuation(&jsonflg);
ResponseAppend_P(PSTR("\"pH%d\":%s"), idx + offset, ph_chr);
@ -682,11 +685,11 @@ void AdcShow(bool json) {
}
case ADC_MQ: {
float mq = AdcGetMq(idx);
char mq_chr[6];
char mq_chr[FLOATSZ];
dtostrfd(mq, 2, mq_chr);
float mqnumber =Adc[idx].param1;
char mqnumber_chr[6];
char mqnumber_chr[FLOATSZ];
dtostrfd(mqnumber, 0, mqnumber_chr);
if (json) {
@ -754,8 +757,8 @@ void CmndAdcParam(void) {
Adc[idx].param2 = strtol(ArgV(argument, 3), nullptr, 10);
Adc[idx].param3 = phHigh * ANALOG_PH_DECIMAL_MULTIPLIER;
Adc[idx].param4 = strtol(ArgV(argument, 5), nullptr, 10);
AddLog(LOG_LEVEL_INFO, PSTR(D_LOG_APPLICATION "Analog pH probe calibrated. cal-low(pH=ADC) %2_f=%d, cal-high(pH=ADC) %2_f=%d"),
&phLow, Adc[idx].param2, &phHigh, Adc[idx].param4);
// AddLog(LOG_LEVEL_INFO, PSTR("ADC: Analog pH probe calibrated. cal-low(pH=ADC) %2_f = %d, cal-high(pH=ADC) %2_f = %d"), &phLow, Adc[idx].param2, &phHigh, Adc[idx].param4);
}
if (ADC_CT_POWER == XdrvMailbox.payload) {
if (((1 == Adc[idx].param1) & CT_FLAG_ENERGY_RESET) > 0) {
@ -796,11 +799,11 @@ void CmndAdcParam(void) {
ratioMQCleanAir=15;
}
}
Adc[idx].param2 = (int)(a * ANALOG_MQ_DECIMAL_MULTIPLIER); // Exponential regression
Adc[idx].param3 = (int)(b * ANALOG_MQ_DECIMAL_MULTIPLIER); // Exponential regression
Adc[idx].param4 = (int)(ratioMQCleanAir * ANALOG_MQ_DECIMAL_MULTIPLIER); // Exponential regression
AddLog(LOG_LEVEL_INFO, PSTR(D_LOG_APPLICATION "Analog MQ reset: mq%d, a=%2_f, b=%2_f, ratioMQCleanAir=%2_f"),
Adc[idx].param1, &a, &b, &ratioMQCleanAir);
Adc[idx].param2 = (int)(a * ANALOG_MQ_DECIMAL_MULTIPLIER); // Exponential regression
Adc[idx].param3 = (int)(b * ANALOG_MQ_DECIMAL_MULTIPLIER); // Exponential regression
Adc[idx].param4 = (int)(ratioMQCleanAir * ANALOG_MQ_DECIMAL_MULTIPLIER); // Exponential regression
// AddLog(LOG_LEVEL_INFO, PSTR("ADC: MQ reset mq%d, a = %2_f, b = %2_f, ratioMQCleanAir = %2_f"), Adc[idx].param1, &a, &b, &ratioMQCleanAir);
}
} else { // Set default values based on current adc type
// AdcParam 2
@ -829,7 +832,7 @@ void CmndAdcParam(void) {
if (value % 10) { break; }
value /= 10;
}
char param3[33];
char param3[FLOATSZ];
dtostrfd(((double)Adc[idx].param3)/10000, precision, param3);
ResponseAppend_P(PSTR(",%s,%d"), param3, Adc[idx].param4);
}