Skip to content

Extending the Firmware

The Sensor Net firmware is designed to be extended. This page covers the most common modifications: adding a new sensor type, increasing network range, and building a decoder for another platform.

Suppose you want to add a humidity sensor (for example, an SHT31 or DHT22). Here is the complete process:

Add the new sensor type to the enum in proto/messages.proto:

enum SensorType {
SENSOR_UNKNOWN = 0;
SENSOR_TEMPERATURE = 1;
SENSOR_PRESSURE = 2;
SENSOR_HUMIDITY = 3; // New
}

Run the protobuf code generator to update the C structs:

Terminal window
pip install nanopb
./scripts/generate_proto.sh

The updated files are placed in firmware/node/lib/proto/.

Create a new directory firmware/node/lib/Sensor/ (if it does not already contain your new files) and implement the Sensor interface:

HumiditySensor.h
#pragma once
#include "Sensor.h"
class HumiditySensor : public Sensor {
public:
bool begin() override;
SensorReading read() override;
const char *name() override { return "SHT31"; }
const char *unit() override { return "%RH"; }
};
HumiditySensor.cpp
#include "HumiditySensor.h"
#include <Wire.h>
bool HumiditySensor::begin() {
// Initialize the sensor over I2C
// Return true if successful, false if the sensor is not detected
}
SensorReading HumiditySensor::read() {
// Read from the sensor and return a SensorReading
// with the value and sensor_type set appropriately
}

The exact implementation depends on your sensor’s I2C protocol. Consult the sensor’s datasheet or use an existing Arduino library.

In config.h, add a new constant:

#define NODE_HUMIDITY 3

In main.cpp, add a conditional block for the new node type:

#elif NODE_TYPE == NODE_HUMIDITY
#include "HumiditySensor.h"
HumiditySensor sensor;

This follows the same pattern used by the existing temperature and pressure node types.

In the receiver’s pollReceive() function in main.cpp, update the switch statement or if/else chain that maps sensor_type values to string labels, so the serial output prints the correct type name for your new sensor.

Set NODE_TYPE to NODE_HUMIDITY in config.h, build, and flash:

Terminal window
pio run -t upload

Open the serial monitor and verify that the node reads the sensor and transmits reports.

If you need more range (for example, across a campus or between buildings), adjust two radio parameters in config.h:

#define LORA_SPREADING_FACTOR 10 // Was 7
#define LORA_BANDWIDTH 125.0 // Was 500.0

Higher spreading factor and narrower bandwidth trade data rate for range. At SF10 / 125 kHz, each packet takes roughly 8 times longer to transmit, but the signal can travel significantly further and penetrate more obstacles.

Important: All nodes must use the same spreading factor and bandwidth. If you change these on one node, you must change them on every node and reflash.

You can also increase MESH_MAX_HOPS in config.h to allow packets to traverse more intermediate relay nodes:

#define MESH_MAX_HOPS 5 // Was 3

To send readings more or less frequently, change REPORT_INTERVAL_MS:

#define REPORT_INTERVAL_MS 10000 // 10 seconds instead of 5

Longer intervals reduce radio congestion, which is important in larger networks. Shorter intervals give more responsive data at the cost of more airtime.

Because Sensor Net uses Protocol Buffers, you can generate decoders in other languages from the same .proto file. For example, to build a Python decoder:

Terminal window
pip install grpcio-tools
python -m grpc_tools.protoc -I proto --python_out=. proto/messages.proto

This generates a Python module with classes for SensorReport and SensorType. You can then read raw bytes from the serial port and decode them directly, bypassing the text-based [REPORT] format.

If your new sensor requires an Arduino library (for example, an Adafruit driver), add it to platformio.ini:

lib_deps =
RadioLib@^6.4
U8g2@^2.35
Nanopb@^0.4
adafruit/Adafruit BMP280 Library@^2.6
adafruit/Adafruit SHT31 Library@^2.0 ; New

PlatformIO downloads the library automatically on the next build.