Skip to content

Commit 49cd6e4

Browse files
committed
added library and documentation
1 parent c65deb3 commit 49cd6e4

File tree

16 files changed

+1666
-0
lines changed

16 files changed

+1666
-0
lines changed
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
# Auto detect text files and perform LF normalization
2+
* text=auto
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
MIT License
2+
3+
Copyright (c) 2017 Olav Kallhovd
4+
5+
Permission is hereby granted, free of charge, to any person obtaining a copy
6+
of this software and associated documentation files (the "Software"), to deal
7+
in the Software without restriction, including without limitation the rights
8+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9+
copies of the Software, and to permit persons to whom the Software is
10+
furnished to do so, subject to the following conditions:
11+
12+
The above copyright notice and this permission notice shall be included in all
13+
copies or substantial portions of the Software.
14+
15+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21+
SOFTWARE.
Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
Latest release and change log here: https://github.com/olkal/HX711_ADC/releases
2+
3+
This an Arduino library for the HX711 24-bit ADC for weight scales.
4+
Data retrieval from the HX711 is done without blocking the mcu, also on the 10SPS rate setting and with Multiple HX711's performing conversions simultaneously.
5+
Tare function can also be performed without blocking the mcu.
6+
7+
Filtering and smoothing: "Moving average" method from a rolling data set combined with removal of high/low outliers is used for the retrieved value.
8+
9+
Selectable values in the config.h file:
10+
- Moving average data set of 1, 2, 4, 8, 16, 32, 64 or 128 samples (default:16).
11+
- Ignore high outlier; one sample is added to the data set, the peak high value of all samples in the data set is ignored (default:1)
12+
- Ignore low outlier; one sample is added to the data set, the peak low value of all samples in the data set is ignored (default:1)
13+
- Enable delay for writing to sck pin. This could be required for faster mcu's like the ESP32 (default: no delay)
14+
- Disable interrupts when sck pin is high. This could be required to avoid "power down mode" if you have some other time consuming (>60µs) interrupt routines running (default: interrupts enabled)
15+
16+
Caution: using a high number of samples will smooth the output value nicely but will also increase settling time and start-up/tare time (but not response time). It will also eat some memory.
17+
18+
Important: The HX711 sample rate can be set to 10SPS or 80SPS (samples per second) by pulling pin 15 high (80SPS) or low (10SPS), ref HX711 data sheet.
19+
On fabricated HX711 modules there is usually a solder jumper on the PCB for pin 15 high/low. The rate setting can be checked by measuring the voltage on pin 15.
20+
ADC noise is worst on the 80SPS rate. Unless very quick settling time is required, 10SPS should be the best sample rate for most applications.
21+
22+
Start up and tare: from start-up/reset, the tare function seems to be more accurate if called after a "pre-warm-up" period running conversions continuously for a few seconds. See example files.
23+
24+
Hardware and ADC noise:
25+
Wires between HX711 and load cell should be twisted and kept as short as possible.
26+
Most available HX711 modules seems to follow the reference design, but be aware that some modules are poorly designed with under-sized capacitors, and noisy readings.
27+
The Sparkfun module seems to differ from most other available modules as it has some additional components for noise reduction.
28+
29+
To get started: Install the library from Arduino Library Manager. Begin with the Calibration.ino example file, then move on to the Read_1x_load_cell.ino example file.
30+
31+
If you need to keep the tare/zero-offset value after a device reboot, please see example Persistent_zero_offset.ino example file.
32+
33+
HX711_ADC Library Documentation
34+
```
35+
Initialization:
36+
begin(): Initializes the communication with the HX711 and sets the gain to 128 (default).
37+
begin(uint8_t gain): Initializes the communication with the HX711 and sets the gain (32, 64, or 128).
38+
Tare (Zero Point Calibration):
39+
tare(): Performs tare operation (blocking, waits until finished).
40+
tareNoDelay(): Initiates tare operation (non-blocking, continues in background).
41+
getTareStatus(): Returns true if the tare operation is complete.
42+
43+
Data Acquisition:
44+
update(): Reads a new weight sample (blocking, waits for conversion).
45+
dataWaitingAsync(): Checks if new weight data is available (non-blocking).
46+
updateAsync(): Reads new weight data if available (non-blocking, called after dataWaitingAsync).
47+
getData(): Returns the latest weight value (after applying calibration and filtering).
48+
49+
Calibration:
50+
setCalFactor(float cal): Sets the calibration factor for weight conversion (weight = raw data / calFactor).
51+
getCalFactor(): Returns the current calibration factor.
52+
getNewCalibration(float known_mass): Calculates and sets a new calibration factor based on a known mass.
53+
54+
Other Functions:
55+
setSamplesInUse(int samples): Sets the number of samples used for averaging and filtering (rounded down).
56+
getSamplesInUse(): Returns the current number of samples in use.
57+
resetSamplesIndex(): Resets the index for the dataset.
58+
refreshDataSet(): Refreshes the entire dataset with new conversions (blocking).
59+
getDataSetStatus(): Checks if the dataset is filled with conversions.
60+
getSignalTimeoutFlag(): Indicates if the HX711 communication timed out.
61+
setReverseOutput(): Reverses the output value (positive/negative).
62+
getTareOffset(): Gets the current tare offset (raw data value).
63+
setTareOffset(long newoffset): Sets a new tare offset (raw data value).
64+
powerUp(): Powers up the HX711 chip.
65+
powerDown(): Powers down the HX711 chip.
66+
getReadIndex(): Returns the current dataset read index (debugging).
67+
getConversionTime(): Returns the latest conversion time in milliseconds (debugging).
68+
getSPS(): Estimates the HX711 conversions per second (debugging).
69+
getTareTimeoutFlag(): Returns the tare operation timeout flag (debugging).
70+
disableTareTimeout(): Disables the tare operation timeout.
71+
getSettlingTime(): Calculates the estimated settling time based on conversion time and sample count (debugging).
72+
```
Lines changed: 223 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,223 @@
1+
/*
2+
-------------------------------------------------------------------------------------
3+
HX711_ADC
4+
Arduino library for HX711 24-Bit Analog-to-Digital Converter for Weight Scales
5+
Olav Kallhovd sept2017
6+
-------------------------------------------------------------------------------------
7+
*/
8+
9+
/*
10+
This example file shows how to calibrate the load cell and optionally store the calibration
11+
value in EEPROM, and also how to change the value manually.
12+
The result value can then later be included in your project sketch or fetched from EEPROM.
13+
14+
To implement calibration in your project sketch the simplified procedure is as follow:
15+
LoadCell.tare();
16+
//place known mass
17+
LoadCell.refreshDataSet();
18+
float newCalibrationValue = LoadCell.getNewCalibration(known_mass);
19+
*/
20+
21+
#include <HX711_ADC.h>
22+
#if defined(ESP8266)|| defined(ESP32) || defined(AVR)
23+
#include <EEPROM.h>
24+
#endif
25+
26+
//pins:
27+
const int HX711_dout = 4; //mcu > HX711 dout pin
28+
const int HX711_sck = 5; //mcu > HX711 sck pin
29+
30+
//HX711 constructor:
31+
HX711_ADC LoadCell(HX711_dout, HX711_sck);
32+
33+
const int calVal_eepromAdress = 0;
34+
unsigned long t = 0;
35+
36+
void setup() {
37+
Serial.begin(57600); delay(10);
38+
Serial.println();
39+
Serial.println("Starting...");
40+
41+
LoadCell.begin();
42+
//LoadCell.setReverseOutput(); //uncomment to turn a negative output value to positive
43+
unsigned long stabilizingtime = 2000; // preciscion right after power-up can be improved by adding a few seconds of stabilizing time
44+
boolean _tare = true; //set this to false if you don't want tare to be performed in the next step
45+
LoadCell.start(stabilizingtime, _tare);
46+
if (LoadCell.getTareTimeoutFlag() || LoadCell.getSignalTimeoutFlag()) {
47+
Serial.println("Timeout, check MCU>HX711 wiring and pin designations");
48+
while (1);
49+
}
50+
else {
51+
LoadCell.setCalFactor(1.0); // user set calibration value (float), initial value 1.0 may be used for this sketch
52+
Serial.println("Startup is complete");
53+
}
54+
while (!LoadCell.update());
55+
calibrate(); //start calibration procedure
56+
}
57+
58+
void loop() {
59+
static boolean newDataReady = 0;
60+
const int serialPrintInterval = 0; //increase value to slow down serial print activity
61+
62+
// check for new data/start next conversion:
63+
if (LoadCell.update()) newDataReady = true;
64+
65+
// get smoothed value from the dataset:
66+
if (newDataReady) {
67+
if (millis() > t + serialPrintInterval) {
68+
float i = LoadCell.getData();
69+
Serial.print("Load_cell output val: ");
70+
Serial.println(i);
71+
newDataReady = 0;
72+
t = millis();
73+
}
74+
}
75+
76+
// receive command from serial terminal
77+
if (Serial.available() > 0) {
78+
char inByte = Serial.read();
79+
if (inByte == 't') LoadCell.tareNoDelay(); //tare
80+
else if (inByte == 'r') calibrate(); //calibrate
81+
else if (inByte == 'c') changeSavedCalFactor(); //edit calibration value manually
82+
}
83+
84+
// check if last tare operation is complete
85+
if (LoadCell.getTareStatus() == true) {
86+
Serial.println("Tare complete");
87+
}
88+
89+
}
90+
91+
void calibrate() {
92+
Serial.println("***");
93+
Serial.println("Start calibration:");
94+
Serial.println("Place the load cell an a level stable surface.");
95+
Serial.println("Remove any load applied to the load cell.");
96+
Serial.println("Send 't' from serial monitor to set the tare offset.");
97+
98+
boolean _resume = false;
99+
while (_resume == false) {
100+
LoadCell.update();
101+
if (Serial.available() > 0) {
102+
if (Serial.available() > 0) {
103+
char inByte = Serial.read();
104+
if (inByte == 't') LoadCell.tareNoDelay();
105+
}
106+
}
107+
if (LoadCell.getTareStatus() == true) {
108+
Serial.println("Tare complete");
109+
_resume = true;
110+
}
111+
}
112+
113+
Serial.println("Now, place your known mass on the loadcell.");
114+
Serial.println("Then send the weight of this mass (i.e. 100.0) from serial monitor.");
115+
116+
float known_mass = 0;
117+
_resume = false;
118+
while (_resume == false) {
119+
LoadCell.update();
120+
if (Serial.available() > 0) {
121+
known_mass = Serial.parseFloat();
122+
if (known_mass != 0) {
123+
Serial.print("Known mass is: ");
124+
Serial.println(known_mass);
125+
_resume = true;
126+
}
127+
}
128+
}
129+
130+
LoadCell.refreshDataSet(); //refresh the dataset to be sure that the known mass is measured correct
131+
float newCalibrationValue = LoadCell.getNewCalibration(known_mass); //get the new calibration value
132+
133+
Serial.print("New calibration value has been set to: ");
134+
Serial.print(newCalibrationValue);
135+
Serial.println(", use this as calibration value (calFactor) in your project sketch.");
136+
Serial.print("Save this value to EEPROM adress ");
137+
Serial.print(calVal_eepromAdress);
138+
Serial.println("? y/n");
139+
140+
_resume = false;
141+
while (_resume == false) {
142+
if (Serial.available() > 0) {
143+
char inByte = Serial.read();
144+
if (inByte == 'y') {
145+
#if defined(ESP8266)|| defined(ESP32)
146+
EEPROM.begin(512);
147+
#endif
148+
EEPROM.put(calVal_eepromAdress, newCalibrationValue);
149+
#if defined(ESP8266)|| defined(ESP32)
150+
EEPROM.commit();
151+
#endif
152+
EEPROM.get(calVal_eepromAdress, newCalibrationValue);
153+
Serial.print("Value ");
154+
Serial.print(newCalibrationValue);
155+
Serial.print(" saved to EEPROM address: ");
156+
Serial.println(calVal_eepromAdress);
157+
_resume = true;
158+
159+
}
160+
else if (inByte == 'n') {
161+
Serial.println("Value not saved to EEPROM");
162+
_resume = true;
163+
}
164+
}
165+
}
166+
167+
Serial.println("End calibration");
168+
Serial.println("***");
169+
Serial.println("To re-calibrate, send 'r' from serial monitor.");
170+
Serial.println("For manual edit of the calibration value, send 'c' from serial monitor.");
171+
Serial.println("***");
172+
}
173+
174+
void changeSavedCalFactor() {
175+
float oldCalibrationValue = LoadCell.getCalFactor();
176+
boolean _resume = false;
177+
Serial.println("***");
178+
Serial.print("Current value is: ");
179+
Serial.println(oldCalibrationValue);
180+
Serial.println("Now, send the new value from serial monitor, i.e. 696.0");
181+
float newCalibrationValue;
182+
while (_resume == false) {
183+
if (Serial.available() > 0) {
184+
newCalibrationValue = Serial.parseFloat();
185+
if (newCalibrationValue != 0) {
186+
Serial.print("New calibration value is: ");
187+
Serial.println(newCalibrationValue);
188+
LoadCell.setCalFactor(newCalibrationValue);
189+
_resume = true;
190+
}
191+
}
192+
}
193+
_resume = false;
194+
Serial.print("Save this value to EEPROM adress ");
195+
Serial.print(calVal_eepromAdress);
196+
Serial.println("? y/n");
197+
while (_resume == false) {
198+
if (Serial.available() > 0) {
199+
char inByte = Serial.read();
200+
if (inByte == 'y') {
201+
#if defined(ESP8266)|| defined(ESP32)
202+
EEPROM.begin(512);
203+
#endif
204+
EEPROM.put(calVal_eepromAdress, newCalibrationValue);
205+
#if defined(ESP8266)|| defined(ESP32)
206+
EEPROM.commit();
207+
#endif
208+
EEPROM.get(calVal_eepromAdress, newCalibrationValue);
209+
Serial.print("Value ");
210+
Serial.print(newCalibrationValue);
211+
Serial.print(" saved to EEPROM address: ");
212+
Serial.println(calVal_eepromAdress);
213+
_resume = true;
214+
}
215+
else if (inByte == 'n') {
216+
Serial.println("Value not saved to EEPROM");
217+
_resume = true;
218+
}
219+
}
220+
}
221+
Serial.println("End change calibration value");
222+
Serial.println("***");
223+
}

0 commit comments

Comments
 (0)