0.3.0 HX711

This commit is contained in:
rob tillaart 2021-11-16 17:42:29 +01:00
parent 36c3e468a0
commit b59bfcd56f
18 changed files with 281 additions and 73 deletions

View File

@ -2,6 +2,10 @@ compile:
# Choosing to run compilation tests on 2 different Arduino platforms
platforms:
- uno
- leonardo
- due
- zero
# - due
# - zero
# - leonardo
- m4
- esp32
# - esp8266
# - mega2560

View File

@ -4,11 +4,14 @@ name: Arduino CI
on: [push, pull_request]
jobs:
arduino_ci:
runTest:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
# - uses: Arduino-CI/action@latest
- uses: Arduino-CI/action@master
# Arduino-CI/action@v0.1.1
- uses: ruby/setup-ruby@v1
with:
ruby-version: 2.6
- run: |
gem install arduino_ci
arduino_ci.rb

View File

@ -1,7 +1,7 @@
//
// FILE: HX711.cpp
// AUTHOR: Rob Tillaart
// VERSION: 0.2.3
// VERSION: 0.3.0
// PURPOSE: Library for Loadcells for UNO
// URL: https://github.com/RobTillaart/HX711
//
@ -12,6 +12,9 @@
// 0.2.1 2020-12-28 add arduino-ci + unit test
// 0.2.2 2021-05-10 add read_median(), fix typo, add mode operandi
// 0.2.3 2021-05-26 add running_average() mode
// 0.3.0 2021-11-14 fix #11 shiftIn timing
// update build-CI, readme.md, badges
#include "HX711.h"
@ -28,7 +31,7 @@ HX711::~HX711() {}
void HX711::begin(uint8_t dataPin, uint8_t clockPin)
{
_dataPin = dataPin;
_dataPin = dataPin;
_clockPin = clockPin;
pinMode(_dataPin, INPUT);
@ -55,6 +58,11 @@ bool HX711::is_ready()
}
// from datasheet page 4
// When output data is not ready for retrieval,
// digital output pin DOUT is high. Serial clock
// input PD_SCK should be low. When DOUT goes
// to low, it indicates data is ready for retrieval.
float HX711::read()
{
// this waiting takes most time...
@ -69,9 +77,12 @@ float HX711::read()
noInterrupts();
// Pulse the clock pin 24 times to read the data.
v.data[2] = shiftIn(_dataPin, _clockPin, MSBFIRST);
v.data[1] = shiftIn(_dataPin, _clockPin, MSBFIRST);
v.data[0] = shiftIn(_dataPin, _clockPin, MSBFIRST);
// v.data[2] = shiftIn(_dataPin, _clockPin, MSBFIRST);
// v.data[1] = shiftIn(_dataPin, _clockPin, MSBFIRST);
// v.data[0] = shiftIn(_dataPin, _clockPin, MSBFIRST);
v.data[2] = _shiftIn();
v.data[1] = _shiftIn();
v.data[0] = _shiftIn();
// TABLE 3 page 4 datasheet
// only default verified, so other values not supported yet
@ -271,4 +282,27 @@ void HX711::power_up()
digitalWrite(_clockPin, LOW);
}
// MSB_FIRST optimized shiftIn
// see datasheet page 5 for timing
uint8_t HX711::_shiftIn()
{
uint8_t value = 0;
uint8_t mask = 0x80;
while(mask > 0)
{
digitalWrite(_clockPin, HIGH);
delayMicroseconds(1); // T2 >= 0.2 us
if (digitalRead(_dataPin) == HIGH)
{
value |= mask;
}
digitalWrite(_clockPin, LOW);
delayMicroseconds(1); // keep duty cycle ~50%
mask >>= 1;
}
return value;
}
// -- END OF FILE --

View File

@ -2,7 +2,7 @@
//
// FILE: HX711.h
// AUTHOR: Rob Tillaart
// VERSION: 0.2.3
// VERSION: 0.3.0
// PURPOSE: Library for Loadcells for UNO
// URL: https://github.com/RobTillaart/HX711
//
@ -15,7 +15,7 @@
#include "Arduino.h"
#define HX711_LIB_VERSION (F("0.2.3"))
#define HX711_LIB_VERSION (F("0.3.0"))
const uint8_t HX711_AVERAGE_MODE = 0x00;
@ -39,7 +39,7 @@ public:
void reset();
// checks if loadcell is ready to read.
// checks if load cell is ready to read.
bool is_ready();
// wait until ready,
@ -142,6 +142,7 @@ private:
uint8_t _mode = 0;
void _insertSort(float * array, uint8_t size);
uint8_t _shiftIn();
};
// -- END OF FILE --

View File

@ -1,22 +1,39 @@
[![Arduino CI](https://github.com/RobTillaart/HX711/workflows/Arduino%20CI/badge.svg)](https://github.com/marketplace/actions/arduino_ci)
[![Arduino-lint](https://github.com/RobTillaart/HX711/actions/workflows/arduino-lint.yml/badge.svg)](https://github.com/RobTillaart/HX711/actions/workflows/arduino-lint.yml)
[![JSON check](https://github.com/RobTillaart/HX711/actions/workflows/jsoncheck.yml/badge.svg)](https://github.com/RobTillaart/HX711/actions/workflows/jsoncheck.yml)
[![License: MIT](https://img.shields.io/badge/license-MIT-green.svg)](https://github.com/RobTillaart/HX711/blob/master/LICENSE)
[![GitHub release](https://img.shields.io/github/release/RobTillaart/HX711.svg?maxAge=3600)](https://github.com/RobTillaart/HX711/releases)
# HX711
Arduino library for HX711 24 bit ADC used for load cells and scales.
Arduino library for HX711 24 bit ADC used for load cells and scales.
## Description
This HX711 library has an interface which is a superset of a library made by bogde.
This HX711 library has an interface which is a superset of a library made by Bogde.
Some missing functions were added to get more info from the lib.
Another important difference is that this library uses floats. The 23 bits mantisse
of the IEE754 float matches the 24 bit ADC very well. Furthermore it gave a smaller
footprint.
Another important difference is that this library uses floats.
The 23 bits mantissa of the IEE754 float matches the 24 bit ADC very well.
Furthermore it gave a smaller footprint.
### Breaking change 0.3.0
In issue #11 it became clear that the timing of the default **shiftIn()** function that
reads the value of the internal ADC was too fast on some processor boards for the HX711.
This resulted in missing the first = sign bit and value read could be a factor two
higher than should. If one calibrated the sensor this would be compensated with the
factor that is derived in the calibration process.
In 0.3.0 a dedicated **shiftIn()** function is added into this library that uses hard
coded delays to keep the timing of the clock within datasheet parameters.
This should guarantee that the sign bit is read correctly on all platforms.
Drawback is that reading the HX711 takes an ~50 extra microseconds.
How much this affects performance is to be investigated.
## Main flow
@ -37,26 +54,105 @@ Steps to take for calibration
1. save the offset and scale for later use e.g. EEPROM.
## Pricing
## Interface
#### Base
- **HX711()** constructor.
- **~HX711()**
- **void begin(uint8_t dataPin, uint8_t clockPin)** sets a fixed gain 128 for now.
- **void reset()** set internal state to start condition.
- **bool is_ready()** checks if load cell is ready to read.
- **void wait_ready(uint32_t ms = 0)** wait until ready, check every ms.
- **bool wait_ready_retry(uint8_t retries = 3, uint32_t ms = 0)** wait max retries.
- **bool wait_ready_timeout(uint32_t timeout = 1000, uint32_t ms = 0)** wait max timeout.
- **float read()** raw read.
- **float read_average(uint8_t times = 10)** get average of times raw reads. times = 1 or more.
- **float read_median(uint8_t times = 7)** get median of multiple raw reads.
times = 3..15 - odd numbers preferred.
- **float read_medavg(uint8_t times = 7)** get average of "middle half" of multiple raw reads.
times = 3..15 - odd numbers preferred.
- **float read_runavg(uint8_t times = 7, float alpha = 0.5)** get running average over times measurements.
The weight alpha can be set to any value between 0 and 1, times >= 1.
- **uint32_t last_read()** returns timestamp in milliseconds.
#### Gain
read datasheet - see also Connections HX711 below
- **void set_gain(uint8_t gain = 128)** values: 128 (default), 64 32 - only 128 tested & verified.
- **uint8_t get_gain()** returns set gain.
#### Mode
Get and set the operational mode for get_value() and indirect get_units().
In median and medavg mode only 3..15 samples are allowed.
- **void set_average_mode()**
- **void set_median_mode()**
- **void set_medavg_mode()**
- **void set_runavg_mode()** default alpha = 0.5.
- **uint8_t get_mode()**
#### Get values
get values corrected for offset and scale
- **float get_value(uint8_t times = 1)** read value, corrected for offset.
- **float get_units(uint8_t times = 1)** read value, converted to proper units.
- **void set_scale(float scale = 1.0)** set scale factor; scale > 0.
- **float get_scale()** returns set scale factor.
- **void set_offset(long offset = 0)** idem.
- **long get_offset()** idem.
#### Tare & calibration
Steps to take for calibration
1. clear the scale
1. call tare() to set the zero offset
1. put a known weight on the scale
1. call calibrate_scale(weight)
1. scale is calculated.
1. save the offset and scale for later use e.g. EEPROM.
- **void tare(uint8_t times = 10)** call tare to calibrate zero level
- **float get_tare()** idem.
- **bool tare_set()** checks if a tare has been set.
- **void calibrate_scale(uint16_t weight, uint8_t times = 10)** idem.
#### Power management
- **void power_down()** idem.
- **void power_up()** idem.
#### Pricing
Some price functions were added to make it easy to use this library
for pricing goods or for educational purposes. These functions are under discussion
if they will stay. Another set of function to add weights together didn't make it in
the 0.2.0 release, it is on a todo list.
for pricing goods or for educational purposes.
These functions are under discussion if they will stay.
For weight conversion functions see https://github.com/RobTillaart/weight
- **float get_price(uint8_t times = 1)** idem.
- **void set_unit_price(float price = 1.0)** idem.
- **float get_unit_price()** idem.
## Notes
### Scale values for loadcells
### Scale values for load cells
These scale values worked pretty well with a set of loadcells,
Use calibrate to find your values.
These scale values worked pretty well with a set of load cells I have,
Use calibrate to find your favourite values.
- 5 KG loadcell scale.set_scale(420.52);
- 20 KG loadcell scale.set_scale(127.15);
- 5 KG load cell scale.set_scale(420.52);
- 20 KG load cell scale.set_scale(127.15);
### Connections HX711
@ -67,31 +163,32 @@ Use calibrate to find your values.
### Connections
| HX711 Pin | Color |
|:----:|:----:|
| E+ | red |
| E- | black |
| A- | white |
| A+ | green |
| B- | not connected |
| B+ | not connected |
| HX711 Pin | Colour |
|:---------:|:--------------:|
| E+ | red |
| E- | black |
| A- | white |
| A+ | green |
| B- | not connected |
| B+ | not connected |
| HX711 Pin | Color |
|:----:|:----:|
| E+ | red |
| E- | black |
| A- | blue |
| A+ | white |
| B- | not connected |
| B+ | not connected |
| HX711 Pin | Colour |
|:---------:|:--------------:|
| E+ | red |
| E- | black |
| A- | blue |
| A+ | white |
| B- | not connected |
| B+ | not connected |
### Temperature
Loadcells do have a temperature related error.
Load cells do have a temperature related error. (check datasheet)
This can be reduced by doing the calibration and take the tare
at the temperature one also does the measurements.
at the temperature one also uses for the measurements.
Another way to handle this is to add a good temperature sensor
(e.g. DS18B20, SHT85) and compensate for the temperature
@ -101,3 +198,17 @@ differences in your code.
## Operation
See examples
## Future
- update documentation
- add examples
- test different load cells
- optimize the build-in **ShiftIn()** function to improve performance again.
#### the adding scale
- void weight_clr(), void weight_add(), float weight_get() - adding scale

View File

@ -9,6 +9,7 @@
// 0.1.0 2020-06-16 initial version
//
// to be tested
#include "HX711.h"
@ -20,6 +21,7 @@ uint8_t clockPin = 7;
float w1, w2, previous = 0;
void setup()
{
Serial.begin(115200);
@ -33,16 +35,17 @@ void setup()
Serial.print("UNITS: ");
Serial.println(scale.get_units(10));
// loadcell factor 20 KG
// load cell factor 20 KG
// scale.set_scale(127.15);
// loadcell factor 5 KG
scale.set_scale(420.0983);
// load cell factor 5 KG
scale.set_scale(420.0983); // TODO you need to calibrate this yourself.
scale.tare();
Serial.print("UNITS: ");
Serial.println(scale.get_units(10));
}
void loop()
{
// read until stable
@ -71,4 +74,6 @@ void loop()
delay(100);
}
// END OF FILE
// -- END OF FILE --

View File

@ -9,6 +9,7 @@
// 0.1.0 2020-06-16 initial version
//
#include "HX711.h"
HX711 scale;
@ -54,6 +55,7 @@ void setup()
scale.set_unit_price(0.031415); // we only have one price
}
void loop()
{
Serial.print("UNITS: ");
@ -63,4 +65,6 @@ void loop()
delay(250);
}
// END OF FILE
// -- END OF FILE --

View File

@ -9,6 +9,7 @@
// 0.1.0 2020-06-16 initial version
//
#include "HX711.h"
HX711 scale;
@ -48,11 +49,13 @@ void setup()
Serial.println(scale.get_units(10));
Serial.println("\nScale is calibrated, press a key to continue");
// Serial.println(scale.get_scale());
// Serial.println(scale.get_offset());
while(!Serial.available());
while(Serial.available()) Serial.read();
}
void loop()
{
Serial.print("UNITS: ");
@ -60,4 +63,6 @@ void loop()
delay(250);
}
// END OF FILE
// -- END OF FILE --

View File

@ -9,6 +9,7 @@
// 0.1.0 2020-06-15 initial version
//
#include "HX711.h"
HX711 scale;
@ -19,6 +20,7 @@ uint8_t clockPin = 7;
uint32_t start, stop;
volatile float f;
void setup()
{
Serial.begin(115200);
@ -34,11 +36,11 @@ void setup()
measure(10);
// TODO find a nice solution for this calibration..
// loadcell factor 20 KG
// load cell factor 20 KG
// scale.set_scale(127.15);
// loadcell factor 5 KG
scale.set_scale(420.0983);
// load cell factor 5 KG
scale.set_scale(420.0983); // TODO you need to calibrate this yourself.
// reset the scale to zero = 0
scale.tare();
@ -54,6 +56,11 @@ void setup()
delay(1000);
measure(10);
/*
* PERFORMANCE
* 100x get_units(1) = 9404352 (UNO)
* VAL: 0.05
*/
Serial.println("\nPERFORMANCE");
start = micros();
f = 0;
@ -75,9 +82,9 @@ void setup()
}
Serial.print(" VAL:");
Serial.println(f * 0.01, 4);
}
void loop()
{
// continuous scale 4x per second
@ -86,6 +93,7 @@ void loop()
delay(250);
}
void measure(uint8_t cnt)
{
Serial.print(" RAW: ");
@ -100,3 +108,4 @@ void measure(uint8_t cnt)
// -- END OF FILE --

View File

@ -9,6 +9,7 @@
// 0.1.0 2020-06-15 initial version
//
#include "HX711.h"
HX711 scale;
@ -19,6 +20,7 @@ uint8_t clockPin = 7;
uint32_t start, stop;
volatile float f;
void setup()
{
Serial.begin(115200);
@ -30,21 +32,23 @@ void setup()
scale.begin(dataPin, clockPin);
// TODO find a nice solution for this calibration..
// loadcell factor 20 KG
// load cell factor 20 KG
// scale.set_scale(127.15);
// loadcell factor 5 KG
scale.set_scale(420.0983);
// load cell factor 5 KG
scale.set_scale(420.0983); // TODO you need to calibrate this yourself.
// reset the scale to zero = 0
scale.tare();
measure();
}
void loop()
{
}
void measure()
{
Serial.println("Counting get_units() calls for 1 minute...");
@ -66,3 +70,4 @@ void measure()
// -- END OF FILE --

View File

@ -9,6 +9,7 @@
// 0.1.0 2020-06-15 initial version
//
#include "HX711.h"
HX711 scale;
@ -19,6 +20,7 @@ uint8_t clockPin = 7;
uint32_t start, stop;
volatile float f;
void setup()
{
Serial.begin(115200);
@ -30,14 +32,15 @@ void setup()
scale.begin(dataPin, clockPin);
// TODO find a nice solution for this calibration..
// loadcell factor 20 KG
// load cell factor 20 KG
// scale.set_scale(127.15);
// loadcell factor 5 KG
scale.set_scale(420.0983);
// load cell factor 5 KG
scale.set_scale(420.0983); // TODO you need to calibrate this yourself.
// reset the scale to zero = 0
scale.tare();
}
void loop()
{
// continuous scale 4x per second
@ -46,4 +49,6 @@ void loop()
delay(250);
}
// -- END OF FILE --

View File

@ -9,6 +9,7 @@
// 0.1.0 2021-05-10 initial version
//
#include "HX711.h"
HX711 scale;
@ -19,6 +20,7 @@ uint8_t clockPin = 7;
uint32_t start, stop;
volatile float f;
void setup()
{
Serial.begin(115200);
@ -30,10 +32,10 @@ void setup()
scale.begin(dataPin, clockPin);
// TODO find a nice solution for this calibration..
// loadcell factor 20 KG
scale.set_scale(127.15);
// load cell factor 20 KG
scale.set_scale(127.15); // TODO you need to calibrate this yourself.
// loadcell factor 5 KG
// load cell factor 5 KG
// scale.set_scale(420.0983);
// reset the scale to zero = 0
scale.tare();
@ -52,6 +54,7 @@ void setup()
Serial.println(f, 2);
}
void loop()
{
// continuous scale once per second
@ -62,3 +65,4 @@ void loop()
// -- END OF FILE --

View File

@ -9,6 +9,7 @@
// 0.1.0 2021-05-13 initial version
//
#include "HX711.h"
HX711 scale;
@ -19,6 +20,7 @@ uint8_t clockPin = 7;
uint32_t start, stop;
volatile float f;
void setup()
{
Serial.begin(115200);
@ -52,6 +54,7 @@ void setup()
Serial.println(f, 2);
}
void loop()
{
// continuous scale once per second
@ -60,4 +63,6 @@ void loop()
delay(1000);
}
// -- END OF FILE --

View File

@ -9,6 +9,7 @@
// 0.1.0 2021-05-13 initial version
//
#include "HX711.h"
HX711 scale;
@ -19,6 +20,7 @@ uint8_t clockPin = 7;
uint32_t start, stop;
volatile float f;
void setup()
{
Serial.begin(115200);
@ -91,8 +93,11 @@ void setup()
Serial.println("\ndone...");
}
void loop()
{
}
// -- END OF FILE --

View File

@ -1,8 +1,9 @@
# Syntax Coloring Map For HX711
# Syntax Colouring Map For HX711
# Datatypes (KEYWORD1)
# Data types (KEYWORD1)
HX711 KEYWORD1
# Methods and Functions (KEYWORD2)
begin KEYWORD2
reset KEYWORD2
@ -16,6 +17,7 @@ read KEYWORD2
read_average KEYWORD2
read_median KEYWORD2
read_medavg KEYWORD2
read_runavg KEYWORD2
set_average_mode KEYWORD2
set_median_mode KEYWORD2
@ -49,8 +51,13 @@ get_price KEYWORD2
set_unit_price KEYWORD2
get_unit_price KEYWORD2
# Instances (KEYWORD2)
# Constants (LITERAL1)
HX711_LIB_VERSION LITERAL1
HX711_AVERAGE_MODE LITERAL1
HX711_MEDIAN_MODE LITERAL1
HX711_MEDAVG_MODE LITERAL1
HX711_RUNAVG_MODE LITERAL1

View File

@ -15,7 +15,7 @@
"type": "git",
"url": "https://github.com/RobTillaart/HX711"
},
"version": "0.2.3",
"version": "0.3.0",
"license": "MIT",
"frameworks": "arduino",
"platforms": "*"

View File

@ -1,5 +1,5 @@
name=HX711
version=0.2.3
version=0.3.0
author=Rob Tillaart <rob.tillaart@gmail.com>
maintainer=Rob Tillaart <rob.tillaart@gmail.com>
sentence=Arduino library for HX711 loadcell amplifier

View File

@ -53,6 +53,7 @@ unittest(test_constructor)
assertEqual(0, scale.last_read());
}
unittest(test_gain)
{
HX711 scale;