Skip to content

Commit

Permalink
1.2.0
Browse files Browse the repository at this point in the history
  • Loading branch information
olkal committed Apr 18, 2020
1 parent 1159dfe commit 621f999
Show file tree
Hide file tree
Showing 11 changed files with 679 additions and 390 deletions.
9 changes: 4 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@

#18.04.2020: New version 1.2.0!
Latest release and change log here: https://github.com/olkal/HX711_ADC/releases

This an Arduino library for the HX711 24-bit ADC for weight scales.
Expand All @@ -16,16 +16,15 @@ Selectable values in the config.h file:

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.

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.
On fabricated 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.
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.
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.
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.

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.

Measuring units: Adjust the scaling factor with the function setCalFactor(float) in setup, so that the "readable" output matches your preferred unit.

Hardware and ADC noise:
Wires between HX711 and load cell should be twisted and kept as short as possible.
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.
The Sparkfun module seems to differ from most other available modules as it has some additional components for noise reduction.

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.
277 changes: 158 additions & 119 deletions examples/Calibration/Calibration.ino
Original file line number Diff line number Diff line change
@@ -1,183 +1,222 @@
//-------------------------------------------------------------------------------------
// HX711_ADC.h
// Arduino master library for HX711 24-Bit Analog-to-Digital Converter for Weigh Scales
// Olav Kallhovd sept2017
// Tested with : HX711 asian module on channel A and YZC-133 3kg load cell
// Tested with MCU : Arduino Nano, ESP8266
//-------------------------------------------------------------------------------------
// This is an example sketch on how to use this library
// Settling time (number of samples) and data filtering can be adjusted in the config.h file

// This example shows how to calibrate the load cell and optionally save the calibration
// value to EEPROM, and also how to change the value.
// The value can later be fetched from EEPROM in your project sketch.
/*
-------------------------------------------------------------------------------------
HX711_ADC
Arduino library for HX711 24-Bit Analog-to-Digital Converter for Weight Scales
Olav Kallhovd sept2017
-------------------------------------------------------------------------------------
*/

/*
This example file shows how to calibrate the load cell and optionally store the calibration
value in EEPROM, and also how to change the value manually.
The result value can then later be included in your project sketch or fetched from EEPROM.
To implement calibration in your project sketch the simplified procedure is as follow:
LoadCell.tare();
//place known mass
LoadCell.refreshDataSet();
float newCalibrationValue = LoadCell.getNewCalibration(known_mass);
*/

#include <HX711_ADC.h>
#include <EEPROM.h>

//HX711 constructor (dout pin, sck pin):
HX711_ADC LoadCell(4, 5);
//pins:
const int HX711_dout = 4; //mcu > HX711 dout pin
const int HX711_sck = 5; //mcu > HX711 sck pin

int eepromAdress = 0;
//HX711 constructor:
HX711_ADC LoadCell(HX711_dout, HX711_sck);

const int calVal_eepromAdress = 0;
long t;

void setup() {
Serial.begin(57600); delay(10);
Serial.println();
Serial.println("Starting...");

LoadCell.begin();
long stabilizingtime = 2000; // preciscion right after power-up can be improved by adding a few seconds of stabilizing time
boolean _tare = false; //set this to false if you don't want tare to be performed in the next step
LoadCell.start(stabilizingtime, _tare);
if (LoadCell.getTareTimeoutFlag() || LoadCell.getSignalTimeoutFlag()) {
Serial.println("Timeout, check MCU>HX711 wiring and pin designations");
while (1);
}
else {
LoadCell.setCalFactor(1.0); // user set calibration value (float), initial value 1.0 may be used for this sketch
Serial.println("Startup is complete");
}
while (!LoadCell.update());
calibrate(); //start calibration procedure
}

void loop() {
static boolean newDataReady = 0;
const int serialPrintInterval = 0; //increase value to slow down serial print activity

// check for new data/start next conversion:
if (LoadCell.update()) newDataReady = true;

// get smoothed value from the dataset:
if (newDataReady) {
if (millis() > t + serialPrintInterval) {
float i = LoadCell.getData();
Serial.print("Load_cell output val: ");
Serial.println(i);
newDataReady = 0;
t = millis();
}
}

// receive command from serial terminal
if (Serial.available() > 0) {
float i;
char inByte = Serial.read();
if (inByte == 't') LoadCell.tareNoDelay(); //tare
else if (inByte == 'r') calibrate(); //calibrate
else if (inByte == 'c') changeSavedCalFactor(); //edit calibration value manually
}

// check if last tare operation is complete
if (LoadCell.getTareStatus() == true) {
Serial.println("Tare complete");
}

}

void calibrate() {
Serial.println("***");
Serial.println("Start calibration:");
Serial.println("It is assumed that the mcu was started with no load applied to the load cell.");
Serial.println("Now, place your known mass on the loadcell,");
Serial.println("then send the weight of this mass (i.e. 100.0) from serial monitor.");
float m = 0;
boolean f = 0;
while (f == 0) {
Serial.println("Place the load cell an a level stable surface.");
Serial.println("Remove any load applied to the load cell.");
Serial.println("Send 't' from serial monitor to set the tare offset.");

boolean _resume = false;
while (_resume == false) {
LoadCell.update();
if (Serial.available() > 0) {
m = Serial.parseFloat();
if (m != 0) {
Serial.print("Known mass is: ");
Serial.println(m);
f = 1;
if (Serial.available() > 0) {
float i;
char inByte = Serial.read();
if (inByte == 't') LoadCell.tareNoDelay();
}
else {
Serial.println("Invalid value");
}
if (LoadCell.getTareStatus() == true) {
Serial.println("Tare complete");
_resume = true;
}
}

Serial.println("Now, place your known mass on the loadcell.");
Serial.println("Then send the weight of this mass (i.e. 100.0) from serial monitor.");

float known_mass = 0;
_resume = false;
while (_resume == false) {
LoadCell.update();
if (Serial.available() > 0) {
known_mass = Serial.parseFloat();
if (known_mass != 0) {
Serial.print("Known mass is: ");
Serial.println(known_mass);
_resume = true;
}
}
}
float c = LoadCell.getData() / m;
LoadCell.setCalFactor(c);
Serial.print("Calculated calibration value is: ");
Serial.print(c);
Serial.println(", use this in your project sketch");
f = 0;

LoadCell.refreshDataSet(); //refresh the dataset to be sure that the known mass is measured correct
float newCalibrationValue = LoadCell.getNewCalibration(known_mass); //get the new calibration value

Serial.print("New calibration value has been set to: ");
Serial.print(newCalibrationValue);
Serial.println(", use this as calibration value (calFactor) in your project sketch.");
Serial.print("Save this value to EEPROM adress ");
Serial.print(eepromAdress);
Serial.print(calVal_eepromAdress);
Serial.println("? y/n");
while (f == 0) {

_resume = false;
while (_resume == false) {
if (Serial.available() > 0) {
char inByte = Serial.read();
if (inByte == 'y') {
#if defined(ESP8266)
#if defined(ESP8266)|| defined(ESP32)
EEPROM.begin(512);
#endif
EEPROM.put(eepromAdress, c);
#if defined(ESP8266)
#endif
EEPROM.put(calVal_eepromAdress, newCalibrationValue);
#if defined(ESP8266)|| defined(ESP32)
EEPROM.commit();
#endif
EEPROM.get(eepromAdress, c);
#endif
EEPROM.get(calVal_eepromAdress, newCalibrationValue);
Serial.print("Value ");
Serial.print(c);
Serial.print(newCalibrationValue);
Serial.print(" saved to EEPROM address: ");
Serial.println(eepromAdress);
f = 1;
Serial.println(calVal_eepromAdress);
_resume = true;

}
else if (inByte == 'n') {
Serial.println("Value not saved to EEPROM");
f = 1;
_resume = true;
}
}
}

Serial.println("End calibration");
Serial.println("For manual edit, send 'c' from serial monitor");
Serial.println("***");
Serial.println("To re-calibrate, send 'r' from serial monitor.");
Serial.println("For manual edit of the calibration value, send 'c' from serial monitor.");
Serial.println("***");
}

void changeSavedCalFactor() {
float c = LoadCell.getCalFactor();
boolean f = 0;
float oldCalibrationValue = LoadCell.getCalFactor();
boolean _resume = false;
Serial.println("***");
Serial.print("Current value is: ");
Serial.println(c);
Serial.println(oldCalibrationValue);
Serial.println("Now, send the new value from serial monitor, i.e. 696.0");
while (f == 0) {
float newCalibrationValue;
while (_resume == false) {
if (Serial.available() > 0) {
c = Serial.parseFloat();
if (c != 0) {
newCalibrationValue = Serial.parseFloat();
if (newCalibrationValue != 0) {
Serial.print("New calibration value is: ");
Serial.println(c);
LoadCell.setCalFactor(c);
f = 1;
}
else {
Serial.println("Invalid value, exit");
return;
Serial.println(newCalibrationValue);
LoadCell.setCalFactor(newCalibrationValue);
_resume = true;
}
}
}
f = 0;
_resume = false;
Serial.print("Save this value to EEPROM adress ");
Serial.print(eepromAdress);
Serial.print(calVal_eepromAdress);
Serial.println("? y/n");
while (f == 0) {
while (_resume == false) {
if (Serial.available() > 0) {
char inByte = Serial.read();
if (inByte == 'y') {
#if defined(ESP8266)
#if defined(ESP8266)|| defined(ESP32)
EEPROM.begin(512);
#endif
EEPROM.put(eepromAdress, c);
#if defined(ESP8266)
#endif
EEPROM.put(calVal_eepromAdress, newCalibrationValue);
#if defined(ESP8266)|| defined(ESP32)
EEPROM.commit();
#endif
EEPROM.get(eepromAdress, c);
#endif
EEPROM.get(calVal_eepromAdress, newCalibrationValue);
Serial.print("Value ");
Serial.print(c);
Serial.print(newCalibrationValue);
Serial.print(" saved to EEPROM address: ");
Serial.println(eepromAdress);
f = 1;
Serial.println(calVal_eepromAdress);
_resume = true;
}
else if (inByte == 'n') {
Serial.println("Value not saved to EEPROM");
f = 1;
_resume = true;
}
}
}
Serial.println("End change calibration value");
Serial.println("***");
}

void setup() {
Serial.begin(9600); delay(10);
Serial.println();
Serial.println("Starting...");
LoadCell.begin();
long stabilisingtime = 2000; // tare preciscion can be improved by adding a few seconds of stabilising time
LoadCell.start(stabilisingtime);
if (LoadCell.getTareTimeoutFlag()) {
Serial.println("Tare timeout, check MCU>HX711 wiring and pin designations");
}
else {
LoadCell.setCalFactor(1.0); // user set calibration value (float)
Serial.println("Startup + tare is complete");
}
while (!LoadCell.update());
calibrate();
}
void loop() {
//update() should be called at least as often as HX711 sample rate; >10Hz@10SPS, >80Hz@80SPS
//longer delay in sketch will reduce effective sample rate (be carefull with delay() in the loop)
LoadCell.update();

//get smoothed value from the data set
if (millis() > t + 250) {
float i = LoadCell.getData();
Serial.print("Load_cell output val: ");
Serial.println(i);
t = millis();
}

//receive from serial terminal
if (Serial.available() > 0) {
float i;
char inByte = Serial.read();
if (inByte == 't') LoadCell.tareNoDelay();
else if (inByte == 'c') changeSavedCalFactor();
}

//check if last tare operation is complete
if (LoadCell.getTareStatus() == true) {
Serial.println("Tare complete");
}

}
Loading

0 comments on commit 621f999

Please sign in to comment.