Hi,
has anyone else got any experience with DS18B20’s or other one-wire devices?
Here’s what I have.
Fez Domino. Di1 connected to DS18B20 data pin on breadboard. Pullup resistor on breadboard from data pin to +3v3 (or +5v, doesn’t matter). +3v3 and GND connected back to Fez relevant headers.
Pseudocode:
OW.reset;
iterate devices into array with OW.search_getnextdevice; debug.print shows correct ID for all.
ow.reset;
ow.write(0x55) to match device ID
ow.write actual device ID
ow.write 0, 0
ow.write 0x7f (register value for 12-bit resolution)
ow.reset
ow.write(0x55) to match device ID
ow.write actual device ID
ow.write 0x44 (convert temp)
Wait_750msec
ow.reset
ow.write 0x55 to match
ow.write actual device ID
ow.write 0xbe (read scratchpad)
2x ow.readbyte and then manipulate for correct temperature.
sleep 10sec and repeat again.
When i have one device connected, my code works as expected. Temperatures read as per ambient temp, put finger on chip and temp goes up, take it off and it goes down.
When I connect two devices though, I get weirdness.
One device will read temperature as expected. A second device will only read 85 deg C, which basically means the conversion did not work. It seems to be related to code, since when i disconnect the “working” DS18B20 from the breadboard, the one showing 85 now reads ambient correctly; plug the other one back in and it reads temperature correct but the other one will now stay on it’s last scratchpad reading until you reset the Fez or the OW network (pull power from it) and then it’ll read 85.
thanks Chris for your code - didn’t actually help though since your code uses SkipROM code 0xCC which according to the datasheet apparently only works with a single slave device on the bus.
I tracked it down - not enough Reset()s. I had missed a reset in the loop to initiate the temperature conversion, so I was writing to the first slave ok, then the subsequent ones were failing since they weren’t waiting for the command.
I’m in the works of making a 1-wire station device. Here is code I wrote to record temperature from a DS18B20 until disconnected. Haven’t tried it yet as I’m working on Thermochron stuff. Let me know if you try it and how it works.
ushort temperature;
byte[] romid = new byte[8];
// read every second
while (ow.Reset())
{
ow.WriteByte(0x33);
ow.Read(romid, 0, 8);
ow.WriteByte(0x44); // Start temperature conversion
while (ow.ReadByte() == 0) ; // wait while busy
ow.Reset();
ow.WriteByte(0xCC); // skip ROM
ow.WriteByte(0xBE); // Read Scratchpad
temperature = ow.ReadByte(); // LSB
temperature |= (ushort)(ow.ReadByte() << 8); // MSB
Debug.Print("Temperature: " + temperature / 16);
string romstr = new string(ToHexString(romid));
string filename = "\\" + romstr + ".CSV";
string dtastr = "";
// SD Card is inserted
// Create a new storage device
PersistentStorage sdPS = new PersistentStorage("SD");
// Mount the file system
sdPS.MountFileSystem();
// Assume one storage device is available, access it through NETMF
string rootDirectory = VolumeInfo.GetVolumes()[0].RootDirectory;
FileStream FileHandle = new FileStream(rootDirectory + @ filename, FileMode.Append);
// write the data and close the file
dtastr = temperature + "," + DateTime.Now.ToString();
byte[] data = Encoding.UTF8.GetBytes(dtastr);
try
{
FileHandle.Write(data, 0, data.Length);
}
catch (Exception)
{
throw;
}
FileHandle.Close();
sdPS.UnmountFileSystem();
sdPS.Dispose();
Thread.Sleep(1000);
}
So if I can figure that out, how then is it meant to be used? I read a sequence of 9 bytes into an array, that is the 9 bytes returned from a DS18B20. Byte 9 is the CRC. What should I be passing to CalculateCRC?
Your algorithm is much the same as Chris’ and the GHI example, in that it’ll work fine for a single device on the bus (the SkipROM 0xCC being the key).
I’ll post my code eventually, but it’s still in a state of flux - until then I wouldn’t see yours as having any issue, it just wouldn’t be able to read and report temps from two devices.
I raised the issue of the CalcCRC where it only produces an 8-bit instead of a 16-bit CRC. Chimp said that they will implement that I believe in a response.
We already have 8-bit CRC calculation which is what brett needs, correct? The 16-bit will be added in future but this is not a high priority. CRC16 can still be done in C#
probably 8-bit is all I need. But it looks like my “issue” is more general in nature.
This project may have been started in VC# 2008 with an earlier version of the firmware and GHI NETMF SDK. Right now though, it’s running fine with 4.0.3.0 showing in all versions of the GHI assemblies listed in the right-hand pane.
In my code I have:
OneWire ow = new OneWire((Microsoft.SPOT.Hardware.Cpu.Pin)FEZ_Pin.Digital.Di1);
Intellisense doesn’t list the CRC method at all. Typing ow.r shows the read/readbit/readbyte/reset, but the extent of what i have listed is:
dispose
read
readbit
readbyte
reset
search_getnextdevice
search_isdevicepresent
search_restart
write
writebit
writebyte
(plus things like gettype that are not specific to the onewire class)
Any thoughts on what is not in sync, or what I’m doing wrong?
Here is what I needed to add to the project I’m working:
using System;
using System.Text;
using System.Threading;
using Microsoft.SPOT;
using Microsoft.SPOT.Hardware;
using GHIElectronics.NETMF.Hardware;
using GHIElectronics.NETMF.FEZ;
using System.IO;
using Microsoft.SPOT.IO;
using GHIElectronics.NETMF.IO;
using GHIElectronics.NETMF.System;
I did have an issue recently when I upgraded where I needed to ensure the VC Studio was using the correct version of GHI references. Here’s the post about that fix: http://www.tinyclr.com/forum/2/269/
Mmmm, now to figure out what parameters to be passing for the 8-byte array that I’ve read out (plus a ninth byte, the CRC). I am assuming I need to pass all 8 bytes, and if it doesn’t match the 9th then I have a problem…
Keep in mind that you can read the accumulator to get higher accuracy. You can refer to my page at the Arduino playground for more info (see .5 degree resolution section toward bottom)