Internet Of Things – Remote Temperature Sensor Project


Last fall, I ordered the brand new < $5 (now < $3) ESP8266 WiFi microcontroller. Some months later, I finally had the time to play around with this cheap and yet powerful device. It can be used in several ways:

As a standard “Wifi modem”, accepting AT commands over a serial port, typically in conjunction with a regular microcontroller / computer system. Compared with my old Wifi modules, the price and size is much smaller. This usage is pretty standard, and you can upload new firmware versions to improve the features of the device.

With modified firmware, running as an LUA interpreter. This way, one can create LUA programs that will run on the Device, with no need for an additional microcontroller.

As a “regular” microcontroller / development board, where you use an IDE and download code to be run on the ESP8266. There is on Github a great project: Arduino-compatible IDE with ESP8266 support.  I can now use my Arduino IDE and code the ESP8266 pretty much like I would any other Arduino compatible board.  Many libraries will work directly, but of course not those that directly manipulate low level registers etc.

Doing som IOT stuff !

I decided to create a real “Internet of Things” Device, namely a remote temperature sensor. In addition to creating something useful with the EDP8266, I wanted to try out some of the services/IOT plattforms that are available. After some research, I ended up using ThingSpeak. Their free solution accepts unlimited amounts of data, and only limited to an upload frequency of max. 1 new entry every 15 seconds. They have a well documented API, with code examples for several plattforms, as well as a components  for graphing etc. They also have tools for creating automatic actions to received data: For example “Temperature sensor warmer than -18c, send Twitter message”. The great thing with using an IOT Infrastructure like Thingspeak, is that you can make the code on the sensor side simple, and on the “backend” side capitalize on the IOT vendors tools. Then, one can use standard web design mechanisms for end-user “front-end” interface etc.

The Remote temperature sensor

The concept of the Remote Sensor is a wifi-device with one or more temperature sensors.  One should be able to find current temperature and a log of temperature changes, with alerts etc. In this version I have 2 sensors, one inside my project box, and one external sensor on a 1 m. cable. This sensor can then conveniently be placed outdoors through window/ventilation opening, inside the freezed etc.

The system measures each sensor every 15 Seconds, and uploads the value to ThingSpeak if the temperature has changed more than a threshold, for example 0,2c since last upload. If completely stable temperatures, I regardless uploads a value every hour to show that the sensor and connection is alive.

The finished “Product” is quite small, and with an open box looks like the folllowing:


The key is shown to illustrate the small size. Components used:

Approx price
Where to buy
ESP8266 wifi microcontroller$3Multiple on eBay
25W 3-15V to 0.5-30V Auto DC-DC Boost Buck Converter $5,5Multiple on eBay. Note: This Board is a little "overkill" for this Project, a more simple step-Down to 3.3V converter would work fine
DS18B20 sensor (in "transistor" packaging)$0,7Multiple on e-bay etc.
1m Waterproof Digital Thermal Probe Sensor DS18B20$2Sensor in waterproof enclosure, 1 meter cable. Multiple vendors on e-bay.
Mounting Board$1 - $3I like the Adafruit Perma-Proto Quarter-sized Breadboard PCB.
Resistor, 4,7 K Ohm 0,25 W$0,05Any standard resistor will do
On/Off Switch$0,7
2,1 mm Power Jack$ 0,7

ESP8266 pinout / installation

The ESP8266 must have 3.3 V for both I/O and Power Supply. To program the device, I used the Adafruit FTDI friend, where one can set these by solder jumpers. The ESP8266 is programmed by having the GPIO-0 grounded. For normal use, GPIO-0 has no Connection.


Note: There are many versions of boards using the ESP8266. This is a popular, low cost version. There are other versions that exposes more GPIO than this one. For my purposes, one port for the temperature sensors was fine.


  • RX goes to TX on the FTDI
  • TX goes to RX on the FTDI
  • GPIO-0 to ground when Programming, no Connection when normal use
  • GND – GND
  • VCC – 3.3V power source (up to 0,3 A !)
  • GPIO-2 is Connected to the sensors, With a 4,7K pull-up resistor connected to VCC.

The temperature sensors I used was the DS18B20 (Maxim / Dallas): Datasheet. It uses a one-wire connection and supports wide range of I/O and VCC. Low cost and widely supported in Libraries.

Connection is VCC –  3.3V, Signal to GPIO-2 and GND-GND.


 * Read Temperature with Dallas DS18B20, connect to Wifi and send temperature to Thingsspeak infrastrucure
 * An "is alive" temperature reading is sent every hour, else temp changes is sent on every temp change of more than 0,3C
 * This code is in the public domain, without any warranties or guarantees of any sort.
 * The code contains serial port debugging information / status messages - and can be removed for "production" systes. 

#include <ESP8266WiFi.h>
#include <OneWire.h>
#include <DallasTemperature.h>

const char* ssid     = "ssid";            // The  ssid  for your wifi network
const char* password = "wifipassword";    // The  password for your wifi network
String THINGSPEAK_KEY = "ThingSpeakKey";  // The key from ThingSpeak for you channel

#define MINWAIT 15000    // Number of millis minimum before possible updates to ThingSpeak = 15 SEC
#define SHOWLIFE 60      // Nubmer of minutes between sending "proof of life" signal, even with no temp changes   
#define CHANGEDIFF 0.3   // How much temp change should create an update

byte server[]  = { 184, 106, 153, 149 }; // ThingSpeak IP Address:

WiFiClient client;

#define ONE_WIRE_BUS 2   // Data wire is plugged into pin 2 on the Arduino

OneWire oneWire(ONE_WIRE_BUS); // Setup a oneWire instance 
DallasTemperature sensors(&amp;oneWire); // Pass our oneWire reference to Dallas Temperature. 

DeviceAddress insideThermometer;
DeviceAddress outsideThermometer;

boolean outsideSensorOK = false;
boolean insideSensorOK = false;

float tempC, LastOutsideTemp, LastInsideTemp = 0;
long lastupdate;

void setup() {


  // Connect to WiFi

   Serial.print("Connecting to ");
   WiFi.begin(ssid, password);
   while (WiFi.status() != WL_CONNECTED) {

   Serial.println("WiFi connected");  
   Serial.print("Found ");
   Serial.print(sensors.getDeviceCount(), DEC);
   Serial.println(" devices.");

   // report parasite power requirements
   Serial.print("Parasite power is: "); 
   if (sensors.isParasitePowerMode()) Serial.println("ON");
      else Serial.println("OFF");
   if (!sensors.getAddress(insideThermometer, 0)) {
       Serial.println("Unable to find inside Thermometer"); 
   } else{
       insideSensorOK = true;
       Serial.print("Inside  Thermometer address: ");
       sensors.setResolution(insideThermometer, 12); 
       LastInsideTemp = sensors.getTempC(insideThermometer);   

   if (!sensors.getAddress(outsideThermometer, 1)) {
       Serial.println("Unable to find outside Thermometer"); 
   } else{
       outsideSensorOK = true;
       Serial.print("Outside  Thermometer address: ");
       sensors.setResolution(outsideThermometer, 12);    
       LastOutsideTemp = sensors.getTempC(outsideThermometer);   
} // setup

void loop() {

   // call sensors.requestTemperatures() to issue a global temperature 
   // request to all devices on the bus

   sensors.requestTemperatures(); // Send the command to get temperatures

   if (outsideSensorOK == true) {
       tempC = sensors.getTempC(outsideThermometer);   
       Serial.print("Outside Temp C: ");
       Serial.print(" Temp F: ");
       Serial.print(DallasTemperature::toFahrenheit(tempC)); // Converts tempC to Fahrenheit
       if ( abs(tempC - LastOutsideTemp) > CHANGEDIFF ) {        
                  Serial.print("Outdoor Temp Change larger than threshold - sending to ThingSpeak");
                  lastupdate = millis();
                  LastOutsideTemp = tempC;
                  ToThingsspeak(false, tempC);                  
       } else if (abs(millis()-lastupdate) > (SHOWLIFE * 60 * 1000) ) {
                  Serial.print("Need to send keep alive signal to ThingSpeak");
                  lastupdate = millis();
                  ToThingsspeak(false, tempC);                                    
   sensors.requestTemperatures(); // Send the command to get temperatures

   if (insideSensorOK == true) {
       tempC = sensors.getTempC(insideThermometer);   
       Serial.print(" Inside Temp C: ");
       Serial.print(" Temp F: ");
       Serial.print(DallasTemperature::toFahrenheit(tempC)); // Converts tempC to Fahrenheit
       if ( abs(tempC - LastInsideTemp) > CHANGEDIFF ) {        
                  Serial.print("Indoor Temp Change larger than threshold - sending to ThingSpeak");
                  lastupdate = millis();
                  LastInsideTemp = tempC;
                  ToThingsspeak(true, tempC);                  
       } else if (abs(millis()-lastupdate) > (SHOWLIFE * 60 * 1000) ) {
                  Serial.print("Need to send keep alive signal to ThingSpeak");
                  lastupdate = millis();
                  ToThingsspeak(true, tempC);                                    
} // loop

// --------------------------------------------------------------------------------------------------------------

void ToThingsspeak(boolean InsideSensor, float TheTempC)

    String addStuff = "field";
    if (InsideSensor == true) addStuff+= "1="; else addStuff += "2="; 
    addStuff+= String(int(TheTempC))+ "." + String(getDecimal(TheTempC)); 
    Serial.print("The data into UpdateThingsSpeak: "); 
 }  // ToThingsspeak
void updateThingSpeak(String tsData) 
   if (client.connect(server, 80)) 
      client.print("POST /update HTTP/1.1\n"); 
      client.print("Connection: close\n"); 
      client.print("X-THINGSPEAKAPIKEY: "+THINGSPEAK_KEY+"\n"); 
      client.print("Content-Type: application/x-www-form-urlencoded\n"); 
      client.print("Content-Length: "); 
      if (!client.connected()) 
      Serial.println("Connection to ThingSpeak failed after POST");    
    } else 
      Serial.println("Connection to ThingSpeak Failed before POST");    
} //  updateThingSpeak
long getDecimal(float val)
 int intPart = int(val);
 long decPart = 100*(val-intPart); //I am multiplying by 100 assuming that the foat values will have a maximum of 2 decimal places
 if(decPart>0)return(decPart);           //return the decimal part of float number if it is available 
 else if(decPart<0)return((-1)*decPart); //if negative, multiply by -1
 else if(decPart=0)return(00);           //return 0 if decimal part of float number is not available

// function to print a device address
void printAddress(DeviceAddress deviceAddress)
  for (uint8_t i = 0; i < 8; i++)
    if (deviceAddress[i] < 16) Serial.print("0");
    Serial.print(deviceAddress[i], HEX);

void printWifiStatus() {
   // print the SSID of the network you're attached to:
   Serial.print("SSID: ");

   // print your WiFi shield's IP address:
   IPAddress ip = WiFi.localIP();
   Serial.print("IP Address: ");

   // print the received signal strength:
   long rssi = WiFi.RSSI();
   Serial.print("signal strength (RSSI):");
   Serial.println(" dBm");

Note that a lot of the above code can be deleted for “production” purposes.  All the logging to Serial ports is to show some of the features of the libraries.

Seeing it in action. This is the ecternal sensor, published as an Public Channel on ThingSpeak.

So, this is how warm/cold it is in Oslo right now !

I have ordered some relays and more sensors: I will explore more in this area in the future, With more posts on this blog as I progress..









Leave a Reply

Your email address will not be published. Required fields are marked *