Monday, April 17, 2023

Shipometer progess

 We are on Shipometer 23.04 now. Shipometer 23.03 is a failure, for perhaps multiple reasons.

First, the shipometer is a HAT for a Raspberry Pi that can carry a ZED-F9R GPS+IMU, a BME280 pressure/temperature/humidity sensor, and an ICM20948 9DoF sensor. Even though the GPS+IMU has an IMU built into it, I want the ICM20948 because I can control it at a lower level, and because it has a magnetometer in it as well. 

Finally, it carries an LPC210x as a precision timer. The ZED-F9R generates a pulse-per-second (PPS) which is accurately timed to have its rising edge right at the top of each second, with sub-microsecond accuracy. This PPS is routed to and captured by the Pi, but is also routed to the timer capture input of the LPC210x. This microprocessor is an old ARM7TDMI, but has a hardware 32-bit timer capable at running at 60MHz, with multiple usable capture inputs. The LPC210x is programmed to count at 60MHz, reset after 3.6 billion cycles, capture several inputs, and output the exact timer count of each pulse to its serial port, which is wired to the Pi UART1. This way, the time of each PPS and sensor data-ready signal can be recorded with no latency due to things like interrupts and real-time software.

Anyway, I originally designed a HAT which had all these parts directly soldered. And that scared me to death. The ZED-F9R costs over $200, and I couldn't stand to think of it soldered to about 174 other parts, all of which would have to have been soldered perfectly. Besides, this was back during the Chip Shortage of 2022, which made it impossible to get my ICM20948 sensor as its own part. I happened to have one on a breakout board, so I designed a HAT that had the ZED-F9R soldered directly to it, along with the LPC210x and some glue logic. It also had a socket for the ICM20948 breakout board, as well as the BME680 pressure/temperature/humidity/gas sensor that I had as well.

First, I laid it all out on a breadboard. I got everything working together, if not all at once. I had the GPS running and syncing the Pi. I had an LPC2102 on its own breakout reading the PPS of the GPS as well. I had the sensors attached to the chip select glue logic and working as well. I then designed the HAT based on that.


The first HAT I designed for this project is the Shipometer 23.03 (since it was ordered in March 2023). I ordered all of the parts from Digikey and Mouser (I actually got the GPS months ago, waiting for something like this), a board from OSH Park, and a stencil from OSH Stencils. 


I carefully placed all the parts on the board, then baked it in a toaster oven. This is the first problem -- I wanted to be sure that the pads under the GPS were done, so I left it a little longer than normal. Usually I pull it 10 seconds after I see the paste melt, but this time I left it longer, until the sticker on top of the GPS started bubbling.

I ended up with a great-looking part that didn't seem to work. The LPC210x programmed once, and the GPS never came alive at all -- either by USB or as attached to the hat.

That was disappointing.                                                                                                                                                                                                                                                           

So, I resolved to not solder as much the next time. Shipometer 23.04 is more of a socket -- it just has the LPC210x and chip select logic. This is small enough that I am comfortable soldering it -- all of the parts are cheap enough that I could have made this board multiple times. In order to support the sensors, I came up with something that I am inordinately proud of -- the stamp. Both of these sensors can be either I2C or SPI (I am using SPI) and therefore have similar interfaces. Both devices have an AD0 pin for selecting one of two I2C addresses, and one has an data-ready output (which is what I am timing with the LPC210x). Since they are so similar, I put them both on castellated boards with compatible pinouts. I could interchange the devices, and they would work, but each part actually does have an intended slot. Specifically, the data-ready output would be on the wrong part.

All of the SPI interface is on the left side, while the I2C and data-ready is on the right. In the case of these two sensors, the parts know how to be I2C or SPI depending on their inputs, so a couple of the SPI pins are just wired to their corresponding I2C pin. Finally, the part has 3.3V power supplied at the upper right, 1.8V at the upper left (the stamp just leaves it not connected if 1.8V is not required) and all I/O is at 3.3V. In this case, the ICM20948 is a native 1.8V part, so the stamp carries a level shifter.

Since soldering a stamp commits it, and committing a bad stamp will ruin both the stamp and the board it is attached to, I designed the stamp tester. It is mostly just a set of pins, spaced slightly closer than the stamp width so that each pin applies pressure to the stamp. This allows the stamp to be tested without soldering anything. The stamp tester also includes a 1.8V regulator to supply the upper left corner.

The main board includes the LPC210x I talked about before, along with a chip-select decoder. The Raspberry Pi only comes with two chip-select lines, while at one point I needed up to four -- one for the BME280, two for the LSM9DS1 inertial sensor that I was also investigating (one for inertial and one for magnetometer), and one for the LPC210x. I figured out a clever way to get up to 8 separate SPI devices out of this -- I use up to 3 GPIO pins on the Pi as a chip address, and run those through a 3-to-8 active-low decoder. I don't think I was the first to discover this, as the 74HVC138 is perfectly designed for this purpose. It has its own enable logic,  which sets all of the output pins high (disabled) if this input is disabled. If the chip is enabled, exactly one of its 8 outputs will be set low, enabling the chip select on that one device. We hook the actual chip select of the Pi to the enable of the decoder, and the address GPIO to the address input. We then hook all of the outputs to each device's chip select line. The Pi software will set the address using its GPIO pins, then use the normal SPI driver to talk to what the driver thinks is the one-and-only device out there. When the driver activates the chip select, it actually activates the decoder and activates the one addressed chip select line.

As it happens, I expect to use the serial UART to communicate from the LPC210x to the Pi, and I am using the ICM20948 and not the LSM9DS1, so the CE0 and CE1 pins would have been adequate. Since my software is already expecting to address multiple parts, I decided to leave the decoder in place.

Finally, the hat contains both a 3.3V regulator and a 1.8V regulator. The 3.3V draws off the 5V pins of the Pi, and the 1.8V draws off the 3.3V. There is a fan header on the hat, and I didn't like the idea of attaching a motor to the same 3.3V line that was driving a bunch of sensors.

Finally, there is a socket for the ZED-F9R breakout from Sparkfun (that I already have and have been testing with).

Assembling the BME280 and ICM-20948 stamps both worked fine. I used the stamp tester to run both of them independently with the Pi. Now for the problem. When I dropped the ZED-F9R into the socket on the hat, it lit up and eventually indicated it had a lock (by blinking its own on-board PPS light). However, it never showed up in the UART. This exact same part worked on the breadboard, so I didn't know what the problem was until I looked up the pin assignemnt. I am using UART3 for talking to the GPS, which is using GPIO4 for TX and GPIO7 for RX. I know that TX on one device gets connected to RX on the other, but somehow I still screwed it up on the schematic:


I was able to fix this, though. I cut the traces between the pins, and soldered two bodge wires in my customary color for bidirectional serial -- (R)ed for (R)x from the point of view of the downstream device, and blue for Tx. I also added a pullup on the GPS_RESET line. With that it works.






No comments:

Post a Comment