Go Down

Topic: Sorting out multiple temp data ?>? DS18B20 (Read 4479 times) previous topic - next topic

Criomod

Feb 22, 2011, 09:59 pm Last Edit: Feb 23, 2011, 02:43 am by Criomod Reason: 1
Okay iv recently picked up a few DS18B20's. Using onewire2 lib, I am able to send the temp from my arduino and then collect the data in processing. Now I display it on a bar graph... pretty simple right ??  :smiley-roll:

Code: [Select]
#include <OneWire.h>

/* DS18S20 Temperature chip i/o

*/

OneWire  ds(10);  // on pin 10

float c2f(float cel) {
return (cel);
}

void setup(void) {
  // initialize inputs/outputs
  // start serial port
  Serial.begin(9600);
}



void loop(void) {
  byte i;
  byte present = 0;
  byte data[12];
  byte addr[8];
  int HighByte, LowByte, TReading, Tc_100, Whole;
 
  if ( !ds.search(addr)) {
//Serial.print("No more addresses.\n");
ds.reset_search();
return;
  }

  ds.reset();
  ds.select(addr);
  ds.write(0x44,1);    // start conversion, with parasite power on at the end

  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();
  }
 
  LowByte = data[0];
  HighByte = data[1];
  TReading = (HighByte << 8) + LowByte;
 
  Tc_100 = (6 * TReading) + TReading / 4; // multiply by (100 * 0.0625) or 6.25

  Tc_100 = c2f(Tc_100);
  Whole = (Tc_100 / 100);  // separate off the whole and fractional portions

  Serial.print((byte)Whole); //send the data to the computer
  delay(500);
}


Code: [Select]

import processing.serial.*;
Serial myPort;

int tempC; // Data received from the serial port
int tempF;
PFont font;


 void setup() {  
   
 size(800, 600);    
 myPort = new Serial(this, "COM4", 9600);  
 font = createFont("Arial", 22);  
 textAlign(CENTER);  
 textFont(font);

}

 void draw(){  

 background(255);
 fill(0, 0, 255);

 rect(390,600,20,-tempC / 1.5);
 text(tempC,width/2,height-tempC-20);

 drawGraph();

}

 void drawGraph(){    

 if (myPort.available() > 0)
 {    
    tempF = myPort.read();
    tempC = ((tempF*9)/5) + 32;
 }  
 
 }


Now here is where i run into a problem. If I add a second DS18B20 to the OneWire bus I get both readouts to display on the same bar graph. How can i seperate sensor1 & sensor2, and then have 2 bar graph displays?      
   

robtillaart

YOu only shared half of the code (missing the Arduino part) or?

You can manage multiple sensors by sending an ID with the reading. YOur protocol could become something like
"<ID,VALUE>"  which has explicit ID's
The < and > are needed as packet separators:  < means new packet, then you know the next int is the ID of teh sensor, then a comma, and then the value of the sensor, followed by a > indicate the end.

another option is
<value, value>  which has implicit id's.

hopes this helps you get started.
Rob Tillaart

Nederlandse sectie - http://arduino.cc/forum/index.php/board,77.0.html -
(Please do not PM for private consultancy)

Criomod

#2
Feb 23, 2011, 04:50 am Last Edit: Feb 23, 2011, 08:11 am by Criomod Reason: 1
robtillaart, I thought about the post you left, and i came up with this.  

First I add the Dallas Tempeture Control library (TCL) along with the OneWire2 Library.

I managed to seperate the 2 sensors to readout celcius tempeture as you suggested.
ie: <value,value>

<22.50,22.41>
<22.52,22.43>  
<22.50,22.41>
<22.52,22.43>  

                                                            Arduino Code:
Code: [Select]


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

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

// Setup a oneWire instance to communicate with any OneWire devices (not just Maxim/Dallas temperature ICs)
OneWire oneWire(ONE_WIRE_BUS);

// Pass our oneWire reference to Dallas Temperature.
DallasTemperature sensors(&oneWire);

// arrays to hold device addresses
uint8_t sensorA[8], sensorB[8];

void setup(void)
{
 // start serial port
 Serial.begin(9600);

 // Start up the library
 sensors.begin();
 

 
}

void loop(void)
{
 // call sensors.requestTemperatures() to issue a global temperature
 // request to all devices on the bus
 
 sensors.requestTemperatures();
 
 Serial.print("<"); //Send NEW Packet to computer

 Serial.print(sensors.getTempCByIndex(0)); //Send SensorA data to computer
 
 Serial.print(","); // Seperater...

 Serial.print(sensors.getTempCByIndex(1)); //Send SensorB data to computer

 Serial.print(">"); //Send END Packet to computer
 Serial.println();
}



Now im not sure how to seperate the 2 values once iv read them in processing.
Am I heading in the right direction? thanks.  

robtillaart


Code looks very good, I would prefer another pin for the onewire as PIN2 and PIN3 are the IRQ lines, and in that sense a bit special. However if you don't use IRQ's pin2 is as good as any. Furthermore the Dallas Lib provides a datatype for DeviceAddresses, and I would use a higher baudrate to speed up communication.

Code: [Select]
// Data wire is plugged into port 2 on the Arduino
#define ONE_WIRE_BUS 2

// Setup a oneWire instance to communicate with any OneWire devices (not just Maxim/Dallas temperature ICs)
OneWire oneWire(ONE_WIRE_BUS);

// Pass our oneWire reference to Dallas Temperature.
DallasTemperature sensors(&oneWire);

// DS18B20 addresses
[color=red]DeviceAddress[/color] sensorA, sensorB;   // is a datatype defined in the Dallas lib

void setup(void)
{
  // start serial port
  Serial.begin([color=red]115200[/color]);   // communicate as fast as possible

  // Start up the library
  sensors.begin();
}


You should be able to see nice output in the serial monitor.
In your processing application  you do somthing similar - in "reverse". In pseudocode:

Code: [Select]

loop()
{
  skipTo("<");                       // record start
  temp1 = readUntil(",");
  skipTo(",");                       // the field separator
  temp2 = readUntil(">");
  skipTo(">");                       // record end

  displayTemp();
}



succes
Rob Tillaart

Nederlandse sectie - http://arduino.cc/forum/index.php/board,77.0.html -
(Please do not PM for private consultancy)

Criomod

#4
Feb 24, 2011, 05:00 am Last Edit: Feb 24, 2011, 05:49 am by Criomod Reason: 1
alright so im sending a "string" of temp. data from my arduino to processing through serial comm.

like this:

22.50,22.41
22.52,22.43  
22.50,22.41
22.52,22.43  
                                                       Ardiuno Code:
Code: [Select]

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

OneWire oneWire(10); // port 10
DallasTemperature sensors(&oneWire); // Pass our oneWire reference to Dallas Temperature.
DeviceAddress sensorA, sensorB; // arrays to hold device addresses

void setup(void)
{
 
 Serial.begin(115200); // start serial port
 sensors.begin(); // Start up the library
}

void loop(void)
{
 
 sensors.requestTemperatures();
 
 Serial.print(sensors.getTempCByIndex(0)); //Send SensorA data to computer
 Serial.print(","); // Seperater...
 Serial.print(sensors.getTempCByIndex(1)); //Send SensorB data to computer

 
 Serial.println();
 
 delay(750);
}


Iv tried this method below and all i can collect is zeros... ???  Any suggestions?
Like this:

Sensor0 : 0           Sensor1 : 0
Sensor0 : 0           Sensor1 : 0
Sensor0 : 0           Sensor1 : 0
Sensor0 : 0           Sensor1 : 0

                                                       Processing Code:
Code: [Select]

import processing.serial.*;
Serial myPort; // Create object from Serial class

void setup() {  
   
 size(200, 200);  
 myPort = new Serial(this, "COM4", 115200);
 
 // read bytes into a buffer until you get a linefeed.
 myPort.bufferUntil('\n');

}

void draw(){  

 background(255);
 fill(0, 0, 225);

}

// serialEvent  method is run automatically by the Processing applet
// whenever the buffer reaches the  byte value set in the bufferUntil()
// method in the setup():

void serialEvent(Serial myPort) {
 // read the serial buffer:
 String myString = myPort.readStringUntil('\n');
 // if you got any bytes other than the linefeed:
   myString = trim(myString);

   // split the string at the commas
   // and convert the sections into integers:
   int sensors[] = int(split(myString,','));

   // print out the values you got:
   for (int sensorNum = 0; sensorNum < sensors.length; sensorNum++) {
     print("Sensor " + sensorNum + ": " + sensors[sensorNum] + "\t");
   }
   
   // add a linefeed after all the sensor values are printed:
   println();

 }



And then I was wondering what data i was gathering in processing so i tried this test sketch.
Seems like all im getting is : -1-1-1-1-1-1-1-1-1-1-1-1-1-1-1 in the serial monitor. What is going on?

                                                          Test Code:
Code: [Select]
import processing.serial.*;
Serial myPort; // Create object from Serial class
int val;
void setup() { 
   
  size(200, 200);   
  myPort = new Serial(this, "COM4", 115200);
 
  // read bytes into a buffer until you get a linefeed.
  val = myPort.read();
}

void draw(){   

  background(255);
  fill(0, 0, 225);
 
  println(val);

}

PaulS

In the last code, the read from the serial port happens once, in setup, with no test to see IF there is anything to read. Since that read occurs immediately after the serial port is opened, which reset the Arduino, of course there is nothing to read, so read returned a -1. Then, in draw(), you just print that value over and over again.

In your original code, I think that you need to print the string read from the serial port, before splitting it up. I think you also need to evaluate whether this is doing what you expect it to:
    int sensors[] = int(split(myString,','));
I know the documentation says this works, but...

The input string, you said, should be something like 22.50,22.41, which would split into two strings, "22.50" and "22.41", which you then try to convert to integers. If you are going to the trouble of sending floats, why convert them in Processing to ints?
The art of getting good answers lies in asking good questions.

robtillaart


add :

int count = sensors.getDeviceCount();

and print the value of count - does the sketch see the sensors

Rob Tillaart

Nederlandse sectie - http://arduino.cc/forum/index.php/board,77.0.html -
(Please do not PM for private consultancy)

Criomod

#7
Feb 24, 2011, 10:19 pm Last Edit: Feb 24, 2011, 11:20 pm by Criomod Reason: 1
I added
Code: [Select]
int count = sensors.getDeviceCount(); and
Code: [Select]
Serial.print(count); to the Arduino code.

it shows:  2 2 2 2 2 2 2  so its seeing both sensors on the bus?


I also modified the Test Sketch to see what the serial port was receiving in Processing.

Code: [Select]

import processing.serial.*;
Serial myPort; // Create object from Serial class
int val;
void setup() {  
   
 size(200, 200);  
 myPort = new Serial(this, "COM4", 115200);
 
}

void draw(){  
 
  if ( myPort.available() > 0) {  // If data is available,
   val = myPort.read();         // read it and store it in val
 }
 
 background(255);            
 if (val == 0) {              // If the serial value is 0,
   fill(0);                   // set fill to black
 }
 else {    
   print(val);                
 }
 
 println();

}
}



and now im getting values in the serial monitor. :smiley-surprise:




Criomod

ALRIGHT! I think iv got it.  As PaulS mentioned, the problem was converting the string to int. when it should of been float value.  now i get a nice read out in the processing serial monitor.  Thanks alot guys.

Sensor 0: 31.94   Sensor 1: 33.13   
Sensor 0: 31.56   Sensor 1: 32.81   
Sensor 0: 31.25   Sensor 1: 32.5   
Sensor 0: 30.94   Sensor 1: 32.19   
Sensor 0: 30.56   Sensor 1: 31.87   
Sensor 0: 30.31   Sensor 1: 31.62

                                                    Processing Code:
Code: [Select]
import processing.serial.*;
Serial myPort; // Create object from Serial class

void setup() { 
   
  size(200, 200);   
  myPort = new Serial(this, "COM4", 115200);
 
  myPort.bufferUntil('\n');    // read it and store it in val

}

void draw(){   

  background(255);
 
}

// serialEvent  method is run automatically by the Processing applet
// whenever the buffer reaches the  byte value set in the bufferUntil()
// method in the setup():

void serialEvent(Serial myPort) {
  // read the serial buffer:
  String myString = myPort.readStringUntil('\n');
  // if you got any bytes other than the linefeed:
    myString = trim(myString);

    // split the string at the commas
    // and convert the sections into float values:
    float sensors[] = float(split(myString,','));

    // print out the values you got:
    for (int sensorNum = 0; sensorNum < sensors.length; sensorNum++) {
      print("Sensor " + sensorNum + ": " + sensors[sensorNum] + '\t');
    }
   
    // add a linefeed after all the sensor values are printed:
    println();

  }

gadjet

#9
Apr 27, 2011, 10:38 pm Last Edit: May 03, 2011, 09:59 pm by gadjet Reason: 1
Hi,
I've been using the Arduino for a couple of months now and my DS18B20s have just arrived from China and I'm trying to get to grips with using multiple sensors on the one input.

I came across the Dallas Library and I pretty sure I can get it going but I keep getting an error when I send to the Arduino, I'm not very experienced at C.

The code is as above in this post but I've tried other code as well.

Code: [Select]
#include <OneWire.h>
#include <DallasTemperature.h>
// Data wire is plugged into port 10 on the Arduino
#define ONE_WIRE_BUS 10

// Setup a oneWire instance to communicate with any OneWire devices (not just Maxim/Dallas temperature ICs)
OneWire oneWire(ONE_WIRE_BUS);

// Pass our oneWire reference to Dallas Temperature.
DallasTemperature sensors(&oneWire);


I get the error "no matching function for call to 'DallasTemperature::DallasTemperature(OneWire*)" at the last line.
I suspect, as everyone else here uses it OK then it's an issue with my installation of the Libraries ??

Any suggestions would be appreciated.

Just to let you know, in case any one else has this problem, I had downloaded the wrong version of the Dallas library DOH!

Cheers,
Phil

Go Up