From da4aa5057deaefaa8d546705adcadee355313368 Mon Sep 17 00:00:00 2001 From: rob tillaart Date: Sun, 6 Nov 2022 20:24:21 +0100 Subject: [PATCH] 0.3.1 FastShiftIn --- libraries/HX711/.arduino-ci.yml | 17 ++ libraries/HX711/CHANGELOG..md | 77 ++------- libraries/HX711/HX711.cpp | 55 +++++- libraries/HX711/HX711.h | 39 ++++- libraries/HX711/README.md | 157 +++++++++++------- .../HX_performance/HX_performance.ino | 3 +- .../HX_performance/performance_0.3.4.txt | 34 ++++ libraries/HX711/keywords.txt | 8 + libraries/HX711/library.json | 2 +- libraries/HX711/library.properties | 2 +- libraries/HX711/test/unit_test_001.cpp | 43 ++++- 11 files changed, 288 insertions(+), 149 deletions(-) create mode 100644 libraries/HX711/examples/HX_performance/performance_0.3.4.txt diff --git a/libraries/HX711/.arduino-ci.yml b/libraries/HX711/.arduino-ci.yml index cecf5850..10c0e10b 100644 --- a/libraries/HX711/.arduino-ci.yml +++ b/libraries/HX711/.arduino-ci.yml @@ -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 + diff --git a/libraries/HX711/CHANGELOG..md b/libraries/HX711/CHANGELOG..md index ea49a0ff..c43c44ec 100644 --- a/libraries/HX711/CHANGELOG..md +++ b/libraries/HX711/CHANGELOG..md @@ -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 - diff --git a/libraries/HX711/HX711.cpp b/libraries/HX711/HX711.cpp index 23e69ae6..f9b6a7c4 100644 --- a/libraries/HX711/HX711.cpp +++ b/libraries/HX711/HX711.cpp @@ -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); } diff --git a/libraries/HX711/HX711.h b/libraries/HX711/HX711.h index 9b92b46a..48ee1c64 100644 --- a/libraries/HX711/HX711.h +++ b/libraries/HX711/HX711.h @@ -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 -- + diff --git a/libraries/HX711/README.md b/libraries/HX711/README.md index 8b806f71..751623f7 100644 --- a/libraries/HX711/README.md +++ b/libraries/HX711/README.md @@ -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 diff --git a/libraries/HX711/examples/HX_performance/HX_performance.ino b/libraries/HX711/examples/HX_performance/HX_performance.ino index aa8ff3ee..b76dbaff 100644 --- a/libraries/HX711/examples/HX_performance/HX_performance.ino +++ b/libraries/HX711/examples/HX_performance/HX_performance.ino @@ -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 -- - diff --git a/libraries/HX711/examples/HX_performance/performance_0.3.4.txt b/libraries/HX711/examples/HX_performance/performance_0.3.4.txt new file mode 100644 index 00000000..baca106a --- /dev/null +++ b/libraries/HX711/examples/HX_performance/performance_0.3.4.txt @@ -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 + diff --git a/libraries/HX711/keywords.txt b/libraries/HX711/keywords.txt index 3579da59..69127cac 100644 --- a/libraries/HX711/keywords.txt +++ b/libraries/HX711/keywords.txt @@ -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 + diff --git a/libraries/HX711/library.json b/libraries/HX711/library.json index cea6df30..e7f70196 100644 --- a/libraries/HX711/library.json +++ b/libraries/HX711/library.json @@ -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": "*", diff --git a/libraries/HX711/library.properties b/libraries/HX711/library.properties index e3e35210..d17af5e6 100644 --- a/libraries/HX711/library.properties +++ b/libraries/HX711/library.properties @@ -1,5 +1,5 @@ name=HX711 -version=0.3.3 +version=0.3.4 author=Rob Tillaart maintainer=Rob Tillaart sentence=Arduino library for HX711 load cell amplifier diff --git a/libraries/HX711/test/unit_test_001.cpp b/libraries/HX711/test/unit_test_001.cpp index 5c410a3f..9a7274ec 100644 --- a/libraries/HX711/test/unit_test_001.cpp +++ b/libraries/HX711/test/unit_test_001.cpp @@ -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()); }