Refactor HX711 memory use

This commit is contained in:
Theo Arends 2024-09-10 15:59:25 +02:00
parent 07eb51764a
commit d8f01ed4c0
3 changed files with 191 additions and 178 deletions

View File

@ -5,7 +5,7 @@ All notable changes to this project will be documented in this file.
## [14.2.0.4] ## [14.2.0.4]
### Added ### Added
- HX711 optional calibration precision option on command ``Sensor34 2 <weight in gram> <precision>`` where `<precision>` is 1 to 10 (#13983) - HX711 optional calibration precision option on command ``Sensor34 2 <weight in gram> <precision>`` where `<precision>` is 1 to 20 (#13983)
- Matter support for Zigbee Occupancy and Light 0/1/2 (OnOff / Dimmer / White Color Temperature) (#22110) - Matter support for Zigbee Occupancy and Light 0/1/2 (OnOff / Dimmer / White Color Temperature) (#22110)
- KNX additional KnxTx functions and define KNX_USE_DPT9 (#22071) - KNX additional KnxTx functions and define KNX_USE_DPT9 (#22071)

View File

@ -122,7 +122,7 @@ The latter links can be used for OTA upgrades too like ``OtaUrl https://ota.tasm
## Changelog v14.2.0.4 ## Changelog v14.2.0.4
### Added ### Added
- Command ``SetOption69 1`` to enable Serial Bridge inverted Receive [#22000](https://github.com/arendst/Tasmota/issues/22000) - Command ``SetOption69 1`` to enable Serial Bridge inverted Receive [#22000](https://github.com/arendst/Tasmota/issues/22000)
- HX711 optional calibration precision option on command ``Sensor34 2 <weight in gram> <precision>`` where `<precision>` is 1 to 10 [#13983](https://github.com/arendst/Tasmota/issues/13983) - HX711 optional calibration precision option on command ``Sensor34 2 <weight in gram> <precision>`` where `<precision>` is 1 to 20 [#13983](https://github.com/arendst/Tasmota/issues/13983)
- Energy command ``PowerSet 60,230`` to calibrate both Current and Power with known resistive load of 60W at 230V using calibrated Voltage - Energy command ``PowerSet 60,230`` to calibrate both Current and Power with known resistive load of 60W at 230V using calibrated Voltage
- Energy command ``CurrentSet 60,230`` to calibrate both Power and Current with known resistive load of 60W at 230V using calibrated Voltage - Energy command ``CurrentSet 60,230`` to calibrate both Power and Current with known resistive load of 60W at 230V using calibrated Voltage
- Energy Log level 4 message when (Calculated) Apparent Power is less than Active Power indicating wrong calibration [#20653](https://github.com/arendst/Tasmota/issues/20653) - Energy Log level 4 message when (Calculated) Apparent Power is less than Active Power indicating wrong calibration [#20653](https://github.com/arendst/Tasmota/issues/20653)

View File

@ -44,7 +44,7 @@
#define HX_SCALE 120 // Default result of measured weight / reference weight when scale is 1 #define HX_SCALE 120 // Default result of measured weight / reference weight when scale is 1
#endif #endif
#ifndef HX711_CAL_PRECISION #ifndef HX711_CAL_PRECISION
#define HX711_CAL_PRECISION 1 // When calibration is to course, raise this value. #define HX711_CAL_PRECISION 1 // When calibration is to course, raise this value to max 20 (otherwise uint32_t overflow)
#endif #endif
@ -70,40 +70,40 @@
#define D_JSON_WEIGHT_ABSC_B "AbsConvB" #define D_JSON_WEIGHT_ABSC_B "AbsConvB"
enum HxCalibrationSteps { HX_CAL_END, HX_CAL_LIMBO, HX_CAL_FINISH, HX_CAL_FAIL, HX_CAL_DONE, HX_CAL_FIRST, HX_CAL_RESET, HX_CAL_START }; enum HxCalibrationSteps { HX_CAL_END, HX_CAL_LIMBO, HX_CAL_FINISH, HX_CAL_FAIL, HX_CAL_DONE, HX_CAL_FIRST, HX_CAL_RESET, HX_CAL_START };
enum HxCalibrationMsgs { HX_MSG_CAL_FAIL, HX_MSG_CAL_DONE, HX_MSG_CAL_REFERENCE, HX_MSG_CAL_REMOVE };
const char kHxCalibrationStates[] PROGMEM = D_HX_CAL_FAIL "|" D_HX_CAL_DONE "|" D_HX_CAL_REFERENCE "|" D_HX_CAL_REMOVE; const char kHxCalibrationStates[] PROGMEM = D_HX_CAL_FAIL "|" D_HX_CAL_DONE "|" D_HX_CAL_REFERENCE "|" D_HX_CAL_REMOVE;
struct HX { typedef struct Hx_t {
long reads[HX_SAMPLES]; long reads[HX_SAMPLES];
long raw_empty = 0; long raw_empty;
long raw_absolute; long raw_absolute;
long raw = 0; long raw;
long weight = 0; long weight;
long last_weight = 0; long last_weight;
long offset = 0; long offset;
long scale = 1; long scale;
long weight_diff = 0; long weight_diff;
uint8_t type = 1; uint16_t weight_delta;
uint8_t sample_count = 0; uint8_t sample_count;
uint8_t calibrate_step = HX_CAL_END; uint8_t calibrate_step;
uint8_t calibrate_timer = 0; uint8_t calibrate_timer;
uint8_t calibrate_msg = 0; uint8_t calibrate_msg;
int8_t pin_sck; int8_t pin_sck;
int8_t pin_dout; int8_t pin_dout;
bool tare_flg = false; bool tare_flg;
bool weight_changed = false; bool weight_changed;
uint16_t weight_delta = 4; } Hx_t;
} Hx; Hx_t* Hx = nullptr;
/*********************************************************************************************/ /*********************************************************************************************/
bool HxIsReady(uint16_t timeout) { bool HxIsReady(uint16_t timeout) {
// A reading can take up to 100 mS or 600mS after power on // A reading can take up to 100 mS or 600mS after power on
uint32_t start = millis(); uint32_t start = millis();
while ((digitalRead(Hx.pin_dout) == HIGH) && (millis() - start < timeout)) { while ((digitalRead(Hx->pin_dout) == HIGH) && (millis() - start < timeout)) {
yield(); yield();
} }
return (digitalRead(Hx.pin_dout) == LOW); return (digitalRead(Hx->pin_dout) == LOW);
} }
long HxRead(void) { long HxRead(void) {
@ -113,17 +113,17 @@ long HxRead(void) {
uint8_t filler = 0x00; uint8_t filler = 0x00;
// pulse the clock pin 24 times to read the data // pulse the clock pin 24 times to read the data
data[2] = TasShiftIn(Hx.pin_dout, Hx.pin_sck, MSBFIRST); data[2] = TasShiftIn(Hx->pin_dout, Hx->pin_sck, MSBFIRST);
data[1] = TasShiftIn(Hx.pin_dout, Hx.pin_sck, MSBFIRST); data[1] = TasShiftIn(Hx->pin_dout, Hx->pin_sck, MSBFIRST);
data[0] = TasShiftIn(Hx.pin_dout, Hx.pin_sck, MSBFIRST); data[0] = TasShiftIn(Hx->pin_dout, Hx->pin_sck, MSBFIRST);
// set the channel and the gain factor for the next reading using the clock pin // set the channel and the gain factor for the next reading using the clock pin
for (unsigned int i = 0; i < HX_GAIN_128; i++) { for (unsigned int i = 0; i < HX_GAIN_128; i++) {
digitalWrite(Hx.pin_sck, HIGH); digitalWrite(Hx->pin_sck, HIGH);
#ifdef ESP32 #ifdef ESP32
delayMicroseconds(1); delayMicroseconds(1);
#endif #endif
digitalWrite(Hx.pin_sck, LOW); digitalWrite(Hx->pin_sck, LOW);
#ifdef ESP32 #ifdef ESP32
delayMicroseconds(1); delayMicroseconds(1);
#endif #endif
@ -144,36 +144,34 @@ long HxRead(void) {
/*********************************************************************************************/ /*********************************************************************************************/
void HxTareInit(void) { void HxTareInit(void) {
Hx.offset = (Settings->weight_user_tare != 0) ? Settings->weight_user_tare * Hx.scale : Settings->weight_offset; Hx->offset = (Settings->weight_user_tare != 0) ? Settings->weight_user_tare * Hx->scale : Settings->weight_offset;
if (0 == Hx.offset) { if (0 == Hx->offset) {
Hx.tare_flg = true; Hx->tare_flg = true;
} }
} }
void HxCalibrationStateTextJson(uint8_t msg_id) { void HxCalibrationStateTextJson(uint8_t msg_id) {
char cal_text[30]; char cal_text[30];
Hx.calibrate_msg = msg_id; Hx->calibrate_msg = msg_id;
Response_P(S_JSON_SENSOR_INDEX_SVALUE, XSNS_34, GetTextIndexed(cal_text, sizeof(cal_text), Hx.calibrate_msg, kHxCalibrationStates)); Response_P(S_JSON_SENSOR_INDEX_SVALUE, XSNS_34, GetTextIndexed(cal_text, sizeof(cal_text), Hx->calibrate_msg, kHxCalibrationStates));
if (msg_id < 3) { MqttPublishPrefixTopicRulesProcess_P(RESULT_OR_STAT, PSTR("Sensor34")); } if (msg_id < HX_MSG_CAL_REMOVE) { MqttPublishPrefixTopicRulesProcess_P(RESULT_OR_STAT, PSTR("Sensor34")); }
} }
void SetWeightDelta(void) { void SetWeightDelta(void) {
// backwards compatible: restore old default value of 4 grams
if (Settings->weight_change == 0) { if (Settings->weight_change == 0) {
Hx.weight_delta = 4; // backwards compatible: restore old default value of 4 grams
return; Hx->weight_delta = 4;
} }
else if (Settings->weight_change > 100) {
// map upper values 101-255 to // map upper values 101-255 to
if (Settings->weight_change > 100) { Hx->weight_delta = (Settings->weight_change - 100) * 10 + 100;
Hx.weight_delta = (Settings->weight_change - 100) * 10 + 100;
return;
} }
else {
// map 1..100 to 0..99 grams // map 1..100 to 0..99 grams
Hx.weight_delta = Settings->weight_change - 1; Hx->weight_delta = Settings->weight_change - 1;
}
} }
/*********************************************************************************************\ /*********************************************************************************************\
@ -203,64 +201,72 @@ void SetWeightDelta(void) {
bool HxCommand(void) { bool HxCommand(void) {
bool serviced = true; bool serviced = true;
bool show_parms = true; bool show_parms = true;
char argument[XdrvMailbox.data_len];
long value = 0;
for (uint32_t ca = 0; ca < XdrvMailbox.data_len; ca++) { for (uint32_t ca = 0; ca < XdrvMailbox.data_len; ca++) {
if ((' ' == XdrvMailbox.data[ca]) || ('=' == XdrvMailbox.data[ca])) { XdrvMailbox.data[ca] = ','; } if ((' ' == XdrvMailbox.data[ca]) || ('=' == XdrvMailbox.data[ca])) { XdrvMailbox.data[ca] = ','; }
} }
bool any_value = (ArgC() > 1); bool any_value = (ArgC() > 1);
if (any_value) { value = strtol(ArgV(argument, 2), nullptr, 10); } long value;
char argument[32];
if (any_value) {
value = strtol(ArgV(argument, 2), nullptr, 10);
}
switch (XdrvMailbox.payload) { switch (XdrvMailbox.payload) {
case 1: // Reset scale case 1: // Reset scale
if (0 == Settings->weight_user_tare) { if (0 == Settings->weight_user_tare) {
Hx.tare_flg = true; Hx->tare_flg = true;
Response_P(S_JSON_SENSOR_INDEX_SVALUE, XSNS_34, "Reset"); Response_P(S_JSON_SENSOR_INDEX_SVALUE, XSNS_34, "Reset");
} }
show_parms = false; show_parms = false;
break; break;
case 2: // Calibrate case 2: // Calibrate in gram and precision 1 to 10
if (any_value) { if (any_value) {
Settings->weight_reference = value; Settings->weight_reference = (value && (value < (Settings->weight_max * 1000))) ? value : HX_REFERENCE;
if (ArgC() > 2) { if (ArgC() > 2) {
value = strtol(ArgV(argument, 3), nullptr, 10); value = strtol(ArgV(argument, 3), nullptr, 10);
Settings->weight_precision = (value && (value < 11)) ? value : HX711_CAL_PRECISION; Settings->weight_precision = (value && (value <= 20)) ? value : HX711_CAL_PRECISION;
} }
} }
Hx.scale = 1; // Uncalibrated Hx->scale = 1; // Uncalibrated
Hx.sample_count = 0; Hx->sample_count = 0;
Hx.offset = 0; // Disable tare while calibrating Hx->offset = 0; // Disable tare while calibrating
Hx.calibrate_step = HX_CAL_START; Hx->calibrate_step = HX_CAL_START;
Hx.calibrate_timer = 1; Hx->calibrate_timer = 1;
// HxCalibrationStateTextJson(3); // D_HX_CAL_REMOVE // HxCalibrationStateTextJson(HX_MSG_CAL_REMOVE);
HxCalibrationStateTextJson(2); // D_HX_CAL_REFERENCE HxCalibrationStateTextJson(HX_MSG_CAL_REFERENCE);
show_parms = false; show_parms = false;
break; break;
case 3: // WeightRef to user reference case 3: // WeightRef to user reference in gram
if (any_value) { Settings->weight_reference = value; } if (any_value) {
Settings->weight_reference = (value && (value < (Settings->weight_max * 1000))) ? value : HX_REFERENCE;
}
break; break;
case 4: // WeightCal to user calculated value case 4: // WeightCal to user calculated value
if (any_value) { if (any_value) {
Settings->weight_calibration = value; // Allow zero for re-init Settings->weight_calibration = value; // Allow zero for re-init
Hx.scale = (value) ? Settings->weight_calibration : 1; // Fix divide by zero Hx->scale = (value) ? Settings->weight_calibration : 1; // Fix divide by zero
} }
break; break;
case 5: // WeightMax case 5: // WeightMax in kg
if (any_value) { Settings->weight_max = value; } if (any_value) {
Settings->weight_max = (value) ? value : HX_MAX_WEIGHT / 1000;
}
break; break;
case 6: // WeightItem case 6: // WeightItem in gram
if (strchr(XdrvMailbox.data, ',') != nullptr) { if (any_value) {
Settings->weight_item = (unsigned long)(CharToFloat(ArgV(argument, 2)) * 10); Settings->weight_item = (unsigned long)(CharToFloat(ArgV(argument, 2)) * 10);
} }
break; break;
// case 7: // WeightSave // case 7: // WeightSave
// Settings->energy_frequency_calibration = Hx.weight; // Settings->energy_frequency_calibration = Hx->weight;
// Response_P(S_JSON_SENSOR_INDEX_SVALUE, XSNS_34, PSTR(D_JSON_DONE)); // Response_P(S_JSON_SENSOR_INDEX_SVALUE, XSNS_34, PSTR(D_JSON_DONE));
// show_parms = false; // show_parms = false;
// break; // break;
case 8: // Json on weight change case 8: // Json on weight change
if (any_value) { Settings->SensorBits1.hx711_json_weight_change = value &1; } if (any_value) {
Settings->SensorBits1.hx711_json_weight_change = value &1;
}
break; break;
case 9: // WeightDelta case 9: // WeightDelta
if (any_value) { if (any_value) {
@ -270,16 +276,20 @@ bool HxCommand(void) {
break; break;
case 10: // Fixed (user) tare case 10: // Fixed (user) tare
if (any_value) { if (any_value) {
Settings->weight_user_tare = (1 == value) ? Hx.raw : value; Settings->weight_user_tare = (1 == value) ? Hx->raw : value;
HxTareInit(); HxTareInit();
Hx.weight_diff = Hx.weight_delta +1; // Force display of current weight Hx->weight_diff = Hx->weight_delta +1; // Force display of current weight
} }
break; break;
case 11: // AbsoluteConversion, A case 11: // AbsoluteConversion, A
if (any_value) { Settings->weight_absconv_a = value; } if (any_value) {
Settings->weight_absconv_a = value;
}
break; break;
case 12: // AbsoluteConversion, B case 12: // AbsoluteConversion, B
if (any_value) { Settings->weight_absconv_b = value; } if (any_value) {
Settings->weight_absconv_b = value;
}
break; break;
} }
@ -303,19 +313,21 @@ bool HxCommand(void) {
/*********************************************************************************************/ /*********************************************************************************************/
long HxWeight(void) { long HxWeight(void) {
return (Hx.calibrate_step < HX_CAL_FAIL) ? Hx.weight : 0; 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)) { if (PinUsed(GPIO_HX711_DAT) && PinUsed(GPIO_HX711_SCK)) {
Hx.pin_sck = Pin(GPIO_HX711_SCK); Hx = (Hx_t*)calloc(sizeof(Hx_t), 1); // Need calloc to reset registers to 0/false
Hx.pin_dout = Pin(GPIO_HX711_DAT); if (nullptr == Hx) { return; }
pinMode(Hx.pin_sck, OUTPUT); // Hx->calibrate_step = HX_CAL_END; // HX_CAL_END = 0
pinMode(Hx.pin_dout, INPUT);
digitalWrite(Hx.pin_sck, LOW); Hx->pin_sck = Pin(GPIO_HX711_SCK);
Hx->pin_dout = Pin(GPIO_HX711_DAT);
pinMode(Hx->pin_sck, OUTPUT);
pinMode(Hx->pin_dout, INPUT);
digitalWrite(Hx->pin_sck, LOW);
SetWeightDelta(); SetWeightDelta();
@ -324,10 +336,12 @@ void HxInit(void) {
if (!Settings->weight_precision) { Settings->weight_precision = HX711_CAL_PRECISION; } if (!Settings->weight_precision) { Settings->weight_precision = HX711_CAL_PRECISION; }
if (!Settings->weight_calibration) { Settings->weight_calibration = HX_SCALE * Settings->weight_precision; } if (!Settings->weight_calibration) { Settings->weight_calibration = HX_SCALE * Settings->weight_precision; }
if (!Settings->weight_reference) { Settings->weight_reference = HX_REFERENCE; } if (!Settings->weight_reference) { Settings->weight_reference = HX_REFERENCE; }
Hx.scale = Settings->weight_calibration; Hx->scale = Settings->weight_calibration;
HxTareInit(); HxTareInit();
HxRead(); HxRead();
Hx.type = 1; } else {
free(Hx);
Hx = nullptr;
} }
} }
} }
@ -336,123 +350,123 @@ void HxEvery100mSecond(void) {
long raw = HxRead(); long raw = HxRead();
if (-1 == raw) { return; } if (-1 == raw) { return; }
if (Hx.sample_count < HX_SAMPLES) { // Test for HxSaveBeforeRestart() if (Hx->sample_count < HX_SAMPLES) { // Test for HxSaveBeforeRestart()
Hx.reads[Hx.sample_count] = raw; Hx->reads[Hx->sample_count] = raw;
} }
Hx.sample_count++; Hx->sample_count++;
if (HX_SAMPLES == Hx.sample_count) { if (HX_SAMPLES == Hx->sample_count) {
Hx.sample_count = 0; Hx->sample_count = 0;
// Sort HX_SAMPLES // Sort HX_SAMPLES
for (uint32_t i = 0; i < HX_SAMPLES; i++) { for (uint32_t i = 0; i < HX_SAMPLES; i++) {
for (uint32_t j = i + 1; j < HX_SAMPLES; j++) { for (uint32_t j = i + 1; j < HX_SAMPLES; j++) {
if (Hx.reads[j] > Hx.reads[i]) { if (Hx->reads[j] > Hx->reads[i]) {
std::swap(Hx.reads[i], Hx.reads[j]); std::swap(Hx->reads[i], Hx->reads[j]);
} }
} }
} }
// Drop two lows and two highs from average // Drop two lows and two highs from average
long sum_raw = 0; long sum_raw = 0;
for (uint32_t i = 2; i < HX_SAMPLES -2; i++) { for (uint32_t i = 2; i < HX_SAMPLES -2; i++) {
sum_raw += Hx.reads[i]; sum_raw += Hx->reads[i];
} }
Hx.raw_absolute = (sum_raw / (HX_SAMPLES -4)) * Settings->weight_precision; // Uncalibrated value Hx->raw_absolute = (sum_raw / (HX_SAMPLES -4)) * Settings->weight_precision; // Uncalibrated value
Hx.raw = Hx.raw_absolute / Hx.scale; // grams Hx->raw = Hx->raw_absolute / Hx->scale; // grams
if ((0 == Settings->weight_user_tare) && Hx.tare_flg) { // Reset scale based on current load if ((0 == Settings->weight_user_tare) && Hx->tare_flg) { // Reset scale based on current load
Hx.tare_flg = false; Hx->tare_flg = false;
Settings->weight_offset = Hx.raw_absolute; // Save for restart use Settings->weight_offset = Hx->raw_absolute; // Save for restart use
Hx.offset = Hx.raw_absolute; Hx->offset = Hx->raw_absolute;
} }
long value = Hx.raw_absolute - Hx.offset; // Uncalibrated value long value = Hx->raw_absolute - Hx->offset; // Uncalibrated value
Hx.weight = value / Hx.scale; // grams Hx->weight = value / Hx->scale; // grams
if (Hx.weight < 0) { // We currently do not support negative weight if (Hx->weight < 0) { // We currently do not support negative weight
Hx.weight = 0; Hx->weight = 0;
} }
if (Hx.calibrate_step) { if (Hx->calibrate_step) {
Hx.calibrate_timer--; Hx->calibrate_timer--;
// AddLog(LOG_LEVEL_DEBUG, PSTR("HX7: Step %d, weight %d, last %d, raw %d, empty %d"), Hx.calibrate_step, Hx.weight, Hx.last_weight, Hx.raw, Hx.raw_empty); // AddLog(LOG_LEVEL_DEBUG, PSTR("HX7: Step %d, weight %d, last %d, raw %d, empty %d"), Hx->calibrate_step, Hx->weight, Hx->last_weight, Hx->raw, Hx->raw_empty);
if (HX_CAL_START == Hx.calibrate_step) { // Skip reset just initiated if (HX_CAL_START == Hx->calibrate_step) { // Skip reset just initiated
if (0 == Hx.offset) { if (0 == Hx->offset) {
Hx.calibrate_step--; // HX_CAL_RESET Hx->calibrate_step--; // HX_CAL_RESET
Hx.last_weight = Hx.weight; // Uncalibrated value Hx->last_weight = Hx->weight; // Uncalibrated value
Hx.raw_empty = Hx.raw; Hx->raw_empty = Hx->raw;
} }
Hx.calibrate_timer = HX_CAL_TIMEOUT * (10 / HX_SAMPLES); Hx->calibrate_timer = HX_CAL_TIMEOUT * (10 / HX_SAMPLES);
} }
else if (HX_CAL_RESET == Hx.calibrate_step) { // Wait for stable reset else if (HX_CAL_RESET == Hx->calibrate_step) { // Wait for stable reset
if (Hx.calibrate_timer) { if (Hx->calibrate_timer) {
if (Hx.weight < Hx.last_weight -100) { // Load decrease detected if (Hx->weight < Hx->last_weight -100) { // Load decrease detected
Hx.last_weight = Hx.weight; Hx->last_weight = Hx->weight;
Hx.raw_empty = Hx.raw; Hx->raw_empty = Hx->raw;
// HxCalibrationStateTextJson(2); // D_HX_CAL_REFERENCE // HxCalibrationStateTextJson(HX_MSG_CAL_REFERENCE);
} }
else if (Hx.weight > Hx.last_weight +100) { // Load increase detected else if (Hx->weight > Hx->last_weight +100) { // Load increase detected
Hx.calibrate_step--; // HX_CAL_FIRST Hx->calibrate_step--; // HX_CAL_FIRST
Hx.calibrate_timer = HX_CAL_TIMEOUT * (10 / HX_SAMPLES); Hx->calibrate_timer = HX_CAL_TIMEOUT * (10 / HX_SAMPLES);
} }
} else { } else {
Hx.calibrate_step = HX_CAL_FAIL; Hx->calibrate_step = HX_CAL_FAIL;
} }
} }
else if (HX_CAL_FIRST == Hx.calibrate_step) { // Wait for first reference weight else if (HX_CAL_FIRST == Hx->calibrate_step) { // Wait for first reference weight
if (Hx.calibrate_timer) { if (Hx->calibrate_timer) {
if (Hx.weight > Hx.last_weight +100) { if (Hx->weight > Hx->last_weight +100) {
Hx.calibrate_step--; // HX_CAL_DONE Hx->calibrate_step--; // HX_CAL_DONE
} }
} else { } else {
Hx.calibrate_step = HX_CAL_FAIL; Hx->calibrate_step = HX_CAL_FAIL;
} }
} }
else if (HX_CAL_DONE == Hx.calibrate_step) { // Second stable reference weight else if (HX_CAL_DONE == Hx->calibrate_step) { // Second stable reference weight
if (Hx.weight > Hx.last_weight +100) { if (Hx->weight > Hx->last_weight +100) {
Hx.calibrate_step = HX_CAL_FINISH; // Calibration done Hx->calibrate_step = HX_CAL_FINISH; // Calibration done
Settings->weight_offset = Hx.raw_empty; Settings->weight_offset = Hx->raw_empty;
Hx.offset = Hx.raw_empty; Hx->offset = Hx->raw_empty;
Settings->weight_calibration = (Hx.weight - Hx.raw_empty) / Settings->weight_reference; // 1 gram Settings->weight_calibration = (Hx->weight - Hx->raw_empty) / Settings->weight_reference; // 1 gram
Hx.weight = 0; // Reset calibration value Hx->weight = 0; // Reset calibration value
HxCalibrationStateTextJson(1); // D_HX_CAL_DONE HxCalibrationStateTextJson(HX_MSG_CAL_DONE);
} else { } else {
Hx.calibrate_step = HX_CAL_FAIL; Hx->calibrate_step = HX_CAL_FAIL;
} }
} }
if (HX_CAL_FAIL == Hx.calibrate_step) { // Calibration failed if (HX_CAL_FAIL == Hx->calibrate_step) { // Calibration failed
Hx.calibrate_step--; // HX_CAL_FINISH Hx->calibrate_step--; // HX_CAL_FINISH
HxTareInit(); HxTareInit();
HxCalibrationStateTextJson(0); // D_HX_CAL_FAIL HxCalibrationStateTextJson(HX_MSG_CAL_FAIL);
} }
if (HX_CAL_FINISH == Hx.calibrate_step) { // Calibration finished if (HX_CAL_FINISH == Hx->calibrate_step) { // Calibration finished
Hx.calibrate_step--; // HX_CAL_LIMBO Hx->calibrate_step--; // HX_CAL_LIMBO
Hx.calibrate_timer = 3 * (10 / HX_SAMPLES); Hx->calibrate_timer = 3 * (10 / HX_SAMPLES);
Hx.scale = Settings->weight_calibration; Hx->scale = Settings->weight_calibration;
if (Settings->weight_user_tare != 0) { // Re-enable fixed tare if needed if (Settings->weight_user_tare != 0) { // Re-enable fixed tare if needed
Settings->weight_user_tare = Hx.raw_empty / Hx.scale; Settings->weight_user_tare = Hx->raw_empty / Hx->scale;
HxTareInit(); HxTareInit();
} }
} }
if (!Hx.calibrate_timer) { if (!Hx->calibrate_timer) {
Hx.calibrate_step = HX_CAL_END; // End of calibration Hx->calibrate_step = HX_CAL_END; // End of calibration
Hx.weight_diff = Hx.weight_delta +2; Hx->weight_diff = Hx->weight_delta +2;
} }
} else { } else {
if (Settings->SensorBits1.hx711_json_weight_change) { if (Settings->SensorBits1.hx711_json_weight_change) {
if (abs(Hx.weight - Hx.weight_diff) > Hx.weight_delta) { // Use weight_delta threshold to decrease "ghost" weights if (abs(Hx->weight - Hx->weight_diff) > Hx->weight_delta) { // Use weight_delta threshold to decrease "ghost" weights
Hx.weight_diff = Hx.weight; Hx->weight_diff = Hx->weight;
Hx.weight_changed = true; Hx->weight_changed = true;
} }
else if (Hx.weight_changed && (abs(Hx.weight - Hx.weight_diff) < Hx.weight_delta)) { else if (Hx->weight_changed && (abs(Hx->weight - Hx->weight_diff) < Hx->weight_delta)) {
ResponseClear(); ResponseClear();
ResponseAppendTime(); ResponseAppendTime();
HxShow(true); HxShow(true);
ResponseJsonEnd(); ResponseJsonEnd();
MqttPublishTeleSensor(); MqttPublishTeleSensor();
Hx.weight_changed = false; Hx->weight_changed = false;
} }
} }
} }
@ -460,7 +474,7 @@ void HxEvery100mSecond(void) {
} }
void HxSaveBeforeRestart(void) { void HxSaveBeforeRestart(void) {
Hx.sample_count = HX_SAMPLES +1; // Stop updating Hx.weight Hx->sample_count = HX_SAMPLES +1; // Stop updating Hx->weight
} }
#ifdef USE_WEBSERVER #ifdef USE_WEBSERVER
@ -477,18 +491,18 @@ void HxShow(bool json) {
uint16_t count = 0; uint16_t count = 0;
float weight = 0; float weight = 0;
if (Hx.calibrate_step < HX_CAL_FAIL) { if (Hx->calibrate_step < HX_CAL_FAIL) {
if ((Settings->weight_absconv_a != 0) && (Settings->weight_absconv_b != 0)) { if ((Settings->weight_absconv_a != 0) && (Settings->weight_absconv_b != 0)) {
weight = (float)Settings->weight_absconv_a / 1e9 * Hx.raw_absolute + (float)Settings->weight_absconv_b / 1e6; weight = (float)Settings->weight_absconv_a / 1e9 * Hx->raw_absolute + (float)Settings->weight_absconv_b / 1e6;
} }
else { else {
if (Hx.weight && Settings->weight_item) { if (Hx->weight && Settings->weight_item) {
count = (Hx.weight * 10) / Settings->weight_item; count = (Hx->weight * 10) / Settings->weight_item;
if (count > 1) { if (count > 1) {
snprintf_P(scount, sizeof(scount), PSTR(",\"" D_JSON_COUNT "\":%d"), count); snprintf_P(scount, sizeof(scount), PSTR(",\"" D_JSON_COUNT "\":%d"), count);
} }
} }
weight = (float)Hx.weight / 1000; // kilograms weight = (float)Hx->weight / 1000; // kilograms
} }
} }
char weight_chr[33]; char weight_chr[33];
@ -496,16 +510,16 @@ void HxShow(bool json) {
if (json) { if (json) {
ResponseAppend_P(PSTR(",\"HX711\":{\"" D_JSON_WEIGHT "\":%s%s,\"" D_JSON_WEIGHT_RAW "\":%d,\"" D_JSON_WEIGHT_RAW_ABS "\":%d}"), ResponseAppend_P(PSTR(",\"HX711\":{\"" D_JSON_WEIGHT "\":%s%s,\"" D_JSON_WEIGHT_RAW "\":%d,\"" D_JSON_WEIGHT_RAW_ABS "\":%d}"),
weight_chr, scount, Hx.raw, Hx.raw_absolute); weight_chr, scount, Hx->raw, Hx->raw_absolute);
#ifdef USE_WEBSERVER #ifdef USE_WEBSERVER
} else { } else {
WSContentSend_PD(HTTP_HX711_WEIGHT, weight_chr); WSContentSend_PD(HTTP_HX711_WEIGHT, weight_chr);
if (count > 1) { if (count > 1) {
WSContentSend_PD(HTTP_HX711_COUNT, count); WSContentSend_PD(HTTP_HX711_COUNT, count);
} }
if (Hx.calibrate_step) { if (Hx->calibrate_step) {
char cal_text[30]; char cal_text[30];
WSContentSend_PD(HTTP_HX711_CAL, GetTextIndexed(cal_text, sizeof(cal_text), Hx.calibrate_msg, kHxCalibrationStates)); WSContentSend_PD(HTTP_HX711_CAL, GetTextIndexed(cal_text, sizeof(cal_text), Hx->calibrate_msg, kHxCalibrationStates));
} }
#endif // USE_WEBSERVER #endif // USE_WEBSERVER
} }
@ -542,13 +556,13 @@ void HandleHxAction(void) {
AddLog(LOG_LEVEL_DEBUG, PSTR(D_LOG_HTTP D_CONFIGURE_HX711)); AddLog(LOG_LEVEL_DEBUG, PSTR(D_LOG_HTTP D_CONFIGURE_HX711));
char stemp1[20]; char stemp1[32];
if (Webserver->hasArg("save")) { if (Webserver->hasArg("save")) {
String cmnd = F("Sensor34 6 ");
WebGetArg("p2", stemp1, sizeof(stemp1)); WebGetArg("p2", stemp1, sizeof(stemp1));
cmnd += (!strlen(stemp1)) ? 0 : (unsigned long)(CharToFloat(stemp1) * 1000); unsigned long weight_item = (!strlen(stemp1)) ? 0 : (unsigned long)(CharToFloat(stemp1) * 1000);
ExecuteWebCommand((char*)cmnd.c_str()); snprintf_P(stemp1, sizeof(stemp1), PSTR("Sensor34 6,%d"), weight_item); // WeightItem
ExecuteWebCommand(stemp1);
HandleConfiguration(); HandleConfiguration();
return; return;
@ -563,11 +577,10 @@ void HandleHxAction(void) {
} }
if (Webserver->hasArg("calibrate")) { if (Webserver->hasArg("calibrate")) {
String cmnd = F(D_CMND_BACKLOG "0 Sensor34 3 ");
WebGetArg("p1", stemp1, sizeof(stemp1)); WebGetArg("p1", stemp1, sizeof(stemp1));
cmnd += (!strlen(stemp1)) ? 0 : (unsigned long)(CharToFloat(stemp1) * 1000); unsigned long weight_ref = (!strlen(stemp1)) ? 0 : (unsigned long)(CharToFloat(stemp1) * 1000);
cmnd += F(";Sensor34 2"); // Start calibration snprintf_P(stemp1, sizeof(stemp1), PSTR("Sensor34 2,%d"), weight_ref); // Start calibration
ExecuteWebCommand((char*)cmnd.c_str()); ExecuteWebCommand(stemp1);
HandleRoot(); // Return to main screen HandleRoot(); // Return to main screen
return; return;
@ -593,7 +606,10 @@ void HandleHxAction(void) {
bool Xsns34(uint32_t function) { bool Xsns34(uint32_t function) {
bool result = false; bool result = false;
if (Hx.type) { if (FUNC_INIT == function) {
HxInit();
}
else if (Hx) {
switch (function) { switch (function) {
case FUNC_EVERY_100_MSECOND: case FUNC_EVERY_100_MSECOND:
HxEvery100mSecond(); HxEvery100mSecond();
@ -627,9 +643,6 @@ bool Xsns34(uint32_t function) {
break; break;
#endif // USE_HX711_GUI #endif // USE_HX711_GUI
#endif // USE_WEBSERVER #endif // USE_WEBSERVER
case FUNC_INIT:
HxInit();
break;
} }
} }
return result; return result;