Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add HX711 absolute weight conversion #15292

Closed
wants to merge 4 commits into from

Conversation

ThomDietrich
Copy link
Contributor

@ThomDietrich ThomDietrich commented Apr 4, 2022

Description:

Related issue (if applicable): fixes #13983

Implemented as discussed in issue ticket. Tested and working as expected.

Checklist:

  • The pull request is done against the latest development branch
  • Only relevant files were touched
  • Only one feature/fix was added per PR and the code change compiles without warnings
  • The code change is tested and works with Tasmota core ESP8266 V.2.7.4.9
  • The code change is tested and works with Tasmota core ESP32 V.2.0.3
  • I accept the CLA.

NOTE: The code change must pass CI tests. Your PR cannot be merged unless tests pass

uint32_t keeloq_serial; // FC4
uint32_t keeloq_count; // FC8
//uint32_t keeloq_serial; // FC4 TODO discuss
//uint32_t keeloq_count; // FC8 TODO discuss
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is not finished yet. Waiting for advise how to proceed.

This new functions needs two variables in permanent memory. The absolute weight is calculated from raw value following the formula

     weight =  absconv_a / 1e9 * raw + absconv_b / 1e6;

Typical config values from one of my setups are:

  • absconv_a = 953499
  • absconv_b = 15418390

The end result of the computation is a weight with a few decimals (e.g. 0-200kg, two decimals). The size of those variables can therefore certainly be reduced.

I am not sure about other builds and configs though. Another user could end with raw_weight values in different ranges and would need to apply a and b in lower or higher ranges. How do we avoid overflows and invalid user inputs?

Any help is highly appreciated.

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I just made these variables available in settings.h

I think you need to find some kind of scaling to keep the values within the space of a uint32_t being 0 to 4.294.967.295 while keeping in mind results of calculation being also within this range. Using floats makes things worse as the float range is a lot smaller.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks!

Okay let me think of a reasonable scaling

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Having some difficulties wrapping my head around this.

 weight =  a * raw + b;
 weight =  A / 1e9 * raw + B / 1e6;
 weight =  absconv_a / 1e9 * raw + absconv_b / 1e6;
  • raw is currently of type long
  • absconv_a and absconv_b are of type long as well (meaning they are signed, which contradicts uint32_t)
    • absconv_b can be positive or negative, therefore signed long makes sense
  • the weight result realistically lies below 200kg and could also be negative when the setup is changed, lets say [-400..400]

Therefore, result of the calculation should always be within range, under reasonable parameters. How much sanity checking of these parameters do we need to implement?

Assuming weight results between [-400..400]:

  • we can likewise limit b to [-400..400]
  • we can limit a to something around 400 / max(long)

Not sure if this is the right way forward.


For reference, some of my setup configurations:

image

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just changed both absconv to int32_t (long)

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've played around with this and I wonder why we need such an elaborate formula.

Considering my situation. I have a loadcell which, when no load is attached results in a raw value of 1253. When I load a weight of known 280grams it returns a value of 1533. So all I need is a possibility to decrease the raw value with 1253 and I have the weigth.

What am I missing here?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hey @arendst,
Did you go through the internal calibration process prior to this experiment?
Asking because I mostly ignore this function and use standard values for all my devices. In combination with the calibration formula (like examples given above) I have a deterministic approach to build reproducible devices. I have a dozend of these devices operational, number growing.

{"Sensor34":{"WeightRef":5000,"WeightCal":22,"WeightMax":200000,"WeightItem":0.0,"WeightChange":ON,"WeightDelta":10}}

I understand that all of this could feel like a solution that is not in line with functionality that is already there. My use case is to build devices which are calibrated and produce absolute weight measurements (10-90kg) across reboots, in permanent installations over years. The approach as described works quite satisfying for allmost two years now. However, so far the y=ax+b conversion is done in Home Assistant and I wanted to change that.

Should we discuss a different (more Tasmota integrated) approach?

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's continue here #13983 (reply in thread)

@@ -441,6 +464,9 @@ void HxShow(bool json)
}
weight = (float)Hx.weight / 1000; // kilograms
}
if (Hx.absconv_a != 0 && Hx.absconv_b != 0) {
weight = (float)Hx.absconv_a / 1e9 * Hx.raw + (float)Hx.absconv_b / 1e6;
}
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Am I right in the conclusion that using the raw value here makes current calibration efforts useless? How do you define the absconv parameters? By trial and error?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No you are correct. No offense, but I didn't find the implemented calibration combined with taring the weight upon startup useful for my use case (and wonder in which use case it is). The strategy I follow is to take a few raw weights for known masses, then run a simple linear regression, e.g. here: https://mycurvefit.com to get to the absconv parameters of y=ax+b.
It's not as integrated but is a good deterministic process. Let me know if you believe we should have a discussion about a different path!

Copy link
Owner

@arendst arendst Apr 7, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

My implemented use case is based on a commercial kitchen scale like the Ikea one.

After power on the user adds an empty dish, selects the reset button to zero the result and then is able to weigh anything he adds to the dish. Hence the zero button in the GUI.

There are ofcourse other uses which may use your suggested solution.

As your implementation doesn't interfere with mine I'll add it now so users can get some experience with it.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Interesting element you brought up!

USE_HX711_GUI is not defined for FIRMWARE_SENSORS. As a result I did never see this "zero button in GUI" you refered to. Maybe this should be changed?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@arendst ping in case you missed this.

arendst added a commit that referenced this pull request Apr 7, 2022
Add commands ``Sensor34 10 <valueA>`` and ``Sensor34 11 <valueB>`` to use HX711 absolute weight conversion (#15292)
@arendst
Copy link
Owner

arendst commented Apr 7, 2022

Merged for testing

@arendst arendst closed this Apr 7, 2022
@ThomDietrich ThomDietrich deleted the hx711-absconv branch April 8, 2022 11:56
arendst added a commit that referenced this pull request Apr 9, 2022
- Add HX711 command ``Sensor34 10 0|1|<weight in gram>`` to set HX711 fixed tare (0 = use auto tare, 1 = use calibrated tare, Any other value is user selected tare)
- HX711 removed command ``Sensor34 7`` as now active tare is persistent resulting in calculated current weight
- Changed HX711 commands ``Sensor34 11 <valueA>`` and ``Sensor34 12 <valueB>`` to use HX711 absolute weight conversion (#15292)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

2 participants