Writing code With Mu
Adafruit recommends the Mu editor to type your code into and interact with your project. You can find out how to install Mu on mac, PC, and Linux in this guide page on the Adafruit Learning System.
The advantage to using Mu is it has an editor and added features like direct save to the board's REPL interactive command line and print output. Mu can even plot values for you.
The code below will use the adafruit_tinylora
library which provides high-level access to your radio transceiver's features.
The code for sending data using a Si7021 sensor to a Things Network Gateway is shown below:
# SPDX-FileCopyrightText: 2021 ladyada for Adafruit Industries # SPDX-License-Identifier: MIT """Using TinyLoRa with a Si7021 Sensor. """ import time import adafruit_si7021 import board import busio import digitalio from adafruit_tinylora.adafruit_tinylora import TTN, TinyLoRa try: # typing from typing import Annotated, TypeAlias bytearray4: TypeAlias = Annotated[bytearray, 4] bytearray16: TypeAlias = Annotated[bytearray, 16] except ImportError: pass # Board LED led = digitalio.DigitalInOut(board.D13) led.direction = digitalio.Direction.OUTPUT # Create library object using our bus i2c port for si7021 i2c = busio.I2C(board.SCL, board.SDA) sensor = adafruit_si7021.SI7021(i2c) # Create library object using our bus SPI port for radio spi = busio.SPI(board.SCK, MOSI=board.MOSI, MISO=board.MISO) # RFM9x Breakout Pinouts cs = digitalio.DigitalInOut(board.D5) irq = digitalio.DigitalInOut(board.D6) rst = digitalio.DigitalInOut(board.D4) # Feather M0 RFM9x Pinouts # cs = digitalio.DigitalInOut(board.RFM9X_CS) # irq = digitalio.DigitalInOut(board.RFM9X_D0) # rst = digitalio.DigitalInOut(board.RFM9X_RST) # TTN Device Address, 4 Bytes, MSB devaddr: bytearray4 = bytearray([0x00, 0x00, 0x00, 0x00]) # TTN Network Key, 16 Bytes, MSB nwkey: bytearray16 = bytearray( [ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ] ) # TTN Application Key, 16 Bytess, MSB app: bytearray16 = bytearray( [ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ] ) ttn_config = TTN(devaddr, nwkey, app, country="US") lora = TinyLoRa(spi, cs, irq, rst, ttn_config) # Data Packet to send to TTN data: bytearray4 = bytearray(4) while True: temp_val = sensor.temperature humid_val = sensor.relative_humidity print("Temperature: %0.2f C" % temp_val) print("relative humidity: %0.1f %%" % humid_val) # Encode float as int temp_val = int(temp_val * 100) humid_val = int(humid_val * 100) # Encode payload as bytes data[0] = (temp_val >> 8) & 0xFF data[1] = temp_val & 0xFF data[2] = (humid_val >> 8) & 0xFF data[3] = humid_val & 0xFF # Send data packet print("Sending packet...") lora.send_data(data, len(data), lora.frame_counter) print("Packet Sent!") led.value = True lora.frame_counter += 1 time.sleep(2) led.value = False
Using Mu (or a text editor), copy this code and save it to your computer, naming it code.py
.
Note: The code is configured to use a RFM9x breakout by default. If you are using a Feather M0 RFM9x, delete the following lines:
# RFM9x Breakout Pinouts
cs = digitalio.DigitalInOut(board.D5)
irq = digitalio.DigitalInOut(board.D6)
rst = digitalio.DigitalInOut(board.D4)
Then, uncomment (remove the #
) the following lines to enable the RFM9x's builtin D0 and CS pins
Feather M0 RFM9x Pinouts
irq = digitalio.DigitalInOut(board.RFM9X_D0)
cs = digitalio.DigitalInOut(board.RFM9X_CS)
rst = digitalio.DigitalInOut(board.RFM9X_RST)
Installing Code on CircuitPython
Navigate to where you saved your code.py file. Copy (by dragging the file and dropping it) the file to the CIRCUITPY drive.
While the code will appear to run, it is not yet set up for your Application or Device. We'll do that next.
While we can send data to The Things Network, and our gateway might notice it, it isn't registered to a device yet. To register your device with The Things Network using ABP, you'll need to set three unique identifiers in the code.py
file: the Network Session Key
, the Device Address
, and the Application Session Key
.
Navigate to the Device Overview page for your Feather device.
Make sure the Activation Method is set to ABP.
Before adding the unique identifiers to our sketch, we'll need to first expand them by clicking the <> icon.
These are your keys. We're going to enter them into our code.py
, but we need to be careful - the keys on the Things Network console use parentheses or curly braces { } instead of brackets [ ].
First, copy the Device Address from the TTN console to the devaddr
variable in the code.
Then, remove the braces { } from the device address.
A device address copied from The Things Network console would look like: { 0x26, 0x02, 0x1F, 0x07 }
. In the code.py, it'd look like: devaddr = bytearray([0x26, 0x02, 0x1F, 0x07])
.
Then, copy the Network Session Key from the TTN console to the NwkSkey
variable in the code. Make sure to modify the code to remove the parentheses/curly braces { }.
Finally, copy the Application Session Key from the TTN console to the AppSkey
variable in the code. Make sure to modify the code to remove the parentheses/curly braces { }.
That's all for now - we're ready to run our code!
Upon saving (ctrl/cmd +s) your code, the board will refresh.
But where is the output? The serial monitor is hidden by default in Mu Editor.
In the Mu Editor, click the Serial button on the top icon-bar to bring up the Serial REPL.
You should see the temperature and humidity values printed to the console. The packet's status (sending, or timed out and unable to send) should appear shortly after. The LED on your Feather should also blink the onboard LED when it successfully sends a packet to The Things Network.
If you see Packet Sent!, rejoice - your packet has sent to the Things Network. But, while it's been sent, we want to check and make sure it's been received.
If you're using a Raspberry Pi: The Pi does not have an onboard LED located at pin D13, so it will not blink when the packet is sent. In the code, comment out every line which uses the LED, like the following:
led = digitalio.DigitalInOut(board.D13)
to # led = digitalio.DigitalInOut(board.D13)
Checking Data on The Things Network Console
We want to make sure the data has been received on the other end. To do this, we'll navigate to the The Things Network Console and select the application. From the menu on the right hand side of the page, Click Data.
If everything worked correctly, you'll see the payload from your device streaming into the page, in real time.
Neat, right? But while we received a payload, we still don't understand what it means. It's been sent to The Things Network and decoded on the client (Gateway) side, so it's not an AES-encrypted payload anymore. It's just not read-able by humans.
If you're sending packets in strange formats or encodings (like we are!), The Things Network Console has a programmable data decoder to decode the packets, and assign useful labels to the data.
Copy and paste the decoder script below into the decoder's integrated text editor and click save.
Then, click the data tab. Next to the raw payload data, you should see the decoded data for humidity and temperature.
// TinyLoRa - Si7021 Decoder function Decoder(bytes, port) { var decoded = {}; // Decode bytes to int var celciusInt = (bytes[0] << 8) | bytes[1]; var humidInt = (bytes[2] << 8) | bytes[3]; // Decode int to float decoded.celcius = celciusInt / 100; decoded.humid = humidInt / 100; return decoded; }
Text editor powered by tinymce.