Learning Goals 5 min
Plain LoRa is two modules talking. LoRaWAN is the protocol that lets thousands of devices share a public network. The Things Network (TTN) is a free, community-run global LoRaWAN with gateways covering ~200 countries. By the end of this lesson you will:
- Explain the LoRaWAN three-layer architecture: end-device → gateway → network server.
- Register a device on TTN and pick its activation method (OTAA vs ABP).
- Decode an uplink message in TTN's console and route it to a webhook or MQTT integration.
Warm-Up 10 min
No hardware required — today is conceptual + a free TTN account.
Check coverage
Visit ttnmapper.org. Search your area. If you see gateway dots, you have free LoRaWAN coverage. If not, you'd need to deploy your own gateway (a costly extra) or use a different network like Helium / Senet.
New Concept · The LoRaWAN architecture 25 min
Three layers
- End-device: your battery-powered Arduino + LoRa module. Sends "uplinks" (data going up) periodically. Sleeps in between.
- Gateway: a more capable LoRa receiver, often roof-mounted, with internet connectivity. Forwards every packet it hears to a network server. Doesn't belong to any device — "public" gateway can hear any device near it.
- Network server: a cloud service that decrypts and routes messages. TTN is the most popular free one.
Plus the "application": your code or service that consumes the data. Could be a webhook, an MQTT integration, a Node-RED flow, an HTTP endpoint.
Flow of an uplink
- End-device packages 10 bytes of sensor data, encrypts with its session key, sends as LoRa packet.
- Every gateway in range hears it. Each one forwards to TTN, tagged with its own location + RSSI.
- TTN deduplicates (multiple gateways may have heard the same packet), decrypts using the device's key.
- TTN routes the decrypted payload to the configured destination — your webhook, MQTT broker, etc.
- Your application receives the payload + metadata (which gateways, when, how strong).
Activation: OTAA vs ABP
| Method | How | Security | Use |
|---|---|---|---|
| OTAA (Over The Air Activation) | Device joins on first boot with a known DevEUI + AppEUI + AppKey. Network gives it a fresh session key. | Strongest (session keys rotate). | Default. Always pick this unless you have a reason not to. |
| ABP (Activation By Personalisation) | Session keys are baked into the device's firmware. Skips the join procedure. | Weaker (keys never rotate). | Rare. Useful when you can't wait for the join, or testing. |
Device classes
| Class | Behaviour | Use |
|---|---|---|
| Class A | Mostly asleep. Tx then opens two short Rx windows. Lowest power. | Sensor nodes (default). |
| Class B | Class A plus periodic scheduled Rx slots. | Devices needing more frequent server commands. |
| Class C | Continuously listening except while transmitting. | Mains-powered actuators (door locks, valves). |
For battery-powered sensors, always Class A.
Setting up a device on TTN
- Create a free TTN account at
thethingsnetwork.org. - Console → Applications → Create application. Name it.
- Add an End Device → Manually (or pick a board if it's in the catalogue).
- Pick frequency plan (EU868 / US915 / AS923 etc.) — match your region.
- LoRaWAN version: latest (1.0.3 or 1.1).
- Activation mode: OTAA.
- Note the auto-generated DevEUI, AppEUI (or JoinEUI), AppKey. Copy these into your sketch.
Sketch — using MCCI LMIC library
The most popular Arduino LoRaWAN library. Install via Library Manager ("MCCI LoRaWAN LMIC library").
Configuration is more involved than plain LoRa — you need to set the DevEUI / AppEUI / AppKey, schedule transmissions (respecting duty cycle), handle the join, and parse downlinks. Adafruit and TTN publish example sketches; start from those.
// Skeleton — full LMIC sketches are 200+ lines; this is the shape.
#include <lmic.h>
#include <hal/hal.h>
static const u1_t DEVEUI[8] = { /* from TTN, LSB order */ };
static const u1_t APPEUI[8] = { /* from TTN, LSB order */ };
static const u1_t APPKEY[16] = { /* from TTN, MSB order */ };
void os_getDevEui(u1_t* buf) { memcpy_P(buf, DEVEUI, 8); }
void os_getArtEui(u1_t* buf) { memcpy_P(buf, APPEUI, 8); }
void os_getDevKey(u1_t* buf) { memcpy_P(buf, APPKEY, 16); }
void setup() {
os_init();
LMIC_reset();
LMIC_startJoining();
}
void loop() {
os_runloop_once();
}Once joined, you'd call LMIC_setTxData2(port, data, len, confirmed) to queue an uplink. The library handles channel hopping, duty-cycle enforcement, and downlink receipt.
Worked Example · Register and send your first uplink 20 min
Step 1 — set up the TTN application
Follow the steps in §3 above. Get DevEUI / AppEUI / AppKey.
Step 2 — wire and program
Same RFM95 wiring as L04-18. Use the "ttn-otaa-feather-us915-dht22" example (or the EU868 version) from the LMIC library and replace the keys with yours.
Step 3 — observe the join
Serial Monitor shows "Joining..." → "Joined!" within a minute (assuming a gateway is in range).
Step 4 — observe the first uplink
In TTN console → your application → your device → Live data. You'll see incoming packets, with the gateway that received them, RSSI, decoded bytes.
Step 5 — add an integration
TTN → Application → Integrations → MQTT or Webhooks. Configure to forward every uplink to your service. Now your TTN packets land in MQTT (Home Assistant!) or a custom HTTPS endpoint.
Step 6 — send a downlink
From TTN console → your device → Messaging → Downlink. Enter a hex payload. Send. Your device receives on its next Rx window.
Basic 5 min
The TTN free tier gives you ~30 s of airtime per device per day. SF7 packet ≈ 50 ms. SF12 ≈ 1500 ms. Max daily packets at each SF?
Challenge 1 5 min
The TTN console shows your device's keys in human (MSB-first) order:
DevEUI 70B3D57ED005A1B2 JoinEUI 0000000000000001 AppKey 2B7E151628AED2A6ABF7158809CF4F3C
Write the three arrays for the LMIC skeleton above. Remember: DevEUI and AppEUI (JoinEUI) go in LSB first. AppKey stays MSB first.
It works if each byte is written as 0x.. and the order is right. With real hardware, the Serial Monitor shows "Joined!".
Challenge 2 5 min
Your device sends 1 packet per hour at SF9 (~250 ms per packet, at ~100 mA). It sleeps at 5 µA. It runs on 2 × AA (2,500 mAh). Estimate the years of life.
Send a temperature of 23.45 °C and a humidity of 61 % in just 3 bytes. Multiply the temperature by 100 and store it in 2 bytes, high byte first. Store humidity in 1 byte.
Write the three bytes in hex. Then write the C++ lines that fill uint8_t payload[3] from a float temperature and an int humidity.
TTN's free tier allows ~30 s of airtime per device per day. With the SF9 packet from Q3, how many uplinks fit in a day? What is the shortest gap between them, in minutes?
It works if every answer shows its working, with units.
Challenge 3 · Check a tracker plan before you build it 10 min
A teammate plans a TTN pet tracker. It sends a GPS fix every 10 minutes. It must last 6 months. Their plan uses SF10 (~500 ms per packet).
- Count the packets per day. Does SF10 fit TTN's 30 s a day? If not, how often could it send at SF10?
- At SF7 (~50 ms per packet), does a fix every 10 minutes fit?
- Each fix-and-send uses 40 µAh. Sleep is 5 µA. Work out the charge per day.
- Pick the smallest battery that lasts 183 days: 500, 1,000, 1,200 or 2,000 mAh.
It works if you show the original plan breaks the airtime rule. Name a battery and the days it lasts.
Recap 5 min
LoRaWAN = LoRa physical + a network layer with gateways + a network server. TTN is the free public option. Register a device on TTN, copy keys into your sketch, use LMIC library, see packets in the console. Tomorrow we leave radio and go industrial: Modbus on RS-485.
- LoRaWAN
- Network protocol on top of LoRa. Standardised by the LoRa Alliance. Adds encryption, addressing, gateway support.
- End-device
- Your sensor / actuator. Talks LoRa to gateways.
- Gateway
- Receiver with internet. Forwards packets to a network server. Doesn't process the contents.
- Network server
- Cloud service that authenticates devices, decrypts payloads, routes to applications. TTN is the most popular free one.
- OTAA / ABP
- Activation methods. OTAA = join procedure with key derivation. ABP = static keys.
- DevEUI / AppEUI / AppKey
- Identifiers and the root key used during OTAA join.
- Class A / B / C
- Power-vs-listening tradeoffs. Class A = always-sleep, briefly-listen; Class C = always listening.
- Uplink / downlink
- Device → server / server → device. Uplinks are frequent; downlinks are rare and limited.
- LMIC library
- The standard Arduino LoRaWAN library. Handles channels, duty cycle, joins.
- TTN integrations
- Outputs: MQTT, webhooks, Node-RED. Forward uplinks to your service.
Extra Mission 5 min
Part 1 — Plan a real LoRaWAN deployment
Pick a sensor you would put on TTN — a bike tracker, a garden rain gauge, a letterbox alert. On paper, plan it.
Your plan must include:
- What it sends, and the payload laid out byte by byte.
- The SF, and how often it sends, checked against TTN's 30 s a day.
- OTAA or ABP, with a reason.
- A battery estimate, done like Challenge 3.
- The gateways near you that could hear it (look on
ttnmapper.org).
Part 2 — Make it
Make a free TTN account and register your device. Put its keys into the LMIC sketch in the right byte order, and add your payload-packing code. If you have LoRa hardware and a gateway in range, send a real uplink.
Bring back next class: the sketch, and a screenshot of your TTN device page or its Live data. For ARD-L04-20, bring an RS-485 module (MAX485) if you have one.