Improving the canonical Arduino HX711 library for ESP32 and beyond

hx711

#1

The HX711 is a bit too slow for the ESP32 (or the ESP too fast), here is an advice to
slow down the ESP32 itself to 80 MHz:


Bienenwaage im Eigenbau
HX711 library archeology
HX711 library archeology
Getting a list of all predefined compiler macros
#2

Most interesting question: Did you also switch to https://github.com/queuetue/Q2-HX711-Arduino-Library or was it simply the one used in this video?

But besides this… slowing down a CPU in favour of getting reasonable results of a particular sensor because your library seems to behave wrong, can be considered the wrong way - if it is not a small front end processor dedicated to that sensor, but here it isn’t.

A much better approach is to have the used function (here: shiftIn()) be aware of clockspeed, or even better, together with frequency, fine-tune it’s duty cycle. Others have this problem too, and so his fix led into a fork of the Bogde/HX711 lib (currently only two commits ahead of bogde):


This is also an upstream issue, and so @lemio escalated it there:


"Software efficiency halves every 18 months, compensating for Moore’s Law.” - David May’s law


#3

…and the ringing of that signal in the video needs taming (though it is not reason of the problem discussed here):


#9

We have used the Arduino HX711 library from “bogde” for a long time and with different boards.

We did some adjustments while switching to the ESP8266 a longer time ago and now the same is needed for the ESP32.

We found some (suboptimal) solutions for this, see inital posting, and also a fork of Bodge’s lib optimized for the ESP32:

I think Lemio’s lib is not compatible with the ESP8266 so it would be nice if we can merge the best of all in the well known bodge lib.


#10

Hi Clemens,

good idea, lot’s of people are still struggling with the same issues over and over again, even with ESP8266 and the legacy constructor stuff, which is still available. See also the following issue where we added some notes the other day about an early spring cleanup which is dearly needed.

Cheers,
Andreas.


#14

Thanks a bunch! While this is a good start, I always felt this still missed out on the interrupt handling side. Lucky enough, this already got addressed by protecting the sensor reading with a critical section, see disable interrupts when CLOCKing in the same thread.

Good to finally see how you would do this from ESP-IDF userspace:

// Enter critical section. Turn off interrupts.
portMUX_TYPE mux = portMUX_INITIALIZER_UNLOCKED;
portENTER_CRITICAL(&mux);

// Do some critical stuff here.
// Please note the ESP32 has two cores, so really every code accessing the
// hardware should be protected by appropriate synchronization mechanisms.

// Leave critical section. Turn on interrupts again.
portEXIT_CRITICAL(&mux);

Please also read this important piece on how to program for the ESP32.

As indicated in the IDF documentation, those calls are not only for disabling interrupts on the ESP32, but also protect from the multi-core concurrent access of the same variable, see ESP-IDF FreeRTOS SMP Changes: Critical Sections & Disabling Interrupts.

See also Protect code when accessing shared resources.


#15

In the Facebook group to Side Project: HaniMandl, halbautomatischer Honig-Abfüllbehälter Marc is using the adaption of the HX711.cpp form lemio to get the lib running with the ESP32: HX711/HX711.cpp at master · lemio/HX711 · GitHub

Other people recommaned to use the normal bogde lib HX711/HX711.cpp at master · bogde/HX711 · GitHub and remove this section in HX711.cpp

#ifndef ESP8266
	#if ARDUINO_VERSION <= 106 
    // "yield" is not implemented as noop in older Arduino Core releases, so let's define it.
    // See also: https://stackoverflow.com/questions/34497758/what-is-the-secret-of-the-arduino-yieldfunction/34498165#34498165
   	void yield(void) {};
	#endif
#endif

#16

erm… yes. And what should that change, given that this legacy case doesn’t really affect anybody nowadays?
If this conditional matches, the ARDUINO_VERSION has to be revised! ;)


#17

Both conditions will probably evaluate to truthy values when running on ESP32, so this will activate the guard on modern platforms, which is clearly wrong.

As this was introduced (by me, actually) to support ancient ArduinoCore/AVR HALs, we should really get rid of this before even thinking about getting the guard right by applying ARDUINO_VERSION archeology.

Apparently, this pragma already evaluates to true when running on ESP8266, see Solution to ESP8266 wdt issue and "yield()" problem · Issue #73 · bogde/HX711 · GitHub.

Solution

(while completely maintaining backward compatibility)

Background

The constant evaluated through the #pragma is actually called ARDUINO and probably was only called ARDUINO_VERSION in the early days, see Solution to ESP8266 wdt issue and "yield()" problem · Issue #73 · bogde/HX711 · GitHub.

Actually, the guard was improved by adding #ifndef ESP8266 only recently, see more stability for ESP8266 by el3ctrician · Pull Request #113 · bogde/HX711 · GitHub. Obviously, this will still not work on ESP32.


#18

@thias had this some day (don’t know what SDK, don’t like to search that… ;)


#19

See also above and…

They already did just that:

I’m curious… is ARDUINO_VERSION actually defined for Arduino boards? I’ve done a text search over every Arduino IDE directory, and then the whole PC, and the only reference to ARDUINO_VERSION that was found was in HX711.cpp. Just to double-check, I plugged in my old Arduino Uno and tried to use ARDUINO_VERSION in some code, but the result was error: 'ARDUINO_VERSION' was not declared in this scope. (This was with a clean install of the Arduino IDE, along with the ESP8266 boards.)

See also:


#20

cargo-culting for too looong… Bp


#21

Hi there,

Just wanted to let you know that we managed to make a start in the dry dock [1] (branch “spring-cleaning”) by pulling in various pieces from the issue tracker of the Arduino HX711 library as well as a fork supporting ESP32 already (@lemio/HX711) as suggested here (thanks, @weef!).

Now, we are looking forward to receive test reports from people owning real hardware. While being at it, we will also be happy to hear about further suggestions. Note: We didn’t even try to compile this yet, so there might be dragons.

With kind regards,
Andreas.

[1] GitHub - hiveeyes/HX711 at spring-cleaning


#22

A short detour…

HX711 library archeology

While working on Using Bogdan's canonical HX711 library on the ESP32, we stumbled upon the origins of this well known library used throughout the Arduino community.

Weihong Guan uploaded this image to


@clemens and @mois probably might know about the roots of this library already, others might enjoy the time travel.


#25

It compiles now for the ESP32 what it not does with this lines!


#26

Just wanted to give you an update about this. We have been able to compile successfully for all of the atmelavr , espressif8266 , espressif32 , atmelsam and ststm32 platforms, but we don’t have any hardware around to conduct further tests.

So, we would like this to get more eyeballs and we will be happy to hear about successful reports from the community running this on real iron, actually on as much as possible things supported by the Arduino framework. Maybe someone of you can afford some minutes if you still have a MCU and a HX711 breakout around on your workbench?

Even if you have moved on to a next generation chip this library could make it work already. We will appreciate your feedback, thanks in advance.

Pull request:

Branch “spring-cleaning”, with changes: