Introduction: Arduino Feeding Xively.com With Temperature From DS18B20

This instructable will explain how to:
* connect a DS18B20 temperature sensor to an arduino
* read from the sensor using the 1-wire interface
* send that data to xively.com directly from the arduino
* view the resulting graph on the internet

http://xively.com is an Internet of Things host that generates graphs based on data you provide. In this example I am going to use it to monitor the temperature in my room. It's not a hackerspace, my wife keeps it far too tidy for that.

Step 1: Parts List

* Arduino with ethernet shield
I have an arduino Uno clone and a wiznet 5100 shield.
* Power supply (it can be powered via the USB port)
I was fortunate that my router has USB ports that provide the 5v output meaning the arduino  is powered whenever the router is and saves a plug, electricity, the environment and the  future of the world.
* DS18B20 temperature sensor
* RJ45 network cable connected between the arduino and your router

Step 2: Schematic

* Arduino gnd to DS18B20 both outer legs
* Arduino 5v to 4.7k resistor leg 1
* 4.7k resistor leg 2 to DS18B20 middle leg
* Arduino digital pin 2 to DS18B20 middle leg
* RJ45 cable from Arduino to router
* Power to Arduino (via USB or barrel jack, I use USB from my router)

Step 3: Prerequisites

Three libraries are required for the arduino:
onewire library from http://www.pjrc.com/teensy/td_libs_OneWire.html (specifically http://www.pjrc.com/teensy/arduino_libraries/OneWire.zip)
httpclient library from https://github.com/amcewen/HttpClient (https://github.com/amcewen/HttpClient/archive/master.zip)
Xively library from https://github.com/xively/xively_arduino (https://github.com/xively/xively_arduino/archive/master.zip)
install these libraries in your arduino/library directory.

An account with http://xively.com (formerly pachube.com and cosm.com)
Sign up for a free developer account at https://xively.com/get_started/
Pick a username, password, set your address and timezone etc. You will receive a confirmation email, click the activation link to avtivate your account.
You can choose to take the test drive to learn about xively or skip it, this is completely up to you.
Doing the test drive? I'll wait
- \ | / - \ | /
Done? Let's continue

Step 4: Add a New Device to Xively

You should now be on the Development Devices page of xively. This is where the fun starts.

Click on +Add Device

Give the new device a name eg Arduino DS18B20 temperature logger

Fill in a description about the device, its location such as My Hackerspace, and yourself if you like. I tend to add a link to my web site here although there is a dedicated web address area later in the instructions.

Choose whether the data is public or private. Do you really want the world knowing how hot your hackerspace is? I choose public unless it is something like an alarm which I keep private.

Click on the Add Device button at the bottom of the page

Step 5: The Xively Interface for Your New Device, and All the Access Codes

You will now be on a page with a lot of information. Don't be overwhelmed – it is mainly set and forget stuff.

The page is broken up into 8 parts:
* product ID, secret, serial number, activation code
* status (Activated), feed ID, feed URL (this shows the data on a graph), API endpoint
* “Add channels to your device!” - the arduino will handle this in the sketch
* request log – this is for debugging and confirming everything is working from the arduino side
* location – the geographical location of the sensor (optional)
* api keys – we will need this later in the arduino sketch
* metadata – can be edited
* triggers – ping a web page when something happens (eg temperature drops below freezing)

Step 6: Arduino Sketch

<code>
#include <SPI.h>
#include <Ethernet.h>
#include <HttpClient.h>
#include <Xively.h>
#include <OneWire.h>


// MAC address for your Ethernet shield
byte mac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED };

// Your Xively key to let you upload data
char xivelyKey[] = ""; // enter the key, under API Keys
unsigned long feedId = 0; // enter your feed ID, under Activated
int frequency = 15000; // delay between updates (milliseconds)

// Analog pin which we're monitoring (0 and 1 are used by the Ethernet shield)
int sensorPin = 2;

// Define the strings for our datastream IDs
char sensorId[] = "temp";
XivelyDatastream datastreams[] = {
  XivelyDatastream(sensorId, strlen(sensorId), DATASTREAM_FLOAT),
};
// Finally, wrap the datastreams into a feed
XivelyFeed feed(feedId, datastreams, 1 /* number of datastreams */);

EthernetClient client;
XivelyClient xivelyclient(client);

// initialize the one-wire interface
OneWire ds(sensorPin);  // on pin 2 (a 4.7K resistor is necessary)
/*
5v - 4.7k resistor - 18B20 middle pin - D2
gnd - 18B20 both legs (joined together)
*/

void setup() {
  // put your setup code here, to run once:
  Serial.begin(9600);
 
  Serial.println("Starting single datastream upload to Xively...");
  Serial.println();

  while (Ethernet.begin(mac) != 1)
  {
    Serial.println("Error getting IP address via DHCP, trying again...");
    delay(5000);
  }
  Serial.print("IP address: ");
  for (byte thisByte = 0; thisByte < 4; thisByte++)
  {
    // print the value of each byte of the IP address:
    Serial.print(Ethernet.localIP()[thisByte], DEC);
    Serial.print(".");
  }
  Serial.println();
}

void loop() {
byte present = 0;
byte type_s;
byte data[12];
byte addr[8];
float celsius;
int i;

if ( !ds.search(addr))
{
  Serial.println("No more addresses.");
  delay(250);
         ds.reset_search();
  return;
}
if (OneWire::crc8(addr, 7) != addr[7])
{
  Serial.print("CRC is not valid!");
  return;
}
// the first ROM byte indicates which chip
switch (addr[0])
{
  case 0x10:
   Serial.print("  Chip = DS18S20");  // or old DS1820
   type_s = 1;
   break;
  case 0x28:
   Serial.print("  Chip = DS18B20");
   type_s = 0;
   break;
  case 0x22:
   Serial.print("  Chip = DS1822");
   type_s = 0;
   break;
  default:
   Serial.println("Device is not a DS18x20 family device.");
   return;
}
        Serial.println();
       
ds.reset();
ds.select(addr);
ds.write(0x44, 1);        // start conversion, with parasite power on at the end

delay(1000);     // maybe 750ms is enough, maybe not
// we might do a ds.depower() here, but the reset will take care of it.

present = ds.reset();
ds.select(addr);
ds.write(0xBE);         // Read Scratchpad

for ( i = 0; i < 9; i++) {           // we need 9 bytes
    data[i] = ds.read();
}
int16_t raw = (data[1] << 8) | data[0];
if (type_s)
{
  raw = raw << 3; // 9 bit resolution default
  if (data[7] == 0x10)
  {
   // "count remain" gives full 12 bit resolution
   raw = (raw & 0xFFF0) + 12 - data[6];
  }
}
else
{
  byte cfg = (data[4] & 0x60);
  // at lower res, the low bits are undefined, so let's zero them
  if (cfg == 0x00)
   raw = raw & ~7;  // 9 bit resolution, 93.75 ms
  else if (cfg == 0x20)
   raw = raw & ~3; // 10 bit res, 187.5 ms
  else if (cfg == 0x40)
   raw = raw & ~1; // 11 bit res, 375 ms
  //// default is 12 bit resolution, 750 ms conversion time
}
celsius = (float)raw / 16.0;
        datastreams[0].setFloat(celsius);
        Serial.print("Current temperature: ");
        Serial.print(datastreams[0].getFloat());
        Serial.println(" celsius");
  Serial.println("Uploading it to Xively");
  int ret = xivelyclient.put(feed, xivelyKey);
  Serial.print("xivelyclient.put returned ");
  Serial.println(ret);

  Serial.println();
  delay(frequency);
}
</code>

Step 7: Welcome to the Internet of Things!

Once you have uploaded the code to the Arduino you should start to see information appear in the Request Log section and datapoints appear on the graph.

Congratulations, you are now updating the world with the temperature in your hackerspace :)

What's next? That's up to you.

How many times of day does your front door open?
What is the water level of your begonias?
Is your washing machine finished?
Is the coffee machine empty?
How loud are the kids playing music while you are out?

There are millions of possibilities for monitoring, just take a look around you. Does it do something? Then there must be a way to monitor it.

Here for the world to see is the temperature in my hackerspace<bs><bs><bs><bs><bs><bs><bs><bs><bs><bs><bs> living room:
https://xively.com/feeds/1238358657

Currently it is 26.5 degrees C, and it is supposed to be autumn.

Step 8:

I have not tested this code yet (but it does compile at least!)

This version should create temp_nnnnnnnnnnnn for each individual DS sensor and upload the data to xively.

Hopefully it will make the code multiple sensor friendly.

Greg

Comments

author
gregoryfenton (author)2013-11-04

I apologise, I forgot to do the actual reading of the chip in the above code :P

You need to add the following

for ( i = 0; i < 9; i++) { // we need 9 bytes
data[i] = ds.read();

after

ds.write(0xBE); // Read Scratchpad

author
MartinV94 (author)gregoryfenton2016-09-12

Hi there..

Is it still possible to use xively ?

author
silver111 (author)2015-01-14

Hi. is there a way to give their own names sensors (data streams)? Eg. Kitchen, living room, etc. I have 6 sensors.

author
gregoryfenton (author)silver1112015-01-14

Hi
The lines to change are
<code>// Define the strings for our datastream IDs

char sensorId[] = "temp";</code>
specifically, change "temp" to each of your device names eg "garage temp"

author
silver111 (author)gregoryfenton2015-12-09

I need to call each of the sensors connected to a single Arduino otherwise. Eg. Kitchen, garage, lounge.

author
silver111 (author)gregoryfenton2015-01-15

I have been thinking about this for sensor 1 = kitchen, sensor 2 = living room and so on. Where to enter the name of the second third and subsequent sensors? Everyone must have a different name.

author
voorkomen (author)2015-08-03

This setup will prevent you from using the capabilities of this perfectly designed IC. That is the adressing multiple IC's (temperature readouts) on the same line.

author
şerafettink (author)2014-11-05

I want to make circuit b using 4 sensors and 4 single resistor sensor connections print.4 sensor enough for my seven-inch screen. Is there another Arduino, or need

author
silver111 (author)2014-05-04

Hi. if someone was able to run it with multiple sensors (5)?

author
erojs (author)silver1112014-09-04

for multiple sensors in the end of the code after Serial.println("Uploading it to Xively");

replace

datastreams[0] = {
XivelyDatastream(sensorId, strlen(sensorId), DATASTREAM_FLOAT),
};

with

XivelyDatastream datastreams[0] = XivelyDatastream(sensorId, strlen(sensorId), DATASTREAM_FLOAT);

Worked for me, hope that helps.

author
silver111 (author)silver1112014-05-05

slightly corrected and in my code runs on multiple sensors.

I just have a problem with the naming of streams. What I mean is that the individual data struienia zwoimi call names and not the serial numbers of sensors.

author
gockenbr (author)silver1112014-06-17

silver111,

May I ask what you did to get multiple sensors working? I'd like to add additional temp probes but haven't been having much luck.

author
sidbin (author)2014-02-13

Error:

Serial.println("Uploading it to Xively");
datastreams[0] = {
XivelyDatastream(sensorId, strlen(sensorId), DATASTREAM_FLOAT),
};

  • ------------------------
sketch_feb13d.ino: In function 'void loop()':

sketch_feb13d:178: error: expected primary-expression before '{' token
sketch_feb13d:178: error: expected `;' before '{' token

author
silver111 (author)sidbin2014-05-05

Hi. if you were able to run the project with multiple sensors?

author
gregoryfenton (author)sidbin2014-02-13

There is a missing after the , in that line. I will have a look shortly and get b back to you.

author
chetan0412 (author)2014-04-12

Error,

Please give solution...

IP address: 192.168.1.6.

Chip = DS18B20

Current temperature: 33.13 celsius

Uploading it to Xively

xivelyclient.put returned -3

author
chetan0412 (author)2014-04-12

Connection and setup done but not working...

author
denisr (author)2014-04-10

Greg; Hi. As with rparkera and sidbin below, I have the same problem with the multiple sources sketch that they have.

I get the following errors:

Multiple_Xively.ino: In function 'void loop()':

Multiple_Xively:179: error: expected primary-expression before '{' token

Multiple_Xively:179: error: expected `;' before '{' token

Multiple_Xively:188: error: expected `}' at end of input

You were going to get back to sidbin, but don't seem to have done so.

And for the record, I have only just started using Arduino as it's the most practical solution (I think) to a long running temperature monitoring problem I have.

Thanks...!

author
rparkera (author)2014-03-21

Hi there - great instructable. Many thanks

Did you ever get back on sidbin's query? I have exactly the same problem. The single datastream works fine - but I can't get the multiple sources working. Help!

author
agavrin (author)2014-03-12

Some other example to use for xively reporting - use it to track URL performance..

http://linuxadvices.blogspot.ru/2014/02/log-url-performance-in-xively.html

author
fiolin (author)2014-02-26

Works for me thank you to share it

author
la3bna (author)2014-02-05

here is my feed:

https://xively.com/feeds/163946092

But I don't think it's public yet. Can you help me with that?

author
gregoryfenton (author)la3bna2014-02-05

It works for me :)

author
gregoryfenton (author)2014-02-05

Check step 5 and look at the picture. At the top it says "public".

If yours is set to private, click on the button (it looks like a pencil) to edit the settings.

Change it from "Private Device" to "Public Device", click "save and continue".

All done :)

Feel free to post a link to your public feed :)

author
la3bna (author)gregoryfenton2014-02-05

Thanks! I didn't see that until you pointed it out for me

(facepalm)

author
boernic (author)2013-12-01

hi i have followed your instructable and it works great!

im am thinking of adding some xtra ds18b20 sensors and wonder how to adress them any hints?

thanks

Nico

author
gregoryfenton (author)boernic2013-12-01

Just plug them in in parallel. The code will read them in order.
To update more than one datastream, look at the dataStreams[] parts of the code.

author

Thanks for the tutorial. I tried it and its working great with 1 sensor, but i cant see how to get a second or more sensors working. Any chance you could elaborate on the above a little more? Thanks in advance...

author
marijnbilsen (author)2014-01-03

Hi guys I need your help,

I've followed all the steps in this great tutorial but it doesn't work for me.

I keep on getting "No more addresses" in the serial monitor and xively is not receiving any datapoints.

What does this mean and how could it be solved?

It would be really great if one of you could help me

author
speedy25 (author)2013-12-10

Hey guys I have a problem.
I would like to add more sensors (DS18B20) and it fails.

Could you help me i am a beginner.

Thank you in advance for your help

standa

author
zenius (author)2013-11-22

Hi,
Thanks for your intructable ! :-)
It worked perfectly for 9 minutes, but now it's not sending anything…
What is the problem ?

author
gregoryfenton (author)zenius2013-11-22

Hi Zenius :)

Are you powering the Arduino from a steady power supply?
Have you tried resetting the Arduino?
Mine has been running pretty much continuously since it was set up with no issues apart from when the network cable became loose a couple of times. I think it has also only been turned off a couple of times too when I was sorting out round the router.

Get back to me :)

author
theohegg (author)2013-11-06

Hi there! Im trying to use your xively code but Im getting an "i" was not declared in this scope error. Would you know why this might be ? Im a bit new to arduino

author
gregoryfenton (author)theohegg2013-11-06

Fixed in the code.

I missed the line
int i;
after
float celcius;

I apologise for the oversight.

author
theohegg (author)gregoryfenton2013-11-06

Thx a lot. Now it works perfect

author
gregoryfenton (author)theohegg2013-11-06

Glad I could help :)

What's your xively link so I can see it working? :)

author
theohegg (author)gregoryfenton2013-11-06

This is my link. https://xively.com/feeds/1172808344 Tried to get a second temp read working but luck so far

author
cpoplawski (author)2013-10-05

I have everything wired up the same way as in your sketch except I don't seem to be getting any data from the sensor. When i use the example one wire sketch specific to the sensor it has no problems. any ideas?

author
gregoryfenton (author)cpoplawski2013-11-04

I apologise, I forgot to do the actual reading of the chip in the above code :P

You need to add the following

for ( i = 0; i < 9; i++) { // we need 9 bytes
data[i] = ds.read();

after

ds.write(0xBE); // Read Scratchpad

author
josephyong (author)2013-11-03

Please help, everything is fine just unable to get data from 18B20 Sensor it show IP address: 192.168.0.102.
Chip = DS18B20
Current temperature: 0.00 celsius
Uploading it to Xively
xivelyclient.put returned 200
i have double check the connection is correct.

author
gregoryfenton (author)josephyong2013-11-04

I apologise, I forgot to do the actual reading of the chip in the above code :P

You need to add the following

for ( i = 0; i < 9; i++) { // we need 9 bytes
data[i] = ds.read();

after

ds.write(0xBE); // Read Scratchpad

About This Instructable

59,086views

56favorites

License:

Bio: Focussing currently on supplying open source software to the masses. I supply linux CDs and DVDs across Europe, as well as mirror various open source ... More »
More by gregoryfenton:LinkIt One Tutorials - #14 Traffic lightsLinkIt One Tutorial #13 - Send a tweetLinkIt One tutorials - #0 Fix that pesky Serial port!
Add instructable to: