Small sketch to run a TTN Mapper node on an Adafruit Feather M0 Radio with LoRa Radio Module with an OLED FeatherWing.
See https://ttnmapper.org/ for more information about the TTN Mapper project.
- Adafruit Feather M0 Radio with LoRa Radio Module
- Adafruit OLED FeatherWing
- Female headers to stack the display on top of the Feather
- Optional: SMT uFL connector, pigtail and antenna
- Battery. Either a small 4.2/3.7V LiPo battery or a 5V source through the MicroUSB connector
To expose the RFM95 DIO1 to the M0, solder a bridge from the IO1 to Digital #11 (or any other free port).
The easiest is to solder this bridge on the FeatherWing.
Aside the Adafruit SAMD support you will need the following libraries:
- For the OLED FeatherWing:
- Adafruit_SSD1306(1.1.2)
- Adafruit-GFX-Library (1.2.5)
- For LoRaWan:
Copy ttn_secrets_template.h
to ttn_secrets.h
and set your Application Key and App EUI.
You also need to define a unique Device EUI -- as the Adafruit Feather does not have a serial number, take the one automatically generated in the TTN console.
By default, the node sends a message with *
as payload every minute.
- You can change the
send_packet_interval
inttn_mapper.cpp
(Respect duty cycle!) - To send battery voltage as Cayenne LPP instead of
*
, uncomment#define CAYENNE_LPP
inttn_mapper.cpp
Compile, upload and you should be good to go!
To directly send the tracker location to the TTN Mapper integration you can add a GPS module and use the ttn-mapper-gps
script.
You will need:
- Adafruit Ultimate GPS featherwing
- Male/Female headers to install the GPS between the MCU and the Display
- GPS antenna and pigtail
And the following libraries:
- Adafruit_GPS (1.0.3)
- Adafruit_ZeroTimer (2.0.0)
- Adafruit_ASFcore
Add the TTN Mapper integration to your application in the TTN Console and configure the Payload decoder with:
function Decoder(bytes, port) {
// Decode an uplink message from a buffer
// (array) of bytes to an object of fields.
var decoded = {};
if (port === 2) {
// The port should match the port configured in `ttn_mapper.cpp`
var i = 0;
decoded.latitude = (bytes[i++]<<24) + (bytes[i++]<<16) + (bytes[i++]<<8) + bytes[i++];
decoded.latitude = (decoded.latitude / 1e7) - 90;
decoded.longitude = (bytes[i++]<<24) + (bytes[i++]<<16) + (bytes[i++]<<8) + bytes[i++];
decoded.longitude = (decoded.longitude / 1e7) - 180;
decoded.altitude = (bytes[i++]<<8) + bytes[i++];
decoded.altitude = decoded.altitude - 0x7fff;
decoded.hdop = (bytes[i++]<<8) + bytes[i++];
decoded.hdop = decoded.hdop /10.0;
if (bytes.length >= 14){
decoded.voltage = ((bytes[i++]<<8)>>>0) + bytes[i++];
decoded.voltage /= 100.0;
}
}
return decoded;
}