2021-09-11 mitch
I have a hx711 ADC built into a "load amplifier" that I've wired to a cheap bathroom scale. part: https://www.sparkfun.com/products/13879 datasheet: https://cdn.sparkfun.com/assets/b/f/5/a/e/hx711F_EN.pdf
I have tried to implement a reader for it in python (hx711.py), but have been getting back 24 1s for the reading, regardless of the load on the scale.
I suspect this is due to the strange power down feature that kicks in if PD_SCK is ever left high for >60us. I bought an oscilloscope to prove this, but it hasn't arrived yet.
The suspicion that the python GPIO interface (I used periphery) was too laggy on this platform lead me to desend into the madness that is the user-space GPIO control in Linux. A working example of using the GPIOs in c can be found in c_gpio/g.c . I leaned heavily on the example set by tools/gpio/gpio-utils.c in the linux kernel tree (online https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/tools/gpio/gpio-utils.c). Later, I discovered a direct discussion of this userspace ABI: https://www.kernel.org/doc/html/latest/driver-api/gpio/using-gpio.html
Later, I've decided to try implementing a driver (kernel module) to have even faster control over the GPIO pins (kmod dir), and do this the "right" way.
This was a valuable article in the basics of writing and compiling modern kernel modules.
Also, I should use the official kernel documentation more often: https://www.kernel.org/doc/html/latest/
The GPIO subsystem in the kernel is far more sophisticated than just pulling wires: https://www.kernel.org/doc/html/latest/driver-api/gpio/intro.html
In searching for relevant examples of using it, I discovered that a kernel module for the hx711 is already written and in the mainline (whomp): https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/drivers/iio/adc/hx711.c
It's part of the industrialIO (iio) subsystem: https://www.kernel.org/doc/html/latest/driver-api/iio/intro.html
This driver takes no params, and it wasn't evident to me how I would indicate which GPIO pins were actually wired to the hx711 (PD_SCK and DOUT). This seeming omission of pin numbers had struck me earlier when I was trying to wrap my head around gpiod_get functions, which seemingly return a handle on a single GPIO pin, but don't take a pin number as an argument.
A hint to how this was meant to work, and how the existing hx711 driver must be getting the GPIO pin numbers is here: https://www.kernel.org/doc/html/latest/driver-api/gpio/board.html#device-tree
It seems that device trees, ACPI and "board files" are all mechanisms for defining (among other things) which devices use which GPIO pins, and the drivers use this abstraction so that they can work across devices with different wiring. In retrospect, it makes perfect sense.
This led me to the impulse to somehow edit the device tree on my machine (Raspberry Pi Zero W), to somehow include the hx711 and define which GPIO pins were wired to DOUT and PD_SCLK.
I remembered seeing device tree files in /boot. The one I'm using (I assume) is /boot/bcm2835-rpi-zero-w.dtb.
06:50:07Z brewer [/boot] file bcm2835-rpi-zero-w.dtb
bcm2835-rpi-zero-w.dtb: Device Tree Blob version 17, size=18981, boot CPU=0, string block size=1853, DT structure block size=17056
These things are not stored in an easily-readable way (using cat, for example). They're compiled with a tool called dtc (device tree compiler), and that tool can also decompile them like so:
dtc -I dtb -O dts bcm2835-rpi-zero-w.dtb
Instead of editing the existing device tree, the preferred approach seems to be specifying an overlay (in /boot/config.txt), so the job seems to be writing and compiling an overlay.
I've cribbed this overlay DTS in hx711.dts, but I had to delete the #include and manually expand the defines (GPIO_ACTIVE_HIGH -> 0). The right way to do this would be to run the dts through a C preprocessor to resolve the includes and defines (ala https://stackoverflow.com/questions/50658326/device-tree-compiler-not-recognizes-c-syntax-for-include-files), but I didn't have the steam.
This didn't work, and I've found another discussion and overlay here: https://www.raspberrypi.org/forums/viewtopic.php?p=1543134
Surprisingly hard to search for, but this section describes parameterized DT Overlays: https://www.raspberrypi.org/documentation/computers/configuration.html#device-trees-overlays-and-parameters