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
read_mean in addition to read_average #5
Comments
Hi Clemens, If I understand correctly you would like to have a read function that does not calculate the average but does calculate the median of 5 or 11 values. (odd numbers are preferred) . I propose to make the following function: float read_median(uint8_t times = 7); I will not copy the idea of doing a delay in the function as that would block all code, So lets start with a non-blocking version. |
Please check the branch - https://github.com/RobTillaart/HX711/tree/read_median fixed 1st bug and a 2nd :) |
@ClemensGruber |
I have tried the From a user perspective I would expect that I don't know what the benefit would be in case we have two functions In case this is to heavy two functions would be possible or a variable where I can specify if the base for Btw the output is currently
So I would change the text to "put 1000 g in the scale" so units gram fits to the output 1000.46 g not kg. This is the output of the original
Changing
|
I like the idea that get_units() could work on both the average or the median. The change should be in get_value(); something like this? float get_value(uint8_t times = 1)
{
if (use_median == true)
{
return read_median(times) - _offset;
}
return read_average(times) - _offset;
}
void set_median_mode() { use_median = true; };
void set_average_mode() { use_median = false; };
bool uses_median() { return use_median; };
It should be in the documentation that use_median will limit the # samples (times) taken due to the internal storage limit. About the time used, I would have expected that read_median(7) would take a bit longer than read_average(7). A quick test (with no device connected) on AVR also gives approx. equal timing for both, 100x read_median(7) = 282230 == way less than 60 seconds by the way Changed 1Kg to 1000 gr in the Kitchen example as that is better. |
Added the following in read_median branch // get set mode for get_value() and indirect get_units().
void set_median_mode() { _mode = HX711_MEDIAN_MODE; };
void set_average_mode() { _mode = HX711_AVERAGE_MODE; };
int get_mode() { return _mode; }; get_value() uses the _mode for selecting read_average() or read_median() Please verify this works for you. It might be possible to add new modi operandi in the future e.g.
The latter is interesting as it might even be better than just the MEDIAN. It removes both outliers and suppresses "small" noise |
About the performance: I have changed the library to the one from Bogdan and Andreas https://github.com/bogde/HX711 testwise and got with 61 seconds nearly the same performance time:
After that I used this test code (back with this lib here :-)
and computed about 500 values each. The mean from all median readings was comparable with the mean readings (median: 1003.73 vs. mean: 1003.69), SD was a bit samller for median 2.34 vs. 2.80 as expected, minimum / maximum was 965.8 / 1008.0 vs. 965.7 / 1011.8, all in gram! Not too much differenc but it could also be up to my setup: workbench not outside, short cables and especially a 100 kg load cell loaded with 1 kg only |
@ClemensGruber Can you do a test in which you add another 1 Kg weight in the last 15 seconds to simulate an outlier. (15 seconds is ~25% of 1 minute so expectation is 75% 1Kg + 25% 2Kg ==> 1.25 Kg on average. |
Started to implement the MEDAVG methode. (if you know a better name, let me know) the idea is given in this sketch: // FILE: medium_average.ino
// AUTHOR: Rob Tillaart
// DATE: 2021-05-13
void setup()
{
Serial.begin(115200);
for (int times = 3; times < 20; times++)
{
uint8_t first = (times + 2) / 4;
uint8_t last = times - first - 1;
Serial.print(times);
Serial.print("\t");
for (int i = 0; i < first; i++) Serial.print("0");
for (int i = first; i <= last; i++) Serial.print("1");
for (int i = last + 1; i < times; i++) Serial.print("0");
Serial.println();
}
Serial.println("done...");
}
void loop(){} output: 3 010
4 0110
5 01110
6 001100
7 0011100
8 00111100
9 001111100
10 0001111000
11 00011111000
12 000111111000
13 0001111111000
14 00001111110000
15 000011111110000
16 0000111111110000
17 00001111111110000
18 000001111111100000
19 0000011111111100000
done... sort the readings, |
@ClemensGruber Please verify it is working for you, |
@ClemensGruber |
@ClemensGruber Thanks |
Many thanks, Rob for merging this feature into master. So it is easily available via Arduino's library manager! I installed the lib now via the library manager and tested
I used the maximum of 15 readings by calculating the value and gave the scale a short press while reading. The results where clearly different. I had nearly same values with the median mode and wide variability with the average. So all seems to work in a good manner! The performance is - also as expected - quite similar for the different modes on my ESP32:
Again many thanks for implementing this! |
There is a second occurrence in the grocery scale example that you may like to change also:
|
@ClemensGruber |
#feature-request
Many thanks Rob for this new HX711 lib! I'm using the library from Bogdan and Andreas since years with your https://github.com/RobTillaart/RunningMedian library. The reason is simple. Outlier have a huge impact for sensor readings and happen in the analog domaine sometimes. So it is a good habit to take the reading several times. The library from Bogdan and yours have a read_average function for this purpose.
Statistically the bad thin on the mean / average funcion is that a hight outlier can kill your average sensor reding in case the outlier is verry high / low. so 568 kg, 25,5 kg, 25,6 kg, 25,3 kg, 25,2 kg will lead to a too high reading also it is averaged.
A more robust statistical value is the mean. No outlier will damage the "real" value and so it is the preferede index for computing an analog input.
So it would be great to have a function like
read_mean()
to get stabile outputs.In my bee hive monitorin sketches I have also implemented (not in the lib but in my code) a customizable wait value between the single read_mean / read_average actions. The reason is that in the wild wind can lead to a misreading, so it is good to wait e.g. 1 second between the single read_mean events. That would be also a perfect additional parameter for read_mean and read_average.
Just as an suggestion to make the library more convenient for different scenarios!
The text was updated successfully, but these errors were encountered: