Go Down

Topic: Temperaturmessung mit mehreren DS18S20 (Read 20947 times) previous topic - next topic

Knippi

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

Gruß Jens

joergsh

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

Jörg

AingTii

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

Clemens

#18
Apr 10, 2016, 11:37 pm Last Edit: Apr 10, 2016, 11:37 pm by Clemens
Du könntest so was verwenden

Code: [Select]

// 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
  }
}



AingTii

Hi Clemens,

dank für die schnelle Antwort.

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

Quote
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

michael_x

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

Die aktuelle

https://github.com/milesburton/Arduino-Temperature-Control-Library

kann jedenfalls     void setResolution(uint8_t);
 
was für Clemens' Beispiel reichen würde.

const byte temperaturePrecision = 12;    ginge auch ;)

maverick1509

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:
Code: [Select]
//---------------------------------------------------------------------------------------------
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;

ElEspanol

#22
Apr 11, 2016, 08:03 pm Last Edit: Apr 12, 2016, 05:54 pm by ElEspanol
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.

Clemens

Ne Idee?
Ja, die libs müssen vorher installiert werden.


Die aktuelle
https://github.com/milesburton/Arduino-Temperature-Control-Library
Ja, genau die! Danke!

Clemens

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/

ElEspanol

Nein, ich rede nicht von der Verzögerung zwischen request und Auslesen, das habe ich blockierungsfrei. Ich rede von der Dauer des sensor.getTempCbyIndex(), also von dem reinen Auslesevorgang. Der benötigt pro Sensor zwischen 28 und 75 ms. Und nimm das mal 15 wie im Code von maverick, dann hast du alle 10 Sekunden einen Hänger von 0,7 Sekunden.

Je nachdem, wie schnell da auf was anderes wie z.B. Tastendrücke reagiert werden muss, ist das viel zu lange.

AingTii

Hallo Zusammen

erst ein mal danke für die schnellen vielen Antworten.

hmmm, mir wäre jetzt nicht bewust, welche lib ich vergessen haben sollte.
oder habe ich eien übersehen...  ::)
Code: [Select]

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


bis auf LowPower.h den nich noch installiert habe, hatte ich bereits alle, evtl. andere Version?!?!?
Die Arduino-Temperature-Control-Library kann ich hier gra dnicht schauen... aber...

Ich schaue mir das Nachher mal an und Teste.

Danke
Gruß AingTii

AingTii

Hallo Zusammen,

so, habe mal ein wenig probiert.

Der Sketch von Clemens läuft, allerdings habe ich dort auch das auffüll Problem,
dass die leeren Sensoren Plätze werden mit Messwerten der anderen befüllt und
teilweise mit mehrfach -127 usw.
Es lag wirklich an dem DallasTemperature welches ich hatte....

Bei dem von maverick1509, bin ich leider irgendwie abgehängt, ich glaube da fehlt zu viel
um es mal eben Lauffähig zu bekommen mit SD Karte usw.

Im Grund habe ich ein Lauffähigen Sketch, nur halt alles einzeln, evtl. hat ja jemand ne Idee,
wie ich es hinbekommen könnte, den Teil mit der Abfrage ob die Adresse richtig ist und die Temperaturabfrage selbst über eine Schleife zu realisieren, so dass ich nur noch die Adressen
definiere und anschleißend nur noch sage 20 Sensoren....

Ich reduziere den Code mal auf nur 2 oder 3 Sensoren und poste ihn gleich.

Danke
Gruß AingTii

Serenifly

Man kann ein Array aus DeviceAdress anlegen:

Code: [Select]

DeviceAddress temperature_sensor_list[] =
{
  { 0x28,0x68,0x2A,0xA4,0x05,0x00,0x00,0xAB },
  { 0x28,0x82,0x38,0xA5,0x05,0x00,0x00,0x3D }
};



Die Größe eines Arrays berechnet man wie üblich mit sizeof() des gesamten Arrays geteilt durch sizeof() eines Elements:
Code: [Select]

const int NUMBER_OF_SENSORS = sizeof(temperature_sensor_list) / sizeof(temperature_sensor_list[0]);



Eine andere Alternative ist ein struct das eine DeviceAdress und eine Float Variable enthält. Und dann ein Array daraus. So hat man gleich die Temperatur dem Sensor zugeordnet.

ElEspanol

#29
Apr 12, 2016, 06:03 pm Last Edit: Apr 12, 2016, 06:07 pm by ElEspanol
Mavericks Code ist sehr einfach, von der SD-Karte etc. ist in dem geposteten nichts zu sehen. Er liest die Sensoren über die Adresse ein, dann gibt es kein Durcheinander, wenn einer fehlt.

Er vermeidet duch die millis() die Blockierung vom request. Es muss aber dafür zwingend   sensor.setWaitForConversion(false); in setup, sonst bringt das nichts.

Hier mal meine Routine, ich lese alle 30 Sekunden ein, und lasse immer eine Sekunde Abstand zwischen den verschiedenen Sensoren. Vielleicht kannst du damit was anfangen. Ih hab an einem Pin 3 und am anderen Pin 2 Sensoren, deswegen 2 Sensorobjekte. und die -127 fange ich auch ab.
Code: [Select]
void DS1820auslesen() {

  static byte zustand, sensorindex;
  static uint32_t intervall = 1000, prev = -intervall, abfrageintervall = 30000, prevabfrageintervall = -abfrageintervall ;
  static bool auslesen, flag;
  if (millis() - prevabfrageintervall > abfrageintervall) auslesen = 1;

  //------------------------------------------------
  if (millis() - prev > intervall && auslesen) {
    zustand++;

    prev = millis();

    switch (zustand)
    {
        uint32_t start;


      case 0:     //Temperatur anfordern
        start = millis();
        sensor.requestTemperatures();
        sensorRetorno.requestTemperatures();
        Serial << "Request " << millis() - start << " ms gedauert" << endl;
        break;

      case 1:     //Temperatur auslesen
        start = millis();
        tempPool = sensor.getTempCByIndex(0);
        Serial << _FLOAT(tempPool, 1) << " C Pool" << endl;             
        if (tempPool != -127) {
          tempPool_alt = tempPool; //
        } else {
          tempPool = tempPool_alt;
          flag = 1;
        }
        break;

      case 2:     //Temperatur auslesen
        start = millis();
        tempLuft = sensor.getTempCByIndex(1);
        Serial << _FLOAT(tempLuft, 1) << " C tempLuft" << endl;             
        if (tempLuft != -127) {
          tempLuft_alt = tempLuft; //
        } else {
          tempLuft = tempLuft_alt;
          flag = 1;
        }
        break;

      case 3:     //Temperatur auslesen
        start = millis();
        tempSonne = sensor.getTempCByIndex(2);
        Serial << _FLOAT(tempSonne, 1) << " C tempSonne" << endl;           
        if (tempSonne != -127) {
          tempSonne_alt = tempSonne; //
        } else {
          tempSonne = tempSonne_alt;
          flag = 1;
        }
        break;

      case 4:     //Temperatur auslesen

        start = millis();
        tempRetornoD = sensorRetorno.getTempCByIndex(0);
        Serial << _FLOAT(tempRetornoD, 1) << " C tempRetornoD" << endl;               
        if (tempRetornoD != -127) {
          tempRetornoD_alt = tempRetornoD;  //
        } else {
          tempRetornoD = tempRetornoD_alt;
          flag = 1;
        }
        break;

      case 5:     //Temperatur auslesen
        start = millis();
        tempRetornoS = sensorRetorno.getTempCByIndex(1);
        Serial << _FLOAT(tempRetornoS, 1) << " C tempRetornoS" << endl << endl;             
        if (tempRetornoS != -127) {
          tempRetornoS_alt = tempRetornoS; //
        } else {
          tempRetornoS = tempRetornoS_alt;
          flag = 1;
        }
        zustand = -1;
        auslesen = 0; // abfrage ist beendet,
        prevabfrageintervall = millis();

        tempErwaermung = tempRetornoS - tempRetornoD;
        if ((tempErwaermung < 0) || !FilterpumpeLaeuft) tempErwaermung = 0;


       
        if (flag) {
          Serial << F("Pool: ") << _FLOAT(tempPool, 1) << F(" C   Luft: ") << _FLOAT(tempLuft, 1) << F(" C   Ruecklauf_S;  ")
          << _FLOAT(tempRetornoS, 2) << F(" C   Ruecklauf_D;  ") << _FLOAT(tempRetornoD, 2)
          << F(" C   Sonne: ") << _FLOAT(tempSonne, 1) << F(" C") << endl << F("hat ") << millis() - start << F(" ms gedauert") << endl;
          Serial << F("Min. eine Auslesung war -127 Grad") << endl << endl;
         flag=0;
        }
        break;
    }
  }
  //-----------------------------------------------
}

Go Up
 


Please enter a valid email to subscribe

Confirm your email address

We need to confirm your email address.
To complete the subscription, please click the link in the email we just sent you.

Thank you for subscribing!

Arduino
via Egeo 16
Torino, 10131
Italy