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 ??
#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);
}
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?
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.
#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.
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.
// 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:
loop()
{
skipTo("<"); // record start
temp1 = readUntil(",");
skipTo(","); // the field separator
temp2 = readUntil(">");
skipTo(">"); // record end
displayTemp();
}
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:
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);
}
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?
I added int count = sensors.getDeviceCount(); and 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.
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();
}
}
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.
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();
}
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.
#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!