Temperaturmessung mit mehreren DS18S20

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

TempTestv1:47: error: no matching function for call to 'DallasTemperature::setResolution(const int&)'

Unterschiedliche Libraries

Die aktuelle

kann jedenfalls    void setResolution(uint8_t);

was für Clemens' Beispiel reichen würde.

const [b]byte[/b] temperaturePrecision = 12;  ginge auch :wink:

Hallo AingTii,
ich lese so 15 Temperatursensoren ein, kannst du ja abändern.
Die Adressender Sensoren werden von einer SD-Karte gelesen. Sollte einer ausfallen oder gewechselt werden, muß ich nur die neue Adresse auf SD-Karte speichern und fertig.
Bei Fragen einfach melden:

//---------------------------------------------------------------------------------------------
void SensorLesen(){ //alle angeschlossenen Sensoren werden eingelesen
 if(millis() - lese_intervall > 7000 && sensorflag == 0){ //nach 8 Sekunden Aktivierung des Busses
  DachSensor.requestTemperatures(); KellerSensor.requestTemperatures();
   sensorflag = 1;
 }
 if(millis() - lese_intervall > 10000){ //nach 10 Sekunden Zuordnen aller Temperaturen zu den entsprechenden Fühlern
  neue_temperatur = true; 
  GasbrennerTemp = KellerSensor.getTempC(Gasbrenner); KachelofenTemp = KellerSensor.getTempC(Kachelofen); 
  VorlaufTempFussboden = KellerSensor.getTempC(VorlaufFussboden); VorlaufTempHeizkoerper = KellerSensor.getTempC(VorlaufHeizkoerper); 
  BrauchwasserTemp[0] = KellerSensor.getTempC(VorlaufBrauchwasser); BrauchwasserTemp[1] = KellerSensor.getTempC(RuecklaufBrauchwasser);
  SpeicherTemp[0] = KellerSensor.getTempC(SpeicherOben); SpeicherTemp[1] = KellerSensor.getTempC(SpeicherMitteO); 
  SpeicherTemp[2] = KellerSensor.getTempC(SpeicherMitteU); SpeicherTemp[3] = KellerSensor.getTempC(SpeicherUnten); 
  SolarTemp[0] = DachSensor.getTempC(Solar1); SolarTemp[1] = DachSensor.getTempC(Solar2); 
  SolarTemp[2] = DachSensor.getTempC(Solar3); SolarTemp[3] = DachSensor.getTempC(Solar4); 
  AussenTemp[0] = DachSensor.getTempC(Aussen1); AussenTemp[1] = DachSensor.getTempC(Aussen2); 
//Formeln für die Berechnung der Vorlauftemperaturen der Fussbodenheizung und der Heizkörper
// constrain gibt Ober- und Untergrenzen vor, die nicht über oder unterschritten werden
  SollTempFussboden = constrain(.80 * 1.8317984 * pow ((20 - AussenTemp[0]), 0.8281902) + 20, 20, 50); // 20,20,50 Solltemperatur Raum, oberer Grenzwert, unterer Grenzwert
  SollTempHeizkoerper = constrain(1.6 * 1.8317984 * pow ((20 - AussenTemp[0]), 0.8281902) + 20, 20, 70); 
  lese_intervall = millis(); sensorflag = 0;

So in der Art hatte ich es auch, obwohl nicht blockierend, summiert sich die Auslesezeit der Sensoren beträchtlich auf, mit teilweise bis zu 75ms pro Sensor.
Ich hab das dann umgeschrieben und lasse immer eine kleine Pause zwischen den einzelnen Sensoren und eine grosse zwischen den Einlesevorgängen.

Dann habe ich das Problem nicht, dass der uC auf kurze Tastendrucke nicht reagiert, wenn er gerade die Sensoren ausliest.

AingTii:
Ne Idee?

Ja, die libs müssen vorher installiert werden.

michael_x:
Die aktuelle
GitHub - milesburton/Arduino-Temperature-Control-Library: Arduino Temperature Library

Ja, genau die! Danke!

ElEspanol:
So in der Art hatte ich es auch, obwohn nicht blockierend, summiert sich die Auslesezeit der Sensoren beträchtlich auf teilweise bis zu 75ms pro Sensor.

Dann habe ich das Problem nicht, dass der uC auf kurze Tastendrucke nicht reagiert, wenn er gerade die Sensoren ausliest.

... oder gar 750 ms bei 12bit Auflösung, vielleicht kann der code hier helfen:
http://www.cupidcontrols.com/2014/10/moteino-arduino-and-1wire-optimize-your-read-for-speed/