Temperature and humidity sensor

This article explores a series of improvements for a simple temperature and humidity sensor that communicates using a 2.4 GHz radio signal. The signal is received by a server (e.g. a Raspberry Pi) which acts as the hub in this system. The data received is stored in an sqlite database, and are visualized using matplotlib.

The primary purpose of the article is to illustrate what advantages can be obtained by moving away from the Arduino platform and to document this process. To keep the transition as straightforward as possible AVR microcontrollers are employed in all designs. Both saving power, to run the system on battery, and reducing the physical dimensions (i.e. size) will be discussed. Certainly, many more improvements in that area could be made and the article will be expanded in the future. Ultimately, the goal is to obtain a system that is cheap enough and small enough to put multiple sensors in every room and have them run on battery for at least a couple of months.

Version 1: Breadboard prototype using Arduino

Setting up a temperature and humidity sensor with a radio on a breadboard is relatively straightforward. We use the Arduino RF24 library, to control the radio transmitter (nRF24L01+), and the Arduino DHT library to read data from the temperature and humidity sensor (DHT22).

Except for simplicity there are really no advantages to that design. Size and cost are obvious problems. But even more limiting is the power consumption. Even on relatively large capacity Li-ion USB battery packs this can barely be run for a day. One of the power draw is the always on status LED, which is not easy to disable (putting a tape over the LED is certainly not going to help with respect to power consumption). Also the power efficiency of going from Li-ion to USB (at 5V) is not stellar, among other issues with the Arduino.

Num. Component
1x Arduino Uno
1x nRF24L01+
1x DHT22/AM2302
many jumper wires

The code that is run on the Arduino can be found here. The temperature and humidity are send once per minute to the hub.

Version 2: Arduino

This is a minor modification that still uses the Arduino platform. Basically the only improvement here is regarding size. Instead of the breadboard and jumper wires we use a perfboard to solder the RF24 radio transceiver and the DHT22 temperature sensor on top. By using some pin headers we can directly plug the perfboard circuit into the Arduino, essentially a homemade Arduino shield.

Num. Component
1x Arduino Uno
1x nRF24L01+
1x DHT22/AM2302
1x perfboard
  pin headers

The case is made using an Anycubic I3 Mega 3d printer. There is an opening for the sensor on top which is fixed with adhesive tape. For fastening the two halves there is currently a very simple snap mechanism, which relies quite heavily on the characteristics of the 3d printer. This should be improved.

Version 3: ATMEGA328P

We now switch from the Arduino to using a microcontroller. This helps us across the board. Most strikingly in terms of battery life, but also a significant reduction in size and cost results. To keep this transition as straightforward as possible, we use the ATMEGA328P microcontroller from AVR (which is at the heart of the Arduino Uno).

The input voltage range of the ATMEGA328P is 1.8-5.5V, for the RF24 we have 1.9-3.6V, and for the DHT22 we have 3.3-5.5V. Thus, there is a common range of operation for all three components, namely 3.3-3.6V. The reader might assume that we can run all of these components on three (rechargeable) AA NiHM batteries. However, fully charged NiHM batteries typically have a voltage of approximately 1.4V. Thus, 3 batteries significantly exceed the tolerance of the RF24 module. For that reason, and to stabilize the battery power supply, we incorporate a LP2950 voltage regulator which reduces the voltage to 3.3V. The LP2950, even for relatively significant currents, can handle the relatively small input-output voltage differential mandated by the combined nominal voltage (3.6V) of the three NiHM batteries.

The AVR microcontroller fits easily, together with all the other components, on a 4x6cm perfboard. Thus, the size of the circuit is comparable to that of the three AA batteries.

Num. Component
1x ATMEGA328P
1x nRF24L01+
1x DHT22/AM2302
1x LP2950ACZ
1x LED
1x R (270 Ohm)
3x AA battery
1x 3xAA battery case
1x perfboard

The code that runs on the AVR is compiled using gcc-avr. There is a good library for reading data from the DHT22. However, I could not get any of the libraries for the RF24 to work. Thus, I wrote some custom C code to send data using the RF24 radio.

Version 4: ATtiny44

The ATMEGA328P is a fairly large microcontroller (28 pins), which in some sense is too beefy for what we need here. Thus, we switch to the ATtiny44 microcontroller (14 pins). This helps us save space on the perfboard. The ATtiny44 is also a bit cheaper.

# Component
1x ATtiny44
1x nRF24L01+
1x DHT22/AM2302
1x LP2950ACZ
1x LED
1x R (270 Ohm)
3x AA battery
1x 3xAA battery case
1x perfboard

The main difference with the ATMEGA328P version is that the ATtiny44 does not have an onboard SPI controller. SPI is emulated on the ATtiny44 via USI and this requires that the MOSI and MISO connections are crossed over. That is, MISO on the RF24 radio is connected with MOSI on the microcontroller and vice versa. This is the opposite configuration compared to both the programmer and to the radio configuration on the ATMEGA328P. However, the actual code changes little.

Hub

All sensor data are communicated to a central hub. At my place I can get reception from everywhere, if I place the hub at a central location. An Arduino with a nRF24L01+ is used to receive the signal which is then communicated via USB to a server and stored in an sqlite database. Python scripts are then used to periodically plot the data and serve them via http. The code for the hub can be found here.