Sunday, June 1, 2014

Cheap remote wireless temperature sensor with arduino and 433mhz rf module and DS18B20 or LM35

ADVERTISEMENT
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

15 comments:

  1. nice project, exactly what i needed.
    nevertheless, 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

    ReplyDelete
    Replies
    1. 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).

      Delete
  2. interesting and useful project
    Outside 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

    ReplyDelete
  3. anyone done an upgrade to RadioHead and DS18B20?

    ReplyDelete
  4. Hi, 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?

    ReplyDelete
  5. Can you make this project with use buzzer, when the rx reach a level condition? Such give warning when high temperature?

    ReplyDelete
    Replies
    1. Yes 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.

      Delete
  6. Could i Use a raspberry pi for the same project?

    ReplyDelete
  7. hello is there a way to just display the received data on the serial monitor instead of lcd ? thanks !

    ReplyDelete
    Replies
    1. Find line with lcd.print(temp); and comment it by adding //
      Then add Serial.println(temp);

      For more info, search on "arduino seral print"


      Delete
  8. Hello,i was not able to receive the external temp on the receiver.Could you look again

    ReplyDelete

  9. Hi,

    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

    ReplyDelete
    Replies
    1. Thanks for the feedback

      1) 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

      Delete
  10. Nice project!

    Here the same, oudoor is not displayed on the LCD,

    Tried serveral things.

    Can you drop an alternative code?


    Thanks in advance,

    Regards,

    Allard

    ReplyDelete
  11. Ü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)
    Szóval Így : vw_setup(1000); // Bits per sec

    ReplyDelete