A simple wireless temperature sensor for homemade weather station |
In this article, we use inexpensive 433/315MHZ inexpensive rf modules to make wireless temperature sensors. The same principle can be used to make any of your sensors wireless.
Compared to nrf24l01 modules, these are unidirectional and needs slightly higher (starting at 5v) working voltages. But for simple uses, these are quite handy as they consume only one digital pin on the Arduino while the nrf modules use 5 pins.
For temperature measurements, I used a ds18b20 digital sensor in this article. But it can be easily modified to use a lm35 sensor. To make the receiver compact and independent of a computer, I used an LCD module which is available as a keypad shield. But any LCD module with the standard LCD library will do the job.
The rf modules usually have 3 pins, two for power supply and one for data / Arduino. It is important to connect a small (17cm wire with 433MHz) to the antenna pins on the transmit module (see figure). In my experience, these links used to work pretty well from my terrace to the living room (around 10 meters and through the thick walls). The module even worked well after keeping inside the refrigerator for about 4-5 meters!
433mhz transmit module connections |
433 mhz receiver module pin connection |
In addition to the sketch, it uses two libraries. A one wire protocol for reading the temperature from ds18b20 sensors and a virtual wire library for sending the temperature reading over the wireless link.
For testing, I kept the remote module outside the room to get the outdoor temperature wirelessly without the trouble of connecting a long wire to the terrace.
Temperature can further be logged on to web based portals (for e.g. exocite) and can be accessed online
wireless temperature sensor with online logging |
Download Libraries
Virtualwire
Onewire
Download and keep the unzipped files in the Arduino libraries folder and restart the Arduino ide.
Wireless temperature receiver using an LCD module
// wireless temperature receiver using a simple 43mhz module and an lcs/keypad shield
// Arduino pin 15 (Analogue 1) is connected to a ds18220 for indoor temperature
// Arduino pin 16 (Analogue 2) is connected to the 433mhz receiver for outdoor temperature
// Arduino pin 17 (Analogue 3) is connected to an led via 330 ohm resistor
// credits to arduino.cc and owners of each libraries and online communities
// more details http://blog.riyas.org/2014/06/cheap-remote-wireless-temperature-sensor-with-arduino-uno-433mhz-rfmodule.html
#include <LiquidCrystal.h>
#include <OneWire.h>
#include <VirtualWire.h>
// select the pins used on the LCD panel
LiquidCrystal lcd(8, 9, 4, 5, 6, 7);
int DS18S20_Pin = 15; //DS18S20 pin
//Temperature chip i/o
OneWire ds(DS18S20_Pin); // on pin 15
void setup()
{
lcd.begin(16, 2); // start the library
lcd.setCursor(0,0);
lcd.print("Outdoor: -----"); // print a simple message
lcd.setCursor(0,1);
lcd.print("Indoor:"); // print a simple message
Serial.begin(9600);
vw_set_ptt_inverted(true); // Required for DR3100
vw_set_rx_pin(16);
vw_setup(4000); // Bits per sec
vw_rx_start();
pinMode(17,OUTPUT); // for an led on pin 17 (Analogue 3)to blink with rf link
}
void loop()
{
uint8_t buf[VW_MAX_MESSAGE_LEN];
uint8_t buflen = VW_MAX_MESSAGE_LEN;
if (vw_get_message(buf, &buflen)) // Non-blocking
{
lcd.setCursor(8,0);
char temp=0;//mod:tim:added a temporary character
for (int i = 0; i < buflen; i++)
{
temp=(char)buf[i];//mod:tim:convert uint to char
Serial.print(temp); //mod:tim:changed buff[i] to temp here
lcd.print(temp);
}
Serial.println("");
if(buf[0]=='1'){
digitalWrite(17,1); //blink with active rf link
}
if(buf[0]=='0'){
digitalWrite(17,0);
}
}
float temperature = getTemp();
Serial.println(temperature);
lcd.setCursor(9,1); // move cursor to second line "1" and 9 spaces over
lcd.print(temperature); // display temperature
lcd.setCursor(0,1); // move to the begining of the second line
}
float getTemp()
{
//returns the temperature from one DS18S20 in DEG Celsius
byte data[12];
byte addr[8];
if ( !ds.search(addr)) {
//no more sensors on chain, reset search
ds.reset_search();
return -1000;
}
if ( OneWire::crc8( addr, 7) != addr[7]) {
Serial.println("CRC is not valid!");
return -1000;
}
if ( addr[0] != 0x10 && addr[0] != 0x28) {
Serial.print("Device is not recognized");
return -1000;
}
ds.reset();
ds.select(addr);
ds.write(0x44,1); // start conversion, with parasite power on at the end
byte present = ds.reset();
ds.select(addr);
ds.write(0xBE); // Read Scratchpad
for (int i = 0; i < 9; i++) { // we need 9 bytes
data[i] = ds.read();
}
ds.reset_search();
byte MSB = data[1];
byte LSB = data[0];
float tempRead = ((MSB << 8) | LSB); //using two's compliment
float TemperatureSum = tempRead / 16;
return TemperatureSum;
}
Wireless temperature transmitter
//simple wireless temperature tranmitter
// DS18S20 sensor is connected to pin 8
// Rf modules tranmit (data) pin is connected to pin 7 on the arduino
// More info: http://blog.riyas.org/2014/06/cheap-remote-wireless-temperature-sensor-with-arduino-uno-433mhz-rfmodule.html
#include <VirtualWire.h>
#include <OneWire.h>
int DS18S20_Pin = 8; //DS18S20 Signal pin on digital 2
OneWire ds(DS18S20_Pin); // on digital pin 2
char *controller;
char msg[6];
void setup()
{
Serial.begin(9600);
pinMode(13,OUTPUT);
vw_set_ptt_inverted(true); //
vw_set_tx_pin(7);
vw_setup(4000);// speed of data transfer Kbps
}
void loop()
{
float temperature = getTemp();
Serial.println(temperature);
dtostrf(temperature, 6, 2, msg);
digitalWrite(13,0);
vw_send((uint8_t *)msg, strlen(msg)); // Send temperature.
vw_wait_tx();
delay(500);
digitalWrite(13,1); // blink the led on pin13
delay(500);
}
float getTemp()
{
//returns the temperature from one DS18S20 in DEG Celsius
byte data[12];
byte addr[8];
if ( !ds.search(addr)) {
//no more sensors on chain, reset search
ds.reset_search();
return -1000;
}
if ( OneWire::crc8( addr, 7) != addr[7]) {
Serial.println("CRC is not valid!");
return -1000;
}
if ( addr[0] != 0x10 && addr[0] != 0x28) {
Serial.print("Device is not recognized");
return -1000;
}
ds.reset();
ds.select(addr);
ds.write(0x44,1); // start conversion, with parasite power on at the end
byte present = ds.reset();
ds.select(addr);
ds.write(0xBE); // Read Scratchpad
for (int i = 0; i < 9; i++) { // we need 9 bytes
data[i] = ds.read();
}
ds.reset_search();
byte MSB = data[1];
byte LSB = data[0];
float tempRead = ((MSB << 8) | LSB); //using two's compliment
float TemperatureSum = tempRead / 16;
return TemperatureSum;
}
en
nice project, exactly what i needed.
ReplyDeletenevertheless, i was not able to receive the external temp on the receiver (it is readable on the serial monitor).
trying to find what is wrong, i saw:
- you mention on the description you use pin 15 (analog 1) while later on you use digital 2 for the indoor temp sensor.
- can you please explain the use of digitalWrite(17,1) on line 44? same on line 47? what is pin 17 used for?
regards,
E
Thanks for the comment. I connected an led on pin 17 to debug ( which i forgot to remove, remember to add a 330ohm resistor), which use to blink while receiving the signals. ( need to add a pinMode(17, OUTPUT); to setup). Indoor temp is using pin 15. ( i mistakenly wrote as pin 2 in the comment).
Deleteinteresting and useful project
ReplyDeleteOutside temperature is not displayed on the LCD display
I checked the oscilloscope signal reception on RX DATA pin Analog2 arduino and is currently only has a rectangular signal amplitude 3Volts (TX DATA to having 5Volts).
what happens?
Regards, Alexander
anyone done an upgrade to RadioHead and DS18B20?
ReplyDeleteHi, In the TX Monitor I cannot se the Temperature but only -1000. I am using a DS18S20 and code as written. Do I have to Change anything?
ReplyDeletethen there is a problem with your Ds18b20 connections. Check the wires and dont forget the PullUp Resistor (4.7k) from VCC -> Data
DeleteCan you make this project with use buzzer, when the rx reach a level condition? Such give warning when high temperature?
ReplyDeleteYes it can be done by adding a buzzer to one of the digital output pins of arduino. Then add an extra line after # float temperature = getTemp(); to check if temperature is above a limit for e.g if (temperature >30.0) {digitalwrite (buzzerpin, HIGH)} will keep it beeping for a higher temperature.
DeleteCould i Use a raspberry pi for the same project?
ReplyDeletehello is there a way to just display the received data on the serial monitor instead of lcd ? thanks !
ReplyDeleteFind line with lcd.print(temp); and comment it by adding //
DeleteThen add Serial.println(temp);
For more info, search on "arduino seral print"
Hello,i was not able to receive the external temp on the receiver.Could you look again
ReplyDelete
ReplyDeleteHi,
Nice project.
The Dallases are working in the monitor and also the Indoor is displayed on the LCD
Exept the main Outdoor temperature is not working here too.. tried serveral options...
Can you give alternative code's?
Thanks in advance,
Regards,
Allard
Thanks for the feedback
Delete1) Connect the outdoor transmit unit to computer and check if the serial port shows temperature readings (set 9600 bauds)
2) If the step 1 is good, then the problem is with rf transmitter. Check if the led on pin13 is blinking and if you have a receiver at 433mhz, you can get a short signal burst. Alternatively just test if the 433mhz modules are working fine
3) Put an led on pin 17 (ie A3 pin of uno) with a 330ohm resistor and it should blink with a proper rf link between the two arduinos
Best regards
Nice project!
ReplyDeleteHere the same, oudoor is not displayed on the LCD,
Tried serveral things.
Can you drop an alternative code?
Thanks in advance,
Regards,
Allard
everything is fine with that Code. you made anywhere else a mistake with the connections
DeleteHi there!
DeleteI want to thank you for the Sourcecode!
it works like a charm.
My Tx-Unit (pro mini ATMega168 5v / cheap ebay RF Transmitter) with Solar Panel and Backup-Battery.
Rx-Unit is also a Pro Mini 168 5v with cheap ebay RF receiver.
If you wan to boost the Signal, you can drive the Tx-Unit with up to 12v
BUT you have the inform you about legal rights in your specific land where you life!
In Germany where i life is a 10mW Transmit limit i think.
grab also a 17,5cm piece of wire and solder it onto both Modules as Antenna
Üdv. Ha valakinem nem megy a kinti szenzor akkor javitsa ki a hibát adó-vevő egységeknél : vw_setup(4000); // Bits per sec // itt át kel írni (1000)
ReplyDeleteSzóval Így : vw_setup(1000); // Bits per sec
Thank you for this really helpful suggestion! After I changed the transmitter- and receiver programs to (vw_setup(1000) everything works fine. Michael
DeleteGreat project-works perfectly. Thanks for sharing!
ReplyDeletecan u share the circuit picture ?
ReplyDeleteThank you for this really helpful comment. The 433MHz connection was o.K but the receiver couldn´t read the message until I changed the program to your suggestion: "vw_setup(1000);"
ReplyDeleteNow it works perfectly! Michael
Vielen Dank! Endlich die richtige Lösung des Empfangproblems! Nach Reduzieren der Bits per sec auf 1000 funktioniert die Datenübertragung problemlos.
ReplyDeleteThank you Csaba Erdös for this helpful advice. After changing the Bits per sec in both Sketches, it worked perfektly!
ReplyDeleteThank you Csaba Erdös for this really helpful advice. After changing both sketches to 1000 Bits per sec , outdoor temperatur was recognised corrcetly.
ReplyDeleteThank You for the first really helpful advise: change the Data rate from 4000 to 1000 B p s. Michael
ReplyDeletePls ,shematic this project,enyone. . .??
ReplyDeletePLS, i need shematic for this project. . . .
ReplyDelete