Load Cell Sensor HX711


The project below is my first foray into embedded using rust.

It is a no-std library for interacting with the hx711 load cell amplifier IC (SparkFun Load Cell Amplifier - HX711 - SEN-13879 - SparkFun Electronics)

The library is meant to provide two modes: an interrupt based mode in which load cell readings are only read when they are ready, and a polling mode, where the main loop will need to ask the IC if it has data ready.

I much prefer interrupt based-code, but it was a struggle to interface it in here, and would love some guidance on how to re-structure it so that the library has more control of the IRQ routine, rather than the user needing to hold a mutex to the object, and then call read() on it during the interrupt.

Also, of course I am looking for feedback that will guide me to be more idiomatically rusty.

The library is below:

Many thanks in advance.

1 Like

Unless the HX711 is something that only works with an ESP32, you might want to refactor your crate so it builds on the abstractions in the embedded-hal.

That way someone can take your code and reuse it on anything that has GPIO pins and timers (or whatever else you need). Like a raspberry pi, for example, because there is an implementation of the embedded-hal that uses Linux's GPIO subsystem.

This sounds complicated, but you've structured your code quite nicely so it should mostly be a case of mechanically changing hard-coded types out for generics.

Something else you may want to do is split your project into a platform-agnostic library crate (based on embedded-hal) then have an ESP32-specific binary (i.e. a crate with a main.rs) which you can use for testing and demos. Cargo workspaces work quite nicely for this. Technically, your code isn't a reusable library at the moment because it's got a main.rs.

1 Like

Hi Michael

Thank you for the feedback. I would like to move this to use the embedded-hal. One of the traits I'm using is specific to the esp-hal, which is the "isOutputPin".

For example, I want to ensure that the pins allocated for this HX711 are suitable input/output pins, and not analog or some other special pin (and some of the functions used on these pins actually require it):

impl<const SCK_PIN: u8, const DT_PIN: u8> HX711<SCK_PIN, DT_PIN>
    GpioPin<Output<PushPull>, SCK_PIN>: GpioProperties,
    <GpioPin<Output<PushPull>, SCK_PIN> as GpioProperties>::PinType: IsOutputPin,
    GpioPin<Input<Floating>, DT_PIN>: GpioProperties,
    <GpioPin<Input<Floating>, DT_PIN> as GpioProperties>::PinType: IsInputPin,
{ ... }

Do you know how I would get around this to be even more generic? The embedded-hal doesn't define traits like IsInputPin. Perhaps I should start with a struct that is embedded-hal specific, and specialise it for the esp-hal implementation, but I'm not quite sure how to do that yet.

Should I prefer implementing traits for my struct, where the struct stores things like pointers/references to pins, delay peripherals, gain mode,offset, scale and the previous reading (this would be the HX711 struct) and the trait LoadCellReader defines is_ready,read,get_last etc...?

I would like to move the more generic code into a lib.rs with a module for the hx711 code. At the moment it's an executable for testing sake, but I see rust supports examples for libraries, and I would love to explore that.

Thank you again. I am still looking for more ways to handle the ownership of the interrupt routine.

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.