Skip to content

Commit 28442ea

Browse files
committed
add read_median() and more
1 parent e548845 commit 28442ea

File tree

12 files changed

+442
-38
lines changed

12 files changed

+442
-38
lines changed

libraries/HX711/HX711.cpp

Lines changed: 107 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
//
22
// FILE: HX711.cpp
33
// AUTHOR: Rob Tillaart
4-
// VERSION: 0.2.1
4+
// VERSION: 0.2.2
55
// PURPOSE: Library for Loadcells for UNO
66
// URL: https://github.com/RobTillaart/HX711
77
//
@@ -10,7 +10,7 @@
1010
// 0.1.1 2019-09-09 change long to float (reduce footprint)
1111
// 0.2.0 2020-06-15 refactor; add price functions;
1212
// 0.2.1 2020-12-28 add arduino-ci + unit test
13-
13+
// 0.2.2 2021-05-10 add read_median(), fix typo, add mode operandi
1414

1515
#include "HX711.h"
1616

@@ -21,6 +21,7 @@ HX711::HX711()
2121

2222
HX711::~HX711() {}
2323

24+
2425
void HX711::begin(uint8_t dataPin, uint8_t clockPin)
2526
{
2627
_dataPin = dataPin;
@@ -33,18 +34,23 @@ void HX711::begin(uint8_t dataPin, uint8_t clockPin)
3334
reset();
3435
}
3536

37+
3638
void HX711::reset()
3739
{
38-
_offset = 0;
39-
_scale = 1;
40-
_gain = 128;
40+
_offset = 0;
41+
_scale = 1;
42+
_gain = 128;
43+
_lastRead = 0;
44+
_mode = HX711_AVERAGE_MODE;
4145
}
4246

47+
4348
bool HX711::is_ready()
4449
{
4550
return digitalRead(_dataPin) == LOW;
4651
}
4752

53+
4854
float HX711::read()
4955
{
5056
// this waiting takes most time...
@@ -85,12 +91,21 @@ float HX711::read()
8591
return 1.0 * v.value;
8692
}
8793

94+
8895
// assumes tare() has been set.
89-
void HX711::callibrate_scale(uint16_t weight, uint8_t times)
96+
void HX711::calibrate_scale(uint16_t weight, uint8_t times)
9097
{
9198
_scale = (1.0 * weight) / (read_average(times) - _offset);
9299
}
93100

101+
// will be obsolete
102+
void HX711::callibrate_scale(uint16_t weight, uint8_t times)
103+
{
104+
calibrate_scale(weight, times);
105+
};
106+
107+
108+
94109
void HX711::wait_ready(uint32_t ms)
95110
{
96111
while (!is_ready())
@@ -99,6 +114,7 @@ void HX711::wait_ready(uint32_t ms)
99114
}
100115
}
101116

117+
102118
bool HX711::wait_ready_retry(uint8_t retries, uint32_t ms)
103119
{
104120
while (retries--)
@@ -120,8 +136,10 @@ bool HX711::wait_ready_timeout(uint32_t timeout, uint32_t ms)
120136
return false;
121137
}
122138

139+
123140
float HX711::read_average(uint8_t times)
124141
{
142+
if (times < 1) times = 1;
125143
float sum = 0;
126144
for (uint8_t i = 0; i < times; i++)
127145
{
@@ -131,18 +149,101 @@ float HX711::read_average(uint8_t times)
131149
return sum / times;
132150
}
133151

152+
153+
float HX711::read_median(uint8_t times)
154+
{
155+
if (times > 15) times = 15;
156+
if (times < 3) times = 3;
157+
float s[15];
158+
for (uint8_t i = 0; i < times; i++)
159+
{
160+
s[i] = read();
161+
yield();
162+
}
163+
_insertSort(s, times);
164+
if (times & 0x01) return s[times/2];
165+
return (s[times/2] + s[times/2+1])/2;
166+
}
167+
168+
169+
float HX711::read_medavg(uint8_t times)
170+
{
171+
if (times > 15) times = 15;
172+
if (times < 3) times = 3;
173+
float s[15];
174+
for (uint8_t i = 0; i < times; i++)
175+
{
176+
s[i] = read();
177+
yield();
178+
}
179+
_insertSort(s, times);
180+
float sum = 0;
181+
// iterate over 1/4 to 3/4 of the array
182+
uint8_t cnt = 0;
183+
uint8_t first = (times + 2) / 4;
184+
uint8_t last = times - first - 1;
185+
for (uint8_t i = first; i <= last; i++) // !! include last too
186+
{
187+
sum += s[i];
188+
cnt++;
189+
}
190+
return sum/cnt;
191+
}
192+
193+
194+
void HX711::_insertSort(float * array, uint8_t size)
195+
{
196+
uint8_t t, z;
197+
float temp;
198+
for (t = 1; t < size; t++)
199+
{
200+
z = t;
201+
temp = array[z];
202+
while( (z > 0) && (temp < array[z - 1] ))
203+
{
204+
array[z] = array[z - 1];
205+
z--;
206+
}
207+
array[z] = temp;
208+
yield();
209+
}
210+
}
211+
212+
213+
float HX711::get_value(uint8_t times)
214+
{
215+
float raw;
216+
switch(_mode)
217+
{
218+
case HX711_MEDAVG_MODE:
219+
raw = read_medavg(times);
220+
break;
221+
case HX711_MEDIAN_MODE:
222+
raw = read_median(times);
223+
break;
224+
case HX711_AVERAGE_MODE:
225+
default:
226+
raw = read_average(times);
227+
break;
228+
}
229+
return raw - _offset;
230+
};
231+
232+
134233
float HX711::get_units(uint8_t times)
135234
{
136235
float units = get_value(times) * _scale;
137236
return units;
138237
};
139238

239+
140240
void HX711::power_down()
141241
{
142242
digitalWrite(_clockPin, LOW);
143243
digitalWrite(_clockPin, HIGH);
144244
}
145245

246+
146247
void HX711::power_up()
147248
{
148249
digitalWrite(_clockPin, LOW);

libraries/HX711/HX711.h

Lines changed: 48 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
//
33
// FILE: HX711.h
44
// AUTHOR: Rob Tillaart
5-
// VERSION: 0.2.1
5+
// VERSION: 0.2.2
66
// PURPOSE: Library for Loadcells for UNO
77
// URL: https://github.com/RobTillaart/HX711
88
//
@@ -15,7 +15,16 @@
1515

1616
#include "Arduino.h"
1717

18-
#define HX711_LIB_VERSION (F("0.2.1"))
18+
#define HX711_LIB_VERSION (F("0.2.2"))
19+
20+
21+
const uint8_t HX711_AVERAGE_MODE = 0x00;
22+
// in median mode only between 3 and 15 samples are allowed.
23+
const uint8_t HX711_MEDIAN_MODE = 0x01;
24+
// medavg = average of the middle "half" of sorted elements
25+
// in medavg mode only between 3 and 15 samples are allowed.
26+
const uint8_t HX711_MEDAVG_MODE = 0x02;
27+
1928

2029
class HX711
2130
{
@@ -41,49 +50,75 @@ class HX711
4150

4251
// raw read
4352
float read();
44-
// multiple raw reads
53+
// get average of multiple raw reads
4554
float read_average(uint8_t times = 10);
55+
56+
// get median of multiple raw reads
57+
// times = 3..15 - odd numbers preferred
58+
float read_median(uint8_t times = 7);
59+
60+
// get average of "middle half" of multiple raw reads.
61+
// times = 3..15 - odd numbers preferred
62+
float read_medavg(uint8_t times = 7);
63+
64+
65+
// get set mode for get_value() and indirect get_units().
66+
// in median and medavg mode only 3..15 samples are allowed.
67+
void set_average_mode() { _mode = HX711_AVERAGE_MODE; };
68+
void set_median_mode() { _mode = HX711_MEDIAN_MODE; };
69+
void set_medavg_mode() { _mode = HX711_MEDAVG_MODE; };
70+
uint8_t get_mode() { return _mode; };
71+
4672
// corrected for offset
47-
float get_value(uint8_t times = 1) { return read_average(times) - _offset; };
73+
float get_value(uint8_t times = 1);
4874
// converted to proper units.
4975
float get_units(uint8_t times = 1);
5076

77+
5178
// TARE
5279
// call tare to calibrate zero
5380
void tare(uint8_t times = 10) { _offset = read_average(times); };
5481
float get_tare() { return -_offset * _scale; };
5582
bool tare_set() { return _offset != 0; };
5683

84+
5785
// CORE "CONSTANTS" -> read datasheet
5886
// GAIN values: 128, 64 32 [only 128 tested & verified]
5987
void set_gain(uint8_t gain = 128) { _gain = gain; };
6088
uint8_t get_gain() { return _gain; };
6189
// SCALE > 0
62-
void set_scale(float scale = 1.0) { _scale = 1 / scale; };
63-
float get_scale() { return 1 / _scale; };
90+
void set_scale(float scale = 1.0) { _scale = 1.0 / scale; };
91+
float get_scale() { return 1.0 / _scale; };
6492
// OFFSET > 0
6593
void set_offset(long offset = 0) { _offset = offset; };
6694
long get_offset() { return _offset; };
6795

96+
6897
// CALIBRATION
6998
// clear the scale
7099
// call tare() to set the zero offset
71100
// put a known weight on the scale
72-
// call callibrate_scale(weight)
101+
// call calibrate_scale(weight)
73102
// scale is calculated.
74-
void callibrate_scale(uint16_t weight, uint8_t times = 10);
103+
void calibrate_scale(uint16_t weight, uint8_t times = 10);
104+
// obsolete typo but just do not want to break interface yet
105+
void callibrate_scale(uint16_t weight, uint8_t times = 10);
106+
75107

76108
// POWER MANAGEMENT
77109
void power_down();
78110
void power_up();
79111

112+
80113
// TIME OF LAST READ
81114
uint32_t last_read() { return _lastRead; };
82115

116+
83117
// PRICING (idem calories?)
84118
float get_price(uint8_t times = 1) { return get_units(times) * _price; };
85-
void set_unit_price(float price) { _price = price; };
86-
float get_unit_price() { return _price; };
119+
void set_unit_price(float price = 1.0) { _price = price; };
120+
float get_unit_price() { return _price; };
121+
87122

88123
private:
89124
uint8_t _dataPin;
@@ -94,6 +129,9 @@ class HX711
94129
float _scale = 1;
95130
uint32_t _lastRead = 0;
96131
float _price = 0;
132+
uint8_t _mode = 0;
133+
134+
void _insertSort(float * array, uint8_t size);
97135
};
98136

99137
// -- END OF FILE --

libraries/HX711/README.md

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -23,16 +23,16 @@ footprint.
2323

2424
First action is to call **begin(dataPin, clockPin)** to make connection to the **HX711**.
2525

26-
Second step is callibration for which a number of functions exist.
26+
Second step is calibration for which a number of functions exist.
2727
- **tare()** measures zero point
2828
- **set_scale(factor)** set a known conversion factor e.g. from EEPROM.
29-
- **callibrate_scale(WEIGHT, TIMES)** determines the scale factor based upon a known weight e.g. 1 Kg.
29+
- **calibrate_scale(WEIGHT, TIMES)** determines the scale factor based upon a known weight e.g. 1 Kg.
3030

31-
Steps to take for callibration
31+
Steps to take for calibration
3232
1. clear the scale
3333
1. call tare() to set the zero offset
3434
1. put a known weight on the scale
35-
1. call callibrate_scale(weight)
35+
1. call calibrate_scale(weight)
3636
1. scale is calculated.
3737
1. save the offset and scale for later use e.g. EEPROM.
3838

@@ -53,7 +53,7 @@ For weight conversion functions see https://github.com/RobTillaart/weight
5353
### Scale values for loadcells
5454

5555
These scale values worked pretty well with a set of loadcells,
56-
Use callibrate to find your values.
56+
Use calibrate to find your values.
5757

5858
- 5 KG loadcell scale.set_scale(420.52);
5959
- 20 KG loadcell scale.set_scale(127.15);

libraries/HX711/examples/HX_grocery_scale/HX_grocery_scale.ino

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -43,11 +43,11 @@ void setup()
4343
while(!Serial.available());
4444
while(Serial.available()) Serial.read();
4545

46-
scale.callibrate_scale(1000, 5);
46+
scale.calibrate_scale(1000, 5);
4747
Serial.print("UNITS: ");
4848
Serial.println(scale.get_units(10));
4949

50-
Serial.println("\nScale is callibrated, press a key to continue");
50+
Serial.println("\nScale is calibrated, press a key to continue");
5151
while(!Serial.available());
5252
while(Serial.available()) Serial.read();
5353

libraries/HX711/examples/HX_kitchen_scale/HX_kitchen_scale.ino

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -39,15 +39,15 @@ void setup()
3939
Serial.println(scale.get_units(10));
4040

4141

42-
Serial.println("\nPut a 1 kg in the scale, press a key to continue");
42+
Serial.println("\nPut 1000 gram in the scale, press a key to continue");
4343
while(!Serial.available());
4444
while(Serial.available()) Serial.read();
4545

46-
scale.callibrate_scale(1000, 5);
46+
scale.calibrate_scale(1000, 5);
4747
Serial.print("UNITS: ");
4848
Serial.println(scale.get_units(10));
4949

50-
Serial.println("\nScale is callibrated, press a key to continue");
50+
Serial.println("\nScale is calibrated, press a key to continue");
5151
while(!Serial.available());
5252
while(Serial.available()) Serial.read();
5353

0 commit comments

Comments
 (0)