Ribbit-Network / ribbit-network-frog-hardware

The sensor for the world's largest crowdsourced network of open-source, low-cost, GHG Gas Detection Sensors.
https://www.ribbitnetwork.org/
MIT License
94 stars 26 forks source link

Support direct hardware UART connection to GPS modules #58

Closed djgood closed 2 years ago

djgood commented 2 years ago

Summary

It would be nice feature to allow direct UART connection to a GPS device. Currently, we only support connections to GPS modules that contain a USB CDC ACM chip. Supporting a direct UART connection would increase the allowable possible hardware configurations users can use with Ribbit. In my case, the GPS module without a USB device was easier to find than one with.

I did some research and testing on the topic and have created this page to summarize my findings.

Background

It's important to start off saying that the UART isn't enabled by default on Raspberry Pis. There are a few different options for configuring the UART on a Raspberry Pi depending on your model and what you're trying to accomplish with the UART, which made it somewhat hard to wrap my head around at first. This page was super helpful for a crash course in the UART configuration on Raspberry Pis.

Also note that I didn't consider using the Mini-UART device that is available on some Raspberry Pis because it requires setting the core clock to a fixed frequency and from what I heard anecdotally has some reliability problems. It might be fine because we're using it at such a low baud but the more reliable hardware is there and is available for us to use so I figured that would be the better option.

Needed Configuration

From my research and testing, I was able to get my Raspberry Pi 3 UART connected directly to the GPS module and have the Ribbit code working with minimal changes. The required configuration for my Raspberry Pi 3 was as follows:

if [ -c /dev/ttyACM0 ]; then echo "USB CDC device detected." GPS_SERIAL_DEV="/dev/ttyACM0" else echo "USB CDC device not found! Falling back to UART0." GPS_SERIAL_DEV="/dev/ttyAMA0" fi

gpsd -Nn -G $GPS_SERIAL_DEV


This just detects if the USB GPS device is present and otherwise falls back to using /dev/ttyAMA0 (which is the Linux file mapping to the UART device).

**How to Configure**

There are two different ways to set the device tree configuration on a Raspberry Pi:
1) Prior to the first boot, mount the SD card image and modify [config.txt](https://www.raspberrypi.com/documentation/computers/config_txt.html) with the desired DT overlay. For my Raspberry Pi 3:

dt_overlay=disable-bt



This is super manual and would require each user that wants to use the UART to enable this setting.

**Important**: This only works before the first boot! More information regarding this [here](https://www.balena.io/docs/reference/OS/advanced/#modifying-configtxt-locally-before-the-first-boot).

2) Modify the device tree overlay in `Device Configuration` on the Balena console. They have a default setting named `Define DT overlays` that can accept the needed overlay (`disable-bt` in my case). Balena even accepts this as a fleet-wide configuration option that would be the default for each device.

![image](https://user-images.githubusercontent.com/25231050/138009547-2dc7322c-95b5-4fc9-b7c3-20b3ca33a19c.png)

Unfortunately both of these cases requires some intervention from the user while setting up or a Ribbit Balena fleet admin to set up some configuration on a user's device.

**Automatic Device Tree Overlay Configuration?**

I had the thought that we can do some detection in the Ribbit code and try to modify the DT overlay on the device ourselves. Unfortunately, the Balena Supervisor keeps track of config.txt and will revert any changes it detects that doesn't match what it has configured from the management console. I did some experimentation with the [Balena Supervisor API](https://www.balena.io/docs/reference/supervisor/supervisor-api/#post-v2localtarget-state) and unfortunately it does not allow dynamically feeding dt overlay configuration while running on a device in production mode. It does work while in local mode, however.

**Conclusion**

The main problem with scaling this to all of the devices in the Ribbit fleet is that depending on the exact model of Raspberry Pi used, we might require different device tree configuration to be set manually somehow. I didn't find a good way of automatically setting device tree configuration while our device state is being controlled by the Balena Supervisor. So unfortunately for now, enabling the UART doesn't really scale to having many people get started on the network with different hardware in a simple manner (i.e. does not require manual intervention).

**Further research**

A final option that I didn't get to investigating because I'm a Yocto noob is that we could offer altered Balena Raspbian images for users that are interested in running a direct UART connection to their GPS module. This image would already have the UART enabled, which would make the process very 'plug and play'.
djgood commented 2 years ago

Update thanks to Flynn from Balena on Discord: What I was trying to achieve with the automatic DT configuration is possible, but I was trying to do it locally through the Supervisor API, which isn't possible. There is another path through the Balena SDK (talking to the cloud API through the internet) where the device can request changes to the dt overlay. This is due to a design choice in Balena where the cloud wants to be the reporter of state changes.

This would give us the flexibility to modify the device tree configuration on the fly to enable the UART if we don't detect a USB device.