Firmware v3


Firmware for the ATTNode v3 is developed using the Arduino IDE, as there is no support for the ATTiny3216 in PlatformIO at the moment. When the PlatformIO-Support is available, the firmware will be adapted to use it instead of Arduino IDE.

The firmware uses the OTAA method to activate the device instead of ABP which was used by the v1/v2 nodes. Deep Sleep is supported, as well as the SHT21 and BME280 sensor. It's also possible to change the sending interval at runtime via LoRa Downlink.


Since the IDE does not support the ATTinys by default, the megaTinyCore is needed. See the installation instructions in the megaTinyCore Repository. You also need to install the MCCI LMIC using ArduinoIDEs Library Manager.

The firmware can be downloaded from my Git Repository

Compile Time Configuration

Before using the firmware you have to copy the file in firmware/config.h.example to firmware/config.h. After this you can open the firmware/firmware.ino with the Arduino IDE. Before compiling and uploading to the board there are some configurations to do in config.h Most options are described with comments in the config.h.example, but will also described here (at times there might be options in the firmware that are not yet added to this documentation)

#define LED_PIN PIN_A7

Sets the pin where the Signaling LED is connected. in the default PCB Layout LED D1 is connected to the ATTiny at Pin A7. If set, the LED will blink twice to signal a successfull OTAA join (which can take severals seconds from powerup).

#define HAS_BME280
#define HAS_SHT21

Sets which sensor is connected to the node. This will include the needed code for the choosen sensor as well as setup the payload format accordingly. At the moment only one sensor can be used at any time. Choosing HAS_NO_SENSOR will just send the battery voltage (e.g. for testing nodes without a sensor).

#define SLEEP_TIME 10

This sets the time to sleep between measurements / sending. The actual sleep time will bei SLEEP_TIME x 64 seconds. The default 10 from the example therefore means 640 seconds of sleep between measurements. This will not be an exact value between received data, as airtime and the send queue in the LMIC can add some seconds of delay as well. This value can be overwritten at runtime via LoRa Downlink. As soon as a value is set via downlink it will take precedence over the value set here.

#define CFG_eu868 1
#define CFG_sx1276_radio 1

This block will set up some stuff for the LMIC as regional bandplan, used radio and disabling some unneeded functionality in the LMIC. See for possible options.

static const u1_t PROGMEM APPEUI[8]={ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
static const u1_t PROGMEM DEVEUI[8]={ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
static const u1_t PROGMEM APPKEY[16] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };

This sets up the needed keys for OTAA activation. The keys can be obtained from the TTN Console if you use TTN. if you use ChirpStack instead be aware that APPEUI is always set to all 0x00 there and you will only need to set DEVEUI and APPKEY.

Attention: APPEUI and DEVEUI have to be in LSB order, which is the opposite of what is displayed by default in the TTN-Console. The byte order can be switched in the console to copy the keys in the right order. The APPEUI is in the correct order (MSB) by default.


The ATTNode v3 uses UPDI for programming by default in contrast to the SPI programming used on the ATTNode v1/v2. This means you will need an UPDI-capable programmer. The programming header is using the pinout defined by the MicroUPDI Project and includes UPDI Programming as well as serial debugging and power. If you don't want or have a MicroUPDI-Programmer you can also use an Arduino Uno/Nano/Pro Mini as described here

After choosing the ATTiny3216 as the target chip in the ArduinoIDE I leave most settings in the Arduino IDE at the defaults, only changing the clock speed to 5MHz to support smaller voltages and use less power, as well as setting the Voltage to UART baud setting to Closer to 3V. See the megaTinyCore documentation for the other options. Some of the Settings require the use of the Burn Bootloader Option to set the correct fuses on the ATTiny.


Limited serial debugging is implemented in the firmware. by default it will just print some states to the serial port. The debugging is enabled by setting the #define DEBUG in the config.h By default the serial debug uses 115200 8N1 settings for the serial communication. The macros DEBUG_PRINT() and DEBUG_PRINTLN() can be used in the code instead of the standard Serial.print() and Serial.println(). The macros will be inclded/excluded at compile time depending on the DEBUG define.

Runtime Configuration

It is possible to change the sleep time / sending interval via LoRa Downlink packets. This makes it possible to remote-configure nodes without reflashing them.

To set a sending interval it has to be scheduled as a downlink paket for the node as a 2-Byte uint value. To set an interval of 10 minutes for example, one has to send the value 0x000A (10 as a 2-Byte Hex), for 5 minutes it would be 0x0005 and so on. If you want to reset the node to the compiled in value just send 0xFFFF. Here is an example setting the interval to 10 at the TTN-Console:

Downlink Packet TTN

Please be aware that the actual sleep time is not exactly the set value in minutes, but rather the set value times 64 seconds. So a value of 10 would mean 640 seconds for example. Cause for this is that the ATTiny3216 sleeps for 32s at a time, so a value of 10 means it sleeps 20 times for 32 seconds.

The received value will be stored in the internal EEPROM of the ATTin3216, so the node will restore the last configured interval after a reset / power loss.

Payload Decoder

The payload format of the ATTNode v3 is the same as for the ATTNode v1/v2 at the moment. The payload decoder as described on the v1/v2 Firmware Page can be used. This also makes it possible to use a mix of v1/v2 and v3 Nodes in the same LoRa application.