Skip navigation

Tag Archives: Ethernet

TempuratureSensor

Living in the great north, the winter cold always presents interesting challenges. A common fear is that your furnace will happen to give out while your away, then your pipes will freeze and burst, transforming your house into an indoor water park. Way back when, in the days of land line telephones, then made little devices that would watch the temp and give you a call if the temperature in your house fell too low. While I could have probably picked up something like that cheap, it wouldn’t have done much good since I don’t have a telephone line in my house. However, I saw it as a good opportunity to exercise my micro-controller skills with my a very simple internet based temperature sensor. While I had played with controllers before, I had never done much beyond blinking lights on a Of course, because I like to dive into things head first, I decided to layout my own custom board for the project. While I was at it, I though it would be a good time to learn SMD soldering as well.

The design is pretty simple, mostly just a combination of the Arduino board and an Ethernet shield. So an Atmega328 with a Wiznet 5100 Ethernet chip. For the temperature sensor, I went with the DS18B20. I had originally put a barrel jack, and the 3.3 and 5 volt regulators in the layout, but since I included the FTDI USB/Serial chip, that actually provides 5v and 3.3v rails from the USB. That way I could just use a cheap used micro USB phone charger for the power supply. I decided to put the Arduino headers in the layout as well, I’m not sure why since it just made routing the board more complicated, but I figured that way I could re-purpose it if needed. I think the rest of the passive parts I ordered from Digi-Key. If you are afraid of working with SMD parts like I was, just watch this, http://www.youtube.com/watch?v=b9FC9fAlfQE. Dave’s lesson is pretty good, and I was able to put my board together with just my 30W Radio Shack iron.

TempSense

Here is the Eagle files for the design. Two things about this design, first I’m not entirely sure about the regulator setup with the barrel jack. I built two boards, on the first one I populated those spots, and the rails seemed to be the right voltage, but the Ethernet never worked on that first board after I tried plugging a supply into the barrel jack. So I left those parts off the second board. Two, the board layout itself is terrible. I mean it works, and I’m no expert on board layout, but it just looks ugly to me looking back on this projects now. The one for sure issue I had was that I forgot to put the 4.7K pullup resistor on the sensors data pin (its missing from the linked files). That’s important, and it doesn’t work without it. However its was really easy just to drop it in between the pins on the back side of the board.

The coding for this was very simple. Usually, the biggest issue with devices like this, is how to access your data over the internet. Without a static IP address or dynamic DNS service, the best way to go is to send your data to a server. I decided to use a free service, Cosm (which is now Xively). The coding was done in the Arduino IDE and was literally just a combination of the DS18B20 example and the Cosm example code. Note in the below code I took out my API key and Feed number.

/**
 * Cosm Arduino sensor client example.
 *
 * This sketch demonstrates connecting an Arduino to Cosm (https://cosm.com),
 * using the new Arduino library to send and receive data.
 *
 * Requirements
 *   * Arduino with Ethernet shield or Arduino Ethernet (board must use the
 *     Wiznet Ethernet chipset)
 *   * Arduino software with version >= 1.0
 *   * An account at Cosm (https://cosm.com)
 *
 * Optional
 *   * An analog sensor connected to pin 2 (note we can still read a value from
 *     the pin without this)
 *
 * Created 8th January, 2013 using code written by Adrian McEwen with
 * modifications by Sam Mulube
 *
 * Full tutorial available here: https://cosm.com/docs/quickstart/arduino.html
 *
 * This code is in the public domain.
 */

#include <SPI.h>
#include <Ethernet.h>
#include <HttpClient.h>
#include <Cosm.h>
#include <OneWire.h> 


#define API_KEY "" // your Cosm API key
#define FEED_ID 0 // your Cosm feed ID


int DS18S20_Pin = 2; //DS18S20 Signal pin on digital 2

//Temperature chip i/o
OneWire ds(DS18S20_Pin); // on digital pin 2


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

unsigned long lastConnectionTime = 0;                // last time we connected to Cosm
const unsigned long connectionInterval = 15000;      // delay between connecting to Cosm in milliseconds

// Initialize the Cosm library

// Define the string for our datastream ID
char sensorId[] = "home_temp";

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

// Wrap the datastream into a feed
CosmFeed feed(FEED_ID, datastreams, 1 /* number of datastreams */);

EthernetClient client;
CosmClient cosmclient(client);

void setup() {
  // put your setup code here, to run once:
  Serial.begin(9600);

  Serial.println("Cosm Sensor Client Example");
  Serial.println("==========================");

  Serial.println("Initializing network");
  while (Ethernet.begin(mac) != 1) {
    Serial.println("Error getting IP address via DHCP, trying again...");
    delay(15000);
  }

  Serial.println("Network initialized");
  Serial.println();
}

void loop() {
  // main program loop
  if (millis() - lastConnectionTime > connectionInterval) {
    // read a value from the pin
    float sensorValue = getTemp();
    // send it to Cosm
    sendData(sensorValue);
    // read the datastream back from Cosm
    getData();
    // update connection time so we wait before connecting again
    lastConnectionTime = millis();
  }
}

// send the supplied value to Cosm, printing some debug information as we go
void sendData(float sensorValue) {
  datastreams[0].setFloat(sensorValue);

  Serial.print("Read sensor value ");
  Serial.println(datastreams[0].getFloat());

  Serial.println("Uploading to Cosm");
  int ret = cosmclient.put(feed, API_KEY);
  Serial.print("PUT return code: ");
  Serial.println(ret);

  Serial.println();
}

// get the value of the datastream from Cosm, printing out the value we received
void getData() {
  Serial.println("Reading data from Cosm");

  int ret = cosmclient.get(feed, API_KEY);
  Serial.print("GET return code: ");
  Serial.println(ret);

  if (ret > 0) {
    Serial.print("Datastream is: ");
    Serial.println(feed[0]);

    Serial.print("Sensor value is: ");
    Serial.println(feed[0].getFloat());
  }

  Serial.println();
}

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;
 //convert to farenheit
 TemperatureSum = ((9.0/5.0) * TemperatureSum) + 32;
 return TemperatureSum;
 
}

And that’s pretty much it. I can watch my house temp wherever I am. https://xively.com/feeds/100416. Since Cosm changed to Xively, I’m not sure what their current pricing scheme is, but the public feed is still free on my current account.