0.3.1 FastShiftIn

This commit is contained in:
rob tillaart 2022-11-06 20:24:21 +01:00
parent 8f8e307b34
commit da4aa5057d
11 changed files with 288 additions and 149 deletions

View File

@ -1,3 +1,18 @@
platforms:
rpipico:
board: rp2040:rp2040:rpipico
package: rp2040:rp2040
gcc:
features:
defines:
- ARDUINO_ARCH_RP2040
warnings:
flags:
packages:
rp2040:rp2040:
url: https://github.com/earlephilhower/arduino-pico/releases/download/global/package_rp2040_index.json
compile:
# Choosing to run compilation tests on 2 different Arduino platforms
platforms:
@ -9,3 +24,5 @@ compile:
- esp32
# - esp8266
# - mega2560
- rpipico

View File

@ -1,110 +1,61 @@
# Change Log
# Change Log HX711
All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](http://keepachangelog.com/)
and this project adheres to [Semantic Versioning](http://semver.org/).
## [0.3.4]
- simplified changelog
- add RP2040 to build-CI
- refactored **set_gain()** to return bool to confirm valid parameter.
- add constants for **set_gain()**
- add unit test for constants.
- improved unit test for **set_gain()**
- updated readme.md
## [0.3.3] - 2022-03-16
### Added
- add HX711_RAW_MODE
### Changed
- update documentation
### Fixed
## [0.3.2] - 2022-03-16
### Added
- add example HX_set_persistent.ino. (won't work for m4)
- add CHANGELOG.md
### Changed
- minor edits
### Fixed
## [0.3.1] - 2021-12-19
### Added
### Changed
- update library.json
- license
- minor edits
### Fixed
## [0.3.0] - 2021-11-14
### Added
### Changed
- update build-CI
- readme.md incl. badges
### Fixed
- fix #11 shiftIn timing
## [0.2.3] - 2021-05-26
----
### Added
## [0.2.3] - 2021-05-26
- add running_average() mode
### Changed
### Fixed
## [0.2.2] - 2021-05-10
### Added
- add read_median()
- add mode operandi
### Changed
### Fixed
- fix typo
## [0.2.1] - 2020-12-28
### Added
- add arduino-ci
- unit test
### Changed
### Fixed
## [0.2.0] - 2020-06-15
### Added
- add price functions
### Changed
- some refactor
### Fixed
----
## [0.1.1] - 2019-09-09
### Added
### Changed
- change long to float (reduce footprint)
### Fixed
## [0.1.0] - 2019-09-04
### Added
- initial version
### Changed
### Fixed

View File

@ -1,10 +1,11 @@
//
// FILE: HX711.cpp
// AUTHOR: Rob Tillaart
// VERSION: 0.3.3
// VERSION: 0.3.4
// PURPOSE: Library for load cells for UNO
// URL: https://github.com/RobTillaart/HX711
//
// HISTORY: see CHANGELOG.md
#include "HX711.h"
@ -34,9 +35,11 @@ void HX711::begin(uint8_t dataPin, uint8_t clockPin)
void HX711::reset()
{
power_down();
power_up();
_offset = 0;
_scale = 1;
_gain = 128;
_gain = HX711_CHANNEL_A_GAIN_128;
_lastRead = 0;
_mode = HX711_AVERAGE_MODE;
}
@ -76,13 +79,24 @@ float HX711::read()
v.data[0] = _shiftIn();
// TABLE 3 page 4 datasheet
// only default verified, so other values not supported yet
uint8_t m = 1; // default _gain == 128
if (_gain == 64) m = 3;
if (_gain == 32) m = 2;
//
// CLOCK CHANNEL GAIN m
// ------------------------------------
// 25 A 128 1 // default
// 26 B 32 2
// 27 A 64 3
//
// only default 128 verified,
// selection goes through the set_gain(gain)
//
uint8_t m = 1;
if (_gain == HX711_CHANNEL_A_GAIN_128) m = 1;
else if (_gain == HX711_CHANNEL_A_GAIN_64) m = 3;
else if (_gain == HX711_CHANNEL_B_GAIN_32) m = 2;
while (m > 0)
{
// delayMicroSeconds(1) needed for fast processors?
digitalWrite(_clockPin, HIGH);
digitalWrite(_clockPin, LOW);
m--;
@ -99,6 +113,32 @@ float HX711::read()
}
// note: if parameter gain == 0xFF40 some compilers
// will map that to 0x40 == HX711_CHANNEL_A_GAIN_64;
// solution: use uint32_t or larger parameters everywhere.
// note that changing gain/channel may take up to 400 ms (page 3)
bool HX711::set_gain(uint8_t gain, bool forced)
{
if ( (not forced) && (_gain == gain)) return true;
switch(gain)
{
case HX711_CHANNEL_B_GAIN_32:
case HX711_CHANNEL_A_GAIN_64:
case HX711_CHANNEL_A_GAIN_128:
_gain = gain;
read(); // next user read() is from right channel / gain
return true;
}
return false; // unchanged, but incorrect value.
}
uint8_t HX711::get_gain()
{
return _gain;
}
// assumes tare() has been set.
void HX711::calibrate_scale(uint16_t weight, uint8_t times)
{
@ -268,8 +308,9 @@ float HX711::get_units(uint8_t times)
void HX711::power_down()
{
digitalWrite(_clockPin, LOW);
// at least 60 us HIGH
digitalWrite(_clockPin, HIGH);
delayMicroseconds(64);
}

View File

@ -2,20 +2,20 @@
//
// FILE: HX711.h
// AUTHOR: Rob Tillaart
// VERSION: 0.3.3
// VERSION: 0.3.4
// PURPOSE: Library for load cells for Arduino
// URL: https://github.com/RobTillaart/HX711
//
// HISTORY: see CHANGELOG.md
//
// NOTES
// Superset of interface of HX711 class of Bogde
// float instead of long as float has 23 bits mantissa.
// NOTES
// Superset of interface of HX711 class of Bogde
// float instead of long as float has 23 bits mantissa.
#include "Arduino.h"
#define HX711_LIB_VERSION (F("0.3.3"))
#define HX711_LIB_VERSION (F("0.3.4"))
const uint8_t HX711_AVERAGE_MODE = 0x00;
@ -30,6 +30,12 @@ const uint8_t HX711_RUNAVG_MODE = 0x03;
const uint8_t HX711_RAW_MODE = 0x04;
// supported values for set_gain()
const uint8_t HX711_CHANNEL_A_GAIN_128 = 128; // default
const uint8_t HX711_CHANNEL_A_GAIN_64 = 64;
const uint8_t HX711_CHANNEL_B_GAIN_32 = 32;
class HX711
{
public:
@ -99,12 +105,25 @@ public:
// CORE "CONSTANTS" -> read datasheet
// GAIN values: 128, 64 32 [only 128 tested & verified]
void set_gain(uint8_t gain = 128) { _gain = gain; };
uint8_t get_gain() { return _gain; };
// CHANNEL GAIN notes
// -------------------------------------
// A 128 default, tested
// A 64
// B 32
// returns true ==> parameter gain is valid
// returns false ==> parameter gain is invalid ==> no change.
// note that changing gain/channel takes up to 400 ms (page 3)
// if forced == true, the gain will be forced set
// even it is already the right value
bool set_gain(uint8_t gain = HX711_CHANNEL_A_GAIN_128, bool forced = false);
uint8_t get_gain();
// SCALE > 0
void set_scale(float scale = 1.0) { _scale = 1.0 / scale; };
float get_scale() { return 1.0 / _scale; };
// OFFSET > 0
void set_offset(long offset = 0) { _offset = offset; };
long get_offset() { return _offset; };
@ -151,4 +170,6 @@ private:
uint8_t _shiftIn();
};
// -- END OF FILE --
// -- END OF FILE --

View File

@ -13,26 +13,26 @@ 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 by [Bogde](https://github.com/bogde/HX711).
Some missing functions were added to get more info from the library.
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.
The 23 bits mantissa of the IEEE754 float matches the 24 bit ADC very well.
Furthermore using floats gave a smaller footprint on the Arduino UNO.
### 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 issue #11 it became clear that the timing of the default **shiftIn()** function to
read the value of the internal ADC was too fast on some processor boards for the HX711.
This resulted in missing the first (= sign) bit or the value read could be a factor two
higher than it 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.
coded delayMicroseconds to keep the timing of the clock within HX711 datasheet parameters.
This should guarantee that the sign bit is always read correctly on all platforms.
Drawback is that reading the HX711 takes an extra 50-55 microseconds.
How much this affects performance is to be investigated.
@ -63,6 +63,7 @@ Steps to take for calibration
- **~HX711()**
- **void begin(uint8_t dataPin, uint8_t clockPin)** sets a fixed gain 128 for now.
- **void reset()** set internal state to start condition.
Since 0.3.4 reset also does a power down / up cycle.
- **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.
@ -78,27 +79,50 @@ The weight alpha can be set to any value between 0 and 1, times >= 1.
- **uint32_t last_read()** returns timestamp in milliseconds.
#### Gain
#### Gain + channel
Read datasheet - see also Connections HX711 below.
Use with care as it is not 100% reliable - see issue #27. (solutions welcome).
- **void set_gain(uint8_t gain = 128)** values: 128 (default), 64 32 - only 128 tested & verified.
- **uint8_t get_gain()** returns set gain.
Read datasheet before use.
Constants (see .h file)
- **HX711_CHANNEL_A_GAIN_128 = 128** This is the default in the constructor.
- **HX711_CHANNEL_A_GAIN_64 = 64**
- **HX711_CHANNEL_B_GAIN_32 = 32** Note fixed gain for channel B.
The selection of channels + gain is in theory straightforward.
- **bool set_gain(uint8_t gain = 128, bool forced = false)** values: 128 (default), 64 or 32.
If one uses an invalid value for the parameter gain, the channel and gain are not changed.
If forced == false it will not set the new gain if the library "thinks" it
already has the right value.
If forced == true, it will explicitly try to set the gain/channel again.
This includes a dummy read() so the next "user" read() will give the right info.
- **uint8_t get_gain()** returns set gain (128, 64 or 32).
By setting the gain to one of the three constants the gain and the channel is selected.
The **set_gain()** does a dummy read if gain has changed (or forced == true) so the
next call to **read()** will return info from the selected channel/gain.
According to the datasheet the gain/channel change may take up to 400ms (table page 3).
Warning 1: if you use **set_gain()** in your program the HX711 can be in different states.
If there is a expected or unexpected reboot of the MCU, this could lead
to an unknown state at the reboot of the code.
So in such case it is strongly advised to call **set_gain()** explicitly in **setup()**
so the device is in a known state.
Warning 2: In practice it seems harder to get the channel and gain selection as reliable
as the datasheet states it should be. So use with care. (feedback welcome)
See discussion #27.
#### 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.
Get and set the operational mode for **get_value()** and indirect **get_units()**.
- **void set_raw_mode()** - will cause **read()** to be called only one time!
- **void set_average_mode()**
- **void set_median_mode()**
- **void set_medavg_mode()**
- **void set_runavg_mode()** default alpha = 0.5.
- **uint8_t get_mode()**
Constants (see .h file for actual value)
Constants (see .h file)
- **HX711_RAW_MODE** new in 0.3.3
- **HX711_AVERAGE_MODE**
@ -107,10 +131,21 @@ Constants (see .h file for actual value)
- **HX711_RUNAVG_MODE**
In **HX711_MEDIAN_MODE** and **HX711_MEDAVG_MODE** mode only 3..15 samples are allowed
to keep memory footprint relative low.
- **void set_raw_mode()** - will cause **read()** to be called only once!
- **void set_average_mode()** take the average of n measurements.
- **void set_median_mode()** take the median of n measurements.
- **void set_medavg_mode()** take the average of n/2 median measurements.
- **void set_runavg_mode()** default alpha = 0.5.
- **uint8_t get_mode()** returns current set mode. Default is **HX711_AVERAGE_MODE**.
#### Get values
Get values corrected for offset and scale.
Note that in **HX711_RAW_MODE** times will be ignored => just read() once.
Get values from the HX711 corrected for offset and scale.
Note that in **HX711_RAW_MODE** times will be ignored => just call **read()** once.
- **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.
@ -138,15 +173,17 @@ Steps to take for calibration
#### Power management
- **void power_down()** idem.
- **void power_up()** idem.
- **void power_down()** idem. Blocks for 64 microseconds. (Page 5 datasheet).
- **void power_up()** wakes up the HX711.
It should reset the HX711 to defaults but this is not always seen.
See discussion issue #27 GitHub. Needs more testing.
#### 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.
These functions are under discussion if they will stay in the library.
For weight conversion functions see https://github.com/RobTillaart/weight
- **float get_price(uint8_t times = 1)** idem.
@ -171,39 +208,27 @@ Use calibrate to find your favourite values.
- A+/A- uses gain of 128 or 64
- B+/B- uses gain of 32
Colour scheme wires of two devices.
### Connections
| HX711 Pin | Colour |
|:---------:|:--------------:|
| E+ | red |
| E- | black |
| A- | white |
| A+ | green |
| B- | not connected |
| B+ | not connected |
| HX711 Pin | Colour |
|:---------:|:--------------:|
| E+ | red |
| E- | black |
| A- | blue |
| A+ | white |
| B- | not connected |
| B+ | not connected |
| HX711 Pin | Colour dev 1 | Colour dev 2 |
|:---------:|:--------------:|:--------------:|
| E+ | red | red |
| E- | black | black |
| A- | white | blue |
| A+ | green | white |
| B- | not connected | not connected |
| B+ | not connected | not connected |
### Temperature
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 uses for the measurements.
Load cells do have a temperature related error. (see datasheet load cell)
This can be reduced by doing the calibration and take the tare
at the operational temperature one 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
differences in your code.
differences in your code.
## Operation
@ -213,18 +238,32 @@ See examples
## Future
#### must
- update documentation
- test B channel explicitly.
- test reset and reboot behaviours.
#### should
- add examples
- test different load cells
- optimize the build-in **ShiftIn()** function to improve performance again.
- investigate read()
- investigate the need of yield after interrupts
- investigate blocking loop at begin of read()
- make enum of the MODE's
- why store the gain as \_gain while the iterations m = 1..3 is used most
- read() less code (changes from explanatory code to vague)
- very small performance gain.
- code moves to both get/set_gain() so footprint might rise.
#### could
- test different load cells
- make enum of the MODE's
- move code to .cpp
#### the adding scale
- void weight_clr(), void weight_add(), float weight_get() - adding scale
- void weight_clr(), void weight_add(), float weight_get() - adding scale
- might be a nice example

View File

@ -70,7 +70,7 @@ void setup()
Serial.print(" VAL: ");
Serial.println(f, 2);
Serial.println("\nPRECISSION");
Serial.println("\nPRECISION");
f = 0;
for (int i = 0; i < 100; i++)
{
@ -104,4 +104,3 @@ void measure(uint8_t cnt)
// -- END OF FILE --

View File

@ -0,0 +1,34 @@
BOARD: UNO
IDE: 1.8.19
SKETCH: HX_performance.ino
LIBRARY VERSION: 0.3.4
UNCONFIGURED
RAW: 0.00
AVG: 0.00
VALUE: 0.00
UNITS: 0.0
CONFIGURED
RAW: 0.00
AVG: 0.00
VALUE: 0.00
UNITS: 0.0
SLEEP
WAKE UP
RAW: 0.00
AVG: 0.00
VALUE: 0.00
UNITS: 0.0
PERFORMANCE
100x get_units(1) = 40904
VAL: 0.00
PRECISION
VAL:0.0000

View File

@ -35,6 +35,9 @@ tare_set KEYWORD2
set_gain KEYWORD2
get_gain KEYWORD2
set_chanA_gain128 KEYWORD2
set_chanA_gain64 KEYWORD2
set_chanB_gain32 KEYWORD2
set_scale KEYWORD2
get_scale KEYWORD2
@ -64,3 +67,8 @@ HX711_AVERAGE_MODE LITERAL1
HX711_MEDIAN_MODE LITERAL1
HX711_MEDAVG_MODE LITERAL1
HX711_RUNAVG_MODE LITERAL1
HX711_CHANNEL_A_GAIN_128 LITERAL1
HX711_CHANNEL_A_GAIN_64 LITERAL1
HX711_CHANNEL_B_GAIN_32 LITERAL1

View File

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

View File

@ -1,5 +1,5 @@
name=HX711
version=0.3.3
version=0.3.4
author=Rob Tillaart <rob.tillaart@gmail.com>
maintainer=Rob Tillaart <rob.tillaart@gmail.com>
sentence=Arduino library for HX711 load cell amplifier

View File

@ -42,13 +42,28 @@ unittest_teardown()
}
unittest(test_constants)
{
assertEqual(0x00, HX711_AVERAGE_MODE);
assertEqual(0x01, HX711_MEDIAN_MODE);
assertEqual(0x02, HX711_MEDAVG_MODE);
assertEqual(0x03, HX711_RUNAVG_MODE);
assertEqual(0x04, HX711_RAW_MODE);
assertEqual(128, HX711_CHANNEL_A_GAIN_128);
assertEqual(64, HX711_CHANNEL_A_GAIN_64);
assertEqual(32, HX711_CHANNEL_B_GAIN_32);
}
unittest(test_constructor)
{
HX711 scale;
scale.begin(dataPin, clockPin);
assertTrue(scale.is_ready()); // pins are default LOW apparently.
// default not read
// pins are default LOW apparently.
assertTrue(scale.is_ready());
// default not read
assertEqual(0, scale.last_read());
}
@ -58,20 +73,34 @@ unittest(test_gain)
HX711 scale;
scale.begin(dataPin, clockPin);
// default
// rewrite with constants?
// HX711_CHANNEL_A_GAIN_128
// HX711_CHANNEL_A_GAIN_64
// HX711_CHANNEL_B_GAIN_32
// default
assertEqual(128, scale.get_gain());
scale.set_gain(32);
assertTrue(scale.set_gain(32));
assertEqual(32, scale.get_gain());
scale.set_gain();
assertTrue(scale.set_gain());
assertEqual(128, scale.get_gain());
scale.set_gain(64);
assertTrue(scale.set_gain(64));
assertEqual(64, scale.get_gain());
scale.set_gain(128);
assertTrue(scale.set_gain(128));
assertEqual(128, scale.get_gain());
// failing invalid parameter
assertFalse(scale.set_gain(100));
assertEqual(128, scale.get_gain());
// failing invalid parameter
// 0x40 == 64 so it will fail to fail.
// assertFalse(scale.set_gain(0xFF40));
// assertEqual(128, scale.get_gain());
}