Communication with 2 x DS18B20

Hi i have 2 DS18B20 sensors and i want to recieve temperature values from both sensors. (one by one)
Each DS18B20 is connected to different pin. (for example pin 10 and pin 11).
How could i do that on code please??

here is the code i am using

#include <OneWire.h>

// OneWire DS18S20, DS18B20, DS1822 Temperature Example
//
// http://www.pjrc.com/teensy/td_libs_OneWire.html
//
// The DallasTemperature library can do all this work for you!
// http://milesburton.com/Dallas_Temperature_Control_Library

OneWire  ds(10);  // on pin 10

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

void loop(void) {
  byte i;
  byte present = 0;
  byte type_s;
  byte data[12];
  byte addr[8];
  float celsius, fahrenheit;
  
  if ( !ds.search(addr)) {
    Serial.println("No more addresses.");
    Serial.println();
    ds.reset_search();
    delay(250);
    return;
  }
  
  Serial.print("ROM =");
  for( i = 0; i < 8; i++) {
    Serial.write(' ');
    Serial.print(addr[i], HEX);
  }

  if (OneWire::crc8(addr, 7) != addr[7]) {
      Serial.println("CRC is not valid!");
      return;
  }
  Serial.println();
 
  // the first ROM byte indicates which chip
  switch (addr[0]) {
    case 0x10:
      Serial.println("  Chip = DS18S20");  // or old DS1820
      type_s = 1;
      break;
    case 0x28:
      Serial.println("  Chip = DS18B20");
      type_s = 0;
      break;
    case 0x22:
      Serial.println("  Chip = DS1822");
      type_s = 0;
      break;
    default:
      Serial.println("Device is not a DS18x20 family device.");
      return;
  } 

  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

  Serial.print("  Data = ");
  Serial.print(present,HEX);
  Serial.print(" ");
  for ( i = 0; i < 9; i++) {           // we need 9 bytes
    data[i] = ds.read();
    Serial.print(data[i], HEX);
    Serial.print(" ");
  }
  Serial.print(" CRC=");
  Serial.print(OneWire::crc8(data, 8), HEX);
  Serial.println();

  // convert the data to actual temperature

  unsigned int 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);
    if (cfg == 0x00) raw = raw << 3;  // 9 bit resolution, 93.75 ms
    else if (cfg == 0x20) raw = raw << 2; // 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;
  fahrenheit = celsius * 1.8 + 32.0;
  Serial.print("  Temperature = ");
  Serial.print(celsius);
  Serial.print(" Celsius, ");
  Serial.print(fahrenheit);
  Serial.println(" Fahrenheit");
}

forgot to mention that i have no problem with any other code (just to be sure is not buggy, some codes doesnt gives negative values)

OneWire  ds(10);  // on pin 10

Can't you hazard a guess as to what to use for the one on the pin 11?

If you put them on separate pins you'd need to create a OneWire bus for each pin. They're designed so that you can connect them all to the same OneWire bus, though, so that's be a more sensible approach unless you have a particular reason for using additional pins.

The first question though, Peter to placing both DS18B20's on one port is how are they enumerated? I really think this will crop up sooner or later..

Bob

Docedison:
The first question though, Peter to placing both DS18B20's on one port is how are they enumerated? I really think this will crop up sooner or later..

Bob

The code already enumerates the devices (all one of them, currently).

I'm sorry, I display my ignorance of the subject,The last time I used 'on of those was with a different (PIC16C711) controller and a different device (DS18S20's, I still have 3 or 4) a long time ago. I do remember that there was an issue with reading the 'device' number though.

Bob

I found that Miles Burton stuff pretty clunky and I think you are proposing a mish-mash of it anyway. Here is something from Sheepdog that actually works. Strip out what you don't need, which is probably most of it. I only used it after a comedy of self-inflicted errors and, particularly since you are using two two sensors, you would be better off working with a one wire system, with the proper libraries, like God and Dallas intended. The time to make the change is probably now, before you waste too much of it, like I did......

/*
Reading two DS18B20s pins 14&15
display to monitor
display to LCD with pin D04 moved to pin 16 (A2)
Code uses Arduino LCD, sheepdog temp reader, SD stuff from Mellis & Igoe
*/

#define tture1 14//no ; here
#define tture2 15//no ; here

// include the library codes:
#include <LiquidCrystal.h>
#include <SD.h>

File myFile;

// initialize the library with the numbers of MY interface pins
LiquidCrystal lcd(8,9,16,5,6,7);

int HighByte, LowByte, TReading, SignBit, Tc_100, Whole, Fract;

void setup() {
    //For each tture sensor: Do a pinMode and a digitalWrite
    pinMode(tture1, INPUT);
    pinMode(tture2, INPUT);

    digitalWrite(tture1, LOW);//Disable internal pull-up.
    digitalWrite(tture2, LOW);

    Serial.begin(9600);
    delay(300);//Wait for newly restarted system to stabilize
    Serial.print("Temperature measurement, two sensors:\n\n");

  // set up the LCD's number of columns and rows: 
  lcd.begin(16, 2);
  lcd.clear();
  // Print a message to the LCD.
  lcd.print("temp   in   out");    
  
  Serial.print("Initializing SD card...");
 
   pinMode(10, OUTPUT);
   
  if (!SD.begin(4)) {
    Serial.println("initialization failed!");
    return;
  }
  Serial.println("initialization done.");
  
  // open the file. note that only one file can be open at a time,
  // so you have to close this one before opening another.
  myFile = SD.open("test.txt", FILE_WRITE);//+++++++++++++++++++ OPEN
  
  // if the file opened okay, write to it:
  if (myFile) {
    Serial.print("Writing to test.txt...");
    myFile.println("testing! Did you forget the date?");
    myFile.close();//++++++++++++++++++++++++++++++++++++++++++++ CLOSE

    Serial.println("done.");
  } else {
    // if the file didn't open, print an error:
    Serial.println("error opening test.txt");
  }
  
}

void loop(){

// set the LCD cursor to column 4, line 1
  // (note: line 1 is the second row, since counting begins with 0):
  lcd.setCursor(4, 1);
  readTture(tture1);//N.B.: Values passed back in globals
  printTture();//N.B.: Takes values from globals. Also...
     //no newline part of printTture;

  delay(120);// Delay... must not be too short.
  
  // set LCD cursor for second temp
  lcd.setCursor(11, 1);
  readTture(tture2);//Now read and report 2nd tture.
  printTture();
  delay(200);// Delay... must not be too short.
  Serial.print("\n");//Start new line
  
       myFile = SD.open("test.txt", FILE_WRITE);//+++++++++++++++++++++++++OPEN
       myFile.println(",   ");
    myFile.close();//>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>CLOSE
  delay(880); 
}



//Everything below here... just copy it into your program "as is".
//You are only likely to need to use readTture(pin) and printTture()
//   directly. Others are subordinate to those.
//These routine access the following global variables...
//   int HighByte, LowByte, TReading, SignBit, Tc_100, Whole, Fract;

void OneWireReset(int Pin) // reset.  Should improve to act as a presence pulse
{
     digitalWrite(Pin, LOW);
     pinMode(Pin, OUTPUT); // bring low for 500 us
     delayMicroseconds(500);
     pinMode(Pin, INPUT);
     delayMicroseconds(500);
}
//end OneWireReset

void OneWireOutByte(int Pin, byte d) // output byte d (least sig bit first).
{
   byte n;

   for(n=8; n!=0; n--)
   {
      if ((d & 0x01) == 1)  // test least sig bit
      {
         digitalWrite(Pin, LOW);
         pinMode(Pin, OUTPUT);
         delayMicroseconds(5);
         pinMode(Pin, INPUT);
         delayMicroseconds(60);
      }
      else
      {
         digitalWrite(Pin, LOW);
         pinMode(Pin, OUTPUT);
         delayMicroseconds(60);
         pinMode(Pin, INPUT);
      }
      d=d>>1; // now the next bit is in the least sig bit position.
   }
}//end OneWireOutByte

byte OneWireInByte(int Pin) // read byte, least sig byte first
{
    byte d, n, b;

    for (n=0; n<8; n++)
    {
        digitalWrite(Pin, LOW);
        pinMode(Pin, OUTPUT);
        delayMicroseconds(5);
        pinMode(Pin, INPUT);
        delayMicroseconds(5);
        b = digitalRead(Pin);
        delayMicroseconds(50);
        d = (d >> 1) | (b<<7); // shift d to right and insert b in most sig bit position
    }
    return(d);
}//end OneWireInByte

void readTture(byte Pin){
//Pass WHICH pin you want to read in "Pin"
//Returns values in... (See global declarations)
  OneWireReset(Pin);
  OneWireOutByte(Pin, 0xcc);
  OneWireOutByte(Pin, 0x44); // perform temperature conversion, strong pullup for one sec

  OneWireReset(Pin);
  OneWireOutByte(Pin, 0xcc);
  OneWireOutByte(Pin, 0xbe);

  LowByte = OneWireInByte(Pin);
  HighByte = OneWireInByte(Pin);
  TReading = (HighByte << 8) + LowByte;
  SignBit = TReading & 0x8000;  // test most sig bit
  if (SignBit) // negative
  {
    TReading = (TReading ^ 0xffff) + 1; // 2's comp
  }
  Tc_100 = (6 * TReading) + TReading / 4;    // multiply by (100 * 0.0625) or 6.25

  Whole = Tc_100 / 100;  // separate off the whole and fractional portions
  Fract = Tc_100 % 100;
};//end readTture

void printTture(){//Uses values from global variables.
//See global declarations.
//N.B.: No new line inside printTture
      myFile = SD.open("test.txt", FILE_WRITE); //+++++++++++++OPEN
if (SignBit) // If it's negative
    {
     Serial.print("-");
     lcd.print("-");

     myFile.print("-");
    };
  Serial.print(Whole);
  Serial.print(".");
  lcd.print(Whole);
  lcd.print(".");
  myFile.print(Whole);
  myFile.print(".");
  if (Fract < 10)
    {
     Serial.print("0");
     lcd.print("0");
     myFile.print("0");
    };
  Serial.print(Fract);
  lcd.print(Fract);
  myFile.print(Fract);
    Serial.print("       ");
    myFile.print(",    ");
  myFile.close();//++++++++++++++++++++++++ CLOSE
};//end printTture

I have a hacked version of one of the Dallas_Temperature_Control library examples that searches for your sensors, displays the device count, addresses and temps in degC and degF and probably some other stuff. You will have to modify this if using 2 pins for the sensors.

I also have a hacked version that allows manual entry of the addresses and the ability to return temps by index instead of address if you are interested. I use this method, partly because I was struggling with the address method and attempting to input the results in an array.

/* Modification of the Dallas Temperature Multiple Example to auto search all devices and report addresses and temps.
  Date 12/18/2012
*/
#include <OneWire.h>
#include <DallasTemperature.h>

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

// Temp Sensor setup
#define DS1820_SENSORS 5 // number of sensors in loop
byte Temp[DS1820_SENSORS][8]; // creates byte var. array called Temp[0-DS1820_SENSORS][8 bytes long]

// 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
DeviceAddress temp[DS1820_SENSORS]; // stores addresses in uint8_t format

// Define variables to store temps for each sensor
float tempC[DS1820_SENSORS];
float tempF[DS1820_SENSORS]; 
float degreesF[DS1820_SENSORS];

void setup(void)
{
  // start serial port
  Serial.begin(9600);
  Serial.println("Dallas Temperature IC Control Library Demo");

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

  // locate devices on the bus
  Serial.print("Locating devices...");
  Serial.print("Found ");
  Serial.print(sensors.getDeviceCount(), DEC);
  Serial.println(" devices.");

  // report parasite power requirements
  Serial.print("Parasite power is: "); 
  if (sensors.isParasitePowerMode()) Serial.println("ON");
  else Serial.println("OFF");

  // search for devices on the bus and assign based on an index.
  // method  search() looks for the next device. Returns 1 if a new address has been
  // returned. A zero might mean that the bus is shorted, there are no devices, 
  // or you have already retrieved all of them. The order is 
  // deterministic. You will always get the same devices in the same order
  //
  // Must be called before search()
  oneWire.reset_search(); 
  byte sensor; 
  byte present = 0;
  byte data[12];
  for (sensor=0;sensor<DS1820_SENSORS;sensor++) {
  if (!sensors.getAddress(Temp[sensor], sensor)) Serial.println("Unable to find address for Device");   
  printAddress(Temp[sensor]);
  }
}

// function to print a device address
void printAddress(DeviceAddress deviceAddress)
{
  for (uint8_t i = 0; i < 8; i++)
  {
  // zero pad the address if necessary
  if (deviceAddress[i] < 16) Serial.print("0");
  Serial.print(deviceAddress[i], HEX);
  }
  Serial.println();
}

// function to print a device's resolution
void printResolution(DeviceAddress deviceAddress)
{
  Serial.print("Resolution: ");
  Serial.print(sensors.getResolution(deviceAddress));
  Serial.println();    
}

void loop(void)
{  
  // loop to print temps
  sensors.requestTemperatures(); // Send the command to get temperatures
  for( int j =0; j < DS1820_SENSORS; j++){
  printData(Temp[j]);
  printTemperature(Temp[j]); // Use a simple function to print out the data
  }
}
  
// main function to print information about a device
void printData(DeviceAddress deviceAddress)
{
  Serial.print("Device Address: ");
  printAddress(deviceAddress);
  Serial.print(" ");
}

void printTemperature(DeviceAddress deviceAddress) // function to print the temperature for a device
{
  int i; 
  tempC[i] = sensors.getTempC(deviceAddress);
  tempF[i] = (DallasTemperature::toFahrenheit(tempC[i])); // Converts tempC to Fahrenheit
  degreesF[i] = tempF[i]; // copies value so PID can read 
  Serial.print("Temperature: ");
  Serial.print(degreesF[i]);
  Serial.println(" degrees F");  
  delay (1000); 
}

I designed a controller on my diecemilia using two separate one-wire busses on digital pins 17 and 18 (the analog pins as all others were used)

I basically just had a separate onewire instance for each bus and had a routine to pick which bus to poll based on where the sensors were remembered.
OneWire DS1(17);
OneWire DS2(18);

That got me around a lot of the problems I initially had.

But the main fix I found was actually regarding bus capacitance or something like that. The 4.7k pullup resistor is a bit weak for longer busses. Switch to a 1k pullup and things should improve a lot. I have 7 sensors spread out on one bus, using 18ga "Sprinkler wire" over 50ft in total length, with short stubs from the main bus to each sensor. It has worked flawlessly for 5 years. Cat5 cable also seems to work good. Use one pair for power and ground, and one wire from another pair for the DQ pin.

PaulS:

OneWire  ds(10);  // on pin 10

Can't you hazard a guess as to what to use for the one on the pin 11?

Some of us dummies didn't realize that "ds" was the name of the bus. I, for one, thought it was a function that established a bus address in the library code, and consequently wasn't something you could have two of, but this thread has opened my eyes.

Regarding enumeration: for buses with multiple sensors, replacing or adding a sensor can screw up the index for the existing sensors, so reading from a separate physical pin always maintains the sensor-to-place (eg, outside, inside, upstairs, downstairs) relationship. From a maintainability standpoint, this is highly desirable.