Problem reading DS18B20 on FEZ cerberus (MF 4.2)

I connected a DS18B20 to my cerberus board (4K7 pull-up on one wire data line for parasite mode).
I read the device using pin PA1.
The search function find the device but I always read 85 deg C (reset default value).
Can anyone help me with this issue?

Output of the program:

286F5A24000000AF: 85.0 deg C
286F5A24000000AF: 85.0 deg C
286F5A24000000AF: 85.0 deg C
286F5A24000000AF: 85.0 deg C

The source of the program is the following:


using System;
using System.Collections;
using System.Threading;
using Microsoft.SPOT;
using Microsoft.SPOT.Hardware;

namespace DS18B20_Demo
{
    public class Program
    {
        public static void Main()
        {
            OutputPort output = new OutputPort((Cpu.Pin) 1, false);
            OneWire ow = new OneWire(output);
            byte[] address = new byte[8];
            while (true)
            {
                ArrayList devs = ow.FindAllDevices();
                if (devs.Count > 0)
                {
                    // Extract serial of the first device on the bus
                    Array.Copy((byte[])devs[0], address, 8);
                    if (address[0] == 0x28)
                    {
                        // It's a DS18B20
                        float temperature = ReadTemperature(ow, address);
                        // !!!!! Always read 85 deg C.
                        Debug.Print(address[0].ToString("X2") + address[1].ToString("X2") + address[2].ToString("X2") + address[3].ToString("X2") + address[4].ToString("X2") + address[5].ToString("X2") + address[6].ToString("X2") + address[7].ToString("X2") + ": " + temperature.ToString("F1") + " deg C");
                    }
                }
                Thread.Sleep(1000);
            }
        }

        private static class DS18B20Command
        {
            public const byte SearchROM = 0xF0;
            public const byte ReadROM = 0x33;
            public const byte MatchROM = 0x55;
            public const byte SkipROM = 0xCC;
            public const byte AlarmSearch = 0xEC;
            public const byte StartTemperatureConversion = 0x44;
            public const byte ReadScratchPad = 0xBE;
            public const byte WriteScratchPad = 0x4E;
            public const byte CopySratchPad = 0x48;
            public const byte RecallEEPROM = 0xB8;
            public const byte ReadPowerSupply = 0xB4;
        }

        private static void WriteBytes(OneWire ow, byte[] data)
        {
            for (var i = 0; i < data.Length; i++)
                ow.WriteByte(data[i]);
        }

        public static float ReadTemperature(OneWire ow, byte[] address)
        {
            var data = 0L;

            // if reset finds no devices, just return 0
            if (ow.TouchReset() == 0)
                return 0;

            // address the device
            ow.WriteByte(DS18B20Command.SkipROM);
            //WriteBytes(ow, address);

            // tell the device to start temp conversion
            ow.WriteByte(DS18B20Command.StartTemperatureConversion);

            // wait for as long as it takes to do the temp conversion,
            // data sheet says ~750ms
            while (ow.ReadByte() == 0)
                System.Threading.Thread.Sleep(1);

            // reset the bus
            ow.TouchReset();

            // address the device
            ow.WriteByte(DS18B20Command.SkipROM);
            //WriteBytes(ow, address);

            // read the data from the sensor
            ow.WriteByte(DS18B20Command.ReadScratchPad);

            // read the two bytes of data
            data = ow.ReadByte(); // LSB
            data |= (ushort)(ow.ReadByte() << 8); // MSB

            // reset the bus, we don't want more data than that
            ow.TouchReset();

            // returns C
            // F would be:  (float)((1.80 * (data / 16.00)) + 32.00);
            return (float)data / 16f;
        } 
    }
}


Hi

Did you connect pin 1 and pin 3 of the DB18B20 together as required for parasite power?

Also, according to the specification, to use parasite power you need to use a strong pullup during temperature conversion. This requires extra components, and I don’t think that C# can do that.

You can try to use a 1K pullup instead of a 4K7.

Try it without parasitic power. I got it working when I abandoned that feature.

I also have a 800ms wait between requesting temp and reading it. Found it a bit erratic without a delay.

Your code doesn’t sleep for 750msec, it checks the data line and does a heap of sleeps; perhaps check how many times through that loop you go, because I suspect none. I think a week or so ago we determined that if the temperature conversion hasn’t finished then you will read 85deg, so that’s likely your problem

Replace

// wait for as long as it takes to do the temp conversion,
// data sheet says ~750ms
while (ow.ReadByte() == 0)
 System.Threading.Thread.Sleep(1);

with

Thread.Sleep(800)

You do also realise that this is a blocking function, meaning if you add a 2nd or 3rd device to the line, your time to read the temperatures will be almost a second per device. If you find the thread from last week there’s some sample code there from me, that has a different way to do this

Thanks for all your replies! I’ve tried every single solution.
The winner is Brett!
Changing the code as proposed resolve the problem.

Summarizing whole operations (for the future uses of anybody):

  1. connect pin 1 and pin 3 of the DS18B20 to GND (parasite mode)
  2. put a pull-up resistor on the data line (1K or 4.7K on PA1 in the example)
  3. use the proposed code replacing the appropriate part as proposed by Brett
  4. have fun with your Cerberus and the DS18B20

Thanks!