OneWire question


let me say first that I’m not familiar bits & bytes magic ???

Ok here goes. I managed to read the temperature from a DS18S20 temperature sensor.
The temperature is read from the first 2 bytes (LSB and MSB) of the scratch-pad.
To get that i do:

        while (one.ReadByte() == 0) { }

        one.WriteByte(DS18B20.ReadScratchPad); // 0xBE

        data = one.ReadByte(); // LSB 
        data |= (ushort)(one.ReadByte() << 8); // MSB

Now I need to read also the temperature from a DS2438. This sensor has 8 pages, and the temperature is read from page 0 byte 1 (LSB) and byte 2 (MSB). Byte 0 contains the configuration which i don’t need at the moment. In the data-sheet is written that to read from the scratch-pad I need to send 0xBE0x00. How do I do that? just like: ?


Second, after that i need to read byte 1 and byte 2 (skipping byte 0) to get the temperature. Here I’m totally clueless, so if someone can point me in the right direction.

In case you want to look at the data-sheets, they can be found here:
DS18B20: [url][/url]
DS2438: [url][/url]


I don’t have a DS2438 to test on, but you should be able to just do this:

while (one.ReadByte() == 0) { }
        one.ReadByte(); // Read one byte and discard it, otherwise you can store it in a variable
        data = one.ReadByte(); // LSB 
        data |= (ushort)(one.ReadByte() << 8); // MSB

You could also put the 0xBE and 0x00 into an array and use the “Write” method instead.

Ok, got it working though something aint right, and i guess the problem is here:

        data = one.ReadByte(); // LSB 
        data |= (ushort)(one.ReadByte() << 8); // MSB

Byte LSB = 0
Byte MSB = 4
data after the above code = 1024
Datasheet says conversion is 0.03125
So returned temperature = 32°C and the actual temperature is 20.5°C

Anyone got a clue what is wrong?

This is what the pdf says about the scratch pad data …

[italic]Byte 0 and byte 1 of the scratchpad contain the LSB and the MSB of the temperature register,
respectively. These bytes are read-only. Bytes 2 and 3 provide access to TH and TL registers. Byte 4 contains the configuration register data, which is explained in detail in the Configuration Register section.
Bytes 5, 6, and 7 are reserved for internal use by the device and cannot be overwritten.
Byte 8 of the scratchpad is read-only and contains the CRC code for bytes 0 through 7 of the scratchpad.
The DS18B20 generates this CRC using the method described in the CRC Generation section.[/italic]

Are you sure you need to skip that first byte? Where did you see that?


Sorry, I should have mentioned that this is about the DS2438

Could you read that entire memory page and post what each byte is? (you should be able to read 8 bytes for that page).

Actually, now that I went back to the manual and looked at it, it appears that you need to shift the bytes received. The least significant 3 bits are always zero, and don’t appear to be part of the calculation. I took their example of 25.0625C, which converts to 802 (0x322) but by shifting the value left 3 bits you get 6416 (0x1910) which matches the register value they report.

According to the values you reported, something is still not right, since 1024 translates to 4C, and I am pretty sure you aren’t experimenting in a room that is 4C. You should be getting a value in the range of 5248 (0x1480). 5248 and 1024 do happen to share one bit in common (the only bit that 1024 has flipped), but that doesn’t really help and serves more as a random fact.

I assume you are reading the proper values from the DS2438 chip. I too struggled with a proper conversion routine, and the code below is what I came up with. (The potentially confusing aspect is the sign extension through the fractional temperature bits.)

// Determine temp in degrees C
// Temp data is 13 bits, of which
// the MS 8 bits are the signed integer part.
// the LS 8 bits contain the 5-bit signed fractional multiplier part shifted up 3 bits.
public float getTempC (byte lsb, byte msb)
	short t; 	// temperature
	float result;
	// temperature is negative if sign bit set
	bool negative = ((msb & 0x80) == 0) ? false : true;
	// construct complete temp value
	t = (short)((msb << 8) + lsb);
	// if negative, take two's complement to get absolute value
	if (negative)
		t = (short)-t;
	// get integer part if any
	result = (float)(t >> 8);
	// remove zero bits and add fractional part if any
	result += ((t >> 3) & 0x1f) * 0.03125f;
	// return value with correct sign
	return (negative) ? -result : result;

Hope this helps!

Bingo, that worked Mooz, thank you so much.
You can’t imagine how many time I spent trying to get this to work.