-
SPI kills LoRa radio
07/21/2018 at 22:15 • 0 commentsI spent some time this week troubleshooting the LoRa communication problems I encountered. To recap: I'm sending tracking packets from the tracker to the GW and the GW responds with an ACK to each packet. Both sides use the same TX power but I see 9-10dB less SNR at the node end. I thought it had something to do with the GW being a small linux SBC and having more noise or something, so I put together a simple STM32-based node to respond with ACKs like the GW does. I also displayed more info: SNR, RSSI, and noise measurements I took while there was no packet in the air. It was all rather confusing, in part because the SNR on the sx1276 LoRa chips doesn't report above about 8dB and at close range while testing it's difficult to actually go that low.
Long story short, I saw that RSSI was within 1dB on both ends but SNR was off by 10dB. So both ends were getting the same signal strength but not the same signal-to-noise. Thus noise had to be the issue. But when I tried to measure the noise floor I got about the same values on both ends. Mystery. The answer turned out to be that reception on the linux end is fully interrupt driven while at the STM32 end the uC keeps polling the radio chip's registers to see the "RX done" flag being raised. That polling over the SPI bus creates enough noise to reduce sensitivity by 10dB!
I did a quick test. Since the ACK comes in immediately I inserted a long-enough sleep before starting to poll such that the first poll happens after the reception is complete. Tada! This brought SNR to the same level on both ends! I then tried something different: I changed the slew rate on the SPI pins to "2Mhz", which has the effect of creating ~6-8ns rise and fall times instead of ~1.6ns. With the original polling that reduced the sensitivity loss from the 10dB to about 1dB. So that creates some options: (a) sleep for the expected time required for the ACK to come in, (b) use an interrupt for RX-done, (c) reduce the slew rate on the SPI pins.
All this is fine and dandy for the test node I was using to try out the different combinations, but on the tracker it's somewhat more complicated. First of all, the SPI bus is used to drive not only the radio but also the flash chip and the display. That means that options (a) and (b) are useless unless the code also avoids talking to these two devices while an ACK might be coming in. At the slow LoRa data rates an ACK takes 300-400ms and currently I'm updating the display twice a second, so there's not much time left.
The other problem is that the GPS and the BLE interface are constantly sending stuff to the STM32 via serial ports and that is bound to also create noise. Those lines don't go to the radio module, but still. The effect of that is unknown.
As a first step forward I ended up reducing the slew rate on all outputs from the STM32 chip. Testing at medium range seems to indicate a 2dB loss in sensitivity, which is not great but a start. I yet have to do a long range test.
On the current stm32l082 chip package I'm out of pins, so I can't separate the radio's SPI bus from the display's. I will probably have to live with the 2dB sensitivity loss for my prototype, if that's what it comes out to be at long distance. I'm pondering what to do for the "real" version. One option is to use a uC chip with more pins so I can dedicate one SPI bus just to the radio, under the assumption that it's just the SPI bus that matters and that I can decouple power sufficiently. The other would be to break things up and use separate PCBs and uCs for radio vs. display, etc.
-
Initial status
07/14/2018 at 22:25 • 0 commentsI've now taken the prototype on several outings and it's starting to become useful. I'm learning how much I can display one the screen so I can actually read it with a quick glance while paddling and bouncing up&down in the ocean. It currently displays speed, min-max speeds over the past 10 seconds, heading, heart rate, time, LoRa RSSI, as well as number of stored trackpoints. Sorely missing is distance covered and to do that properly will take some work.
The LoRa link has been giving me some trouble. It is working but not quite at the distance I need. Right now, trackpoints are recorded to the SPI flash chip and when radio connectivity is available the trackpoints are sent. What is happening is that I don't have connectivity while paddling and then on the drive home as I get closer it starts "spooling" the recorded tracks. So everything is pretty much working except for the fact that I don't quite have the range I need. I've narrowed the problem down to two issues: I have poor antenna positioning in the waterproof case (I knew that) and the anetenna isn't great (knew that too) but in addition I'm loosing close to 10dB of RX sensitivity at my GW, which is "not good". Put differently, both ends TX at the same power level and RX SNR is almost 10dB worse at the GW end. I'm suspecting it's because the radio is on a linux box (a CHIP), but it may well be something else.
From my LoRa GW packets are injected into Node-red where they're processed and injected into the node-red-contrib-web worldmap. The code is currently displaying the "real-time" position (except for the fact that there's no real-time radio connectivity) as well as a track. One of the photos attached here shows one outing of about 6.3mi I did with the tracker.
So far the proof of concept shows lots of promise and at the same time there's lots left to do! Yay!
=== Next steps ===
The thing that bugs me the most is the LoRa radio connection. I've tried a better antenna (home made dipole) and I get connectivity using that, but it's not great from an ergonomic point of view. And it made it clear that if I could solve the 10dB RX sensitivity loss I could do with a smaller antenna. So that's the next thing to fix.
One of the other tasks is to add code both in the tracker an in node-red to smooth the track in order to be able to calculate distance covered without over-inflating it due to GPS-induced zigzags. The keyword here seems to be Ramer-Douglas-Peucker algorithm and some on-line variants thereof.
The other task is to automatically determine the start and end of an outing using some form of geofencing, and then storing the track of each outing in a proper database so it can be processed in various manners and also sent to endomondo or a similar sports tracking site automatically.