Arduino communicatie met een RN2483 LoRaWAN module aan The Things Network

Ik heb vandaag geprobeerd een RN2483 LoRaWAN module met een Arduino aan de praat te krijgen. Het parsen van de communicatie van en naar de mdule ging niet gemakkelijk: de RN2483 module heeft soms een precieze timing, variaties in de antwoorden en de TheThingsNetwork.h bibliotheek is op de meeste combinaties van Arduino’s en uitbreidingen niet te gebruiken (Arduino Diecimila bijvoorbeeld, of Arduino Leonardo met Xbee Shield). En als je moeite hebt om het werkend te krijgen dan heb je met TheThingsNetwork.h als abstractielaag vervolgens ook geen idee wat er verkeerd gaat. Met een terminal daarentegen is het vrij gemakkelijk om een RN2486 met The Things Network aan de gang te krijgen:

> sys reset
RN2486...
> mac join otaa
ok
accepted
> mac tx cnf 1 1234
ok
mac_tx_ok

Bovenstaande instructies is genoeg om data te versturen. Ik heb vandaag daarom een paar uur besteed om de abstractielaag weg te poetsen en de module direct via de seriële Arduino poort aan te sturen.

// Routine that uses the SoftwareSerial library to communicatie
// with an RN2483 LoRaWAN module
// Apart from SoftwareSerial there is no abstraction layer, thus
// all steps and code are visible.
// Note: although this code does work, it is not complete. Take this
// code as an example how to communicate with the RN2483 module

// SoftwareSerial can hook up to any two digital pins. More than
// one serial port can exist, but only one can be open at any time
#include <SoftwareSerial.h>

// Connect the RN2486 module to the following pins
#define LoraRX 8 // Yellow
#define LoraTX 9 // White

// Some variables to set right
byte crlf[2] = {0x0D,0x0A};
String r;
SoftwareSerial lora (LoraRX, LoraTX);

// This is the main send routine
void sendCommand(String cmd) {
  lora.print(cmd);
  lora.write(crlf, 2);
}

// This is the main receive routine
String getResponse() {
  r = "";
  while (!lora.available()) { // Linger here while no response
  } // Might be better to create a timeout

  // There is data to get, get it while it lasts
  while (lora.available()) {
    r = r + char(lora.read());
  } 
  r = r + "";
  r.trim();
  return r;
}

void setup() {
  lora.begin(57600);  // RN2486 default baud rate
  delay(100);  // Short delay to make sure the comms are up

  // Reset the module 
  sendCommand("sys reset");  // Reset the module
  r = getResponse();  // We expect a long string here
  // Containing module version information

  // Connect with the network 
  sendCommand("mac join otaa");  // Join OTAA
  r = getResponse();
  if (r == "ok") {  // That is the response we would like to have
    r = getResponse();  // There is going to be a follow-up
    if (r == "accepted") {
      // We're joined with the network
    } else {
      // 'denied'. No free channel, or max usage exceeded
      // Safe to try again later
    }
  } else { // not ok
    // Something went wrong, might be hardware
    // This should be thrown higher up
  }
  lora.end();
}

void transmitData(int payload) {
  lora.begin(57600);
  delay(100); // Short delay to make sure the comms are up

  // Send the payload confirmed, group 1
  sendCommand("mac tx cnf 1 " + String(payload));
  r = getResponse();
  if (r == "ok") {
    r = getResponse();
    if (r != "mac_tx_ok") {
      // We got data back! Parse the values from r
    } else {
      // 'mac_tx_ok'. No data back, just a succesful send
  } else {
    // 'invalid params'. Invalid parameters, programming error
  }
  lora.end();
}
void loop() {
  // This would be the place to send data, if the
  // connection with The Things Network succeeded

  // transmitData(measureSomeSensor());
}

LoRaWAN gateway construeren en verbinden met The Things Network

The Things Network timmert hard aan de weg om wereldwijde LoRaWAN dekking te realiseren. Ze zijn hiervoor volledig afhankelijk van avonturiers en bedrijven die LoRaWAN gateways doneren. Dat hoeven er nog niet eens zo veel te zijn ook: met een stuk of tien gateways heb je Groningen op de kaart.

Onze waddeneilanden hebben nog weinig tot geen LoRaWAN dekking: op drie geplande (maar nog niet aanwezige) gateways op Terschelling na is het on-ontgonnen gebied. Met één zorgvuldig geplaatste gateway heb je op een eiland op de meeste plaatsen wel bereik, dus dat leek ons een mooi doel: Texel op de TTN-kaart zetten. Stap 1: een LoRaWAN gateway construeren. Stap 2: Texel verbinden met The Things Network. Stap 3: Verschillende eiland-toepassingen realiseren.

De TTN-wiki heeft een goed bouwverhaal over het maken van een gateway. Het verhaal eindigt echter wat abrupt na de bouw en installatie van de software: hoe je de gateway aan de praat krijgt blijft onbesproken. Mooie gelegenheid om het verhaal aan te vullen en van wat ervaringen te voorzien.

Bouw

  • Sourcen van onderdelen: een IMST ic880A-concentrator board, een Raspberry Pi B+, een wifi-dongle, een antenne en verbindingskabeltje (‘SMA pigtail’), een waterdichte doos en wat verbindingsdraadjes
  • Bodemplaat voor in de waterdichte doos passend gemaakt en voorzien van gaten voor de ic880A en de Raspberry Pi
  • Printplaten, antenne en bodemplaat monteren
  • Bedrading leggen
  • Alle aansluiting controleren (en nog een keer controleren)
  • Raspberry Pi verbinden met een USB-voeding. Ook de ic880A wordt hiermee van stroom voorzien. Beide bordjes hebben verschillende leds die nu gaan branden
  • Raspberry Pi voorzien van de meest recente software (apt-get install en apt-get upgrade)
  • Raspberry Pi voorzien van de ic880A software met git clone -b spi https://github.com/ttn-zh/ic880a-gateway.git ~/ic880a-gateway
  • De software installeren

Inregelen en configureren

  • Tijdens de installatie van de software is er in de home directory een directory aangemaakt die ic880-gateway heet. Hiernaast is er een directory in /opt aangemaakt die packet-forwarder heet. Beide softwaremodules hebben hun functie: de gateway regelt het verkeer aan de LoRa (radio) kant, de packet-forwarder zorgt voor het ontvangen en versturen van internetverkeer aan de backhaul (wifi) kant
  • Bij de installatie is de EUI van de gateway getoond. Deze moet aan de TTN kant bij het aanmaken van een nieuwe gateway worden ingevoerd

Testen

  • Een werkende gateway meldt zich binnen enkele seconden met zijn EUI op de staging pagina van The Things Network. Staat de gateway hier niet? Dat verbindt hij niet met TTN
  • Een werkende gateway waarvan de EUI bekend is op TTN wordt op de gateway pagina getoond en de doorvoer wordt gemonitord

Test PIR sensor

ledpen = 0 -- D0/GPIO16

gpio.mode(ledpen, gpio.OUTPUT)
gpio.write(ledpen, gpio.HIGH) -- led uitzetten
pirsensorpen = 2 -- D2/GPIO4
gpio.mode(pirsensorpen, gpio.INT, gpio.PULLUP)

function beweging()
 print("PIR sensor detecteerde beweging")
 gpio.write(ledpen, gpio.LOW) -- led AAN
 tmr.alarm(0,2000, tmr.ALARM_SINGLE, function()
 gpio.write(ledpen, gpio.HIGH) -- led UIT na 2s
 end)
end

-- Roep de functie aan als het signaal begint ("up")
gpio.trig(pirsensorpen, "up", beweging)

LoRaWAN node verbinden met The Things Network

Een LoRaWAN node kan op twee manieren voor het eerst met The Things Network verbinden: Over The Air (OTAA) en Activation By Personalisation (ABP). Deze instructie gaat uit van OTAA, een RN2483 node en een bestaand account op TTN:

  • Maak verbinding met de RN2483. Het gemakkelijkst gaat dat met een seriële verbinding: de RN2483 heeft een terminal waar commando’s uitgewisseld kunnen worden. Voer een algehele factory restore uit: sys factoryRESET
  • Vraag het hardware adres op: mac get deveui
  • Voer het Device EUI in TTN in bij de node administratie
  • Kopieer de gegenereerde App Key uit TTN en voer deze in de node in met mac set appkey <appkey>
  • Kopieer de gegenereerde App EUI uit TTN en voer deze in de node in met mac set appeui <appeui>
  • Bewaar alle sleutels in de RN2483 met mac save
  • Maak verbinding met The Things Network met mac join otaa
  • De RN2483 komt direct terug met ok en na enkele seconden met accepted
  • Verstuur data met mac tx cnf 1 <databyte>

Als er geen gateway met een vrij kaneel in de buurt is zal er geen verbinding gemaakt kunnen worden. De RN2483 komt dan terug met de melding no_free_ch. Afgelopen week midden in Zwolle vastgesteld dat daar geen bruikbare LoRa dekking was, maar in Groningen is overal wel een kanaal vrij.