Debugging LoRa connectivity

After successfully upgrading the firmware of my Uno’s RN2903 LoRa chip, I was still having trouble connecting to The Things Network and seeing a lot of these lines in the serial monitor:

Sending: mac join otaa 
Join not accepted: denied
Check your coverage, keys and backend status.

I’d tried five different locations across two states, so was getting pretty paranoid that it was either something I’d done in my Arduino water quality sensor reading code (I was using Software Serial).

So I asked Leo from TTN Adelaide if it might be possible for him to send me a known working Uno so that I could try it here using stock software. His setup was identical to the one I had been trying, but at least we could rule out hardware failure, and it’d tell me a lot more about trusting my code.

As soon as it arrived I plugged it into my USB power brick so that my laptop couldn’t do anything weird to it (super paranoid), but it didn’t connect successfully. So after a couple of minutes I plugged it into my laptop so I could read the serial monitor output. Same output as mine.

So at this point I could at least feel a little better about my code and hardware, but it was still a bit of a mystery why all of the locations I’d tried didn’t work.

I wandered around the Melbourne CBD with it switched on, monitoring TTN console on my phone for uploads… still nothing.

In a last ditch effort to find some signal, I got myself onto a 38th floor rooftop, switched it on, and almost instantly the join confirmation and payloads started streaming in.

So it was just blackspots all over the Melbourne CBD, East St Kilda, Southbank, Adelaide CBD and Port Willunga.

Test the payload

Next thing to do was to test the payload to see if I was sending a readable byte array.


37 38 2E 32 33 2C 34 32 2C 30 2E 30 30 2C 31 2E 30 30 30 00 

Sending: mac tx uncnf 1 37382E32332C34322C302E30302C312E30303000

Over on the Things Network console I could see that exact byte array appear, which converts to an ASCII string:


So that’s great! It works.

The Things Network console also has a really nice feature where you can decode your byte array into something more human readable, it’s the Payload Formats tab.

There’s some sample code to extend, so here’s what I ended up with:

function Decoder(bytes, port) {
  // Decode an uplink message from a buffer
  // (array) of bytes to an object of fields.
  var decoded = {};

  if (port === 1) {
    var stringFromBytes = String.fromCharCode.apply(String, bytes);
    var stringArray = stringFromBytes.split(',');
    decoded.electrical_conductivity = parseFloat(stringArray[0]);
    decoded.total_dissolved_solids = parseFloat(stringArray[1]);
    decoded.salinity = parseFloat(stringArray[2]);
    decoded.specific_gravity = parseFloat(stringArray[3]);

  return decoded;

It’s very simple, with no error handling or validation (though there is a validation tab when I get some more time).

There’s also a neat Payload Test field, where you can test your decoder as you write it. After I’d ironed out the bugs I switched back over to the Data tab and saw it all working!

Success! The water quality sensor payload is decoded and displayed.

Next step: writing some kind of integrator, so that it can send the data onto a database for visualisation.

Leave a comment

Your email address will not be published. Required fields are marked *