diff --git a/CHANGELOG.md b/CHANGELOG.md index 47ee6ba4b..5ddd7e164 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -13,6 +13,7 @@ All notable changes to this project will be documented in this file. ### Fixed - ESP32 save settings after OTA upload regression from v10.0.0.3 +- HX711 false readings by removing large deviations ## [11.0.0.4] 20220402 ### Added diff --git a/RELEASENOTES.md b/RELEASENOTES.md index 075f722ab..b76d9dfdf 100644 --- a/RELEASENOTES.md +++ b/RELEASENOTES.md @@ -153,6 +153,7 @@ The latter links can be used for OTA upgrades too like ``OtaUrl http://ota.tasmo - Wiegand 34-bit rfid reading and presentation [#14834](https://github.com/arendst/Tasmota/issues/14834) - Orno WE517 power meter phase 2 current reactive [#14841](https://github.com/arendst/Tasmota/issues/14841) - NeoPool NPBit and NPRead/NPReadL output +- HX711 false readings by removing large deviations - ESP32 save settings after OTA upload regression from v10.0.0.3 - ESP32 PowerOnState [#15084](https://github.com/arendst/Tasmota/issues/15084) diff --git a/tasmota/support.ino b/tasmota/support.ino index a40412bc1..2ee1a71b3 100644 --- a/tasmota/support.ino +++ b/tasmota/support.ino @@ -1990,9 +1990,6 @@ uint8_t TasShiftIn(uint8_t dataPin, uint8_t clockPin, uint8_t bitOrder) { } else { value |= digitalRead(dataPin) << (7 - i); } -#ifdef ESP32 - delayMicroseconds(1); -#endif digitalWrite(clockPin, LOW); #ifdef ESP32 delayMicroseconds(1); @@ -2008,9 +2005,6 @@ void TasShiftOut(uint8_t dataPin, uint8_t clockPin, uint8_t bitOrder, uint8_t va } else { digitalWrite(dataPin, !!(val & (1 << (7 - i)))); } -#ifdef ESP32 - delayMicroseconds(1); -#endif digitalWrite(clockPin, HIGH); #ifdef ESP32 delayMicroseconds(1); diff --git a/tasmota/xsns_34_hx711.ino b/tasmota/xsns_34_hx711.ino index 8570d9c3b..63f215f5f 100644 --- a/tasmota/xsns_34_hx711.ino +++ b/tasmota/xsns_34_hx711.ino @@ -65,11 +65,10 @@ enum HxCalibrationSteps { HX_CAL_END, HX_CAL_LIMBO, HX_CAL_FINISH, HX_CAL_FAIL, const char kHxCalibrationStates[] PROGMEM = D_HX_CAL_FAIL "|" D_HX_CAL_DONE "|" D_HX_CAL_REFERENCE "|" D_HX_CAL_REMOVE; struct HX { + long reads[HX_SAMPLES]; long weight = 0; long raw = 0; long last_weight = 0; - long sum_weight = 0; - long sum_raw = 0; long offset = 0; long scale = 1; long weight_diff = 0; @@ -87,8 +86,7 @@ struct HX { /*********************************************************************************************/ -bool HxIsReady(uint16_t timeout) -{ +bool HxIsReady(uint16_t timeout) { // A reading can take up to 100 mS or 600mS after power on uint32_t start = millis(); while ((digitalRead(Hx.pin_dout) == HIGH) && (millis() - start < timeout)) { @@ -97,8 +95,7 @@ bool HxIsReady(uint16_t timeout) return (digitalRead(Hx.pin_dout) == LOW); } -long HxRead(void) -{ +long HxRead(void) { if (!HxIsReady(HX_TIMEOUT)) { return -1; } uint8_t data[3] = { 0 }; @@ -135,22 +132,18 @@ long HxRead(void) /*********************************************************************************************/ -void HxResetPart(void) -{ +void HxResetPart(void) { Hx.tare_flg = true; - Hx.sum_weight = 0; Hx.sample_count = 0; Hx.last_weight = 0; } -void HxReset(void) -{ +void HxReset(void) { HxResetPart(); Settings->energy_frequency_calibration = 0; } -void HxCalibrationStateTextJson(uint8_t msg_id) -{ +void HxCalibrationStateTextJson(uint8_t msg_id) { char cal_text[30]; Hx.calibrate_msg = msg_id; @@ -159,8 +152,7 @@ void HxCalibrationStateTextJson(uint8_t msg_id) if (msg_id < 3) { MqttPublishPrefixTopicRulesProcess_P(RESULT_OR_STAT, PSTR("Sensor34")); } } -void SetWeightDelta() -{ +void SetWeightDelta(void) { // backwards compatible: restore old default value of 4 grams if (Settings->weight_change == 0) { Hx.weight_delta = 4; @@ -197,8 +189,7 @@ void SetWeightDelta() * Sensor34 9 - Set minimum delta to trigger JSON message \*********************************************************************************************/ -bool HxCommand(void) -{ +bool HxCommand(void) { bool serviced = true; bool show_parms = false; char argument[XdrvMailbox.data_len]; @@ -259,8 +250,8 @@ bool HxCommand(void) break; case 9: // WeightDelta if (strchr(XdrvMailbox.data, ',') != nullptr) { - Settings->weight_change = strtol(ArgV(argument, 2), nullptr, 10); - SetWeightDelta(); + Settings->weight_change = strtol(ArgV(argument, 2), nullptr, 10); + SetWeightDelta(); } show_parms = true; break; @@ -282,13 +273,11 @@ bool HxCommand(void) /*********************************************************************************************/ -long HxWeight(void) -{ +long HxWeight(void) { return (Hx.calibrate_step < HX_CAL_FAIL) ? Hx.weight : 0; } -void HxInit(void) -{ +void HxInit(void) { Hx.type = 0; if (PinUsed(GPIO_HX711_DAT) && PinUsed(GPIO_HX711_SCK)) { Hx.pin_sck = Pin(GPIO_HX711_SCK); @@ -313,21 +302,40 @@ void HxInit(void) } } -void HxEvery100mSecond(void) -{ +void HxEvery100mSecond(void) { long raw = HxRead(); if (-1 == raw) { return; } - Hx.sum_raw += raw; - Hx.sum_weight += raw; + if (Hx.sample_count < HX_SAMPLES) { // Test for HxSaveBeforeRestart() + Hx.reads[Hx.sample_count] = raw; + } Hx.sample_count++; if (HX_SAMPLES == Hx.sample_count) { - long average = Hx.sum_weight / Hx.sample_count; // grams - long raw_average = Hx.sum_raw / Hx.sample_count; // grams + Hx.sample_count = 0; + // Sort HX_SAMPLES + for (uint32_t i = 0; i < HX_SAMPLES; i++) { + for (uint32_t j = i + 1; j < HX_SAMPLES; j++) { + if (Hx.reads[j] > Hx.reads[i]) { + std::swap(Hx.reads[i], Hx.reads[j]); + } + } + } + // Drop two lows and two highs from average + long sum_raw = 0; + for (uint32_t i = 2; i < HX_SAMPLES -2; i++) { + sum_raw += Hx.reads[i]; + } + long average = sum_raw / (HX_SAMPLES -4); // grams + + if ((Hx.reads[0] < (average -4)) || (Hx.reads[9] > (average +4))) { + AddLog(LOG_LEVEL_DEBUG, PSTR("HX7: Range %d"), Hx.reads[9] - Hx.reads[0]); +// return; // Consider to drop samples with too much deviation (will fail too on quick load changes like filling a barrel!) + } + long value = average - Hx.offset; // grams Hx.weight = value / Hx.scale; // grams - Hx.raw = raw_average / Hx.scale; + Hx.raw = average / Hx.scale; if (Hx.weight < 0) { if (Settings->energy_frequency_calibration) { long difference = Settings->energy_frequency_calibration + Hx.weight; @@ -414,15 +422,10 @@ void HxEvery100mSecond(void) } } } - - Hx.sum_weight = 0; - Hx.sum_raw = 0; - Hx.sample_count = 0; } } -void HxSaveBeforeRestart(void) -{ +void HxSaveBeforeRestart(void) { Settings->energy_frequency_calibration = Hx.weight; Hx.sample_count = HX_SAMPLES +1; // Stop updating Hx.weight } @@ -436,8 +439,7 @@ const char HTTP_HX711_CAL[] PROGMEM = "{s}HX711 %s{m}{e}"; #endif // USE_WEBSERVER -void HxShow(bool json) -{ +void HxShow(bool json) { char scount[30] = { 0 }; uint16_t count = 0; @@ -496,8 +498,7 @@ const char HTTP_FORM_HX711[] PROGMEM = "
" "

" D_ITEM_WEIGHT " (" D_UNIT_KILOGRAM ")

"; -void HandleHxAction(void) -{ +void HandleHxAction(void) { if (!HttpCheckPriviledgedAccess()) { return; } AddLog(LOG_LEVEL_DEBUG, PSTR(D_LOG_HTTP D_CONFIGURE_HX711)); @@ -550,8 +551,7 @@ void HandleHxAction(void) * Interface \*********************************************************************************************/ -bool Xsns34(uint8_t function) -{ +bool Xsns34(uint8_t function) { bool result = false; if (Hx.type) {