Pages: [1]   Go Down
Author Topic: Reading Multiple DS18B20 sensors on Multiple Inputs  (Read 608 times)
0 Members and 1 Guest are viewing this topic.
Offline Offline
Newbie
*
Karma: 0
Posts: 3
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

I am in the process of creating a 4 channel temperature controller. I am wanting to use DS18B20 sensors. As sensors will be swapped out and moved around, I figure this would cause problems using a single input for them all. So I am thinking one sensor on each input would be the best route. I searched around for examples of how to implement this and was not coming up with anything. Could someone point me in the right direction?
Logged

Dee Why NSW
Offline Offline
Edison Member
*
Karma: 30
Posts: 1708
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

This is the code I used, derived from the sheepdog method. Not such a great idea in principle but works fine if you have the pins to spare.

Another approach is to incorporate the address finder code. This enables you to still use the one-wire system. 

Code:
/*
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
Logged

Offline Offline
Newbie
*
Karma: 0
Posts: 3
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Thanks. I saw that way, I was trying to see if I there were any options.  I was hoping that this was possible with the OneWire and Dallas functions as I have already been playing with them a bit. I am not sure if the using the address finder will work for me or not. What I am really trying to do is if a sensor from "input 4" is put into "input 2" I want that sensor to now be input 2. From my understanding if I reference these by address, it will still be reporting as input 4 correct? That is what I am really wanting to avoid.
Logged

Dee Why NSW
Offline Offline
Edison Member
*
Karma: 30
Posts: 1708
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

What I am really trying to do is if a sensor from "input 4" is put into "input 2" I want that sensor to now be input 2. From my understanding if I reference these by address, it will still be reporting as input 4 correct? That is what I am really wanting to avoid.

No. One-wire is one-wire, and Arduino neither knows nor cares which input is used by which sensor. They report according to their address code, not the terminal by which they are corrected. 

I don't know why you would want to swap them around, other than you find it hard to tell which is which, a problem I solve with paper labels. I misunderstood your intent and thought you were using different sensors and different Arduinos. This situation is in fact the only instance I can think of where building in the address finder is not a pointless exercise. I guess having the sensors constantly stolen might be another.

I now understand you merely want to be secure about mixing them in the same application. I can't see a problem with that, providing you know what the sensors are sensing.
Logged

Offline Offline
Newbie
*
Karma: 0
Posts: 3
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote
I don't know why you would want to swap them around, other than you find it hard to tell which is which, a problem I solve with paper labels. I misunderstood your intent and thought you were using different sensors and different Arduinos. This situation is in fact the only instance I can think of where building in the address finder is not a pointless exercise. I guess having the sensors constantly stolen might be another.

For now, no there would be no reason to swap them around. My thought is that with a final product, where if probes have been replaced or put on a different connection than what was labeled by the end user, you would have problems. It would not be a very user friendly replacement of probes. Just trying to prevent this sort of thing being an issue.

Im thinking out loud here, but the best of both worlds would be to put all the sensors on 1 input and have a menu function where a user can define what sensor is to be read as what "input" and these addresses/input assignment combo would be saved in eeprom. Unfortunately I would have no idea where to start with this.
« Last Edit: January 28, 2013, 10:58:51 am by adamfritzsche » Logged

Pages: [1]   Go Up
Jump to: