Using The Things Network with ATOM Lite and LoRaWAN Unit
2021-07-15 | By M5Stack
License: General Public License Single Board Computers Arduino
* Thanks for the source code and project information provided by @Andreas Motzek
Software apps and online services
1. MicroPython Firmware for ESP32 v1.14Download esp32-idf3-20210202-v1.14.bin from the download page.
https://micropython.org/download/#esp32
Go to https://www.thethingsnetwork.org and sign up for an account if you don't have one.
Story
First, make sure that there is a The Things Network gateway near you. You can find out with the world map on https://www.thethingsnetwork.org. If there is no gateway near, you can setup your own. Instructions for adding gateways can be found here https://www.thethingsindustries.com/docs/gateways/adding-gateways.
Due to regulatory differences, The Things Network uses different frequency plans in different regions of the world. Please make sure that you have the correct version of LoRaWAN Unit: 868 is the right one for Europe, Russia, the Middle East and Africa and 915 is the one for Australia and the Americas. Detailed and authoritative information on frequency plans can be found here https://www.thethingsnetwork.org/docs/lorawan/frequencies-by-country.
Registering at The Things Network
If you do not have an account at The Things Network please sign up at https://www.thethingsnetwork.org.
After that, you can login to the console at https://console.cloud.thethings.network. I am located in Europe that is why I am using "Europe 1" in the cluster picker. If you were residing in other parts of the world, you would choose maybe "North America 1" or "Australia 1".
Click on "Go to applications" and then on "Add application", fill out the form and submit it. You now see the detail page of your application. The application will collect the data from all your devices. So let's create a first device.
Click on "Add end device" and switch to the tab "Manually". Choose "Over the air activation (OTAA)" and "LoRaWAN Version MAC V1.0.2". Click "Start".
Enter an id for your device in "End device ID" and a name in "End device name"; fill "AppEUI" with "0000000000000000" and "DevEUI" with 16 random hex digits. Click "Network layer settings".
Choose the correct "Frequency plan" and "Regional parameters version" for your country and device. For me, that is "Europe 863-870 MHz (SF9 for RX2 - recommended)" and "PHY V1.0.2 REV B". Choose "Supports class C" and click "Join settings".
Generate a random AppKey with the button right to the input field. Click "Add end device". You now see the detail page of your device.
Setting up your ATOM Lite
Connect the ATOM Lite with the LoRaWAN Unit and an USB port of your computer.
1. Install Python, Esptool and Ampy
If you have no Python 3 installation on your computer please download the installer from https://www.python.org/downloads/ and execute it. Then install Esptool and Ampy with
> pip3 install esptool
> pip3 install adafruit-ampy
on the command line.
2. Download and Install Firmware
Download https://micropython.org/resources/firmware/esp32-idf3-20210202-v1.14.bin. If you connect your ATOM Lite to your computer the first time wait a little until Windows installed the driver. Open the Windows Device Manager and look into "COM & LPT" to find the correct COM port, e.g. COM6. Then install the firmware with
> esptool.py --chip esp32 --port COM6 erase_flash
> esptool.py --chip esp32 --port COM6 write_flash -z 0x1000 esp32-idf3-20210202-v1.14.bin
Reset your ATOM Lite after the installation is finished.
3. Download and Install Libraries
Create a folder named lib on your computer. Download the files cooperative_multitasking.mpy, lora_states.mpy and asr6501.mpy from https://bitbucket.org/amotzek/micro-python/downloads/ into that lib folder. In the command line navigate to the folder above lib and then execute
> ampy.exe --port COM6 --delay 3 put lib
to upload the folder to your ATOM Lite.
4. Edit and Upload main.py
From the Code section of this project copy the file main.py to your computer and fill in your DevEUI, AppEUI and AppKey in line 7. You find these in the tab "Overview" on the detail page of your device in The Things Network console. Execute
> ampy.exe --port COM6 --delay 3 put main.py
to upload the file to your ATOM Lite.
Watch Live Data
On the detail page of your device in The Things Network console click on the link "See all activity". You will see a table with the incoming uplink (that means from your device to the network) data messages.
What's next?
The program in main.py sends a message with an increasing decimal number coded in ASCII every 5 minutes. To do something more useful you might want to modify it.
Lines 12-57 control joining the network and sending of messages.
Line 36 constructs and sends the messages.
I had some troubles in writing the driver for the ASR6501 chip that does the network stuff in the LoRaWAN Unit. The response lines to the AT+DTRX command are something between capricious and spooky :-) Therefore, line 46 assumes that sending data was successful if the driver cannot decide after 60 seconds. If you are interested in the source code of the driver, it can be found here https://bitbucket.org/amotzek/micro-python/src/master/src/main/modules/asr6501.py.
Lines 66-84 define procedures that help to display the status with the NeoPixel of the ATOM Lite: yellow - join is in progress, green - join was successful, blue - send is in progress, magenta - send was successful, red - error.
Happy hacking!
Code
from cooperative_multitasking import Tasks
from machine import UART
from lora_states import NOT_JOINED, JOINING, JOINED, SENDING, SENT, RETRY
from asr6501 import ASR6501
tasks = Tasks()
uart2 = UART(2, tx=26, rx=32)
uart2.init(baudrate=115200, bits=8, parity=None, stop=1, txbuf=256, rxbuf=256)
modem = ASR6501(uart2, '...', '...', '...') # DevEUI, AppEUI, AppKey as hex codes
count = 0
def modem_state_changed():
return modem.has_state_changed()
def start_join():
yellow()
modem.send_join()
tasks.when_then(modem_state_changed, end_join)
def end_join():
state = modem.get_state()
if state == JOINING:
tasks.when_then(modem_state_changed, end_join)
elif state == JOINED:
green()
tasks.after(10000, start_send)
elif state == NOT_JOINED:
tasks.after(60000, start_join)
else:
raise NotImplementedError()
def start_send():
global count
count += 1
blue()
modem.send_message(bytes(str(count), 'ASCII'), count % 29 == 1) # message, confirmed
tasks.when_then(modem_state_changed, end_send)
def end_send():
state = modem.get_state()
if state == SENDING:
tasks.only_one_of(tasks.when_then(modem_state_changed, end_send), tasks.after(60000, assume_sent)) # workaround for AT+DTRX response lines
elif state == SENT:
magenta()
tasks.after(300000, start_send)
elif state == RETRY:
red()
tasks.after(300000, start_send)
elif state == NOT_JOINED:
red()
tasks.after(300000, start_join)
else:
raise NotImplementedError()
def assume_sent():
magenta()
tasks.after(240000, start_send)
from machine import Pin
from neopixel import NeoPixel
gpio27 = Pin(27, Pin.OUT)
neopixels = NeoPixel(gpio27, 1)
def yellow():
neopixels[0] = (20, 20, 0)
neopixels.write()
def green():
neopixels[0] = (0, 25, 0)
neopixels.write()
def blue():
neopixels[0] = (0, 0, 25)
neopixels.write()
def magenta():
neopixels[0] = (20, 0, 20)
neopixels.write()
def red():
neopixels[0] = (25, 0, 0)
neopixels.write()
tasks.now(start_join)
while tasks.available():
tasks.run()
Have questions or comments? Continue the conversation on TechForum, DigiKey's online community and technical resource.
Visit TechForum