ATtiny84 Low power LoRa node

** 2020-08-17 ** Update: Due to pin numbering the original code of 2018 does not work on PlatformIO toolset. The code is changed and adapted to function with the current version an arduino-attiny library. The changes are only made in the OOP version of the code on GitLab.

In this post I will show you the development of a Low Power LoRa node with a ATtiny84. A lot of thanks to the guys on The Things Network forum. I took their code for ATtiny85 and modified it to use it for a ATtiny84. I used this processor because I was familiar with it and has more IO pins.

Main modules/electronics used:

  • ATtiny84A microprocessor
  • BME280 sensor
  • RFM95W LoRa module

Technical specifications:

  • 4.8 microAmpere in sleep mode (3.3V)
  • 100mA @51 ms sending data SPF7
  • About 2.2-3.6 V power supply (Lithium Battery)
  • Measurement of Supply voltage, Temperature and Humidity in current version of the software.

Picture of the latest version:

Final version of the node

I used 675 Zinc-Air Batteries to create a real small LoRa node. Here a picture to compare the size to a 9V battery:

The PCB size is 45 x 20 mm. Maximum height is about 18 mm without housing.

The schematic:

The code can be found at https://gitlab.com/iot-lab-org/ATtiny84_low_power_LoRa_node.git

** NEW ** 2018-05-15: OOP code at https://gitlab.com/iot-lab-org/ATtiny84_low_power_LoRa_node_OOP.git

The schematic and PCB design can be found at https://easyeda.com/Leo/ATtiny84_LoRa_Environment_Node-d542dfbcc50d456c80869380bc979266

The total cost (typically Dutch):

Device Shop/webshop Price
ATtiny84 eoo-bv.nl  €       2,90
RFM95W aliexpress.com  €       4,60
BME280 (inclusief header pins-6 voudig) aliexpress.com  €       2,99
Printplaat LJK1801 EasyEDA  €       1,98
Batterijen (2x) 675 Zink Air Kijkshop  €       0,67
Batterij-veren Hackerstore.nl  €       1,10
IC-voet 14 pens eoo-bv.nl  €       0,16
C 100nF, raster 5 mm MKT eoo-bv.nl  €       0,15
C 470uF, 10V, 8,2x12mm axiaal eoo-bv.nl  €       0,10
Header-6pin female martoparts.nl  €       0,25
Header-2pin male martoparts.nl  €       0,03
Dupont-2pin female krimp martoparts.nl  €       0,10
3D print matriaal behuizing    €       0,23
     
Totaal    €     15,25

Current measurements:

Remember to remove the resistor on the BME280 to reduce current in sleep mode. Here (not) shown in second place from the top at the (original) 5 SMD parts.

The calculations I did to get the lifetime. Please correct me if I am wrong:

Information:

  • 4.8 uA in sleep
  • 100 mA @ 51 ms pulse every 5 minutes.

Power used in a year:

rest: 4.8 * 10E-6  A * 24hours * 365.25 days = 0.04104 Ah = 41.04 mAh per Year

sending: 100 *E-3 A * 288 measurements a day * 365.25 days * 51 * 10E-3 seconds / 3600 seconds in an hour = 0.149022 Ah = 149.022 mAh per Year.

Total 190 mAh per Year.

Useable time:

675 Battery (Zinc-Air):  640 mA => 3.37 Year

LS14250 Battery (Lithium): 1200mA => 6.3 Year

LS14500 Battery (Lithium): 2450mA => 12.9 Year

(This is incredible!, I do not believe it)

Testing:

I am now testing a few nodes: outside, in the freezer (-20 degrees Celsius) and room temperature with different batteries.

Inside (box) and outside closure:

I designed and printed this closure myself (3D print). You only have to add 2x M4 x 60mm bolts and 2x M4 nuts. I made the design public available: https://grabcad.com/library/weather-station-stevenson-screen-1. You have to print the mid-section a few (8) times. I learned that it is called Stevenson screen. My design has the looks but not the scientific usability :smile:

23 thoughts on “ATtiny84 Low power LoRa node

  1. Hello,

    Thanks for the complements, great to hear that you’re gonna use my design. Have fun with it!

    About the 470uF capacitor:
    Because of the 3.3 V working voltage a 6,3 Volt Capacitor would be enough. I bought a 10 V capacitor because a 6,3 V was not available or the size was not appropriate for my (physical) design.
    You may choose yourself what size or voltage you want to use. The capacity is also arbitrary, I did not make any calculation. Ik know when the RFM95W is sending data It wil draw 100mA in 50uSeconds.
    I guessed that will be heavy load for the battery, so I decided to add this capacitor to catch this pulse a bit, and to prevent the voltage to drop to much near the end of the lifetime of the battery.

    The 100nF capacitor you mentioned is fine. This 100nF capacitor is a (default) interference suppression capacitor for high frequencies.

    Leo.

  2. wonderful job conventions … I would use it for communication between 2 lora, so if you want to take out the thing network, what can I do to tell you step by step … thanks …

  3. Cheap but neat, I like it. I think the 675 battery with a much higher leakage current (selfdischarging) and narrow temp. working range can’t reach this numbers.
    To even lower current consumption heres my thoughts:
    – ordinary 470uF elko can draw several uA of current (leakage), eg. Nichicon KL series (very low leakage) only up to 0.2uA (200nA)
    – ATinny84 sleeping with wake up on external pin signal draw only ~0.5uA ( http://www.gammon.com.au/forum/?id=11488&reply=9#reply9 ), watchdog is disabled for the external hardware timer eg. TPL5110 with operating current 35nA
    – last but not least, check please this interesting document from TI: http://www.ti.com/general/docs/lit/getliterature.tsp?literatureNumber=swra365b&fileType=pdf
    maby Lora module can do same trick at 2.1V with TPS62730 DC-DC converter (30nA at sleep/bypass mode) and TX current (100mA at 3.3V) will drop by nearly 30% without any penalty like eg. max efective TX RF power output

    Correct: ATtiny85 sleep mode and wake on pin change: >0.2uA at 3.3V, >0.1uA at 2.1V

  4. When you want tot use Lora as a peer-to-peer connection it is better to use other examples.
    The Things Network LoRa is based on the LoRa based transmit technics and the LoRaWAN layer.
    The LoraWAN layer is responsible for encrypting data and authentication etc.
    This LoRaWAN layer uses also a lot of recourses of the microcontroller.

    For Peer-to-Peer connections you do not have to use this layer, It is easier to connect, using only the LoRa Transmit technics.

    An example is available here, it uses an ATmega32u4 and RFM95:

    https://www.elecrow.com/wiki/index.php?title=32u4_with_Lora_RFM95_IOT_Board-868MHz

    You can use the code to use it as starting point to program an ATtiny84 and RFM95.

    I hope this information will help you to solve your problem.

    Leo.

  5. It seems you’re an expert on this area (leak current/minimal power). Thank you very much for your comments on this!
    I’ll study the documentation an use some idea’s in my next designs!

    I’m now studying on Low power ARM processor (STM32L series) to make the node smaller (SMD design) and powerful processing possibilities.

    Leo.

  6. I’m definitely not an expert but thank you 🙂

    STM32L series is a very good choose, these parts are maybe best-in-class for now in power efficiency but i think some new optimised 8-bit MCUs still can beat them in some simple tasks that requires ultra low current consumption.

    You may already know that, but anyway I forgot to mention that ATtiny84A instead of ATtiny84 is a power-optimised version: https://www.google.pl/url?sa=t&source=web&rct=j&url=http://ww1.microchip.com/downloads/en/AppNotes/doc8187.pdf&ved=2ahUKEwiVwpW37ZvbAhWGC-wKHXxPBO4QFjAAegQIBxAB&usg=AOvVaw1H_SRtMiH_iLNmccZ2ewAQ

    sorry about that but 2nd correction on: “ATtiny85 sleep mode and wake on pin change: <0.2uA at 3.3V, <0.1uA at 2.1V" (less than <)

  7. Can i integrate this device in TTN seamless, or is it a Point-tp-point device. It would be nice, if TTN integrattion is possible. Thx. g.

  8. You can integrate this device in TTN seamless. It uses ABP Activation Method.
    I’ve now 4 of these devices running on different batteries (Saft LS14250 and Saft LS14500).
    One of them is placed in a freezer (-20 degrees Celsius).

    Leo.

  9. Hi Leo. Your design works well. I am trying to get pressure data out so I can measure height. Then also voltage. The calculations for pressure seem more complicated and I can’t fit it in. Changing to just one frequency and removing other stuff I get withing 30 bytes of fitting. Did you get pressure to work?
    Just sending raw bytes and calculating elsewhere is beyond my ability.

  10. Hello, verry interesting.

    I looked at the gitlab links but was not able to find the complete *ino file’s
    For me it seems that there are only library’s but no complete code for a ttn node

    Did I missed something? A tip is apreciated.

    Kind regards, Henk

  11. Hello Marco

    I put Vcc in the array and send it to monitor the power consumption or status of the battery, that you will understand.
    The first reason I do not send the pressure, is because I do not need that information. I have 1 pressure sensor on another device, and in my surrounding the pressure is equal (Holland, very flat…)
    But, there was another guy who want to check on his sheep walking uphill and downhill, and he wants to measure pressure to get the height.

    We both found out that the memory of the ATtiny84 is not capable to hold the code to calculate the pressure.
    It seems that every pressure sensor BMP280 has calibration data in it. The code uses this data to recalculate the actual pressure and this is a big calculation. The code wil be about 1k more than the 8k available in the ATtiny84.
    Thats was a disappointment.
    There are three ways to resolve this problem:
    – use an other sensor
    – get the calibration data and just send the raw data. Calculate the actual pressure on the server side (Thats the solution this guy is gonna use)
    – use an other processor (thats what I’m trying to do, using a ARM stm32l151 or 051, I’m now testing and making development boards).

    Greetings,

    Leo.

  12. Hello Henk,

    You can find the source code in main.cpp in the src directory.
    I’m using PlatformIO as development environment, that’s the reason why you do not see a .ino file.
    I think you can copy the source code of this main.cpp in a new Arduino project and you have to make sure you can use the libraries that are in this project.

    Greetings,

    Leo.

  13. Just for other readers of this post:

    We both found out that the memory of the ATtiny84 is not capable to hold the code to calculate the pressure.
    It seems that every pressure sensor BMP280 has calibration data in it. The code uses this data to recalculate the actual pressure and this is a big calculation. The code wil be about 1k more than the 8k available in the ATtiny84.
    Thats was a disappointment.
    There are three ways to resolve this problem:
    – use an other sensor
    – get the calibration data and just send the raw data. Calculate the actual pressure on the server side (Thats the solution Kim is trying to use)
    – use an other processor (thats what I’m trying to do, using a ARM stm32l151 or 051, I’m now testing and making development boards).

    Greetings,

    Leo.

  14. Hi Leo, this is a really great project. Thanks a lot for sharing this very detailed tutorial.
    I was able to rebuild one of these sensors exactly like you described.
    Unfortunatly i a allway receiveng only one Packet over my Gateway. As far as i understood if using ABP there should be some kind of communication between the Device and the Gateway before sending the Data. I receive a Packet every 5 Minutes an 7 Seconds like described in the Code. With a really short Payload for example “0BA00C2C0D57”
    Sorry for the Questions, but does this Payload includes the Temperature and the VCC ?

    What application do you use for Monitoring the Data, i was thinking about to push this data to an Influx DB and present it in Grafana.
    Would be really great if you could help me how to get the Temperature from the Payload.

    Thanks a lot for this great project 🙂

  15. Hello Btrek,

    In the schematic this is not drawn on purpose before the two capacitors, it just because I did not make a very good drawing.
    In the PCB the RM95 is “behind” the capacitors, by the way.

    Leo.

  16. Hello Simon,
    Thanks for the complements. I will try to answer your questions.
    ABP, there is no communication back from the gateway to the device. The device only sends its packet to the air. The advantage is that the time NOT in sleep mode is very short.
    So the gateway should receive 1 packet every 5 minutes (about). The counter for every packet is increasing. After a reset (unplug the power/battery and shortcircuit the power pins on the board, otherwise the Condensator will keep the power on) the counter will be set to zero.
    The payload includes the VCC, temperature and humidity.
    First of all you should extract the bytes from the payload. You can do this in different ways:
    Do it at The Things Network at the PAYLOAD FORMATS place in your application:

    Put in this code:

    function Decoder(Data, port)
    {
    var vccVoltage = (Data[0] << 8) | Data[1]; var temp = (Data[2] << 8) | Data[3]; var hum = (Data[4] << 8 ) | Data[5]; return{ vcc: vccVoltage temperature: temp /100, humidity: hum / 100, } } At your endpoint you can use this output to process further. You can also decode it at your endpoint, but then you have to use more code. I can give you a Java example if you want, but this requires more programming skills. I hope you have enough information to continue. With kind regards, Leo.

  17. Hi Leo, what if you would use an Arduino Pro Mini for increased flash memory? Its power consumption can also be brought down to a few uA.
    The lmic library uses most of the ProMini memory, so your code could be an improvement. However, is it sending over a single channel?

  18. Hello Daniel,

    I think this could work with a hc-srf05 distance sensor. You have to replace the BME code with code/driver for the distance sensor.

    With kind regards,

    Leo Korbee.

  19. Hi Gert,

    I have used an Arduino Mini in my first project. The reason I did not continue with this board is the form factor. I wanted to make a PCB as small as possible.
    Now (if I have time for this) I try to make it even smaller with a ARM STM32 microcontroller. The first tests are hopeful. The cons are that you have to solder SMD components on the PCB.
    But that is a nice challenge.

    My project is sending over multiple channels. You can change this if you want.
    The code you have to look for is this:
    RFM95.cpp:

    // EU863-870 specifications
    switch (TCNT0 % 8)
    {
    case 0x00: //Channel 0 868.100 MHz / 61.035 Hz = 14222987 = 0xD9068B
    RFM_Write(0x06,0xD9);
    RFM_Write(0x07,0x06);
    RFM_Write(0x08,0x8B);
    break;
    case 0x01: //Channel 1 868.300 MHz / 61.035 Hz = 14226264 = 0xD91358
    RFM_Write(0x06,0xD9);
    RFM_Write(0x07,0x13);
    RFM_Write(0x08,0x58);
    break;
    case 0x02: //Channel 2 868.500 MHz / 61.035 Hz = 14229540 = 0xD92024
    RFM_Write(0x06,0xD9);
    RFM_Write(0x07,0x20);
    RFM_Write(0x08,0x24);
    break;
    // added five more channels
    case 0x03: // Channel 3 867.100 MHz / 61.035 Hz = 14206603 = 0xD8C68B
    RFM_Write(0x06,0xD8);
    RFM_Write(0x07,0xC6);
    RFM_Write(0x08,0x8B);
    break;
    case 0x04: // Channel 4 867.300 MHz / 61.035 Hz = 14209880 = 0xD8D358
    RFM_Write(0x06,0xD8);
    RFM_Write(0x07,0xD3);
    RFM_Write(0x08,0x58);
    break;
    case 0x05: // Channel 5 867.500 MHz / 61.035 Hz = 14213156 = 0xD8E024
    RFM_Write(0x06,0xD8);
    RFM_Write(0x07,0xE0);
    RFM_Write(0x08,0x24);
    break;
    case 0x06: // Channel 6 867.700 MHz / 61.035 Hz = 14216433 = 0xD8ECF1
    RFM_Write(0x06,0xD8);
    RFM_Write(0x07,0xEC);
    RFM_Write(0x08,0xF1);
    break;
    case 0x07: // Channel 7 867.900 MHz / 61.035 Hz = 14219710 = 0xD8F9BE
    RFM_Write(0x06,0xD8);
    RFM_Write(0x07,0xF9);
    RFM_Write(0x08,0xBE);
    break;
    // FSK 868.800 Mhz => not used in this config
    // 869.525 – SF9BW125 (RX2 downlink only) for package received

    }

    The TCNT0 gives a random number and with modulo you can randomize 0-7.
    You can change this to switch to one or more frequencies.

    With kind regards,

    Leo Korbee.

Leave a Reply

Your email address will not be published. Required fields are marked *