Table of Contents
This blog post discusses a very low-cost, near-credit-card-sized Internet of Things (IoT) device called the EasyNode, that attaches to LoRaWAN networks. It can be used to capture sensor data or to control actuators.
The project is easy-to-build (well it has to live up to its name). All parts chosen are currently in-stock.
What does it do?
The block diagram shows what it’s all about:
The device is battery-powered and will communicate to the existing LoRaWAN network in your area, forwarding sensor measurements, or accepting control or actuator commands, remotely. The EasyNode contains a basic built-in temperature sensor to get started with environmental monitoring, and it is straightforward to attach additional I2C sensors of any type, or to use analog or digital inputs. There are connections for adding a basic external temperature sensor too. The EasyNode has a couple of open drain digital outputs to activate external circuits for operating relays and so on.
The EasyNode can be connected to a battery (well, two batteries – a coin cell, and three AAA cells) and placed anywhere with LoRaWAN coverage. It will periodically log to an SD card and transmit the temperature measurements, and these are retrievable from anywhere via the Internet of course. The EasyNode goes into a deep sleep regularly, to conserve power; it does that by shutting down the power to almost the entire board, leaving just the system power controller functioning from the coin cell.
The EasyNode is configured using a text file (config.txt) on the SD card. Logged data is in an easy-to-use format (CSV file format), ready for charting with Excel. The logged data timestamps are in ISO 8601 format, therefore Python (or any other language) libraries should have no trouble interpreting the files.
The user is able to configure the device (via the config.txt file) with credentials such that it can connect (at approximately 868 MHz or 915 MHz depending on the country) to any LoRaWAN network in the area. Often you can create a free account for this, so there are no charges to transmit or receive information with the EasyNode. I used The Things Network in the UK, and there was no charge.
If there is no accessible LoRaWAN network in the desired area, then it is possible to buy the infrastructure devices known as LoRaWAN gateways, and extend the network yourself. It costs a few hundred pounds/dollars to purchase a LoRaWAN gateway to do this, and it will provide a zone, in good locations, of several kilometers in diameter. It is possible to assemble a LoRaWAN gateway with a Raspberry Pi and a gateway HAT board (that’s what I did), but in practice, it is not much cheaper than just buying a ready-made, known working gateway.
How Does it Work?
The EasyNode has circuitry that periodically powers up the Pi Pico. The Pico reads its configuration from either internal Flash or SD card, then reads any attached sensors and appends the measurement to a CSV file on the SD card, and then powers up a LoRa radio. The Pico communicates to the LoRaWAN network and then requests for power to be shut down. The process repeats regularly. Since the Pico, sensors, and the LoRa radio are only powered up intermittently, it is possible for the batteries to last for a long time (hopefully years).
The power to the board is handled by a System Power Controller which is based around an MSP430 microcontroller running real-time clock (RTC) software. The Pico can send commands, and query the system controller, using I2C. The Pico sends I2C commands with the wake-up schedule, and the System Controller handles the power enablement/shutdown.
The Pico is connected to an SD card, so that configuration is made easy using text files. The SD card config.txt file is only read when a particular button is pressed and transferred to the Pico’s internal Flash in a scrambled format (there is a separate security chip to store this information, but the code is not implemented for that today). The plain-text config.txt file can be deleted from the SD card after the transfer has occurred.
The System Power Controller contains Real Time Clock (RTC) code, and it provides timestamps for the Pi Pico so that the measurements can be logged to the SD card. A new timestamped file is created on the SD card daily so that a single file does not grow too large.
The file can be directly opened in Excel, select the time and temperature columns, and click on Recommended Charts to plot the data.
The PDF schematic is available on GitHub, but it is also shown here.
The 2-layer Gerber files are on GitHub, ready for uploading to any PCB manufacturer. Most of the parts are soldered on the top side.
It is best to solder in the parts in the order that they are listed in the bill of materials. All parts are currently in-stock from Farnell (the project was deliberately designed with easy-to-find parts despite the world semiconductor shortage) apart from the LoRaWAN module, SD card socket, and coin cell holder, which are available from AliExpress.
The coin cell holder needs to be soldered with the correct orientation, it is labeled on the board (it is easy to accidentally solder it the wrong way, so it’s important to examine the silkscreen legend carefully). To solder the coin cell holder, it was easiest to tin the underside of the coin cell holder, apply a bit of flux and then place it on the board and heat the top of the connections with the iron to reflow the solder.
It is good to wear an ESD wrist-strap while soldering because the MOSFETs are easy to damage. All the parts are easy to hand-solder with a normal soldering iron, except for one part, U6, which is a QFN-packaged IC. That part (and its surrounding components C8, R20, and R21) could be omitted for now, since it is not used by the software yet. It may be more difficult to solder it when the rest of the board is assembled however.
U6 is only present in the more recent revisions of the board; the board that I assembled (revision 1.0) does not have it.
My revision 1.0 board has a couple of bodge wires, but the latest board revision on GitHub has this fixed.
The current working features of the EasyNode are listed here.
- Device configuration via SD card text file
- Temperature measurement from the on-board sensor
- Maintaining Time (RTC) with coin cell battery
- Saving data in CSV format to SD card with timestamps (new file every 24 hours)
- Sending temperature as an integer to the LoRaWAN network (i.e. data uplink)
- Receiving ON/OFF for two open collector outputs from the LoRaWAN network (i.e. data downlink)
- Device sleep and wake up at time intervals
Some future ideas are listed here (some would be software enhancements, others require board modifications or a plug-on board):
- Better temperature sensor (requires a new revision PCB, or a plug-on board) - this has now been done, in the revision 1.3 board. The older MIC280 sensor has been replaced with a more accurate STS21 sensor. It is slightly more difficult to solder, but not too hard, because the pad centers are spaced a reasonable 1mm apart.
- Ability to buffer measurements and log to SD card at a faster rate than transmitting to the network (no hardware changes needed for this)
- Ability to accept logic inputs from (say) door triggers or motion sensors (no hardware changes needed, just code additions, to read the logic inputs and act on them)
- Either a new revision PCB or an add-on card, for at least a couple of thermocouple sensors.
- In the short term until (4) is feasible, to implement an off-board temperature sensor (requires no new hardware, there is space for sensor wires to be soldered, but needs additional code)
- Consider a Micro SD card version, with clearance for the Pico Wireless antenna. Today, the SD card metalwork will be close to the antenna, and also the MOSFETs used for power control might need replacing due to the higher current needed for the Pico Wireless.
Although the project currently functions, there are some known bugs/areas for improvement:
- The interval between temperature measurements is restricted to 255 seconds (4 minutes 15 seconds). If the user attempts to configure any longer interval, it drops to 30 seconds for some unknown reason.
- The LoRaWAN stack stores some data in Flash memory, and it needs to be investigated what it is (it includes credentials) and perhaps the LoRaWAN stack should be modified or configured somehow to not use Flash memory for this.
- Today the sleep mode restarts the entire LoRaWAN stack each time any data needs to be transmitted, i.e. the EasyNode joins the network from scratch at each interval. I believe this is unnecessary and and it needs to be investigated how to keep the network join status while the board sleeps.
- As a knock-on effect of (3), because the join takes quite a few seconds (perhaps 10-20 seconds in some cases) if the join cannot occur for any reason, and if there are repeated attempts, then there is a risk of the LoRaWAN network not accepting any more join requests from that device, and then the only way of re-joining is to delete the device and re-add it in the LoRaWAN provider’s portal. Under normal conditions, this won’t occur, but it is a possibility. I hit it during testing, where I repeatedly powered down the node during times that the join was occurring but not complete.
- As another knock-on effect of (3), since the join action can take quite a long while battery power is wasted during this time. Battery life will increase when (3) is resolved.
- The EasyNode code (not the LoRaWAN stack portion) currently prints the credentials over the USB UART for debugging purposes. This needs to be commented out.
- The EasyNode code should delete the credentials from the text file automatically after it has read them, to prevent someone from taking the SD card and reading it. The workaround, for now, is to temporarily remove the SD card, and insert it into a PC and delete the file there.
- The EasyNode code should be extended to save the credentials in a secure location. The PCB design has space for soldering such a chip, but no code is currently written to make use of it.
- It is unknown what happens during changes to daylight savings time, I have not tested this. Also, no timezone is implemented.
The Pico microcontroller does not have any security features, so it is up to the user to ensure this project is only used for learning, or for purposes where little harm would occur if the device or its credentials were stolen. It’s unlikely to pose a significant risk if your outdoor temperature measurements get stolen by others, or if others spoof the measurements, however with indoor temperature you wouldn’t want anyone to identify occupancy through body heat for instance. It all depends on the use case, and you ought to know the value of the data you’re acquiring so that you can apply more security if required.
The board has a location for a security chip to be soldered down, but the code for it still needs to be written.
The user could reduce the risk of others reading out credentials from the device by (say) potting in epoxy resin, but fundamentally the system has no built-in security today due to the very low-cost processor that is used. If you need security features, for instance for commercial use, then you’ll need to spend more and buy a commercial product.
The software can at least prevent casual extraction of the credentials from the SD card because it could delete them (not forensically), so that if someone were to take the SD card, they could not insert it into another EasyNode and expect it to work. The credentials are currently encrypted (again not forensic-grade) in Flash but the 8-byte secret identifier (seed) used for decryption is stored in the same Flash – there is no secure location in the Pico to store it. It is feasible to modify the code so that the secret identifier is transferred to the System Power Controller and retained in its RAM until the backup battery is removed. It is still not very secure since an external debug tool could be attached to the I2C bus, so it still has limited value.
Sensor data is captured on the SD card and is not encrypted; anyone could unplug the SD card and read the sensor measurements.
System Power Controller Firmware
The System Power Controller project source code is on GitHub. Install Code Composer Studio, and open the project. Obtain either an MSP-EXP430G2ET Launchpad board (this is the cheapest option) or an MSP programmer (either MSP-FET or MSP-FET430UIF). The Launchpad board has a socket for programming the chip.
If you’re using an in-system programmer such as the MSP-FET or MSF-FET430UIF, then the connector J1 on the EasyNode board is wired to the programmer. Incidentally, you can also use the Launchpad board as an in-system programmer too, if you don’t wish to use the chip socket. The Launchpad board documentation describes how to use it in that way.
The connection details for the MSP-FET or MSP-FET430UIF are in the table and photo below. The first step is to make the connections between the unpowered programmer, and the connector J1 on the EasyNode.
|J1 Pin #
|Programmer Pin Name
|Used by the programmer to detect target voltage
Next, to use the programmer, regardless of whether a coin cell or main battery is connected (it’s not necessary for any battery to be connected, but it’s fine if they are), first ensure the Pi Pico is connected to the PC or to any 5V supply via its USB connector, and then connect the programmer USB connection to the PC. The green power LED on the programmer will turn on. Use Code Composer Studio to build and debug the code (press the hammer icon in Code Composer Studio to do that), and the red mode LED on the programmer with turn on. The code is now programmed into the MSP430, and the connection to J1 can be disconnected.
If you’re using the Launchpad board, then the steps are identical, except that the chip is first inserted into the socket on the Launchpad board, and there is no connection to J1. The chip should be removed or inserted into the Easynode board only when there is no power at all to the board (i.e. no coin cell or AAA cells, and no USB connection to the Pico).
If you wish to test if the MSP430 code is successfully running, connect an LED and resistor between pin 11 on the MSP430 chip, and ground. You should see the LED light up for a couple of seconds, every 30 seconds.
The Pi Pico can be programmed without any special equipment. Connect the USB connection to a PC. Hold down the only button on the Pico module (it is a white button labeled BOOTSEL), as well as the RST button on the EasyNode board, and then release the RST button on the Pico board, wait a few seconds and then release the BOOTSEL button. This will put the Pico into Bootloader mode and you’ll see a drive letter appear on the PC. Now you can drag and drop the firmware (it is the .uf2 suffixed file available on GitHub in the prebuilt folder) onto the Pico.
Repeat the process if you ever make modifications to the source code and build a new .uf2 file.
Anyway, initially, there’s no need to compile anything to get going, because the pre-built .uf2 file is on GitHub.
If you wish to build the code, the steps are below (you may need to modify these steps depending on what development environment you are using).
Optionally Building the Pico Code
If you’re not using the prebuilt .uf2 firmware, then create a development folder on your PC, for instance C:\development\pico
Install the Pico SDK, such that the path for it is C:\development\pico\pico-sdk
From the C:\development\pico folder, type the following:
git clone https://github.com/shabaz123/easynode.git
git clone --recurse-submodules https://github.com/sandeepmistry/pico-lorawan.git
git clone --recurse-submodules https://github.com/carlk3/no-OS-FatFS-SD-SPI-RPi-Pico.git
Open the project in CLion (it is free for 30 days; if you don’t wish to use CLion, you can build directly from the command line, or using Visual Code, but it’s pretty easy to use CLion), and in the Open Project Wizard window Environment box, type:
Press OK and wait a minute or so for CLion to build up its index.
Click on the hammer icon, and the code should be built.
Once the code builds successfully, you'll need to make one change in the LoRaWAN stack. Go to the following file:
and in this function:
static uint8_t SX1276GetPaSelect( int8_t power )
(it will be around line 205), add this as the first line in the function:
return RF_PACONFIG_PASELECT_PABOOST; // fix for RFM95W
Click the hammer icon to rebuild the project. The .uf2 file will be in the easynode\cmake-build-debug folder, ready for transferring to the Pi Pico as described above in the Pico Firmware section.
The EasyNode uses text files for configuration. An SD card is required, formatted to FAT (for instance FAT32) on your PC. Place a text file called config.txt on it, with the desired configuration. Example content is shown here:
# example config.txt file
# choose your region
# lorawan_region aus
# lorawan_region india
# lorawan_region north_amer
# 16-char device EUI
# 16-char app or join EUI
# 32-char app key
# wake interval
# realistically needs to be longer than 45 sec
# if longer than 255 sec, then only values wholly
# divisible by 60 are usable, e.g.
# 300, 360, 420 are fine for 5, 6, 7 minutes for example
# seed (can be random) used as a secret 8 hex bytes base64
# can use https://base64.guru/converter/encode/hex
# put any time configuration here
The EasyNode doesn’t read the config file unless the configuration INIT button on the EasyNode is held down while the Pico is starting up. To do that, insert the SD card into the EasyNode, and power it up using the USB connection on the Pi Pico (even if you have a battery attached).
Next, hold down the INIT button, and then press and release the RST button to reboot the Pico. Release the INIT button after about 10 seconds. The SD card configuration will have been read, and the RTC will be configured with the correct time (if the time detail was present in the config.txt file), and the RTC will be configured to wake up the EasyNode at the interval that is in the config.txt file.
Everything is done, and you can unplug the USB connection. If you ever want to troubleshoot the EasyNode, then plug in the USB connection and open up a serial port (115200 baud) to see debug output. Here is some example output:
*** LoRaWAN EasyNode ***
Built on Jul 27 2022 01:59:22
reading config from Flash
check: flash read contains 0x53
seed val is: 0x2211 4433 6655 8877 seed new is: 0xc470 5c53 2d6e 0e54
after unscramble with 0x66: 0x35
sd_spi_go_low_frequency: Actual frequency: 398089
Card Initialized: High Capacity Card
SD card initialized
SDHC/SDXC Card: hc_c_size: 60872
Capacity: 30436 MB
sd_spi_go_high_frequency: Actual frequency: 6250000
read: 34, 6, 39
syspwr_get_date string: 2022-07-27
syspwr_get_time read: 06:59:47
Written to CSV file:
temperature: 27 degC
Initilizating LoRaWAN ... success!
Joining LoRaWAN network ............ joined successfully!
sending temperature: 27 °C (0x1b)... success!
powered from USB
read: 34, 6, 39
syspwr_get_date string: 2022-07-27
syspwr_get_time read: 07:00:37
Written to CSV file:
temperature: 27 degC
sending temperature: 27 °C (0x1b)... success!
Extending the EasyNode
There are a couple of open drain outputs on J2, for controlling devices such as relays. The outputs are implemented in code and ready to use.
If you wish, a transistor can be wired to the board to act as another temperature sensor. The code for it is not implemented but it will be fairly straightforward.
Additional I2C sensors can be attached to the header pins labeled J2. There are a couple of inputs too, but I have not implemented any code to support these things.
A very easy-to-build IoT sensor node, called the LoRaWAN EasyNode was described. All the project files are on GitHub. The EasyNode contains an onboard temperature sensor, and it is possible to send temperature data using a free account with any LoRaWAN service provider, such as The Things Network. I’ll write up the steps to set up the device using The Things Network (since that is what I tested with), it’s pretty straightforward from their website, however, there are already blogs on the element14 website containing The Things Network example screenshots. The steps may differ from other providers.
The EasyNode can also be used as a temperature logger since it contains an SD card. The EasyNode can be used to control devices by adding circuitry to the two open drain outputs on the board.
Thanks for reading!