Filament-Scale-Enhanced
Filament-Scale-Enhanced copied to clipboard
NAU7802 implementation and supporting refactor
Refactor to support the NAU7802 ADC for weight measurements in addition to the HX711. More details can be found in issue #32.
Goals
- Refactor backend to allow for a common
Scaleinterface - Create HX711 driver or wrapper an for existing driver to use the new interface
- Create NAU7802 driver or wrapper for an existing driver to use the new interface
- Add UI elements to settings interface to allow for selecting which driver to use
- Add UI elements to settings interface to allow for configuring lower-level per-driver settings, like HX711 clock/data pin and NAU7802 I2C bus ID
- Implement settings migration to allow for automatic automatic setup of legacy HX711-based installation and settings versioning to allow for more easily updating configuration between versions moving forward
Related Open Issues
This will address issue #32 and may also fully or partially address #28, #26, and #18.
Moving to use of a common "scale" interface and settings versioning should also lay the groundwork to allow for addressing #31, #22, and #17.
The first commit is rough but it should take care of a few of the goals listed above.
- A common
Scaleinterface was added and the backend was refactored to allow for this new interface.- Some basic changes were made the frontend as well to allow for tare/calibrate operations using this new interface.
- A wrapper implementing the
Scaleinterface was created for thehx711driver, which is a pretty robust and easy to implement driver for the HX711 on a Raspberry Pi.- This was tested with a common HX711 breakout with a simple filament scale configuration.
- A wrapper implementing the
Scaleinterface was created for thePyNAU7802driver)- This was tested with both Adafruit and Sparkfun's NAU7802 breakouts with a simple filament scale configuration.
I ran out of time to start in earnest on the frontend changes, settings migration, and basic unit/integration testing, so those remain left to implement before this PR can be considered for proper review/merge.
Finally got some time set aside to get my dev environment reconfigured and dig into this again. Should have a few solid, multi-hour chunks of time to dive in over the next few days.
Right off the bat I found a few embarassing typos that broke things, which I fixed in e6d858d. These slipped in because my original setup involved some copy/paste from my Pi devbox to my main dev PC (gross!). Now I'm just doing git commits directly from the devbox with my dev PC connecting via the VSCode sshfs plugin for easier editing. No more copy/paste errors now. :)
On the dev system I've got two filament scales attached, one via HX711 on the usual pin 20/21 combo and the other via a NAU7802 on I2C. This way I can easily switch between the two by changing the setting in the Octoprint config.
Not sure what the order of operations is going to be but I've got a few chunks of to-do items.
- Refactor
scalelib to take Octoprint settings as input and handle per-device instantiation- As a side goal, I'd like to make it easier to re-init the scale without restarting the whole app, which would allow for proper settings changes.
- Rest API auth
- If there's a REST API it should require and use an API token, at the very least
- Refactor JS and templates
- It looks like there have been some improvements to Octoprint's plugin API since the original JS/templates were created so it could use a refresh to make it easier to work with
- Start investigating settings versioning and migration
- Octoprint looks like it has decent functionality available that should help to organize this but I've only barely scratched the surface there
- Implement proper unit tests for the
scalelibrary- I'm still new to Pythonic unit testing but I'm eager to learn, so this may actually be a higher priority since I'm a bit more comfortable working with at least partially test-driven dev cycles
Latest commit tackles a lot more than I like to bundle into a single commit but most of it had to land at the same time, so I'll let it slide. 😎
- Changed
chipsetting toscale_typeto reflect possible future scale options- Future
Scaleimplementations could pull scale data from an external REST API, an MQTT or other message queue, platform-specific GPIO/SPI/I2C connections, or any other source
- Future
- Refactored
scalemodule- New
get_scale(settings: Dict)simplifies scale init - Added
deinit()method toScaleinterface for releasing resources like GPIOs, I2C busses, etc - Changed
hx711torpi_hx711to reflect theHX711driver's platform requirements - Moved pre- and post-read-in HX711 enable/disable into the
rpi_hx711driver wrapper - Considered changing
nau7802as well but this driver'ssmbus2implementation may work fine on a variety of platforms
- New
- Moved
self.scaleand UI-updatingRepeatingTimerinit to helper methods and added deinit helpers as well - Added new API endpoints in
__init__.on_api_get()spool_weightallows for get/set of spool weight variablescale_typeallows for get/set of scale_type setting, including deinit/reinit ofself.scaleif a change is made
- Added empty stubs for
get_settings_versionandon_settings_migrateto help with future settings migration implementation
I've been doing functional testing as I go, and this commit's had at least these functions manually tested.
- Startup and scale init with all three "scale types"
- All REST API operations, including the new REST
scale_typeandspool_weightget and set ops - Scale
deinit()resource release on HX711 (RPi.GPIO pins) and NAU7802 (smbus2 bus) - At least 20 minutes of continuous run time with both HX711 and NAU7802 drivers
This iteration doesn't use getattr(), but it does return a scale given a settings dict. Between that and breaking out the two main operations - scale init and timer init - into helper methods the on_startup() method is heavily simplified, which is good. Let me know if this looks good or if another implementation would be better, I'm still learning the Pythonic way and I'm flexible. :)
Also rearranged a lot of code to group similar things together and satisfy linters. My first commit was a total mess. :joy:
These are the linters/formatters I tested with and their basic configs, if different from the project's config files:
flake8- No changes
pylintmax-line-length=140to match project'sflake8config- Added
init-hookforpylint-venvto handle OctoPrint dev environment venv imports
mypymypy --disallow-untyped-defs --disallow-untyped-calls --disallow-incomplete-defs --check-untyped-defs --disallow-untyped-decorators ./filament_scale_enhanced/scale/
black(not in project, yet, but handy)--line-length 140to match project'sflake8config
If these linter settings are good then I can enshrine most (or all) of them in their respective configs and add them to the GitHub test.yml workflow.
I've used pre-commit on a few other projects, which can help with running linters/tests in a consistent way during ongoing development. I may look at implementing that here if you're cool with it.
Next stuff...
Didn't dive into REST API Auth, JS/templates, settings versioning, or unit test implementation in these changes but I spent a bit of time researching each as I worked through things. Of those, the JS/template work is probably the foggiest in my head at the moment. For the others I have at least some basic implementation ideas/examples in mind.
Let me know if you've got any feedback on the latest state of the code, or if I've missed implementing any changes suggested on the first commit. If all goes well I should have another few chunks of time like this in the coming days.
I've also caught Caught covid, so I'll see how functional I am. It's put me away from where my 3D printer is, but I have setup a VPN now, which makes it easier to get to. VS Code + Remote SSH is pretty nifty. I think I produced a dist and uploaded for most of my testing, it wasn't super efficient. An editable package would have been potentially easier.
Oof, hope you're feeling better! I ended up getting sidetracked into other tasks over the last few weeks but I'm hoping to have more time to dive back in next week.
Oof, hope you're feeling better! I ended up getting sidetracked into other tasks over the last few weeks but I'm hoping to have more time to dive back in next week.
Turns out Covid doesn't mix well with ADHD! Took months for the brain fog to lift, and I'm just starting to get enough energy back to keep up with work. But I have been 3D printing again! So I'm going to try and get through this, and try and come up with ways to make it easier to approve/merge/release changes.