Forum: Digitale Signalverarbeitung / DSP / Machine Learning DS18b20 Falsche negative Temperaturen.


von DAVID B. (bastler-david)


Lesenswert?

Hallo
Ich habe ein Arduino Nano und ein paar DS18B20 daran angeschlossen bei 
positiven Temperaturen stimmen die werte auch so weit.
Aber sobald es Richtung  minus grade geht wirds schlimm.

Ein Beispiel ein Fühler hat -7 Grad und der nano gibt aufen Display -1,3 
Grad aus und der Abstand wird größer je kälter der Sensor wird welche 
auch mit +5 Volt verbunden ist also mit allen drei pins.

Habe schon ein paar andre beispiele versucht ist aber IMMER das selbe 
bei + grad ist alles ok bei - stimmt ab -1 grad nix mehr.
Zuerst dachte ich ein Sensor ist defekt ok getauscht aber nö keine 
Änderung.

}

DeviceAddress sensor1 = { 0x28, 0xFF, 0x86, 0x2E,  0x74, 0x16, 0x3, 0xAF 
};
DeviceAddress sensor2 = { 0x28, 0xFF, 0x5, 0x72, 0x74, 0x16, 0x3, 0xE0 
};
DeviceAddress sensor3 = { 0x28, 0xFF, 0x2B, 0x3F, 0x73, 0x16, 0x5, 0x60 
};
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];

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

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

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

return tr - (float)0.25 + (cpc - cr)/(float)cpc;
}
else // DS18B20
{
return ((data[1] << 8) + tr) * (float)0.0625;
}
}

void loop(void)
{
  char sensor1Name[] = "1: ";
  char sensor2Name[] = "2: ";
  char sensor3Name[] = "3: ";


  float temp1 = getTemperature(sensor1);
  float temp2 = getTemperature(sensor2);
  float temp3 = getTemperature(sensor3);


  Serial.print(sensor1Name);
  Serial.print(temp1);
  Serial.println(" C");
  Serial.print(sensor2Name);
  Serial.print(temp2);
  Serial.println(" C");
  Serial.print(sensor3Name);
  Serial.print(temp3);
  Serial.println(" C");

Größere/kleiner Werte bei return ((data[1] << 8) + tr) * (float)0.0625; 
verändern verändern positive und negative werte wo bei positive ja 
stimmen :- (

Jemand eine idee ?
VIELEN DANK

von A.H. (Gast)


Lesenswert?

Direkt fällt mir nichts auf, aber als Ideen:

1) Das Programm minimalisieren, um Flüchtigkeitsfehler auszuschließen. 
Also z.B. den Zweig bei "if (address[0] == 0x10) // DS18B20" 
eliminieren, da der eigentlich nicht angesprochen werden sollte.

2) CRC des 0xBE Commands prüfen.

3) Die vollständigen Ergebnisse von ein paar 0xBE Commands als HEX 
ausgeben lassen und von Hand nachrechnen und ggfs. hier nochmal posten.

von DAVID B. (bastler-david)


Lesenswert?

hmm Vielen dank habe noch eine weile versuche gemacht und muss sagen:
SCHEINT jetzt zu stimmen ob Woll ich im Endeffekt nix geändert habe ?
naja allerdings habe ich von 12 auf 10 bit runter geschraubt da ich ohne 
hin nur 0,5 grad brauche und eine Kabellänge von um 15-18 meter woll 
seins dazu tut.
Genauers teste ich später noch.

Also den Adress teil muss ich lassen das scheint was mit der Berechnung 
zu tuhen zu haben da noch ein anderer Sensor (AM2302) verbaut ist und 
ausgelesen wird.

Bei CRC kann ich dir leider nicht ganz folgen.
Wie soll ich das prüfen oder besser mit was vergleichen ?

Vielen dank für deine hilfe

von DAVID B. (bastler-david)


Lesenswert?

hmm komisch Temperatur stimmt nach wie vor nicht. Sensor gibt wert von 
-0,95C aus und mit andern Messapparaturen sinds minus 6 grad.

könnte der 78l05 mit je 1µf bei minus graden ohne Grundlast zu schwingen 
anfangen ?

Auf ein widerstand als Grundlast musste ich verzichten weil der 
widerstand die box mit dem Sensor aufheizte.


Mit einen kurzen kabel und andren Sensor ist die Messung richtig es muss 
also Hardware seitig was sein.

Und da habe ich schon auf ein Festspannungsregler und den 10 bit mode 
gesetzt und die wartezeit ist auch noch bei 750ms ob woll nur 200 nötig 
wären.

von Falk B. (falk)


Lesenswert?

@ DAVID ------ (bastler-david)

>könnte der 78l05 mit je 1µf bei minus graden ohne Grundlast zu schwingen
>anfangen ?

Sollte er eigentlich nicht.

>Mit einen kurzen kabel und andren Sensor ist die Messung richtig es muss
>also Hardware seitig was sein.

Dann hast du möglicherweise ein Timingproblem.

Probiers damit.

Beitrag "Re: Onewire + DS18x20 Library"

von (prx) A. K. (prx)


Lesenswert?

DAVID -. schrieb:
> Jemand eine idee ?

Längeren Code bitte mit entsprechenden Tags einrahmen, und vorher TABs 
durch Leerzeichen ersetzen.

von DAVID B. (bastler-david)


Lesenswert?

Wenn ich als text Datei anhänge wird rum gejammert das man es erst 
runterladen muss macht man es so wird auch gejammert ... wie manns macht 
ists falsch.

Eine frage zum Verständnis: wieso brauchen minus grade andere Timings ?

Schöne library haste da geschrieben !
Du hast dazu nicht auch eine kleine Anleitung was was heist ?

von Carl D. (jcw2)


Lesenswert?

Das Problem ist: "negative Werte werden falsch übertragen".
Wenn man mit dieser Prämisse den Code durchschaut, dann findet man eine 
Schräge bahandlung genau dieser Situation.
Der Sensor liefert in jeder Betriebsart eine int16 Zahl, die als Einheit 
1/16 Grad hat.
Da muß nichts von Hand komplementiert werden, besonders wenn man dabei 
nur die unteren 8-Bit behandelt und die oberen 8 vergißt.
Einfach
1
 float Temperatur = ( (data[1]<<8) | data[0] ) / 16.0;
und gut.

von (prx) A. K. (prx)


Lesenswert?

Carl D. schrieb:
> und gut.

Besser:
  float Temperatur = (int16_t)(data[1]<<8 | data[0]) / 16.0;
Falls man mal über 32 Bits stolpert.

: Bearbeitet durch User
von visitor (Gast)


Lesenswert?

Heisst es in deinem Code wirklich:

/c writeTimeToScratchpad(address);

/c readTimeFromScratchpad(address,data);


Ich hötte bei den Funktionen eher etwas mit ...Temp... erwartet. Oder 
nutzt du die Funktionen der OneWire RTC?

von DAVID B. (bastler-david)


Lesenswert?

Super Vielen dank habe es mal mit rein genommen wird fehlerfrei 
übersetzt.
Müsste es aber nicht:
float  getTemperature = (int16_t)(data[1]<<8 | data[0]) / 16.0;
heißen ?

Vielen dank euch 2.

Mit OneWire RTC kann ich so jetzt auf die schnelle nix anfangen ich 
frage/habe vor 12 (18b20) Sensoren und ein Feuchtigkeits Sensor 
abzufragen diese Daten auf 4 Displays anzuzeigen und am Pc zu senden.
Das wars erst mal.

von Carl D. (jcw2)


Lesenswert?

DAVID -. schrieb:
> Super Vielen dank habe es mal mit rein genommen wird fehlerfrei
> übersetzt.
> Müsste es aber nicht:
> float  getTemperature = (int16_t)(data[1]<<8 | data[0]) / 16.0;

Nein, denn du benutzt C und nicht Pascal.
Deine Funktion wird einfach zu:
1
float  getTemperature() {
2
  return (data[1]<<8 | data[0]) / 16.0;
3
}

A.K.:
> Besser:
>  float Temperatur = (int16_t)(data[1]<<8 | data[0]) / 16.0;
> Falls man mal über 32 Bits stolpert.

wobei das "(int16_t)" nur dokumentiert, was der Compiler eh macht: Mit 
"native Integer" zu rechnen. Und das ist dann bei einer 32-Bit Plattform 
immernoch korrekt, aber kompakter als z.B. 16Bit auf ARM mit 
Signextension etc. Wenn schon, dann "int_fast16_t", dann hat man min 
16Bits oder eben mehr, wenn die Architektur damit besser kann.

von (prx) A. K. (prx)


Lesenswert?

Carl D. schrieb:
> Und das ist dann bei einer 32-Bit Plattform immernoch korrekt,

Eben nicht. Der Cast (int16_t) erzwingt die Vorzeichenerweiterung des 
16-Bit Wertes des Sensors. Auf 32-Bit Plattformen sind ints 32 Bits 
breit und daher ist data[1]<<8 immer positiv, ohne Cast damit auch das 
Gesamtergebnis.

> Wenn schon, dann "int_fast16_t"

Es funktioniert nur mit int16_t, d.h. mit einem Datentyp, der genau 16 
Bits gross ist. Ganz konform ist es trotzdem nicht, denn es wird 
Zweierkomplement vorausgesetzt - aber das ist heute nur noch akademisch.

: Bearbeitet durch User
von CC (Gast)


Lesenswert?

DAVID -. schrieb:
> if (data[1] > 0x80)
> {
> tr = !tr + 1; //twos complement adjustment
> tr = tr * -1; //flip value negative.
> }

Dieser Teil kommt mir seltsam vor. Ist vielleicht
1
  tr = ~tr + 1;
gemeint?

von (prx) A. K. (prx)


Lesenswert?

CC schrieb:
> Dieser Teil kommt mir seltsam vor.

Ist schlicht falsch. Spielt aber beim DS18B20 keine Rolle, da dieser 
Codezweig nur beim DS18S20 greift.

: Bearbeitet durch User
von DAVID B. (bastler-david)


Lesenswert?

ok:
> tr = !tr + 1; //twos complement adjustment
> tr = tr * -1; //flip value negative.

Ist raus DANKE

und ist das jetzt so gemeint ?
}

float getTemperature(byte* address)
{
int tr;
byte data[10];
float Temperatur = (int16_t)(data[1]<<8 | data[0]) / 16.0;


Muss ich da beim Sensor auslesen dann:
 float temp1 = getTemperature(sensor1);
Oder
 float temp1 = Temperature(sensor1);
nehmen ? Verstehe den unterschied noch nicht ganz.

von (prx) A. K. (prx)


Lesenswert?

DAVID -. schrieb:
> Verstehe den unterschied noch nicht ganz.

Nicht immer sind Tipps buchstabengetreu zu verstehen. Soweit keine 
anderen Erkenntnisse vorliegen werden in Threads oft Grundkenntnisse in 
C als gegeben vorausgesetzt. Da das hier offenbar nicht so ganz der Fall 
ist, wäre ein Blick in ein C Handbuch empfohlen.

von Pete K. (pete77)


Lesenswert?

Kann es sein, dass Du den Sensor zu oft ansprichst und sich der Sensor 
dadurch erwärmt? Versuche mal, den Sensor nur jede Minute auszulesen.

Stimmen die delay(1000)? Es sollten delay(750) ausreichen.

Hast Du die F_CPU Anweisung im Makefile oder im C-File stehen?

von DAVID B. (bastler-david)


Lesenswert?

Die Sensoren sollen wenn ich mit testen durch bin alle 30 sek abgefragt 
werden.
Aber das sich der Sensor bei -7 grad selber um fast 6 grad aufheizt 
halte ich für unwahrscheinlich aber denkbar.
Eher würde sich der 78l05 auf heizen der muss aus 11 volt die 5 volt und 
bis zu 2 milliampere halten :-)
Den CPU Speed habe ich nicht angegeben gehe einfach mal davon aus das 
die arduino IDE das vom nano richtig erkennt bis jetzt gabs auch keine 
Probleme damit.

von (prx) A. K. (prx)


Lesenswert?

DAVID -. schrieb:
> Aber das sich der Sensor bei -7 grad selber um fast 6 grad aufheizt
> halte ich für unwahrscheinlich aber denkbar.

Alle 30 Sekunden zu messen schadet nicht.

von Pete K. (pete77)


Lesenswert?

Wie hast Du die Referenz gemessen? Auch genau an dem DS1820 Sensor?
Ja, ein Linearregler kann schon reichen, um in direkter Nähe die Messung 
zu verfälschen. Da sind die DS Sensoren sehr sensibel.

von DAVID B. (bastler-david)


Lesenswert?

So habe die ändern übernommen und muss sagen nix :-(
dachte ich mir kann ja nicht sein.
dann habe ich dem 78l05 den strom abgezogen ein tag gewartet und sehe da 
es kommen auch minus grade vom Sensor ?
dann reicht also tatsächlich ein kleiner 78l05 der aus 12 Volt 5 Volt 
für den Sensor macht die Temperatur so hoch zu treiben in dem 5x5 cm 
plastikkasten an der Außenseite einer außen mauer.

Würde es reichen den Sensor mit Heißkleber Wasser dicht zu bekommen ?
oder sollte ich langfristig was anderes nehmen ?
er wäre dann den Naturgewalten schutzlos ausgeliefert :-(

auf dem 78l05 würde ich nicht verzichten wollen da ich mir nicht sicher 
bin wegen Spannungsspitzen da das kabel für den Sensor damals neben ein 
Erdkabel für Steckdosen im garten gelegt wurde. es hat war eine 
Abschirmung aber so ganz tauen tute ich der Geschichte nicht.

von Pete K. (pete77)


Lesenswert?

Mein Sensor hängt unter dem Carport. Das ist zwar etwas geschützt und 
vielleicht 1°C zu hoch im Vergleich zur Umgebung außerhalb des Carports. 
Aber ich bin damit zufrieden. Funktioniert seit 3 Jahren.

Wenn die 1,50m entfernte Tür zum Haus aufmache, kann man das in der 
Temperaturkurve auch sehen. Einfaches Durchgehen reicht für eine 
Änderung am DS1820.

Kannst Du vielleicht ein 5V Netzteil nehmen oder einen Schaltregler?

: Bearbeitet durch User
von (prx) A. K. (prx)


Lesenswert?

Einfacher wäre wohl parasitäre Versorgung. 2 Leitungen, sonst nix.

von (prx) A. K. (prx)


Lesenswert?

DAVID -. schrieb:
> Würde es reichen den Sensor mit Heißkleber Wasser dicht zu bekommen ?

Es gibt die auch fertig vergossen:
http://www.komputer.de/zen/index.php?main_page=product_info&products_id=202&zenid=4tnjnrgckt1n7he26tpthtlno6

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.