-
New hardware
02/28/2023 at 05:54 • 1 commentSwitched to the Microchip WLR089 LoRa module and this brings more features. Full list of improvements:
- ARM Cortex M0+ with 256 KB flash and 40KB RAM
- Dual band, 868 MHz and 915 MHz
- USB connectivity
- On-module u.FL antenna connector so no RF path needs to be on my PCB
- Switched to the Quectel LC86L GNSS module, capable of tracking GPS and also GLONASS
- Added an Analog Devices ADXL362 low-power accelerometer for activity tracking
- Added a software-controlled LED and a button
- Added an on-board I2C temperature sensor for monitoring safe operating range of battery
- Updating firmware is much easier through USB, using UF2 bootloader
- Arduino compatibility is possible, as there are ports for the SAM R34 chip in the WLR089 module
Some limitations that have been carried over from original prototype:
- LC86L module requires a much larger ground plane, thus GPS antenna performance may be significantly reduced
- LoRa antenna is packed very tightly in case close to many other components, thus performance at 868 MHz and 915 MHz is greatly reduced
-
Squeak firmware on GitHub
01/13/2023 at 06:06 • 0 commentsYou can find the Squeak firmware for the PIC18LF46K22 running in the RN2483 on GitHub. To build it you need MPLABX v5.50 and the free version of the XC8 v1.45 compiler.
This should also work as a good starting point for simple applications running directly on the RN2483, as most of the fancy things that make up the RN2483 have been stripped out.
The serial port available on the PCB header is available if you comment out #define MCP9701 in eusart1.h. If you have that definition you can use the serial port header for the temperature measurement chip.
Microchip LoRaWAN stack
The only change I made to the stock LoRaWAN stack provided by Microchip is the addition of the LORAWAN_CanSend() to lorawan.c, which reports if the stack can send a packet or not. The stack may be unable to tx because of duty cycle restrictions, and without LORAWAN_CanSend() the only way to tell is to actually transmit a packet. For Squeak this could be a problem if you just spent a lot of battery on getting a GPS fix and then cannot inform the user of this fresh location.
-
Battery testing
12/23/2022 at 08:35 • 0 commentsContinuing on the trails of the battery life not being quite what was expected in the previous project log I checked the battery I used. The battery was one of these but I noticed it was a bit puffed. Discharging it overnight through a power 200 Ohm resistor yielded the following voltage curve.
The resulting 250mAh capacity perfectly accounts for the difference in runtime. I also checked a new, unpuffed 400mAh battery bought in the same batch and that one yielded 375mAh, so I'm not that worried.
As long as I have that curve I might as well check my assumptions on the voltage-to-charge-state LUT.
On the left is the measured battery remaining capacity vs battery voltage, along with a linear fit that's easy to plug into the firmware. On the right is the estimation error given by this simple linear fit with respect to the charge state reported by the fit. So if the device reports 50% charge left, the actual remaining charge is ~46%. But as the error is within 5% of the true value between 10% and 100% I'll live with the linear fit.
Comparing these values to the original LUT I was using it's obvious I was very wrong in using this chart, made specifically for high current LiPo batteries.
The measurements for my battery of battery charge state vs voltage are waaaaay off from those given in the LiPo chart.
Moving forward I'm confident that Squeak will provide a much more accurate battery level.
-
Power profiling
12/19/2022 at 05:42 • 0 commentsIn a previous project log I missed the mark substantially on battery life estimations. While I still don't have a conclusion, I wanted to confirm the tracker's power profile. My measurements so far were done with a cheapish multimeter, and they were:
- Sleep: 9uA
- Radio tx: 33mA
- Radio rx: 14mA
- GPS on: 35mA
Here are updated values, taken with a DMM6500.
Taking a closer look at the sleep current reveals the way the PIC18F sleeps for a long time: it has to wake up every 2 seconds to service its 16bit timer fed by a watch crystal.
Averaging the currents drawn in different modes comes down to:
- Sleep: 8.85uA
- Radio tx: 28.9mA
- Radio Rx: 14.2mA
- GPS on: 26.5mA
So this is actually lower than the initial measurements. I'm not bothering with the 3mA drawn in between Rx and Tx when the MCU is awake, as that is negligible compared to the time the GPS is on.
So my wrong estimates on the battery capacity may still come from:
- Lower than advertised battery capacity at 0.1C discharge rate
- I'm measuring battery voltage wrong
- I'm using a voltage-to-charge LUT that's not appropriate for the battery
-
Squeak Cloud Service
12/12/2022 at 04:56 • 0 commentsSqueak uses LoRaWAN for connectivity but the data on the network has to make it to the pet owner. Solutions in the previous posts did get the job done but were rather hacky, having to go through Google Sheets or to configure Datacake for Squeak. These also required users to poll the data for any location updates.
The Squeak Cloud Service is a custom platform that uses AWS for data storage and for the business logic and a Telegram bot to allow owners to interact with their hardware.
Bot commands
- /loc <tracker name>
will report the last status transmitted by the tracker and when this status was received. The last position measured is also provided as a shared location -
/find <tracker name>
triggers a downlink that will request a new GPS measurement to be made just for the next uplink. When the uplink is received the bot will share location - /gps_on <tracker name>
turns on GPS measurements for uplinks. For each received uplink the bot will share the new location - /gps_off <tracker name>
turns off GPS measurements for uplinks
The user is contacted by the bot in any of the following cases:
- a packet with a GPS measurement has been received
- tracker battery <= 20%
- tracker temperature >= 50 deg. C
- /loc <tracker name>
-
Adding a logo
12/05/2022 at 06:16 • 0 commentsI could not resist the temptation to add a logo to the case. Also made the case a bit taller to remove the humps for the GPS antenna and temperature sensor.
-
(Almost) No code data logging to Google Sheets
11/29/2022 at 05:13 • 0 commentsHelium has this cool integration to Google Sheets through Google Forms. Once you register the tracker on the Helium console you can follow this guide on how to dump the data into Google Sheets.
The only code you need to massage the data is in the custom decoder. For example if you just want to fill counter, battery and temperature values in your spreadsheet this can be as simple as filling which bytes go where in the template built by the Helium console from your Google Form.
function Decoder(bytes, port) { // TODO: Transform bytes to decoded payload below var decodedPayload = { "battery": bytes[3], "counter": (bytes[1] << 8) + bytes[2], "temperature": bytes[4] }; // END TODO return Serialize(decodedPayload) }
You can add fancier fields, like latitude and longitude by decoding them similarly to how you do it for Datacake.
Then you can plot your data in Google Sheets or download the Excel file and do it locally.
-
Adding a temperature sensor
11/28/2022 at 06:04 • 0 commentsFor testing the performance of the tracker I'd want to leave one in my car. But it contains a rechargable lithium battery and I'd feel much better if it could alert me if the temperature is outside the battery's recommended range.
To make no changes on the PCB I repurposed a UART header I used for debugging to accomodate a TO-92 Microchip MCP9701. This was possible since the UART pins can also be used as ADC inputs on the PIC18F46K22 used in the RN2483.
So I used one pin for reading the voltage from the MCP9701 and the other for turning it on or off. It's fairly low power (6uA or so) so it can safely be powered from a GPIO.
Now every uplink contains temperature data that can trigger an alert.
-
Magnetic charging connector
11/25/2022 at 05:45 • 0 commentsWhile I initially considered a USB connector for charging the battery, I eventually settled on this magnetic connector. There are also 3D files to make designing it into the case real easy. The tracker is getting heavy though, at 36 g (1.27 oz).
-
Datacake integration: Seeing Squeak on a map
11/20/2022 at 18:05 • 0 commentsDatacake can be used to integrate and visualize IoT data. It's a paid service, but you get two devices for free. It readily integrates with The Things Network and you can easily have a web interface for the Squeak tracker.
After registering Squeak in the The Things Network application, define a webhook for bidirectional communication with Datacake.
Use a custom payload decoder for Datacake to make sense of what's being sent
function Decoder(payload, port) { var decoded = {}; decoded.counter = (payload[1] << 8) | payload[2]; decoded.battery = payload[3]; decoded.temperature = payload[4]; gpsYy = payload[5] >> 1; gpsMo = ((payload[5] & 0x01) << 3) | ((payload[6] & 0xE0) >> 5); gpsDd = payload[6] & 0x1F; gpsHh = (payload[7] & 0xF8) >> 3; gpsMi = ((payload[7] & 0x07) << 3) | ((payload[8] & 0xE0) >> 5); lat = ((payload[9] << 24) | (payload[10] << 16) | (payload[11] << 8) | payload[12]); lng = ((payload[13] << 24) | (payload[14] << 16) | (payload[15] << 8) | payload[16]); gpsTs = 0; gpsLat = -1000; gpsLon = -1000; if ((lat > -500) && (lng > -500)) { ts = new Date(2000 + gpsYy, gpsMo - 1, gpsDd, gpsHh, gpsMi, 0, 0); //console.log(ts.getTimezoneOffset()); // Maybe one needs to adjust for timezones here. For now it looks like Datacake runs on the UTC timezone which is great. gpsTs = ts.getTime() / 1000; gpsLatF = lat / 10000000.0; gpsLatDD = ~~gpsLatF; gpsLatMM = (gpsLatF - gpsLatDD) * 100.0/60.0; gpsLat = gpsLatDD + gpsLatMM; gpsLonF = lng / 10000000.0; gpsLonDD = ~~gpsLonF; gpsLonMM = (gpsLonF - gpsLonDD) * 100.0/60.0; gpsLon = gpsLonDD + gpsLonMM; } decoded.timestamp = gpsTs; decoded.location = "(" + gpsLat + "," + gpsLon + ")"; return decoded; }
Add fields for the values you're interested in from the decoded structure. Things like battery, location, etc. Also add a downlink configuration to be able to send a command to turn on the GPS.
function Encoder(measurements, port) { return [0x02, 0x01, 0x03]; }
This payload says it should try to send an uplink every 4 minutes, and the GPS should be on for the following 3 packets. A UI is fairly easy to build up once you have the decoder, fields, and encoder set up.