Temperaturmessung mit mehreren DS18S20

Hallo,
ich möchte gerne mit meinem Mega 2560 + 16x2 Display und zwei DS18S20 zwei Temperaturen messen. Ein DS18S20 soll die Temperatur in meinem Aquarium messen und der andere die Temperatur im Unterschrank.
Die Temperatur im Aquarium messe ich bereits mit nachfolgenden Sketch. Nun soll ein weiterer DS18S20 mit eingebunden werden und zur Anzeige gebracht werden. So wie in etwa ein Innen- und Außenthermometer.
Z.Z. habe ich den einen DS18S20 wie im Bild dargestellt angeschlossen.

#include <LiquidCrystal.h> 
#include "Wire.h"
#include <OneWire.h> 
#define DS1307_I2C_ADDRESS 0x68  // This is the I2C address
// Arduino version compatibility Pre-Compiler Directives
#if defined(ARDUINO) && ARDUINO >= 100   // Arduino v1.0 and newer
  #define I2C_WRITE Wire.write 
  #define I2C_READ Wire.read
#else                                   
  #define I2C_WRITE Wire.send 
  #define I2C_READ Wire.receive
#endif

// Initialisierung des LCD
LiquidCrystal lcd(22, 23, 24, 25, 26, 27);
OneWire  ds(28); 

// Globale Variablen
byte i;
byte present = 0;
byte data[12];
byte addr[8];
float Temp;
byte second, minute, hour, dayOfWeek, dayOfMonth, month, year;
int u, j, k = 0;
//float temp_in, temp_out;
byte zero;
char  *Day[] = {"","So","Mo","Di","Mi","Do","Fr","Sa"};
char  *Mon[] = {"","Jan.","Feb.","Mar.","Apr.","Mai.","Jun.","Jul.","Aug.","Sep.","Okt.","Nov.","Dez."};
 
// Wandelt BCD-Werte in Dezimalwerte um
byte bcdToDec(byte val)
{
  return ( (val/16*10) + (val%16) );
}
 
// Daten von RTC erhalten
void getDateDs1307()
{
  // Reset the register pointer
  Wire.beginTransmission(DS1307_I2C_ADDRESS);
  I2C_WRITE(zero);
  Wire.endTransmission();
  Wire.requestFrom(DS1307_I2C_ADDRESS, 7);
}
 
void setup()
{
  
// Start des IIC-Modi
  Wire.begin();


};
 
void loop()
{
// Ausgabe von Datum und Uhrzeit inkl. Abfrageroutine der IIC-RTC 
while(u <= 10)//die Zeit für der Anzeigendauer
{  
  Wire.beginTransmission(DS1307_I2C_ADDRESS);
  I2C_WRITE(zero);
  Wire.endTransmission();
 
  Wire.requestFrom(DS1307_I2C_ADDRESS, 7);
 
// Maskierung der Bits vom RTC-Modul
  second     = bcdToDec(I2C_READ() & 0x7f);
  minute     = bcdToDec(I2C_READ());
  hour       = bcdToDec(I2C_READ() & 0x3f);  // Need to change this if 12 hour am/pm
  dayOfWeek  = bcdToDec(I2C_READ());
  dayOfMonth = bcdToDec(I2C_READ());
  month      = bcdToDec(I2C_READ());
  year       = bcdToDec(I2C_READ());

// Ausgabe des Datums im Format DD,_dd._mmm._'yy 
  lcd.clear();
  lcd.setCursor(0, 0);
  lcd.print(Day[dayOfWeek]);
  lcd.print(", ");
  if (dayOfMonth < 10)
    lcd.print("0");
  lcd.print(dayOfMonth, DEC);
  lcd.print(".");
  lcd.print(" ");
  lcd.print(Mon[month]);
  lcd.print(" '");
  lcd.println(year, DEC);


// Ausgabe der Uhrzeit im Format hh:mm:ss 
  lcd.setCursor(4, 1);
  if (hour < 10)
     lcd.print("0");
  lcd.print(hour, DEC);
  lcd.print(":");
  if (minute < 10)
    lcd.print("0");
  lcd.print(minute, DEC);
  lcd.print(":");
  if (second < 10)
    lcd.print("0");
  lcd.print(second, DEC);
  lcd.print("  ");
  lcd.noCursor();
  u++;
  delay(500);
  j = 0;
  k = 0;
};

while(j <= 10)
{



  // display Sensor data on LCD:
  if ( !ds.search(addr)) {
    // No more Dallas chips present:
    Serial.print("No more addresses.\n");
    ds.reset_search();
    //delay(250);
    //return;
     // Check for family code which is not DS18B20:
  if ( addr[0] != 0x28) {
    Serial.print("Device is not a DS18B20 family device.\n");
    return;
    
  }
  // The DallasTemperature library can do all this work for you!
  ds.reset();
  ds.select(addr);
  ds.write(0x44,0);          // start conversion, with parasite power off
   present = ds.reset();
  ds.select(addr);    
  ds.write(0xBE);             // Read Scratchpad  
  // Check whether chip is present:
  present = ds.reset();
  ds.select(addr);    
  ds.write(0xBE);             // Read Scratchpad
  
   Serial.print("P=");         // Present = 1
  Serial.print(present,HEX);
  Serial.print(" ");
  for ( i = 0; i < 9; i++) {   // we need 9 bytes of data
    data[i] = ds.read();
    Serial.print(data[i], HEX);
    Serial.print(" ");
  }
   Serial.print(" CRC=");
  Serial.print( OneWire::crc8( data, 8), HEX);
  // Calculate temperature. data[1] High Byte, data[0] Low Byte.
  Temp =  ((data[1] << 8) + data[0] ) * 0.0625;  // 12Bit = 0,0625 C per Bit
  Serial.print( " T=");
  Serial.print( Temp, 2);
  Serial.print( " C");
  Serial.println();
  }
  char line[17];
lcd.clear();
  lcd.setCursor(0,0); 
  //sprintf(line, "T=%f C", Temp); funktioniert nicht, Fehler in Compiler?
  dtostrf(Temp, 5, 2, line);
  lcd.print("T=");
  lcd.print(line);
  lcd.print(" C");
j++;
delay(500);
  u = 0;
  };
}

Meine Frage wäre nun, wie binde ich einen zweiten DS18S20 in die Schaltung und in den Sketch ein?

Danke.
Gruß Jens

Die DS18S20 einfach paralell schalten und mit ihrer Adresse ansprechen.

Grüße Uwe

Der Sensor ist über 1-wire angeschlossen. D.h. alle Geräte haben eine gemeinsame Datenleitung (ein Kabel) und werden über ihre Adresse angesprochen.
Falls dir das nicht klar sein sollte, dann empfehle ich dir dich in das 1-wire Protokoll einzulesen.

Hallo,

danke für die "Wegbereitung".
Ich habe die Fühler nun parallel geschaltet und den von uwfed vorgeschlagenen Sketch mit den zuvor ausgelesenen Adressen der beiden DS18S20 umgesetzt.
Leider bekomme ich die Werte der beiden Fühler in Fahrenheit anstatt in °Celsius.
Muss man hier noch so etwas wie eine Umrechnungsformel mit einsetzen?
Anbei der Sketch:

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

OneWire  ds(28); //pin für ds1820

//DeviceAdressen der einzelnen ds1820 Temperatursensoren angeben. (loop anpassen)
DeviceAddress sensor1 = { 0x28, 0x36, 0x2F, 0x99, 0x4, 0x0, 0x0, 0x3A };
DeviceAddress sensor2 = { 0x28, 0xB1, 0xB7, 0xBD, 0x4, 0x0, 0x0, 0xA2 };


char sensor1Name[] = "Unterschrank: ";
char sensor2Name[] = "W.-Temp: ";


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

void writeTimeToScratchpad(byte* address)
{
  //reset the bus
  ds.reset();
  //select our sensor
  ds.select(address);
  //CONVERT T function call (44h) which puts the temperature into the scratchpad
  ds.write(0x44,1);
  //sleep a second for the write to take place
  delay(1000);
}

void readTimeFromScratchpad(byte* address, byte* data)
{
  //reset the bus
  ds.reset();
  //select our sensor
  ds.select(address);
  //read the scratchpad (BEh)
  ds.write(0xBE);
  for (byte i=0;i<9;i++){
    data[i] = ds.read();
  }
}

float getTemperature(byte* address)
{
  int tr;
  byte data[12];

  writeTimeToScratchpad(address);

  readTimeFromScratchpad(address,data);

  //put in temp all the 8 bits of LSB (least significant byte)
  tr = data[0];

  //check for negative temperature
  if (data[1] > 0x80)
  {
    tr = !tr + 1; //two's complement adjustment
    tr = tr * -1; //flip value negative.
  }

  //COUNT PER Celsius degree (10h)
  int cpc = data[7];
  //COUNT REMAIN (0Ch)
  int cr = data[6];

  //drop bit 0
  tr = tr >> 1;

  return tr - (float)0.25 + (cpc - cr)/(float)cpc;
}

void loop(void) 
{
  float temp1 = getTemperature(sensor1);
  float temp2 = getTemperature(sensor2);


  Serial.print(sensor1Name);
  Serial.print(temp1);
  Serial.println(" Celsius");

  Serial.print(sensor2Name);
  Serial.print(temp2);
  Serial.println(" Celsius");


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

Gruß Jens

Hallo Jens,
ich benutze in meinen Anwendungen den Befehl sensors.getTempC(Sensor)
und da ist der Wert dann in °Celsius-
Gruß

Hallo maverick1509,

meinst du so:

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

OneWire  ds(28); //pin für ds1820

//DeviceAdressen der einzelnen ds1820 Temperatursensoren angeben. (loop anpassen)
DeviceAddress sensor1 = { 0x28, 0x36, 0x2F, 0x99, 0x4, 0x0, 0x0, 0x3A };
DeviceAddress sensor2 = { 0x28, 0xB1, 0xB7, 0xBD, 0x4, 0x0, 0x0, 0xA2 };


char sensor1Name[] = "Unterschrank: ";
char sensor2Name[] = "W.-Temp: ";


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

void writeTimeToScratchpad(byte* address)
{
  //reset the bus
  ds.reset();
  //select our sensor
  ds.select(address);
  //CONVERT T function call (44h) which puts the temperature into the scratchpad
  ds.write(0x44,1);
  //sleep a second for the write to take place
  delay(1000);
}

void readTimeFromScratchpad(byte* address, byte* data)
{
  //reset the bus
  ds.reset();
  //select our sensor
  ds.select(address);
  //read the scratchpad (BEh)
  ds.write(0xBE);
  for (byte i=0;i<9;i++){
    data[i] = ds.read();
  }
}

float [color=orange]getTempC[/color](byte* address)
{
  int tr;
  byte data[12];

  writeTimeToScratchpad(address);

  readTimeFromScratchpad(address,data);

  //put in temp all the 8 bits of LSB (least significant byte)
  tr = data[0];

  //check for negative temperature
  if (data[1] > 0x80)
  {
    tr = !tr + 1; //two's complement adjustment
    tr = tr * -1; //flip value negative.
  }

  //COUNT PER Celsius degree (10h)
  int cpc = data[7];
  //COUNT REMAIN (0Ch)
  int cr = data[6];

  //drop bit 0
  tr = tr >> 1;

  return tr - (float)0.25 + (cpc - cr)/(float)cpc;
}

void loop(void) 
{
 
  float temp1 =getTempC(sensor1);
  float temp2 =getTempC(sensor2);
  


  Serial.print(sensor1Name);
  Serial.print(temp1);
  Serial.println(" Celsius");

  Serial.print(sensor2Name);
  Serial.print(temp2);
  Serial.println(" Celsius");


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

zeigt aber leider immer noch die Temperatur in Fahrenheit an.

Gruß Jens

Hi - ich denke du machst es komplizierter als es ist :slight_smile:
Die Lib DallasTemperature nimmt dir die Arbeit ab.

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

#define ONE_WIRE_BUS 2

const int MaxSensors=4;
float temp[MaxSensors];

OneWire oneWire(ONE_WIRE_BUS);
DallasTemperature sensors(&oneWire);

Dann in der Loop:
sensors.requestTemperatures();
temp[index]=sensors.getTempCByIndex(index);

index wird ab 0 hochgezählt und bezeichnet den Temparaturfühler den du haben willst.
Die Funktion requestTemperatures(); dauert ein bisschen, also blockiert quasi die Loop.

Das will man meist nicht haben, vorher ein sensors.setWaitForConversion(false); dann wird nicht gewartet.
Nur musst du dann dafür sorgen das die Funktion innerhalb der Spezifikation der Sensoren angesprungen wird. (Je nach config im Sekundentakt)

Also so läuft es bei mir....
Du hast die Lib DallasTemperature zwar eingelinkt, aber IHMO im Projekt nicht benutzt

Hallo rudirabbit,

danke für die Hilfe, aber wie bekomme ich denn nun die 2 Temp.-Fühler angezeigt?
Bei mir wird immer der gleiche Wert für beide Temp.-Fühler angezeigt.
Hier der Sketch dazu:

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

#define ONE_WIRE_BUS 28

//DeviceAdressen der einzelnen ds1820 Temperatursensoren angeben. (loop anpassen)
DeviceAddress sensor1 = { 
  0x28, 0x36, 0x2F, 0x99, 0x4, 0x0, 0x0, 0x3A };
DeviceAddress sensor2 = { 
  0x28, 0xB1, 0xB7, 0xBD, 0x4, 0x0, 0x0, 0xA2 };

const int MaxSensors=4;


float temp[MaxSensors];

OneWire oneWire(ONE_WIRE_BUS);
DallasTemperature sensors(&oneWire);

char sensor1Name[] = "Unterschrank: ";
char sensor2Name[] = "W.-Temp: ";


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

void loop(void) 
{

  //sensors.setWaitForConversion(false);
  sensors.requestTemperatures();
  temp[1]=sensors.getTempCByIndex(1); 
  temp[2]=sensors.getTempCByIndex(2); 


  Serial.print(sensor1Name);
  Serial.print(temp[1]);
  Serial.println(" Celsius");

  Serial.print(sensor2Name);
  Serial.print(temp[2]);
  Serial.println(" Celsius");
}

Gruß Jens

Hallo an alle,

hat jemand eine Idee und kann mir helfen?

Bei meinem Code wird immer der gleiche Wert für beide Temp.-Fühler angezeigt.

Gruß Jens

Hallo Jens,

probier mal

temp[1]=sensors.getTempCByIndex(0);
temp[2]=sensors.getTempCByIndex(1);

dann geht es.

Gruss Kalli

Oder besser noch

temp[0]=sensors.getTempCByIndex(0);
temp[1]=sensors.getTempCByIndex(1);

Hallo Kalli,
hat funktioniert. :slight_smile:
Vielen Dank dafür.
Der Tipp von MaFu funktioniert nicht. Es wird ein Sensor angezeigt und der andere Zeigt immer den Wert 0 an.

Gruß Jens

Knippi:
Hallo Kalli,
hat funktioniert. :slight_smile:
Vielen Dank dafür.
Der Tipp von MaFu funktioniert nicht. Es wird ein Sensor angezeigt und der andere Zeigt immer den Wert 0 an.

Gruß Jens

Hast Du bei der Serial Ausgabe dann auch temp[0] und temp[1] verwendet?
Oder weiterhin temp[1] und temp[2]?

Arrays in C beginnen bei 0. Bei "MaxSensors=4" geht Dein Array somit von temp[0] bis temp[3] und NICHT von temp[1] bis temp[4]. Wenn Du dann irgendwann den Bereich von MaxSensors ausnutzt und vier Sensoren dranhängst, stehst Du vor dem nächsten Problem wenn Du erst bei temp[1] beginnst.

for (int i = 0; i < MaxSensors; i++)
  temp[i]=sensors.getTempCByIndex(i);

@Jens
Hallo Jens,
kannst Du mir sagen welchen Sensor Du genau genommen hast für die Temperaturmessung im Aquarium? Bin gerade dabei mir einen Aqua Computer auf Arduino Basis zu basteln.

Hallo Marko,
ich würde sowas empfehlen:
http://www.ebay.de/itm/5PCS-Waterproof-Digital-Thermal-Probe-or-Sensor-DS18B20-/261152181792?pt=Mess_Prüftechnik&hash=item3ccde20e20
gruß

Hallo Marko,
es sind genau diese Temperaturfühler, die maverick1509 verlinkt hat.

Gruß Jens

Ich würde gerne 2 DS18b20 an 2 pins betreiben ohne die Adresse eingeben zu müssen. Geht das auch ?

Jörg

Hallo Zusammen,

ich habe hier noch eine Verständnisfrage.

Wenn ich die Temperatur über DallasTemperature.h abrufe, werden ja die Sensoren
automatisch dem Index hinzugefügt und das Problem ist, fällt ein Sensor aus, wird
der Wert des Vorherigen geschrieben.

Kann man das irgendwie kombinieren, die reine 1Wire , mit der eingabe
der fixen Adressen der Sensoren und der Einfachhalberheit mit einer
schleife die sensoren abzufragen?

Denn Momentan, arbeitet ich mit dem 1-Wire Sketch und fixen Adressen, hier
ist es mir noch nicht gelungen über eine Schleife den Sensor1, Sensor2 usw.
zu wechseln, es endet lediglich in Fehlermeldungen.....
Also momentan für jeden Sensor einen Abschnitt im Sketch, auslesen, in eine Variable schreiben
und ausgeben. bzw. wenn der Sensor nicht vorhanden ist, 11111111 schreiben.

Bei späteren 50 oder mehr Sensoren wird das ja ein riesen Sketch....

Daher wäre eine Schleife schon gut, aber die Sicherheit zu merken, wenn ein Sensor ausgefallen ist,
ist ebenso wichtig!

Evtl. hat ja jemand ne Lösung

Danke

Gruß AingTii

Du könntest so was verwenden

// pins hard coded
// D8 DS18B20 one-wire array 

/*
  Open Hive | Temperature
  2015-10 Clemens Gruber | initial sketch

  This code is in the public domain.
*/

// variables you can modify 
// 
// number of temperature devices on bus 
int const temperatureNumDevices = 12;
// resolution for all devices (9, 10, 11 or 12 bits)
const int temperaturePrecision = 12; 
// pin for the temperature sensors
const int temperaturePin = 8;


// libraries
// temperature sensor DS18B20
#include <OneWire.h>  // oneWire for DS18B20
#include <DallasTemperature.h>  // DS18B20 itself 

OneWire oneWire(temperaturePin); // oneWire instance to communicate with any OneWire devices (not just DS18B20)
DallasTemperature temperatureSensors(&oneWire);  // pass oneWire reference to DallasTemperature
uint8_t deviceAddressArray[temperatureNumDevices][8]; // arrays for device addresses

char gradC[4]={' ','°','C','\0'};  // degree sign

// power saving 
#include <LowPower.h>


// we need some variable as char to pass it to payload easily 
char temperatureArrayChar[temperatureNumDevices][6];  // should handle +/-xx.x and null terminator


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

  temperatureSensors.begin();  // start DallasTemperature library
  temperatureSensors.setResolution(temperaturePrecision);  // set resolution of all devices 

  // change index to order devices as in nature 
  // (an other approach can be to order physical devices ascending to device address on cable) 
  if (!temperatureSensors.getAddress(deviceAddressArray[1], 0)) Serial.println("Unable to find address for Device 0"); 
  if (!temperatureSensors.getAddress(deviceAddressArray[6], 1)) Serial.println("Unable to find address for Device 1"); 
  if (!temperatureSensors.getAddress(deviceAddressArray[8], 2)) Serial.println("Unable to find address for Device 2");   
  if (!temperatureSensors.getAddress(deviceAddressArray[5], 3)) Serial.println("Unable to find address for Device 3"); 
  if (!temperatureSensors.getAddress(deviceAddressArray[3], 4)) Serial.println("Unable to find address for Device 4"); 
  if (!temperatureSensors.getAddress(deviceAddressArray[4], 5)) Serial.println("Unable to find address for Device 5");   
  if (!temperatureSensors.getAddress(deviceAddressArray[10], 6)) Serial.println("Unable to find address for Device 6"); 
  if (!temperatureSensors.getAddress(deviceAddressArray[9], 7)) Serial.println("Unable to find address for Device 7"); 
  if (!temperatureSensors.getAddress(deviceAddressArray[0], 8)) Serial.println("Unable to find address for Device 8");   
  if (!temperatureSensors.getAddress(deviceAddressArray[7], 9)) Serial.println("Unable to find address for Device 9"); 
  if (!temperatureSensors.getAddress(deviceAddressArray[11], 10)) Serial.println("Unable to find address for Device 10"); 
  if (!temperatureSensors.getAddress(deviceAddressArray[2], 11)) Serial.println("Unable to find address for Device 11");   
}


void loop() { 
  // output temperature for all device on bus 
  getTemperature(); 
  
  for(int i=0; i<temperatureNumDevices; i++) {
    Serial.print("Temp[");
    Serial.print(i);  // print index 
    Serial.print("]: "); 
    
    Serial.print(temperatureArrayChar[i]);
    Serial.println(gradC);
  }
  Serial.println();
}


// temperature for all device on bus 
void getTemperature() {
  // request temperature on all devices on the bus
  temperatureSensors.setWaitForConversion(false);  // makes it async
  // initiatie temperature retrieval
  temperatureSensors.requestTemperatures();

  // wait at least 750 ms for conversion 
  // to save power go to sleep for this delay 
  Serial.flush();  // flush serial before sleeping 
  LowPower.powerDown(SLEEP_1S, ADC_OFF, BOD_OFF); // delay 60 ms 

  // loop through each device, print out temperature 
  for(int i=0; i<temperatureNumDevices; i++) {
    // print temperature
    float temperatureC = temperatureSensors.getTempC(deviceAddressArray[i]);
    dtostrf(temperatureC, 5, 1, temperatureArrayChar[i]);  // write to char array 
  }
}

Hi Clemens,

dank für die schnelle Antwort.

sieht vielversprechend aus, konnte ich aber nicht Testen....
Endet bei mir allerdings in einer Fehlermeldung

Arduino: 1.6.5 (Windows 7), Platine: "Arduino/Genuino Uno"

TempTestv1.ino: In function 'void setup()':
TempTestv1:47: error: no matching function for call to 'DallasTemperature::setResolution(const int&)'
TempTestv1.ino:47:56: note: candidate is:
In file included from TempTestv1.ino:26:0:
C:\Program Files (x86)\arduino-1.6.5-r5\libraries\DallasTemperature/DallasTemperature.h:96:8: note: void DallasTemperature::setResolution(uint8_t*, uint8_t)
void setResolution(uint8_t*, uint8_t);
^
C:\Program Files (x86)\arduino-1.6.5-r5\libraries\DallasTemperature/DallasTemperature.h:96:8: note: candidate expects 2 arguments, 1 provided
TempTestv1.ino: In function 'void getTemperature()':
TempTestv1:85: error: 'class DallasTemperature' has no member named 'setWaitForConversion'
no matching function for call to 'DallasTemperature::setResolution(const int&)'

Dieser Report hätte mehr Informationen mit
"Ausführliche Ausgabe während der Kompilierung"
aktiviert in Datei > Einstellungen

Ne Idee?

Danke