Pages: [1]   Go Down
Author Topic: ds18s20 and pachube  (Read 1008 times)
0 Members and 1 Guest are viewing this topic.
0
Offline Offline
Newbie
*
Karma: 0
Posts: 10
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

i am wanting to display the data from 3 ds18s20 on pachube feeds, but haven't found nay sample code on how to do this.  do i just replace the analog lines in the code with the digital data?  i also want to graph the status of a digital pins state to track how often it turned on.

Logged

Oxford, UK
Offline Offline
Newbie
*
Karma: 0
Posts: 41
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

I'm using this example code http://community.pachube.com/files/ethernet_Pachube_input_output_1_1.zip

I adapted the 1-wire sample code to address each sensor directly and generate a String to pass into the pachube_in_out function - grab the sensor readings before calling pachube_in_out() and avoid pin 10 for your bus

Code:
void readTempHex(byte *addr, byte *data) {
  
  byte i;
  byte present = 0;
  // The DallasTemperature library can do all this work for you!

  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();
    //Serial.print(data[i], HEX);
    //Serial.print(" ");
  }
  //Serial.println();
}

// Convert Hex temperature reading to Celsius
char *convertReading(byte *hexReading) {
  int HighByte, LowByte, TReading, SignBit, Tc_100, Whole, Fract;
  char reading[20]; // array holding converted temp
  
  LowByte = hexReading[0];
  HighByte = hexReading[1];
  TReading = (HighByte << 8) + LowByte;
  SignBit = TReading & 0x8000;  // test most sig bit
  if (SignBit) // negative
  {
    TReading = (TReading ^ 0xffff) + 1; // 2's comp
  }
  Tc_100 = (TReading*100/2);    

  Whole = Tc_100 / 100;  // separate off the whole and fractional portions
  Fract = Tc_100 % 100;
  if ( !SignBit ) { // positive temp
    sprintf(reading, "%d.%d",Whole, Fract < 10 ? 0 : Fract);
  }
  else { // negative temp
    sprintf(reading, "%c%d.%d",'-', Whole, Fract < 10 ? 0 : Fract);  
  }
  return reading;
}

Here's my feed http://www.pachube.com/feeds/14134
Logged

0
Offline Offline
Newbie
*
Karma: 0
Posts: 10
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

where in the code did you insert this?
any chance you could post your full code?
« Last Edit: December 25, 2010, 05:14:47 pm by ecameron » Logged

Oxford, UK
Offline Offline
Newbie
*
Karma: 0
Posts: 41
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

This is the main program adapted from the pachube download
You can get the addresses for the sensors by running the 1-wire sample code - I'm only putting data so the get feed stuff is commented out

Code:
/* ==============================
 * This code, which assumes you're using the official Arduino Ethernet shield,
 * updates a Pachube feed with your analog-in values and grabs values from a Pachube
 * feed - basically it enables you to have both "local" and "remote" sensors.
 *
 * Tested with Arduino 14
 *
 * Pachube is www.pachube.com - connect, tag and share real time sensor data
 * code by usman (www.haque.co.uk), may 2009
 * copy, distribute, whatever, as you like.
 *
 * v1.1 - added User-Agent & fixed HTTP parser for new Pachube headers
 * and check millis() for when it wraps around
 *
 * =============================== */

#include <SPI.h>
#include <Ethernet.h>
#include <OneWire.h>
#include <stdio.h> // for function sprintf

byte SENSOR_0[] = { 0x10, 0xD2, 0x6E, 0xBB, 0x0, 0x8, 0x0, 0x91 }; //YOUR SENSOR ADDRESSES HERE
byte SENSOR_1[] = { 0x10, 0xA6, 0x3C, 0xEA, 0x1, 0x8, 0x0, 0x3F };

byte temp_0[9];
byte temp_1[9];

OneWire  ds(9);  // bus on pin 9 - problems on pin 10

//#undef int() // needed by arduino 0011 to allow use of stdio


#define SHARE_FEED_ID              XXXXX     // this is your Pachube feed ID that you want to share to
//#define REMOTE_FEED_ID             256      // this is the ID of the remote Pachube feed that you want to connect to
//#define REMOTE_FEED_DATASTREAMS    4        // make sure that remoteSensor array is big enough to fit all the remote data streams
#define UPDATE_INTERVAL            10000    // if the connection is good wait 10 seconds before updating again - should not be less than 5
#define RESET_INTERVAL             10000    // if connection fails/resets wait 10 seconds before trying again - should not be less than 5

#define PACHUBE_API_KEY            "YOUR_KEY_HERE" // fill in your API key

byte mac[] = { YOUR_ARDUINO_MAC_ADD_HERE };
byte ip[] = { YOUR_ARDINO_IP_HERE };
byte gateway[] = { YOUR_ROUTER_IP_HERE };      
byte subnet[] = { 255, 255, 255, 0 };
byte remoteServer[] = { 173, 203, 98, 29 }; // new pachube ip

//float remoteSensor[REMOTE_FEED_DATASTREAMS];        // we know that feed 256 has floats - this might need changing for feeds without floats

void setup()
{
  Serial.begin(9600);
  setupEthernet();

  //pinMode(3, OUTPUT);
  //pinMode(5, OUTPUT);
  //pinMode(6, OUTPUT);
}

void loop()
{

  // call 'pachube_in_out' at the beginning of the loop, handles timing, requesting
  // and reading. use serial monitor to view debug messages
      readTempHex(SENSOR_0, temp_0);
      readTempHex(SENSOR_1, temp_1);

  pachube_in_out();

  // then put your code here, you can access remote sensor values
  // by using the remoteSensor float array, e.g.:

  //analogWrite(3, (int)remoteSensor[3] * 10); // remoteSensor is a float
  //analogWrite(5, (int)remoteSensor[1]);

  // you can have code that is time sensitive (e.g. using 'delay'), but
  // be aware that it will be affected by a short pause during connecting
  // to and reading from ethernet (approx. 0.5 to 1 sec).
  // e.g. this code should carry on flashing regularly, with brief pauses
  // every few seconds during Pachube update.

  //digitalWrite(6, HIGH);
  //delay(100);
  //digitalWrite(6, LOW);
  //delay(100);

}

Here's the 1-wire functions to read each sensor and convert the hex value to a string - this is based on the 1-wire sample code

Code:
void readTempHex(byte *addr, byte *data) {
  
  byte i;
  byte present = 0;
  // The DallasTemperature library can do all this work for you!

  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();
    //Serial.print(data[i], HEX);
    //Serial.print(" ");
  }
  //Serial.println();
}

// Convert Hex temperature reading to Celsius
char *convertReading(byte *hexReading) {
  int HighByte, LowByte, TReading, SignBit, Tc_100, Whole, Fract;
  char reading[20]; // array holding converted temp
  
  LowByte = hexReading[0];
  HighByte = hexReading[1];
  TReading = (HighByte << 8) + LowByte;
  SignBit = TReading & 0x8000;  // test most sig bit
  if (SignBit) // negative
  {
    TReading = (TReading ^ 0xffff) + 1; // 2's comp
  }
  Tc_100 = (TReading*100/2);    

  Whole = Tc_100 / 100;  // separate off the whole and fractional portions
  Fract = Tc_100 % 100;
  if ( !SignBit ) { // positive temp
    sprintf(reading, "%d.%d",Whole, Fract < 10 ? 0 : Fract);
  }
  else { // negative temp
    sprintf(reading, "%c%d.%d",'-', Whole, Fract < 10 ? 0 : Fract);  
  }
  return reading;
}

More to follow in next post - max limit!
Logged

Oxford, UK
Offline Offline
Newbie
*
Karma: 0
Posts: 41
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Here's the pachube functions that build the string to PUT - I tested this by hard coding a string to make sure I could update before adding the live data

Code:
String pachube_data;

boolean found_status_200 = false;
boolean found_session_id = false;
boolean found_CSV = false;
char *found;
unsigned int successes = 0;
unsigned int failures = 0;
boolean ready_to_update = true;
boolean reading_pachube = false;

boolean request_pause = false;
boolean found_content = false;

unsigned long last_connect;

int content_length;

void pachube_in_out(){

  if (millis() < last_connect) last_connect = millis();

  if (request_pause){
    if ((millis() - last_connect) > interval){
      ready_to_update = true;
      reading_pachube = false;
      request_pause = false;
      found_status_200 = false;
      found_session_id = false;
      found_CSV = false;

      //Serial.print("Ready to connect: ");
      //Serial.println(millis());
    }
  }

  if (ready_to_update){
    Serial.println("Connecting...");
    if (localClient.connect()) {

      // here we assign comma-separated values to 'data', which will update Pachube datastreams
      // we use all the analog-in values, but could of course use anything else millis(), digital
      // inputs, etc. . i also like to keep track of successful and failed connection
      // attempts, sometimes useful for determining whether there are major problems.
      pachube_data = String(convertReading(temp_0));
      pachube_data += ",";
      pachube_data += String(convertReading(temp_1));
      
      //sprintf(pachube_data,"%d,%d,%d,%d,%d,%d,%d,%d",analogRead(0),analogRead(1),analogRead(2),analogRead(3),analogRead(4),analogRead(5), successes + 1, failures);
      Serial.println(pachube_data);
    
      //content_length = strlen(pachube_data);
      content_length = pachube_data.length();

/*
      Serial.println("GET request to retrieve");

      localClient.print("GET /api/");
      localClient.print(REMOTE_FEED_ID);
      localClient.print(".csv HTTP/1.1\nHost: pachube.com\nX-PachubeApiKey: ");
      localClient.print(PACHUBE_API_KEY);
      localClient.print("\nUser-Agent: Arduino (Pachube In Out v1.1)");
      localClient.println("\n");
*/

      Serial.println("PUT, update");

      localClient.print("PUT /api/");
      localClient.print(SHARE_FEED_ID);
      localClient.print(".csv HTTP/1.1\nHost: pachube.com\nX-PachubeApiKey: ");
      localClient.print(PACHUBE_API_KEY);

      localClient.print("\nUser-Agent: Arduino (Pachube In Out v1.1)");
      localClient.print("\nContent-Type: text/csv\nContent-Length: ");
      localClient.print(content_length);
      localClient.print("\nConnection: close\n\n");
      localClient.print(pachube_data);



      localClient.print("\n");

      ready_to_update = false;
      reading_pachube = true;
      request_pause = false;
      interval = UPDATE_INTERVAL;

      Serial.print("finished PUT: ");
      Serial.println(millis());

    }
    else {
      Serial.print("connection failed!");
      Serial.print(++failures);
      found_status_200 = false;
      found_session_id = false;
      found_CSV = false;
      ready_to_update = false;
      reading_pachube = false;
      request_pause = true;
      last_connect = millis();
      interval = RESET_INTERVAL;
      setupEthernet();
    }
  }

  while (reading_pachube){
    while (localClient.available()) {
      checkForResponse();
    }

    if (!localClient.connected()) {
      disconnect_pachube();
    }
  }
}

void disconnect_pachube(){
  Serial.println("disconnecting.\n=====\n\n");
  localClient.stop();
  ready_to_update = false;
  reading_pachube = false;
  request_pause = true;
  last_connect = millis();
  found_content = false;
  resetEthernetShield();
}


void checkForResponse(){  
  char c = localClient.read();
  //Serial.print(c);
  buff[pointer] = c;
  if (pointer < 64) pointer++;
  if (c == '\n') {
    found = strstr(buff, "200 OK");
    if (found != 0){
      found_status_200 = true;
      //Serial.println("Status 200");
    }
    buff[pointer]=0;
    found_content = true;
    clean_buffer();    
  }

  if ((found_session_id) && (!found_CSV)){
    found = strstr(buff, "HTTP/1.1");
    if (found != 0){
      char csvLine[strlen(buff)-9];
      strncpy (csvLine,buff,strlen(buff)-9);

      //Serial.println("This is the retrieved CSV:");    
      //Serial.println("---");    
      //Serial.println(csvLine);
      //Serial.println("---");  
      Serial.println("\n--- updated: ");
      Serial.println(pachube_data);
      Serial.println("\n--- retrieved: ");
      char delims[] = ",";
      char *result = NULL;
      char * ptr;
      result = strtok_r( buff, delims, &ptr );
      int counter = 0;
 /*    
      while( result != NULL ) {
        remoteSensor[counter++] = atof(result);
        result = strtok_r( NULL, delims, &ptr );
      }  
      for (int i = 0; i < REMOTE_FEED_DATASTREAMS; i++){
        Serial.print( (int)remoteSensor[i]); // because we can't print floats
        Serial.print("\t");
      }
*/
      found_CSV = true;

      Serial.print("\nsuccessful updates=");
      Serial.println(++successes);

    }
  }

  if (found_status_200){
    found = strstr(buff, "_id=");
    if (found != 0){
      clean_buffer();
      found_session_id = true;
    }
  }
}

Finally the ethernet function from the pachube example

Code:
Client localClient(remoteServer, 80);
unsigned int interval;

char buff[64];
int pointer = 0;

void setupEthernet(){
  resetEthernetShield();
  //Client remoteClient(255);
  delay(500);
  interval = UPDATE_INTERVAL;
  Serial.println("setup complete");
}

void clean_buffer() {
  pointer = 0;
  memset(buff,0,sizeof(buff));
}

void resetEthernetShield(){
  Serial.println("reset ethernet");
  Ethernet.begin(mac, ip, gateway, subnet);
}

If you can't get this working I have some separate test sketches that might help you
Logged

0
Offline Offline
Newbie
*
Karma: 0
Posts: 10
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

my feed is now updating, but the units don't look right.  the sensor is sitting above my heating register which is set to 68* F.  i would love to go ahead and do the conversion of the feed from C to F, but at this point, i just want it to work.


http://www.pachube.com/feeds/13805


i pasted the code you posted into the sketches and replaced the lines with my info. i also deleted the lines for the second sensor since i only have one attached right now.
Logged

Oxford, UK
Offline Offline
Newbie
*
Karma: 0
Posts: 41
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Evan, glad to see you managed to get your feed up and running - unless you're measuring something pretty hot it looks like your reading isn't quite right. I used this test sketch to make sure my sensors where reading correctly - connect your board via USB and check the output on the serial monitor

Code:
/*

  ReadTempTest
 
  Sketch to read temperature from Maxim DS18S20 sensors on 1-Wire bus
  and display HEX and DEC readings on serial monitor
  
  Hex values must be supplied for each DS18S20 - these can be obtained
  from OneWireTest sketch
  
  
  Example output
  27 0 4B 46 FF FF 1 10 E0
  28 0 4B 46 FF FF D 10 57
  19.5
  20.0

*/

#include <OneWire.h>

byte SENSOR_0[] = { 0x10, 0xD2, 0x6E, 0xBB, 0x0, 0x8, 0x0, 0x91 }; // sensor 0 address
byte SENSOR_1[] = { 0x10, 0xA6, 0x3C, 0xEA, 0x1, 0x8, 0x0, 0x3F }; // sensor 1 address

byte temp_0[9];
byte temp_1[9];

OneWire  ds(9);  // bus on pin 9 - problems on pin 10

void setup(void) {
  Serial.begin(9600);  
}

void loop(void) {
  readTempHex(SENSOR_0, temp_0);
  readTempHex(SENSOR_1, temp_1);
  Serial.print(convertReading(temp_0));  //problem with println!
  Serial.println();
  Serial.print(convertReading(temp_1));
  Serial.println();
  delay(1000);  
}
  
void readTempHex(byte *addr, byte *data) {
  
  byte i;
  byte present = 0;
  // The DallasTemperature library can do all this work for you!

  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();
    Serial.print(data[i], HEX);
    Serial.print(" ");
  }
  Serial.println();
}


// Convert Hex temperature reading to Celsius
char *convertReading(byte *hexReading) {
  int HighByte, LowByte, TReading, SignBit, Tc_100, Whole, Fract;
  char reading[20]; // array holding converted temp
  
  LowByte = hexReading[0];
  HighByte = hexReading[1];
  TReading = (HighByte << 8) + LowByte;
  SignBit = TReading & 0x8000;  // test most sig bit
  if (SignBit) // negative
  {
    TReading = (TReading ^ 0xffff) + 1; // 2's comp
  }
  Tc_100 = (TReading*100/2);    

  Whole = Tc_100 / 100;  // separate off the whole and fractional portions
  Fract = Tc_100 % 100;
  if ( !SignBit ) { // positive temp
    sprintf(reading, "%d.%d",Whole, Fract < 10 ? 0 : Fract);
  }
  else { // negative temp
    sprintf(reading, "%c%d.%d",'-', Whole, Fract < 10 ? 0 : Fract);  
  }
  return reading;
}

Have you got a 4.7K pull up resistor? Also this code is configured to work with the sensors in parasitic mode
Logged

Pages: [1]   Go Up
Jump to: