Mir ist bereits vieles klarer:
Offenbar gibt es gewaltige Unterschiede zwischen D18S20, D18B20 und DS1820
Nur D18S20 und D18B20 haben 12-bit auflösung, der DS1820 von Conrad aber nur 9-bit
Hab mir das jetzt noch mal auf der Webseite angesehen: tatsächlich steht dort eine auflösung von 0.5 grad drauf. Auch auf den Sensor steht DS1820...
Selbst Schuld.
Das war mein Code:
char buffer[10];
OneWire ds(10);
typedef struct {
byte data1;
byte data2;
byte unknown[4];
byte countRemain;
byte countPerCelsius;
byte unknown2[2];
} scratchpad;
scratchpad *sp;
void setup() {
Serial.begin(57600);
}
float precise = -1;
float lessPrecise = -1;
float readTemp2Ways() {
/* 1st option */
byte i;
byte present = 0;
byte data[9];
byte addr[8];
while ( !ds.search(addr) || OneWire::crc8( addr, 7) != addr[7]) {
ds.reset_search();
}
ds.reset();
ds.select(addr);
ds.write(0x44,1); // start conversion, with parasite power on at the end
delay(1000); // maybe 750ms is enough, maybe not we might do a ds.depower() here, but the reset will take care of it.
ds.reset();
ds.select(addr);
ds.write(0xBE); // Read Scratchpad
for ( i = 0; i < 9; i++) { // we need 9 bytes
data[i] = ds.read();
}
sp = reinterpret_cast<scratchpad*>(data) ;
sp->data1 = sp->data1 >> 1; //drop bit 0
//calculate the temperature based on this formula :
//TEMPERATURE = TEMP READ - 0.25 + (COUNT PER Celsius Degree - COUNT REMAIN)
// (COUNT PER Celsius Degree)
precise = sp->data1 - (float)0.25 + (sp->countRemain - sp->countPerCelsius)/(float) sp->countRemain;
/* second option */
int HighByte, LowByte, TReading, SignBit, Tc_100, Whole, Fract;
char buf[20];
LowByte = data[0];
HighByte = data[1];
TReading = (HighByte << 8) + LowByte;
SignBit = TReading & 0x8000; // test most sig bit
if (SignBit) // negative
{
TReading = (TReading ^ 0xffff) + 1; // 2's comp
}
Tc_100 = (TReading*100/2);
Whole = Tc_100 / 50; // separate off the whole and fractional portions
Fract = Tc_100 % 100;
sprintf(buf, "%c%d.%d degree C ",SignBit ? '-' : '+', Whole, Fract < 10 ? 0 : Fract);
Serial.println(buf);
}
void loop() {
readTemp2Ways();
dtostrf(precise, 2, 5, buffer);
Serial.print("precise ");
Serial.println(buffer);
delay(1000);
}
Die 1. einfache Variante funktioniert "rock solid", die andere springt. Manchmal sind beide Werte "plausibel", aber das ist reiner Zufall.
Wieder was gelernt. Kann man den D18B20 überhaupt vernünftig in AT/DE beziehen? Fand mit kurzem Suchen keinen Shop damit.
In jeden Fall danke für die guten Tips und für das zuhören :-)
lg,
Thomas