Low power sensors using nRF24L01+ and ATTiny

Smart home devices are expensive. A simple temperature sensor costs quite a bit. If you want one in each room it quickly gets costly. If you want door sensors on all doors and windows it’s pricey.

Cost is not necessarily a problem. If you know what you need you can make a budget. But if you don’t know what you need then it stands in the way of experimentation. I want to be able to put up a bunch of stuff in the house and see what I can do with it. It’s hard to justify that cost for other than oneself.

So I’ve been on and off playing around with different ways to create cheap sensors. Not just to have these sensors, but because it is fun to learn.

This is something of a report on my latest adventures within this.

Hardware

I started out with Arduino pro minis as they are easy to program and test things with. And it all starts with communication. My thought of sensor network consists of nodes that are sensors and/or actuators (think lights and motors), and gateways that can receive sensor readings and send commands to actuators. Since cost has been an issue, I’ve come to fall in love with nRF24L01+ – super cheap and low power radio modules.

Arduinos are super convenient, but they are entire boards. You can do a bunch of stuff to get them power efficient. However my thought is that all I really need is the MCU. So instead I want my sensors to run on ATTiny84 chips. They are a little harder to flash, but you can use the same Arduino tools as for an Arduino. Libraries even come with attiny compatibility so it’s hardly any difference from a software standpoint. You have less memory but these sensors only read a value and send the value to the radio module so I don’t need much memory.

Getting radio to work

The nRF chip communicates using SPI. It requires no more than 3.6V. More and they break. It draws very little current when it is idle, like microamps. But when it wakes up to send data it quickly draws around 15mA. It means the power source must allow quick power draw without causing a massive voltage drop. A capacitor helps. (The capacitor acts as a low pass filter, smoothing out a potential voltage drop.) In my setup I power the sensors with either 5V from wall connected DC transformer, or by battery. I therefore use a 3.3V pull-down component, and a 0.1uF capacitor. I’m not sure I actually need this when powering with batteries and will test this out soon. I use two AA as batteries. I’ve been successful using CR2032 occasionally but it often fails. I think I need better capacitors. A CR2032 does not have a high peak power draw and can’t deliver enough power when sending without too much of a voltage drop (causing the radio to stop working). A bigger on like CR2450 should work but haven’t paid my hands on any yet.

Powering the device is the main thing. After that comes wiring and software, but they are easy. I use the RF24 library by TMRH20 for software. It details the wiring. Make sure you get the CE and CSN correct. I’ve flipped those at several occasions.

I’ve had a lot of issues with getting Ack messages through. I think it has to do with power source and can possibly be fixed with capacitors. Still need to work on this. The data gets through, but it would be nice to know if data gets received or not. Especially for actuators. Most sensors will send it’s data again in a while so a drop of message is no biggie, except for door sensors that I’d like to resend every second until received by a gateway.

My setup consists of an Arduino pro mini communicating with a computer over serial. Essentially byte data received by the Arduino is sent in ASCII over the serial (simplifies debugging). Received data is published on mqtt to be subscribed on. The Arduino also reads from the serial and any data received is sent out over radio. It takes address and 32 bytes of data. There is very little logic on the gateway.

The idea is to be able to have several gateways around the house. Using raspberry pis would make them cheap. Using esp8266 or esp32 would make it even cheaper.

The gateway computer code is written in node.js.

Obviously I can connect the nRF chip directly to the gpio on an RPi, but this is simpler. I also have a bunch of computers laying around acting as gateways now.

Getting them to sleep

While power draw is low on the radio when idle, the MCU still draws power unless put to sleep. (Otherwise it just churns away at whatever clockspeed you’ve configured, looking for something to do. Delays are merely loops doing nothing but counting clockcycles.) So, we must tell it to go to sleep, getting it to use as little power as possible, and still be able to wake it up to occasionally do something useful.

When sleeping the sensors are barely using any current at all. Somewhere I read people saying that similar setups use less current than the battery looses by just laying around. This would mean that e.g. a door sensor on a window that never opens will work will function for the duration of the lifetime of the battery. That is quite impressive.

However, if this is the case, how will I know if the sensor is still working? To fix this I’m planning on also waking it up occasionally and send a heartbeat. That way I will be able to detect when a gateway haven’t heard from a sensor in a while and act accordingly.

Waking up

Getting it to sleep is fairly easy. Set some bits in some registers and off to sleep it goes. Getting it to wake up is done through interrupt. An interrupt is something that allows an MCU to halt it’s normal control flow to do something different for a while. It also happens to wake up a sleeping MCU.

I use two types of interrupts in my sensors so far. First one is a watch dog timer. It essentially let you specify a duration in which you want to be interrupted. It can be anything from a few milliseconds, to a few seconds (8s on the attiny). The second one is Pin Change interrupt that will alert the MCU that the logical value on a pin has changed. I use these in essentially the same way: I setup the interrupt I want to use, power down the radio, and go to sleep. When it wakes up I power up the radio, and continue the program which typically involves reading the value of an external sensor and send that to the radio module.

An important lesson I learned recently was to implement each ISR callback for each type of interrupt. E.g. there are two pin change interrupt handlers, PCINT0 and PCINT1, and one for WDT.

In the case of temperature sensor I ask the cpu to sleep for 8 seconds. I do that 6 times, and then send the temperature. The reason is that I don’t need to know the temperature every 8 seconds. Once a minute is fine. 6*8s is close enough.

On the door sensor I set the interrupt to react to the door pin – the pin that is high when the door is open and low when closed. This means that the sensor is basically sleeping almost all the time.

Summary

So far I’ve got very power efficient nodes for temperature and doors. They send data to a gateway that publish it over mqtt. I’ve implemented sending data to nodes, but have no nodes setup for it yet. Xmas lights might be a candidate as I have a bunch of WS2812B lights lying around.

I recommend anyone being interested to look at mysensors.org.

For the code for all this and more details, checkout my repos:

Nrf-gateway – nodejs server gayeway
Nrf-nodes – Arduino code for the nodes

Posted in Coding, Hardware

Valentine’s IoT mirror

I have for the longest time wanted to get into electronics. While I have been tinkering with connecting lights and motors to batteries since a very low age, taken several electronics courses both in highschool and at university, I’ve never done anything practical. Recently however I started using my now-of-age reserves of money towards DIY-electronic stuff in order to try and finally do something. In the last couple of weeks I’ve learned how easy it really is once you actually have the components you need, and how the DIY culture, especially around Arduino, have made these things incredibly accessible. It’s safe to say that we’ve come a long way since the days of holding a small toy lightbulb against a 4.5V battery (which I did as a kid).

Since when I get into something I tend to immerse myself quite deeply. Therefore, for this valentines day I quite readily jumped to the idea of building something with my newfound skills and toys. I therefore decided to connect a few LEDs in the shape of a heart that could flash in interesting ways to give to my girlfriend. As you can see in the video, it eventually turned into a mirror with hidden heart-shaped LEDs that can be controlled through a web interface on the local network.

I had at this point built up a sensor network at home using nRF24L01+ for wireless communication (which is an incredibly cheap but easy to use RF-module), and both Arduino Pro Minis as well as ATtiny85s as brains. Therefore I already had one of the radio modules connected to an Arduino communicating serially with a small server in the house. All I had to do was to figure out how I could control and drive a bunch of LEDs (ended up using 14) from the Arduino, and then try and package it nicely to be a suitable gift.

The mirror is built using an Arduino Pro Mini 5V, a nRF24L01+, driven using a 12V power adapter. Pretty sure 12V is overkill, but it’s what I had lying around. The nRF24L01+ must be run on 3.3V so it’s also using a voltage regulator that I put on the control board for the LEDs. The LED control is two 547 transistors and the LEDs are current limited using 470ohm. I figured that I couldn’t run the current for all 14 LEDs through one transistor (they would consume about 150mA, and I didn’t have any other transistors lying around) and therefore split them over two. Also ended up connecting the base of the transistors to two different pins on the Arduino, and could theoretically control the upper and lower part of the heart individually. Just ended up not doing that.

The mirror is continuously listening to radio traffic. When a control message arrives, it changes the mode of the LEDs. The software on the mirror is therefore incredibly simple. The server however had to be slightly modified. To this point the server was only listening to sensor nodes, and not transmitting any information back. I therefore had to change both the Arduino program to listen to serial communication and forward the data to the radio, and the software running on the server. The current server software was in Python, but decided to change to NodeJS. Since I also wanted to be able to control from a web interface, I took the time to also build a simple rest-api for sending the command to the mirror using HTTP. Thus the server software now listens to the serial for sensor readings from my sensors in the house and stores that in a database, as well as receives HTTP requests for sending out data packets to listening nodes.

Finally I created a super simple web page with four buttons for selecting one of the four settings on the mirror: heart-beat, off, on, and smooth pulse.

It was a fun project, girlfriend was happy, and I can now move on to the next projects. The project gave me experience in designing and soldering a PCB (using vero board), cutting such board using a drill, how simple it can be to put things together in not too shabby ways.

Posted in Coding, Hardware