Introduction: LOG Wireless Temperature Monitoring

About: Lazy Old Geek

So this Lazy Old Geek (LOG) loves gadgets. My friend told me about and sent me a couple of NRF24L01+ modules.

So, being a Geek, I needed an application for them and I decided on a bunch of wireless temperature modules sending information back to a central location. Actually I have to give some of the credit and inspiration to Maniacbug:

Step 1: NRF24L01+ Module

So what is an NRF24L01+ ? Technically, it’s that little black chip in the middle of those modules in the picture. It allows wireless communications between similar devices. That’s how cellphones work. That’s how wi-fi works. The chip is called a transceiver as it has both a transmitter and receiver in it so it can send and receive information. The ‘+’ is just an upgraded version of the NRF24L01.

Simple: Basically, it allows two devices to communicate wirelessly over a distance. It’s similar to Bluetooth.

TechnoGeek: Here is the website for the IC itself.

The NRF24L01+ module includes all the supported electronics to make a complete transceiver that will easily interface with an Arduino. They’re available on eBay for about $2 a piece.

Warning: Most modules are fairly standard with eight pin interface but I guess there are some with 10 pins.

And there is a version with an amplifier and antenna for longer range:
With some power modifications, this one should work fine with my PCBs.

NRF24L01+ and the Arduino: As I like to work with the Arduino, I searched for an Arduino library for the NRF24L01+. My favorite is the one from Maniacbug, again:
And here’s some getting started info:

Step 2: DS18B20 Temperature Sensor

There are a lot of temperature sensors out there. I’ve used a lot of them in different projects. The LM35 is pretty cheap. But for this project, I chose the DS18B20. It’s only about $1.30:

Here’s the datasheet

The primary reason I selected the DS18B20 is the accuracy. It is calibrated to +/- 0.5C. Most of the other cheap temperature sensors have to (or should be) calibrated at various temperature points to achieve better accuracy.
Irrelevant Information: Calibration: A typical two point calibration is to use freezing temperature of water, 32F (0C)and boiling point of water, 212F (100C). But wait! This boiling point is only true at sea level. My altitude is about 4600 ft. so boiling water is about 203F. Okay, this is a lot of work and I’m LAZY so I will just assume that the DS18B20 is as accurate as claimed.
Secondary reason: the DS18B20 is digital as opposed to analog. Analog sensors accuracy varies with associated components and noise. Digital data is not subject to any of that.
Technobabble: The DS18B20 data is transferred serially, specifically SPI (Serial Peripheral Interface). But serial is digital. Simply speaking, there are two versions of digital data, serial and parallel.
Third reason: This one only a Geek can love. The DS18B20 uses something called a 1-wire buss. In theory what this means is that you only need one wire to connect the DS18B20 to the receiver (Arduino, in this case). In practice you need two wires as the circuit needs a ground. And full disclosure, I’m using three.
Mostly irrelevant Info: Some readers may have noticed that the picture shows the DS18B20 labeled as Dallas but the datasheet is Maxim. And I’m pretty sure the DS in DS18B20 stands for Dallas Semiconductor. Well, Dallas Semiconductor designed and manufactured a lot of really great ICs. I’m fairly certain they developed the 1-wire devices. Alas, they were bought out by Maxim.

DS18B20 and the Arduino: So, of course the Arduino needs a special library for the DS18B20 or actually for the One wire. I think there may be variants on this library or at least different versions but I used this one:

Here’s some more info on DS18B20:

I am also using the Dallas Temperature library. I think the only thing I’m using it for is the conversion of Centigrade to Fahrenheit, which I could’ve written myself. However, there’s a lot of other things you can do with this library.

Step 3: Putting It Together

So I could buy a bunch of Arduino UNOs or clones and proto shields but that gets expensive.
Since I’ve been in to making PCBs, I decided to make my own Arduino with NRF24L01+ modules.
WARNING: If you design your own PCBs, be careful with where you place the NRF24L01+ module. On my first PCBs I had it hanging over the Atmega328 IC and I couldn’t get it to work. I’m pretty sure it’s because of RF interference. The NRF24L01+ module and the AtMega328 both have 8/16MHz clocks and I’m pretty sure they were interfering with each other. I moved the module so that it sticks away from the AtMega. See picture.

So one PCB has the AtMega, a NRF24L01 connector and a DS18B20 on it. This one needed to be portable, so I needed battery power.
Power Requirements:
AtMega328      2.7Vdc  Arduino (2.9Vdc??)
Apparently the AtMega with 16MHz clock won’t work at less than 3.78Vdc.
          NRF24L01+     1.9Vdc
          DS18B20          3.0Vdc
Anyway, I decided to use 18650 Lithium ion batteries, which have voltages from about 4.2Vdc down to 2.0Vdc. With this design, the temperature module will operate at decreasing voltage as the battery discharges over time.
WARNING: Since the LOG Temperature PCBs don’t have a voltage regulator, you need to connect an 18650 battery to them even to load an Arduino sketch.
To make the project more complicating, I decided to use the AtMega328P at 8MHz so that they should be able to work at lower voltages.

The second PCB has the AtMega328P, a NRF24L01+ connector and a Nokia 5110 LCD on it.
Nokia 5110:

This will display the temperatures and the battery voltages from the Temperature PCBs.

PROBLEM: When I tested some of the Temperature PCBs, I noticed that the battery voltages were a little high. This design sets the Arduino using its internal 1.1Vdc reference and uses a voltage divider to bring it into useable range.
SOLUTION: Well, I don’t know if my voltage divider resistors are too far out of tolerance or the 1.1V reference isn’t great but I put a correction factor in the sketches. The calculated multipler is 4.2 but I tried 3.9 to get better results.

Step 4: Power Consumption

Some Arduinoites may have seen 3.3V Arduinos and noticed that they have 8MHz clocks instead of the usually 16MHz clocks. For example:
Well, there is a reason why they run at 8MHz instead of 16MHz:
If my calculations are right, this means that at 16MHz, the AtMega328P is guaranteed to work down to about 3.78V, so is not guaranteed to work down to 3.3Vdc or lower. I suspect that most AtMega328Ps will run at lower voltages but they may not.

My Temperature modules are powered by 18650 Li-Ion batteries. I am hoping to allow operation down to 3Vdc so I decided to go with the 8MHz.
Implementing 8MHz: The hardware is pretty easy, just use an 8MHz crystal instead of the usual 16MHz. Software is a little harder. To work properly at 8MHz, the Arduino has to have an 8MHz bootloader installed.

8MHz Bootloader:
Some of you may already have a method to do this but here is one fairly simple way to do it:

Now I have a special ISP cable to do this and I recently converted my MTS_Optiloader PCB to do this but I use the same basic software procedure as above.
When selecting the Atmega328 8MHz bootload, I think the following will work:
          Arduino Fio
          Lilypad Arduino w/Atmega328
Arduino Pro or Pro Mini (3.3V, 8 MHz) w/ ATmega328
I like to use the last one.
Once the Atmega328P is bootloaded, I would suggest you label it as 8MHz.
Caution: Being a GEEK, I’m programming a lot of Arduinos, some which are 16MHz and some 8MHz. Try to remember to select the correct ‘board’. I just tried to program an 8MHz with Arduino UNO selected, it failed to program. So it shouldn’t cause major confusion.

So I got a few of these PCBs made and working.  I installed some charged 18650 batteries in the Temp modules and ran them.
PROBLEM: The batteries lasted less than a day.
SOLUTION: Since the Temp modules aren’t doing anything between samples, I decided to try to put them to sleep.
Well, I found a pretty nice little library that does what I need:

This is used in the battery-operated sketches to reduce battery drain.

Step 5: LOG PCBs

My Remote Temperature PCB and TemperatureLCD5110 PCB schematics are shown. The Boards are available in the Eagle ZIP file.

Remote Temperature PCB BOM
1  Remote Temperature PCB
4  0.01uFd capacitor
2  22pF capacitor
1  47uFd capacitor
1  1n4148 diode
1  DS18B20 Temp sensor
1  Atmega328P microcontroller
1  28pin IC socket
1  NRF24L01+ module
1  10K resistor
1  4.7K resistor
1  240K resistor
1  75K resistor
1  1.5k resistor
1  JST2.0 connector
1  8MHz crystal
1  tactile pushbutton
1  LED 3mm
1  18650 battery and holder
Male and female header pins

Estimated total cost is about $12@

TemperatureLCD5110 PCB BOM
1  TemperatureLCD5110 PCB
1  JST2.0 connector
4  0.01uFd capacitor
2  22pF capacitor
1  47uFd capacitor
1  DS18B20 Temp sensor
1  Atmega328P microcontroller
1  28pin IC socket
1  NRF24L01+ module
1  LCD5110 display
5  10K resistor
1  4.7K resistor
1  1K resistor
1  16MHz crystal
1  tactile pushbutton
1  L78L33 voltage regulator
Male and female header pins

Estimated total cost is about $17


Both PCBs are single sided so some jumpers are needed.
GN1 and GN2 are ground points. I usually hook a wire between them for testing purposes. It’s a good place to attach DMMs and/or oscilloscope.
The NRF24L01+ will work from 1.9 to 3.6Vdc. Since a fully charged 18650 is about 4.2V, diode, D1, is added so the voltage to NRF24L01+ doesn’t exceed 3.6Vdc.
The TemperatureLCD5110 PCB can be powered by USB or by a 5Vdc supply. There are places for two DS18B20 temperature sensors on this PCB but the sketch only supports one.

Step 6: Sketch Setup

So this is a rather complicated project for Arduino sketches.
I used Arduino 1.0.3 version.
The following libraries need to be added. They are in a zip file:
Adafruit_GFX                    LCD5110
Adafruit_PCD8544            LCD5110
DallasTemperature           DS18B20
One Wire                          DS18B20
Narcoleptic                        Atmega328 sleep
RF24Master                      NRF24L01+
RF24NetworkMaster          NRF24L01+

DS18B20 Address
Each DS18B20 sensor has a unique address. You need to know that address so that you can talk to it.
I would recommend that you test each DS18B20 on a breadboard and get its address.
If you haven’t done this or can’t remember, here’s a way to find it after it’s already installed on one of these PCBs.

Connect the TemperatureLCD5110 PCB or RemoteTemperature PCB to your PC with a USB adapter. I use a PL2303 module but you can also use a USB-BUB.
WARNING: Since the RemoteTemperature PCBs don’t get voltage from the USB, you need to connect an 18650 battery to them even to load an Arduino sketch.

In the Arduino environment, make sure the correct serial port is selected. Make sure the correct Board is selected:
TemperatureLCD5110 PCB      Arduino UNO
RemoteTemperature PCB         Arduino Pro or Pro Mini (3.3V, 8 MHz) w/ ATmega328

Under ‘File’ ‘Examples’ scroll down to OneWire and select
In the sketch about eight lines down, you will see this
OneWire  ds(10);  // on pin 10 (a 4.7K resistor is necessary)
10 is the Digital pin used in the example. Change it to:
OneWire  ds(4);  // on pin 10 (a 4.7K resistor is necessary)
Upload the program. Open your Serial Monitor and set for 9600 baud. You should see something like the next picture.
The first line shows the address: 28 6B 88 B4 4 0 0 D1
FYI, this is in hexadecimal. Write it down or put it in a database.
When you exit the environment, you don’t need to save the changes.

NRF24L01 address:
The NRF24L01+ modules also have an address but unlike the DS18B20 they are not unique to the physical module. The addressing is done in software.
Now, I am using ManiacBug’s network addressing, RF24NetworkMaster which is an extension of his RF24 library.
For this version, the channel is 90, node 0 is the TemperatureLCD5110 PCB and the RemoteTemperature PCBs are nodes 1 – 5. This sketch will not support more than 5 RemoteTemperature PCBs.

TemperatureLCD5110 PCB sketch setup:
The TemperatureLCD5110 PCB sketch needs to be setup for your particular situation. First the DS18B20 address must match the sensor.
Using a text editor (I use Notepad++ but Notepad or Wordpad will work), open up LCD5110Receive.ino.
Find the line similar to this one:
DeviceAddress Therm1 = { 0x28, 0x6B, 0x88, 0xB4, 0x04, 0x00, 0x00, 0xD1 };
Change it so that the hexadecimal numbers match the address you found on your DS18B20. ( NOTE: That each number is prefixed with 0x so that it is identified as hexadecimal. Either 0x0 or 0x00 should work)

Next you will need to select the number of RemoteTemperature PCBs you will be using:
// Number of Temperature sensors
#define NumNodes 3
Change this as needed (maximum of five)

One other line you may want to change is the LCD5110 contrast:
          display.setContrast(55);     // Choose best contrast
This is under void setup(){
Try various values and decide on your preference.

Fahrenheit or Centigrade:
If you want Centigrade instead of Fahrenheit, change:
          bool centigrade = false;
          bool centigrade = true;

RemoteTemperature PCB sketch setup:
Note in the picture I put a red number in the lower right corner. This identifies the RemoteTemperature PCB.
I could have been clever and elegant and maybe stored module specific information in the EEPROM but I’m LAZY so I just wrote individual sketches for each module. What I would suggest is copy the TempTransmit1 directory to TempTransmit2 and change the .ino file to TempTransmit2 and make the following changes to all. Repeat for other modules.

One, you need to put in the correct DS18B20 address as above:
DeviceAddress Therm1 = { 0x28, 0x6B, 0x88, 0xB4, 0x04, 0x00, 0x00, 0xD1 };
  The 0x prefix comverts it to hexadecimal.
Two, you need to put in the correct node address
// Address of our node
const uint16_t this_node = 1;
Change it to the number you marked on the PCB. Start with 1 and sequence up.
You might also want to change the sleepDelay.
          int sleepDelay = 10000;     // in milliseconds
This is the length of time (10 seconds), the AtMega sleeps between sending samples. I’m fairly certain this is limited to a maximum of about 32 seconds. If you increase the sleepDelay, it means the battery will last a little longer between charges.

Step 7: Operation

So if you have the TemperatureLCD5110 PCB and at least one RemoteTemperature module running, the LCD should display the temperature and voltage of the module. This may take a while depending on the sleepDelay you set. My setup isn’t very robust and some samples may not be received. Many factors may influence this:
Voltage of 18650
Distance and obstructions between the modules
About every minute, the LCD temperatures and voltages will clear to zero. This is so you can tell if the modules are sending new data or you’re just seeing old data. If a module stays at 0, it probably means the battery voltage is too low. I suspect the modules will run down to about 3Vdc.

Temperature module LEDs should blink about every 10 seconds (sleepDelay). If they don’t blink, the AtMega has probably stopped working. Try pushing the Reset button or replacing the 18650 battery.
Caution: the blinking LED does not necessarily mean it is transmitting.

You can scatter the RemoteTemperature modules around in various rooms and maybe outside to monitor temperatures in different spots.

Battery life: You can tell if the battery is probably dead if the LED is no longer blinking and/or the LCD shows zero. Well, I’ve had various problems with my modules but had a couple where the battery lasted over 30 days. This depends on many factors, battery capacity, charger, components. But that is long enough for my needs.

Weekend Projects Contest

Participated in the
Weekend Projects Contest

Arduino Contest

Participated in the
Arduino Contest