DS1820 auslesen (wahrscheinlich zum 531. mal)

Hallo,

ich habe hier ein kleines Problem. Ich musste vor ein paar Jahren meine Heizungssteuerung durch einen Raspberry Pi ersetzen. Das funktioniert fast einwandfrei, nun habe ich den Raspberry durch einen Arduino nano ersetzt, weil man auch noch analoge Eingänge hat und das ganze stabiler läuft.

Es funktioniert soweit alles, bis auf den Aussenfühler. Der Aussenfühler ist ein DS1820 (kein DS18B20) da ich ihn im parasitären Modus betreiben muss, weil die Leitung nur 2-adrig ist. Die DS18B20 lassen sich anscheinend nicht mehr 2-adrig verwenden, zumindest mit dem Arduino nicht.
Zum Auslesen des Sensors verwende ich Teile des Codes von hier:

Das Problem ist jetzt, sobald es aussen unter 0 Grad hat, erhalte ich einen Wert von 4095.5.
Evtl. ist nur eine kleine Änderung am Programm nötig? Vielleicht liest ja auch der Autor "stoffl" hier mit?
Danke schonmal.

faulan:
Evtl. ist nur eine kleine Änderung am Programm nötig?

Ganz bestimmt!

falls dir die Antwort zu wenig war, poste deinen Sketch in codetags, dann kann dir vielleicht jemand helfen.

Hi

Einen DS18B20 kann man heute immer noch parasitär betreiben - da Du aber eh einen DS1820 außen verbaut hast, lass uns Deinen Sketch auf Diesen anpassen.
Den parasitären Mode kannst Du ja immer noch auf dem Schreibtisch ausprobieren.

MfG

Setze Deinen Code bitte in Codetags (</>-Button oben links im Forumseditor oder [code] davor und [/code] dahinter ohne *).

Gruß Tommy

faulan:

faulan:
Hallo,

ich habe hier ein kleines Problem. Ich musste vor ein paar Jahren meine Heizungssteuerung durch einen Raspberry Pi ersetzen. Das funktioniert fast einwandfrei, nun habe ich den Raspberry durch einen Arduino nano ersetzt, weil man auch noch analoge Eingänge hat und das ganze stabiler läuft.

Es funktioniert soweit alles, bis auf den Aussenfühler. Der Aussenfühler ist ein DS1820 (kein DS18B20) da ich ihn im parasitären Modus betreiben muss, weil die Leitung nur 2-adrig ist. Die DS18B20 lassen sich anscheinend nicht mehr 2-adrig verwenden, zumindest mit dem Arduino nicht.
Zum Auslesen des Sensors verwende ich Teile des Codes von hier:
https://stoffl.info/2015/11/21/4415/
Das Problem ist jetzt, sobald es aussen unter 0 Grad hat, erhalte ich einen Wert von 4095.5.
Evtl. ist nur eine kleine Änderung am Programm nötig? Vielleicht liest ja auch der Autor “stoffl” hier mit?
Danke schonmal.

So, hab jetzt mal mein Programm angehängt, es wird nur der Aussensensor ausgelesen, alles andere habe ich der Übersicht halber rausgenommen

//#include <LiquidCrystal_I2C.h>

//dht22
//#include “DHT.h” //DHT Bibliothek laden
//uhrenmodul
//#include “RTClib.h”

//RTC_DS3231 rtc;

//char daysOfTheWeek[7][12] = {“Sonntag”, “Montag”, “Dienstag”, “Mittwoch”, “Donnerstag”, “Freitag”, “Samstag”};
//bool syncOnFirstStart = false; // true, falls die Zeitinformationen der RTC mit dem PC synchronisiert werden sollen.
                              // sollte standardm��ig auf false stehen

#include <Wire.h> // Wire Bibliothek hochladen
//#include <LiquidCrystal_I2C.h>// Vorher hinzugefügte LiquidCrystal_I2C Bibliothek hochladen
//LiquidCrystal_I2C lcd(0x27, 20, 4);   //Hier wird festgelegt um was für einen Display es sich handelt. In diesem Fall einer mit 16 Zeichen in 2 Zeilen.
#include <DallasTemperature.h>

//für parasitären sensor
#define ONE_WIRE_BUS_1 A0  
OneWire oneWire_in(ONE_WIRE_BUS_1);
DallasTemperature sensor_inhouse(&oneWire_in);
//-----------------------------------

//-----------dht22------------
//#define DHTPIN 4
//#define DHTTYPE DHT22
//DHT dht(DHTPIN, DHTTYPE);

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

//DeviceAddress sensor2 = { 0x10, 0xC6, 0xC9, 0xE7, 0x2, 0x8, 0x0, 0xF1 };//raumtemp
//DeviceAddress sensor3 = { 0x10, 0x6A, 0x5C, 0xB5, 0x1, 0x8, 0x0, 0x8E };//vorlauftemp
//DeviceAddress sensor4 = { 0x10, 0x9D, 0x32, 0xE8, 0x2, 0x8, 0x0, 0x6B };//ruecklauf
//DeviceAddress sensor5 = { 0x10, 0x5D, 0x78, 0xE7, 0x2, 0x8, 0x0, 0x3A };//strgtemp
//DeviceAddress sensor6 = { 0x10, 0xD9, 0x9B, 0xB, 0x2, 0x8, 0x0, 0xC3 };//badtemp
//DeviceAddress sensor7 = { 0x10, 0x59, 0x9B, 0xB5, 0x1, 0x8, 0x0, 0x49 };//wwtemp
//DeviceAddress sensor8 = { 0x10, 0x9A, 0xE6, 0x5F, 0x2, 0x8, 0x0, 0xB8 };//obentemp
//DeviceAddress sensor9 = { 0x10, 0xE7, 0x67, 0x0B, 0x02, 0x08, 0x0, 0xBA };//aussentemp
DeviceAddress sensor9 = { 0x10, 0x65, 0xE5, 0x59, 0x3, 0x8, 0x0, 0x2 };//aussentemp
//DeviceAddress sensor10 = { 0x10, 0x23, 0xE5, 0xE7, 0x02, 0x08, 0x0, 0xEA };//kuehlschrank

void setup() {
 // put your setup code here, to run once:

//für parasitären modus
 sensor_inhouse.begin();
 Serial.begin(9600);
//----------------------

}

void loop() {

float aussentemp = getTemperature(sensor9);

Serial.print(aussentemp);
delay(1000);
 
}

/******************************************************
 Temperatur eines Sensors in Grad Celsius ermitteln  *
*****************************************************/
float getTemperature(byte
address)
{
 byte type_s;
 byte data[12];
 float celsius;

writeTimeToScratchpad(address);
 readTimeFromScratchpad(address,data);

switch (address[0])
 {
   case 0x10: // DS18S20 oder alter DS1820
     type_s = 1;
     break;
   case 0x28: // DS18B20
     type_s = 0;
     break;
   case 0x22: // DS1822
     type_s = 0;
     break;
 }

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
 }
 celsius = (float)raw / 16.0;
 return celsius;
 
}

/**************************************************************
 Hilfsfunktionen zum ermitteln der Temperatur eines Sensors  *
*************************************************************/
void writeTimeToScratchpad(byte
address)
{
 ds.reset();
 ds.select(address);
 ds.write(0x44,1);
 delay(1000);
}

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





sorry, ich hoffe ich habe es jetzt richtig reingestellt, ich habe seit Jahren nicht mehr in Foren gepostet

Wenn Du quote weg läßt, kann es noch was werden.

Welchen PullUp-Widerstand verwendest Du an der Datenleitung? Der wird für parasitären Betrieb benötigt.

Gruß Tommy

Ich habe 2 4,7K Widerstände parallel geschaltet, da ich ja noch 8 andere Sensoren verwende, war der eine 4,7k Widerstand zu hoch, es wurde überhaupt kein Sensor mehr erkannt.

Sind die alle parasitär?

Gruß Tommy

Nein nur der besagte. Das ist das schöne am arduino ich kann die ds1820 parasitär oder normal anschliessen, sie werden alle ohne Probleme ausgelesen. Mit dem o.g. Sketch hatte ich vorhin mal einen Versuchsaufbau mit nur einem Sensor vorgenommen, den ich in den Gefrierschrank steckte. Es waren keine anderen Sensoren angeschlossen. Sobald er Minusgrade anzeigen sollte, kam der Wert 4095

Funktioniert der Außensensor im normalen Betrieb?

Für Probleme wird im Datenblatt auf Seite 7 noch eine andere Schaltung vorgeschlagen.

Gruß Tommy

Hi

Da bei Minusgraden das MSB gesetzt ist (und alle unbenutzten hohen Bits), kommt Da schon eine recht große Zahl zuzsammen.
DaBla DS1820, Siehe Seite 5

Wenn Du nun die Temperatur ausliest und, weswegen auch immer, nur die unteren 12 Bit benutzt, wäre zumindest das Maximum 4096 (bzw. eben 1 weniger) erklärt.

Ich sehe derzeit eh nicht, wo etwas mit unsigned gemacht bzw. wo der Wert 'umgedreht' würde.

Ändert sich denn diese 4095.5 und sinkt bei 'kälteren Temperaturen'?

MfG

PS: Ich denke, hier wird ein DS1820 (ohne S) benutzt??
Wobei die Codierung der Temperatur bei Beiden identisch zu sein scheint.

Ja, genaus so ist es, in allen Punkten. Wenn es noch kälter ist, sinkt die Temperatur, bzw. der Wert 4095. Ich könnte den Aussenfühler schon gegen einen DS 18b20 tauschen, aber der läüft bei mir nicht im parasitären Modus und wenn ich dann die anderen ds 1820 mit anschliesse, geht gar nichts mehr, allen Sensoren liefern dann den Wert 0.

Hi

Dein ausgelesener Wert ist einfach nur falsch interpretiert.
Wenn das höchste Bit 1 ist, musst Du in das 2er Komplement umwandeln (alle Bits umdrehen und +1)
So langsam dämmert's bei mir - die 4096 sind 12 Bit, die Auflösung ebenfalls ...
Warum? kA :wink:

Ich denke, Du hast Dir irgendwie die Lib oder Teile des Sketch zerschossen - im Normalfall können die Bibliotheken schon richtig rechnen, auch mit Minus-Graden.
Kann sein, daß Du hier zuvor auf 12Bit begrenzt und die Umrechnung nur auf das 15.te Bit prüft (Welches dann bei Dir Null ist, also ein positives Ergebnis).

Zur Not die Rückgabe händisch in die richtige Temperatur umrechnen, steht Alles so weit im Datenblatt.
Das zeitkritische Auslesen macht die Lib, den Rest kann man 'von Hand' machen - oder man spielt die Lib erneut auf oder benutzt eine Andere.

MfG

Der TE macht das Auslesen doch gar nicht mit der Lib.

Hi

Jain :wink:
Ich meinte, daß das zeitkritische 1-wire-Timing durch die Lib erschlagen wird.
Wobei man hier dann schauen sollte, ob die Lib Einem nicht auch die korrekte Temperatur raus geben kann.
Mir ist trotz dem noch icht klar, warum der Sketch die Ausgabe auf 12 Bit ‘verkürzt’.
Bei negativer Temperatur habe ich bei -0.5° nur gesetzte Bits, 16 Stück.
Das müsste eine 32767.5 ergeben.

Dann eben so:
Unter demunsigned int raw = (data[1] << 8) | data[0]; prüfst Du, ob data[1]>127 ist.
WENN, dann ‘drehst Du raw um’ - also negierst raw (müsste/könnte ~ sein) und addierst 1 zu raw.
Auch merkst Du Dir, daß das Ergebnis jetzt negativ ist (also ein - ausgeben).
Die Zahl sollten jetzt die Minus-Grade sein.

MfG

Danke euch für die Hilfe, aber ich machs jetzt anders:
Für meine ganzen Sensoren im Haus verwende ich die bisherige Routine welche über die Seriennummer die entsprechenden Sensoren ausliest. Da im Haus niemals Minusgrade vorkommen sollten :slight_smile: ist das machbar, denke ich.
Den Aussenfühler hänge ich an einen eigenen Eingang (wo nur dieser Fühler und kein anderer hängt), und lese ihn mit folgendem kurzen Codeschnitzel aus. Die Minusgrade werden hier korrekt dargestellt:

#include <OneWire.h>
#include <DallasTemperature.h>
//Datenkabel ist am Digitalpin 2 angeschlossen
#define ONE_WIRE_BUS 4
// oneWire Bus initialisieren
OneWire oneWire(ONE_WIRE_BUS);
DallasTemperature sensors(&oneWire);
void setup(void)
{
  Serial.begin(9600);
  sensors.begin();
}
void loop(void)
{
  sensors.requestTemperatures();
  Serial.print(sensors.getTempCByIndex(0)); //Bei mehreren Sensoren kann man die Indexnummer ändern
}
​

Hi

Warum machst Du Das dann nicht auch an Deinem Bus?
Wenn sich die Indexe nicht ändern, ist Das Auswürfeln in wenigen Minuten erledigt (ist akut der Sensor mit 1-stelliger Gradzahl ... oder nahe dran).
Selbst nach einem Tausch (egal welchen Sensors!!) kann sich der Platz ändern - wäre dann aber auch in wenigen Minuten wieder bereinigt.

Die gleiche Funktion gibt es mit hoher Wahrscheinlichkeit auch für die ID - dort musst Du dann eben 8 Bytes angeben, statt dem Einen.
Ein Blick in die Lib würde hier Klarheit verschaffen.

MfG

postmaster-ino:
Hi

Warum machst Du Das dann nicht auch an Deinem Bus?
Wenn sich die Indexe nicht ändern, ist Das Auswürfeln in wenigen Minuten erledigt (ist akut der Sensor mit 1-stelliger Gradzahl ... oder nahe dran).
Selbst nach einem Tausch (egal welchen Sensors!!) kann sich der Platz ändern - wäre dann aber auch in wenigen Minuten wieder bereinigt.

Die gleiche Funktion gibt es mit hoher Wahrscheinlichkeit auch für die ID - dort musst Du dann eben 8 Bytes angeben, statt dem Einen.
Ein Blick in die Lib würde hier Klarheit verschaffen.

MfG

Ja, genauso mache ich das jetzt. Die Funktion um die Sensoren über die ID auszulesen lautet: sensors.getTempC(DeviceAdresse) und die Minusgrade werden damit auch korrekt angezeigt.
Danke nochmal !!! Hat mir viel geholfen

Hi

Schön zu hören!
Wenn Du noch Deinen aktuellen Sketch für die Nachwelt hier lassen könntest?
Könnte mir vorstellen, daß dieses Problem durchaus auch anderen Leuten vor die Füße fällt.

MfG

So, jetzt wars doch nicht so einfach. Am Klemmbrett auf dem Schreibtisch hat alles geklappt, in der Praxis leider nicht. Hier mal eine kurze Auflistung was ich gemacht habe:

Ich lese alle Sensoren über die Dallas Library ein, mit folgendem Befehl:

 float untentemp = sensors.getTempC(sensor2);
  float vorlauftemp = sensors.getTempC(sensor3);
  float ruecklauftemp = sensors.getTempC(sensor4);
  float strgtemp = sensors.getTempC(sensor5);
  float badtemp = sensors.getTempC(sensor6);
  float wwtemp = sensors.getTempC(sensor7);
  float obentemp = sensors.getTempC(sensor8);

Die Device Adressen wurden vorher definiert:

DeviceAddress sensor2 = { 0x10, 0xC6, 0xC9, 0xE7, 0x2, 0x8, 0x0, 0xF1 };//raumtemp
DeviceAddress sensor3 = { 0x10, 0x6A, 0x5C, 0xB5, 0x1, 0x8, 0x0, 0x8E };//vorlauftemp
DeviceAddress sensor4 = { 0x10, 0x9D, 0x32, 0xE8, 0x2, 0x8, 0x0, 0x6B };//ruecklauf
DeviceAddress sensor5 = { 0x10, 0x5D, 0x78, 0xE7, 0x2, 0x8, 0x0, 0x3A };//strgtemp
DeviceAddress sensor6 = { 0x10, 0xD9, 0x9B, 0xB, 0x2, 0x8, 0x0, 0xC3 };//badtemp
DeviceAddress sensor7 = { 0x10, 0x59, 0x9B, 0xB5, 0x1, 0x8, 0x0, 0x49 };//wwtemp
DeviceAddress sensor8 = { 0x10, 0x9A, 0xE6, 0x5F, 0x2, 0x8, 0x0, 0xB8 };//obentemp

Nun hatte ich das Problem, das der Aussenfühler, welcher parasitär auch auf dem onewire Bus hängt, nicht auszulesen war. Die ID konnte ausgelesen werden, aber der Sensor nicht, er brachte immer den Fehlercode 85. Auch ein Ändern der Auflösung (9, 10, 11, 12 Bit) brachte auch nichts.
Also definierte ich einen zusätzlichen zweiten Eingang als Onewire:

//-------------------------------------------------------------------------------------
//für aussenfühler
#define ONE_WIRE_BUS2 2
OneWire oneWire2(ONE_WIRE_BUS2);
DallasTemperature sensors2(&oneWire2);
//--------------------------------------

zusätzlich zum normalen Eingang:

#define ONE_WIRE_BUS 3
// oneWire Bus initialisieren
OneWire oneWire(ONE_WIRE_BUS);
DallasTemperature sensors(&oneWire);

auf diesem zusätzlichen Eingang 2 hängt jetzt also der Aussenfühler DS1820 im parasitären Modus

und wird mit folgender Funktion abgefragt:

//für aussenfühler
sensors2.requestTemperatures();
kuehlschrank=sensors2.getTempCByIndex(0);
aussentemp=sensors2.getTempCByIndex(1);

Bitte nicht mit dem Kühlschrank irritieren lassen, ich hatte mal vor ein paar Jahren das Problem, das genau an Weihnachten das Thermostat meines Kühlschranks den Geist aufgab, diese Funktion hatte dann ein Raspberry übernommen. Mittlerweile ist das Thermostat ausgetauscht worden, aber den DS 1820 für den Kühlschrank habe ich beibehalten, so sehe ich am LCD Display immer die aktuelle Kühlschranktemperatur :slight_smile:

Auf jeden Fall scheint jetzt alles so zu funktionieren wie es sein soll.
In der Dallas Library habe ich noch einen Parameter umgestellt: Wenn ein Sensor defekt oder nicht auslesbar ist, wird nun nicht mehr der Wert -127 sondern 99 für diesen Sensor angegeben. Der Wert -127 wäre bei einer Heizungssteuerung fatal, es würde alles aufgeheizt werden.

Die ID meiner Sensoren lese ich immer mit diesem Sketch aus:

#include <OneWire.h>
 
OneWire ow(3); 
 
void setup(void) 
{
  Serial.begin(9600);
  lookUpSensors();
}
 
void lookUpSensors()
{
  byte address[8];
  int i=0;
  byte ok = 0, tmp = 0;
 
  Serial.println("--Suche gestartet--");
  while (ow.search(address))
  {
    tmp = 0;
    //0x10 = DS18S20
    if (address[0] == 0x10)
    {
      Serial.print("Device is a DS18S20 : ");
      tmp = 1;
    } 
    else
    {
      //0x28 = DS18B20
      if (address[0] == 0x28)
      {
        Serial.print("Device is a DS18B20 : ");
        tmp = 1;
      }
    }
    //display the address, if tmp is ok
    if (tmp == 1)
    {
      if (OneWire::crc8(address, 7) != address[7])
      {
        Serial.println("but it doesn't have a valid CRC!");
      } 
      else
      {
        //all is ok, display it
        for (i=0;i<8;i++)
        {
          if (address[i] < 9)
          {
            Serial.print("0");
          }
          Serial.print("0x");
          Serial.print(address[i],HEX);
          if (i<7)
          {
            Serial.print(", ");
          }
        }
        Serial.println("");
        ok = 1;
      }
    }//end if tmp
  }//end while
  if (ok == 0)
  {
    Serial.println("Keine Sensoren gefunden");
  }
  Serial.println("--Suche beendet--");
}
 
void loop(void) 
{
  //do nothing :)
}