Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add support for NAU7802 I2C load cell ADC #32

Open
fivesixzero opened this issue Jun 8, 2022 · 12 comments
Open

Add support for NAU7802 I2C load cell ADC #32

fivesixzero opened this issue Jun 8, 2022 · 12 comments
Labels
enhancement New feature or request help wanted Extra attention is needed

Comments

@fivesixzero
Copy link

The NAU7802 ADC is a pretty solid ADC that has one major advantage over the HX711: I2C communication. This allows for much more reliable reads (addressing #28) from higher-level code since it doesn't require any time-sensitive bit banging while still using only four pins.

The first downside is that the NAU7802 is a bit more expensive, but not prohibitively so. While HX711 breakouts can be found in the $1-5 range from a variety of vendors, NAU7802 breakouts are typically in the $5-20 range from only a few vendors.

Its also much more complex device to set up/manage than comparatively super-simple HX711. On the other hand, that makes it a lot more configurable for different use cases, and there are already some decent drivers to work with.

Driver options/examples:

Boards:

@techman83 techman83 added enhancement New feature or request help wanted Extra attention is needed labels Jun 9, 2022
@techman83
Copy link
Owner

That sounds super neat, it's certainly something that would suit a dedicated thing as it's pretty awkward with the HX11. It would be a great enhancement to have multiple sensing options.

@fivesixzero
Copy link
Author

I started looking into this today. Here are a few things I looked at.

  1. I2C isn't enabled by default on OctoPi
    • Probably nothing some doc can't fix, although it does make setup more complicated for users that aren't comfortable with terminal stuff. Probably a small price to pay for the reliability of the NAU7802 though.
  2. The PyNAU7802/smbus2 driver works fine and both required packages are readily available on PyPy,
    • Did some basic testing with both the SparkFun and Adafruit NAU7802 boards and both appear to work fine with this driver on the the latest OctoPi 1.0.0 nightly build from 2022/06/07, at least with simple testing.

@techman83
Copy link
Owner

Brilliant. If it's not the default, then we can probably just implement a scan when the backend is selected and throw a warning and a link to a section in the Readme or a specific readme for the alternate board.

The first step would likely be busting out the boards into different backends, a config migration would set the HX11 to the default and in the config box we can make them selectable.

@fivesixzero
Copy link
Author

I've never done any Octoprint plugin dev before but I'm taking some time tonight and this weekend to set up a proper dev envrionment and dive in.

As an example I'm looking at this plugin, which involves a lot more complex real-time control of an I2C device via Octoprint.

https://github.com/ArduCAM/ArducamCameraControl/blob/master/ArducamCameraControl/__init__.py
https://github.com/ArduCAM/ArducamCameraControl/blob/master/ArducamCameraControl/static/js/ArducamCameraControl.js

Thankfully the filament scale use case is a lot simpler, since we'll have drivers to work with.

I'm a bit rusty with JS frontend stuff so I'm not sure if I'll be able to get to a proper finish line this weekend but I'll be learning a lot at least.

So far I'm playing with setting up a backend with the SimpleApiPlugin mixin for control from the frontend JS via simple REST requests.

Also, I'll be looking at setting up a common "scale" superclass to provide a common interface for drivers/state to keep things as simple as possible for the frontend.

@techman83
Copy link
Owner

Awesome, more than happy to review code, make suggestions. I'm a bit rusty with JS, but I did a whole bunch of KnockoutJS (which is the MVC Octoprint leans on) with a project like 10 years ago, so it's not entirely foreign to me.

@fivesixzero
Copy link
Author

fivesixzero commented Jun 10, 2022

Looks like I'm actually making some decent progress on the backend parts, but I'm cuirous about your thoughts regarding the customized HX711 driver that's currently included in the project. Since its effectively got to be fully refactored to squeeze it into more standardized interfaces it may be worthwhile to just look for a readily available driver to drop in.

As luck would have it, I'm pretty intimately familiar with the HX711. Recently built and debugged my own driver implementation for CircuitPython with both GPIO and RP2040 PIO (which I wish we had on the Pi, but alas, some day maybe). Its a really great, inexpensive little chip and its pretty forgiving of bitbang timing issues, to a point.

There are a few different HX711 drivers available via PyPi, but these three look the most interesting:

  • https://pypi.org/project/hx711/
    • Looks like a straight-forward GPIO bitbanger, pretty similar to the current implementation here
  • https://pypi.org/project/hx711-multi/
    • This one is interesting, since it easily allows for using a bunch of HX711's at the same time via a shared clock pin. Really neat idea that I hadn't seen before, but its still bitbanging from a Python VM so it could be subject to the same timing quirks already affecting this project.
  • https://pypi.org/project/hx711-rpi-py/
    • Looks a bit more modern, using C bindings to a C library maintained by the same author. That architecture should (theoretically) provide more deterministic results but I haven't tested it yet.

The last one looks the most promising with the most recent development going on so I think I'm going to jump into testing it once I get through some more of the NAU7802 stuff. But if you've got a preference or other ideas I'm definitely open to hearing them. :)

edit: Switched to testing hx711 instead of hx711-rpi-py since the latter requires installation of the libhx711 lib outside of PyPi's scope, which is probably a non-starter for this use case. In some initial testing the hx711 lib looks quite usable though.

@techman83
Copy link
Owner

That all sounds brilliant! So most of my input to the project was to port it to Python 3, some minor reliability improvements, and adding some build automation (DevOps Engineer by day).

My thoughts would be:

  • The migration path should be smooth
  • The default choice shouldn't require external changes or system libraries
  • External requirements should be explicit when selecting a back-end
  • If possible, be able to show if an external requirement hasn't been met

The library that used C bindings looked interesting, but there wasn't a really nice clean way for it to be installed without lots of manual steps. Which realistically rules it out of being usable as a default, there are enough unknowns involved when dealing with the wiring side of things without introducing a complex set of steps to get the software component working (there is an open issue discussing it at length).

@fivesixzero
Copy link
Author

Alright, I managed to get a decent amount of work done on getting things set up. This commit on my fork covers the following work:

  1. Moving to a shared Scale superclass/interface
  2. Replacing the original HX711 implementation with a Scale wrapper around the hx711 driver on PyPi
  3. Adding a Scale wrapper around the PyNAU7802 driver on PyPi
  4. Rework of the settings page to use a REST API for tare and calibrate operations and rely on the new Scale wrapper's interface for everything

The changes have been tested thoroughly with both an HX711 and a NAU7802 setup and both work reliably, which is nice. The HX711 emits occasional error messages when reads take too long but it doesn't look like a serious problem, just a fact of life with the platform. Other than that though it works remarkably well for a quick weekend hack. Changing from currently-default NAU7802 to HX711 in this initial commit just requires changing the plugins.filament_scale.chip setting in the config.yaml:

plugins:
  filament_scale:
    chip: hx711

I definitely agree that the automatic settings migration is an important requirement. Along the way I ended up changing the names of some settings and replaced the original reference_unit value with the commonly used cal_factor. This could add some wrinkles for settings versioning/updating but it should be workable based on what I've read so far about Octoprint plugin settings. Didn't dive too deeply into that yet though.

There are still a few things left to do.

  1. Settings UI for selecting HX711 or NAU7802 needs to be implemented
  2. Settings migration/versioning needs to be handled
  3. Basic access permissions should be implemented for the new REST API
  4. There's probably some extraneous logging that could use some cleaning up
  5. Unit testing hasn't been set up yet, mostly since I'm not well versed in Python unit testing since I come from a Java background

Didn't get to a point where I'm comfortable making a PR but hopefully this should be a good start. Not sure if I'll have enough time to get this to the finish line in the coming weeks or months, unfortunately, but hopefully it's a step in the right direction.

@techman83
Copy link
Owner

If you're happy enough for me to make suggestions or add commits/refactoring, feel free to open a draft PR anyway. We can just chip away at as time allows and get a release out the door. I think it adds some super useful functionality and looks like it could make it much easier to develop on in future.

@fivesixzero
Copy link
Author

fivesixzero commented Jun 15, 2022

Got a draft PR, #33, set up with the work-in-progress from my branch. My available time in the next few weeks will be a bit unpredictable but I'm happy to collaborate on getting this figured out. :)

@techman83
Copy link
Owner

techman83 commented Jun 19, 2022

Awesome! That all looks really good, I finally started playing with my printer again, and I'll order some of those other chips. wait until shipping isn't US$49.95 😳

@fivesixzero
Copy link
Author

Yeah, shipping is kinda nuts from the US suppliers for sure. It looks like Mouser AU has the SparkFun board as well as one from Mikroe that I didn't know existed, if you're looking for cheaper shipping. Looks like DigiKey AU has the SparkFun and Mikroe boards available locally too, with the Adafruit board likely coming into stock in the Fall time frame.

Although I haven't tested with the Mikroe board it should theoretically work just fine, assuming they stuck to the reference design. I'm a big fan of the Qwiic/STEMMA-QT connectors though so if I had to choose I'd probably just get the SparkFun one. :)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request help wanted Extra attention is needed
Projects
None yet
Development

No branches or pull requests

2 participants