Introduction: LoRaWAN Gateway + Seeeduino Motes

This project will let you connect a device to the internet where there is no internet. LoRa radios can send and receive data 6-10 miles away usually, less if there are many occlusions, and much further on a clear day with a line of sight. Chances are, your entire city can be connected with as few as 3 gateways, and perhaps even 1. This means you can install sensor stations around town to measure the humidity, temperature, air quality, noise pollution, smoke, etc. You can use it to launch a connected vineyard business. You could install low power sensors in garbage cans to know when they are full. You could track the location of vehicles and equipment without Wifi or Bluetooth. It really opens up a world of possibilities that Europe, esp. the Netherlands, has up and running.

I made this instructable because it's the one I wish I had. I loved IoT, and I wanted to use it to improve agriculture, smart cities, remote sensing, person projects, etc. But I had a lot of difficulty. I tried for a long time to get gateways running, connecting them to the server, and it never worked out right, and end devices never seemed to work exactly right. So I made this guide. I hope it helps you in your journey.

LoRaWAN stands for Long Range Wide Area Network. There are 2 distinct parts to LoRaWAN.

1. LoRa is the registered trademark and proprietary modulation scheme created by Semtech. In networks, this is level 1 in the network stack.

2. LoRaWAN defines how devices join networks and communicate with gateways. This is level 2 in the network stack.

You could think of LoRa components as being somewhat analogous to Wifi: End points are the devices you're actually interested in, like your phone or laptop. Gateways are like routers; they are your link to the rest of the internet. The LoRaWAN servers process the data you send between the cloud and the end devices. This metaphor isn't perfect, but you get the point.

Through this project, we will:

1. Build a LoRaWAN gateway, and run it.

2. Connect the gateway to the cloud via The Things Network

3. Connect our end device (the Seeeduino) to The Things Network

4. Send data to and from the cloud

Let's get cracking!

Step 1: Parts

  1. Raspberry Pi 2 or 3: $35
    • Raspberry Pi 3 comes with ethernet and Wifi
    • Raspberry Pi 2 comes with ethernet, but would need a Wifi dongle
  2. RHF0M301 hat: $289 if you buy through Seeedstudio, half price if you buy direct from Rising HF.
    • It uses the Semtec SX1301 concentrator module, giving us 10 channels in total
    • This hat for the Pi is from Rising HF, the makers of the radio chip in the Seeeduino LoRaWAN
    • If where you live already has LoRaWAN gateways, you do not need this. If you live in the US like me, chances are, you do.
  3. Seeeduino LoRaWAN (with or without GPS): $40-50
    • This module uses the Rising HF chip RHF76-52, which has support for modes A and C of LoRaWAN
    • The LoRaWAN Modes:
      • A : a mote / end device / sensor sends a message uplink, and then listens for 2 receive windows for a reply. This is the primary use of LoRaWAN technology, usually for collecting sensor data and sending it to the cloud. Every official LoRa device must at least support this mode. It is very low power.
      • B : every mote has a time slot to send messages, and only that time slot. This seems very helpful in industrial settings with many motes. I
      • C : an end device is always listening unless it has something to transmit. This is very power hungry, but will provide the lowest latency.
  4. Optional: LoRa Antenna Kit: $10
    • The pigtail that comes with the Seeeduino LoRaWAN is not a very good antenna. If you want to feel the full power of LoRaWAN, spend $10 to really boost your range.

Step 2: Setup the Gateway Hardware

Connecting the hardware is pretty straightforward. The Rising HF board plugs into another board that sits on top of the Raspberry Pi. It should look something like the picture here. There are just 2 things to keep in mind:

  1. Attach the antenna whenever it's running. Not doing this could damage the device.
  2. Don't attach / detach the shields while the board is running.

Now you've set up the gateway hardware, let's run the packet-forwarder.

Step 3: Setup the Gateway Software

You'll be running a packet forwarder program that sends downlink messages to nodes and sends uplink messages from the nodes to the cloud. There are many packet forwarders out there, nearly all of them forked from this original repo owned by Semtech. I have not had much luck with adapting this packet-forwarder to my needs, but I know others have. We will not be using this one, or any other based on it.

Instead, The Things Network rewrote the entire packet forwarder from scratch in the Go language. We will not compile this, because doing so requires working with a Go environment, it's unnecessary, and it's kinda of a hassle. There are instructions on how to install it on a few concentrators. We will be going through instructions to installing it on a Raspberry Pi with an iC880A concentrator attached. This is a very similar product, and communicates over SPI to the Raspberry Pi the same way. So, download the binary as listed near the top of the page.

The file is named: "imst-rpi-pktfwd.tar.gz". Open the contents with "tar -zxvf imst-rpi-pktfwd.tar.gz". Before we can run the application, we need to open an account on The Things Network, and in the upper right, click on your name, and then click on "Console". This is where you will manage all your gateways, nodes, and applications. Click "Gateways" and click "Register Gateway". Do not select the old Semtech forwarder. If you are in the US, and you have the US gateway, and the US plan motes, select the US plan. If you are somewhere else, you need to get the correct hardware and configuration for that country.

IMPORTANT

You MUST select the plan for the country you're developing in. Different countries have different frequency plans. When you register your gateway on TTN with a certain country plan, and then you run the packet forwarder, the packet forwarder program will grab a json configuration file that will only work for the country that the gateway is registered for. So just check the right one for you.

Now click "register". This will generate a gateway key, which your gateway will use to connect securely to the network.

Now, you will also need an EUI (Extensible Universal Identifier). You can use the Raspberry Pi's MAC address, aka hardware address. You can find this by running

sudo ifconfig | grep eth0

or just look for the hardware address near the top of the output from

 sudo ifconfig

Your gateway id will be its hardware address prefixed by "eui-". So if my MAC address was "0011223344556677", the id will look like "eui-0011223344556677"

Now run,

./packet_forwarder configure

You will be asked to enter the gateway id. Enter it, and then it will ask you for the gateway key. Enter the key you received in The Things Network console. It will ask you some other trivial questions, and then it will be configured. If you ever want to change something really quick without running the configure option, by default it is saved to /home/pi/.pktfwd.yml. You can add / edit values here directly. We're ready to run it!

Step 4: Run the Packet Forwarder

This is where you actually create the gateway. Make sure you're connected to the internet via Wifi or ethernet. Run:

packet-forwarder start --reset-pin 7

By default, this binary is made for the iC880A, which uses pin 22 of the Raspberry Pi for reset. We just need to make this small adjustment to get the packet forwarder started with the Rising HF gateway hat. You can also turn this into a service that starts every time the Pi turns on, which is very helpful.

Step 5: Have the Packet Forwarder Start on Boot

When the Raspberry Pi boots up, you want it to run.

First make a copy of .pktfwd.yml and put it somewhere other than the pi's home directory if you want other users to access it, as I have done below, in "/opt/ttn-gateway-tcp/.pktfwd.yml"

Create a file called, "ttn-gateway-tcp.service" in the directory "/etc/systemd/system, with the following contents:

-------------------------------------------------------------------------------------

[Unit]
Description=The Things Network Gateway
[Service] 
ExecStart=/opt/ttn-gateway-tcp/packet-forwarder start --reset-pin 7 --config /opt/ttn-gateway-tcp/.pktfwd.yml
SyslogIdentifier=ttn-gateway-tcp
Restart=on-failure RestartSec=5
[Install] WantedBy=multi-user.target

-------------------------------------------------------------------------------------

You can also use pi.target or any ".target" scheme in "WantedBy" to limit access.

To run it manually, run:

sudo systemctl daemon-reload 
sudo systemctl enable ttn-gateway-tcp.service
sudo systemctl start ttn-gateway-tcp.service

To see if it was successful, run:

sudo systemctl status ttn-gateway-tcp.service

You should now see the gateway show up in The Things Network Console.

Step 6: Add an Application

In the TTN console, click, "Applications" and add one with whatever name you like. Be sure to select the correct router for your region. For me it is "ttn-router-us-west". Now, under your new application, you can add end devices. Devices need to be activated to join the network. This can be done through 2 ways:

  1. ABP: Activation By Personalisation: You hard code application session keys and network session keys, and the device address. This is the easiest to get working, but is not very fault-tolerant. It requires you, the developer, to hand code different security codes for each device. So for large deployments this is a bad idea. But, joins happen almost immediately.
  2. OTAA: Over The Air Activation: The device sends the app key and the app eui to the network, but doesn't need any other info. TTN will activate the device, and assign it a network session key, an app session key, and a device address. This is preferable for deployed systems, but joining takes a bit longer.

We're going to start with ABP-style activation. So in the console, under your application, under "Devices", click, "Add a Device". Select ABP, and have TTN generate the keys, so you don't have to worry about it. Keep those handy so we can use them later.

Step 7: Caveats

Before we add the Seeeduino, it's important to understand what your gateway is capable of. It is NOT running all 64 channels of the LoRaWAN specification. It is communicating on 8 of them. This is known as "Hybrid" mode, where it's more extensive than straight single-channel LoRa, but it doesn't have the full 64 channel bandwidth of the full LoRaWAN spec. Using a gateway with the bottom 8 channels, and having a mote communicate over all of them will mean significant data loss. Most packets just won't make it. Keep that in mind, and we'll handle this discrepancy in our Seeeduino code by only using the same 8 channels as the gateway.

Step 8: Add the Seeeduino

The wiki is the first place to start: http://wiki.seeed.cc/Seeeduino_LoRAWAN/

Follow the wiki, install the latest version of the firmware, and make sure to get the latest version of the LoRaWAN library installed in the Arduino IDE. Check out a sample Seeeduino project in my repo here: https://github.com/brady-aiello/Seeeduino_LoRaWAN_for_hybrid_gateways Clone or download this repo. The sample code in the Arduino examples for ABP (Activation By Personalization) or OTAA "Over The Air Activation" won't work for us folks with peasant-level 8-channel gateways. So, we'll turn on only 8 channels. It seems there was an easy way to do this built into the RHF76-052's AT command set, which can be called in Arduino code, like so: "lora.setDataRate(DR0, US915HYBRID);" But there's a problem with this technique. It sets our 8 channels to different channels than our gateway is using. We need to make sure they are the same channels our "hybrid" gateway is using. For the US, that's 903.9, 904.1, 904.3, .., 905.3, as shown in the US gateway config that The Things Network uses, here: https://github.com/TheThingsNetwork/gateway-conf The Seeeduino code is using LoRaWAN mode 'A', in which a mote sends uplink data to the cloud, and then waits for 2 receive windows to see if it got a response.

Rename the file "keys_generic.h" to "keys.h", and put in the 6 attributes necessary in the quotes. The file looks like:

#define DEV_ADDR  "Your Device Address"<br>#define DEV_EUI   "Your Device EUI"
#define APP_EUI   "Your App EUI"
#define NWK_S_KEY "Your Network Session Key"
#define APP_S_KEY "Your App Session Key"
#define APP_KEY   "Your App Key"

Once you have done that, you can run the Seeeduino_LoRaWAN_ABP.ino program. Make sure you have selected the correct board and port in the Arduino IDE. To view logs, open the serial monitor in the Arduino IDE. It will take a minute or so to configure the radio. After that, you should see data start showing up in the TTN console. It won't look exactly like the picture above. It will just be raw hex values of our counter. To convert that to something a little more human-readable, we'll need a payload function.

Step 9: Payload Functions

To make your data human-readable, and allow ourselves to send our data other places, we'll need it in JSON format. In the TTN console, under applications, select "Payload Formats". The internet doesn't like raw hex values flying around. Instead, it likes things in JSON format, or Javascript Object Notation. So here, we're just sending 1 byte, and we get that byte (byte[0]) as shown in the picture, and understand that that is our counter variable. So we turn it into a JSON object that looks like:

{
    frame_counter: 3
}

Similarly, you could have a tuple of a 4 byte floating point temperature (74.3), a 4 byte floating point wind velocity (6.3), and a 1 byte integer battery status sent to TTN. In this case, you might have something like this:

/*bytes[0-3]: temp, bytes[4-7]: windspeed, bytes[8]: battery status*/
return { "temp": bytes[0] << 24 | bytes[1] << 16 | bytes[2] << 8 | bytes[3],
        "windspeed": bytes[4] << 24 | bytes[5] << 16 | bytes[6] << 8 | bytes[7],

        "battery": bytes[8] 
}

TTN has a great tutorial here:

Once you finish your payload function, it should show up as human readable text in the TTN console. And now we can pass that data to any one of TTN's integrations, such as Storage Integration (storing data you send to the cloud):

or HTTP Integration (making a custom API for your data):

Step 10: Final Notes

  • Attach the antenna as shown in the first step, and your range should be much further.
  • Connectivity between your Seeeduino mote and your Rising HF gateway are heavily dependent on having line of sight. The closer you are to having perfect line of sight, the more reliable your connection will be.
  • There are other cool features in your Seeeduino, including getting GPS coordinates, and checking battery status, which you can see in the wiki: http://wiki.seeed.cc/Seeeduino_LoRAWAN/

There's a lot to this, and I intend to maintain this for a little while. A couple of the things I intend to do are:

  • Add an example for OTAA in the GitHub repo
  • Add examples for the other country codes that the RisingHF + TTN support

Good luck, and happy hacking!