4.2, OneWire and DS18B20

Has anyone succesfully gotten the perrennial temperature sensor to work with the new 4.2 onewire implementation? I’ve read conflcting stories on who donated it, whether it was the medical device maker or just maxim’s open source bebegin with. Mixed-signal and digital signal processing ICs | Analog Devices

Either way I’m not finding any success in translating previous codeshare contributions to work for this thing.

I’m perplexed as to why ‘ReadByte’ would return an int - and not a byte. What is the nature of TouchReset and its return type. It may just be the DB18B20 I have is fried - or just not getting enough power in the parasitic mode. MSDN isn’t too helpful.

Any help would be appreciated. I just want to read the temp off a single sensor and get back to the rest of my build.

(The gadgeteer ghi temp sensor won’t do it, as I need to have it in liquid about 90’C and would prefer to have a user swappable system.)

Just for you, I updated my DS18B20 driver and posted it on CodeShare: http://www.tinyclr.com/codeshare/entry/438

I only tested it with one sensor, but I have no reason to believe it wouldn’t work with multiple sensors sharing a bus.

How is that for ultimate community support :wink: Thanks godefroi!

godefroi to the rescue, thanks :slight_smile:

If I see something I can help with, I have to jump on it ASAP, because most times it’s over my head :slight_smile:

Very cool.
I’ll try it out tonight and let you know how it goes.

Much appreciated.

It worked like a charm. Took a week to test it (desktop’s video card died on me).

Fantastic thank you so much!

I’m trying to get one of these going using godefroi’s driver and I can only seem to get “No DS18B20 devices found on OneWire bus” errors. So, I assume I have something setup wrong. This is my first attempt at OneWire. I have the sensor attached to an extender (actually a MakeBread) connected to a Cerberus with the latest 4.2 SDK with…

  • gnd to gnd
  • power to +5V
  • signal to socket pin #4
  • 4.7K pullup resistor between pin #4 and +5V

I’m using godefroi’s DS18B20.cs & OneWireBus.cs with this as my test code.

using Microsoft.SPOT;
using ThreelnDotOrg.NETMF.Hardware;
using GT = Gadgeteer;

namespace DS18B20_Thermometer_Test
{
    public partial class Program
    {
        private DS18B20 thermometer;

        // This method is run when the mainboard is powered up or reset.   
        void ProgramStarted()
        {
           Debug.Print("Program Started");

           GT.Socket thermoSocket = GT.Socket.GetSocket(thermoExtender.ExtenderSocketNumber, true, thermoExtender, null);
           thermometer = new DS18B20(thermoSocket.CpuPins[4]);

           var thermoTimer = new GT.Timer(1000);
           thermoTimer.Tick += timer => Debug.Print(thermometer.ReadTemperature().ToString());
           thermoTimer.Start();
        }
    }
}

Any ideas why this isn’t working?

Is it possible you have a DS18S20 instead of a DS18B20? They’re similar, but they have a different family number.

If you do OneWireBus.Scan(), is anything returned?

If you do OneWire.FindAllDevices(), is anything returned? If not, you’re probably looking at a wiring error.

[quote=“godefroi”]
Is it possible you have a DS18S20 instead of a DS18B20? They’re similar, but they have a different family number.[/quote]
I have this…
http://www.amazon.com/dp/B007R9UU5C/ref=pe_175190_21431760_M2T1_ST1_dp_3
It says it’s a B20.

Nope. That’s the line that fails in the driver.

Nothing is returned. Unfortunately, since the sensor is sealed in the cable, I can’t really test it at the sensor. Does anything sound wrong with my setup from the previous post?

No, your wiring as described is correct. Do you have another micro (USBizi based, perhaps) that you can test with? Maybe something in the 4.1 line that uses GHI’s OneWire driver?

I would guess that either your micro is doing something odd (I assume you’re using the latest firmware, I tested with a Cerb40), or the sensor doesn’t work. Maybe the wiring in the sensor is incorrect (wrong colors)?

I’ll try on a Panda this weekend. Maybe it is a 4.2 problem but you aren’t having any problems. So, I have my doubts. I may order some of the DS18B20 parts also to test without the possibility of there being something wrong in the cable. Any ideas on how to test if they perhaps crossed the red & white wires. Maybe I can just pull the end cap off the cable if they used silicone instead of a hard glue. I’ll be out of town until Sunday. I’ll play with it some more then.

I don’t know… I don’t think you’d hurt anything by swapping wires around, but I can’t be sure. I’d definitely try a standard DS18B20 first, because they’re cheap, so if you let the smoke out, your losses are small :wink:

I never got parasitic power to work. I just used 3 wires off the Cerbuino and it was fine.

I’ve never even attempted parasitic power. Maybe I’ll get around to that someday.

(from memory) Parasitic power needs special code since you need to hold the signal on the data line high for a timed interval rather than testing if the conversion is done… I never bothered to get it working either.

I finally got some new DS18B20 parts to test. FindAllDevices() now finds something but it doesn’t seem to pass the test as being in the DS18B20 family. The data that is returned for the one item is pictured. I bought these off eBay. Does that data tell you anything meaningful? If I choose the “Unknown” family then the code runs but ReadTemperature() always returns 85. Perhaps they sent me IQ sensors instead? :wink:

ianlee74,

here’s my multisensor class running on my Cobra, hope it helps:


using System;
using System.Threading;
using System.Collections;

using Microsoft.SPOT;
using Microsoft.SPOT.Hardware;

using GHIElectronics.NETMF.FEZ;
using GHIElectronics.NETMF.Hardware;
using CobraController.Objects;

namespace CobraController
{

	class OWSensors
	{
		#region Enums

		const string DS18S20 = "DS18S20";
		const string DS18B20 = "DS18B20";
		const string DS1822 = "DS1822";
		const string DS2438 = "DS2438";

		const string Temp = "Temp";
		const string Light = "Light";
		const string Hum = "Hum";

		enum Model
		{
			DS18S20 = 0x10,
			DS18B20 = 0x28,
			DS1822 = 0x22,
			DS2438 = 0x26
		}

		enum Command
		{
			SearchROM = 0xF0,
			ReadROM = 0x33,
			MatchROM = 0x55,
			SkipROM = 0xCC,
			AlarmSearch = 0xEC,
			StartTemperatureConversion = 0x44,
			StartVoltageConversion = 0xB4,
			ReadScratchPad = 0xBE,
			WriteScratchPad = 0x4E,
			CopySratchPad = 0x48,
			RecallEEPROM = 0xB8,
			ReadPowerSupply = 0xB4,
			ScratchPadPage0 = 0x00,
			ScratchPadPage3 = 0x03
		}

		enum ScratchPadDS2438
		{
			CONFIGURATION = 0,
			TEMP_LSB = 1,
			TEMP_MSB = 2,
			VOLTAGE_LSB = 3,
			VOLTAGE_MSB = 4,
			CURRENT_LSB = 5,
			CURRENT_MSB = 6,
			THRESHOLD = 7,
			SCRATCHPAD_CRC = 8
		}

		enum SPDS2438
		{
			CONFIGURATION,
			TEMP_LSB,
			TEMP_MSB,
			VOLTAGE_LSB,
			VOLTAGE_MSB,
			CURRENT_LSB,
			CURRENT_MSB,
			THRESHOLD,
			SCRATCHPAD_CRC
		}

		#endregion

		static OneWire ow;
		static double temptemp;

		public OWSensors(FEZ_Pin.Digital pin)
		{
			ow = new OneWire((Cpu.Pin)pin);
		}

		public void GetSensorValues()
		{
			lock (SensorCollection.GetInstance)
			{
				SensorCollection.GetInstance.Collection.Clear();

				int OW_number = 0;
				byte[] OW_address = new byte[8];
				string SensAddress;
				string NewSensAddress;
				string SensModel;
				string SensType;

				if (ow.Reset())
				{
					while (ow.Search_GetNextDevice(OW_address))
					{
						OW_number++;

						SensAddress = GetSensorAddress(OW_address);
						SensModel = GetSensorModel(OW_address);
						SensType = GetSensorType(OW_address);

						if (SensModel == DS2438)
						{
							SensorData sd = new SensorData();
							NewSensAddress = SensAddress + ":T";
							sd.sensorAddress = SensAddress + ":T";
							sd.sensorModel = SensModel;
							sd.sensorType = Temp;
							sd.sensorValue = GetTemperatureC(OW_address);
							temptemp = sd.sensorValue;
							SensorCollection.GetInstance.Collection.Add(sd);

							if (MultiSensor(OW_address))
							{
								sd = new SensorData();
								sd.sensorModel = SensModel;
								sd.sensorType = SensType;
								if (sd.sensorType == Hum) sd.sensorValue = GetHumidity(OW_address, temptemp);
								if (sd.sensorType == Light) sd.sensorValue = GetLightLevel(OW_address);
								//NewSensAddress = SensAddress;
								if (sd.sensorType == Hum)
								{
									NewSensAddress = SensAddress + ":H";
									sd.sensorAddress = SensAddress + ":H";
								}
								if (sd.sensorType == Light)
								{
									NewSensAddress = SensAddress + ":L";
									sd.sensorAddress = SensAddress + ":L";
								}
								SensorCollection.GetInstance.Collection.Add(sd);
							}
						}
						else
						{
							SensorData sd = new SensorData();
							NewSensAddress = SensAddress + ":T";
							sd.sensorAddress = SensAddress + ":T";
							sd.sensorModel = SensModel;
							sd.sensorType = Temp;
							sd.sensorValue = GetTemperatureC(OW_address);
							SensorCollection.GetInstance.Collection.Add(sd);
						}
						//Debug.Print("Model:" + SensModel + " Type:" + SensType + " Address:" + NewSensAddress );
					}
				}
				//Debug.Print("Sensors found: " + SensorCollection.GetInstance.Collection.Count);
			}
		}

		private string GetSensorAddress(byte[] ow_address)
		{
			int i;
			string address = string.Empty;
			for (i = 0; i < 8; i++)
			{
				address += Helpers.FromByteToHex(ow_address[i]);
				if (i < 7)
				{
					address += ":";
				}
			}
			return address;
		}

		private string GetSensorModel(byte[] ow_address)
		{
			switch ((ow_address[0]))
			{
				case (byte)Model.DS18B20:
					return DS18B20;
				case (byte)Model.DS2438:
					return DS2438;
				case (byte)Model.DS18S20:
					return DS18S20;
				case (byte)Model.DS1822:
					return DS1822;
				default:
					return "unknown";
			}
		}

		private bool MultiSensor(byte[] ow_address)
		{
			byte[] model = new byte[1];
			ow.Reset();
			ow.WriteByte((byte)Command.MatchROM);
			ow.Write(ow_address, 0, ow_address.Length);
			ow.WriteByte((byte)Command.ReadScratchPad);
			ow.WriteByte((byte)Command.ScratchPadPage3);
			ow.Read(model, 0, 1);
			return model[0] > 0 ? true : false;
		}

		private string GetSensorType(byte[] ow_address)
		{
			byte[] model = new byte[1];
			ow.Reset();
			ow.WriteByte((byte)Command.MatchROM);
			ow.Write(ow_address, 0, ow_address.Length);
			ow.WriteByte((byte)Command.ReadScratchPad);
			ow.WriteByte((byte)Command.ScratchPadPage3);
			ow.Read(model, 0, 1);

			switch (model[0])
			{
				case 25:
					return Hum;
				case 27:
					return Light;
				default:
					return "na";
			}
		}

		private float GetTemperatureC(byte[] ow_address)
		{
			float TemperatureC = 0;
			byte[] scratchpad = new byte[9];
			ushort tempLow = 0;
			ushort tempHigh = 0;
			byte countremain = 0;
			byte countc = 0;
			ushort temp = 0x0;
			float result = 0f;
			bool negative = false;
			int temptemp;
			short t = 0;

			switch (ow_address[0])
			{
				case (byte)Model.DS18S20:
					ow.Reset();
					ow.WriteByte((byte)Command.MatchROM);
					ow.Write(ow_address, 0, ow_address.Length);
					ow.WriteByte((byte)Command.StartTemperatureConversion);
					while (ow.ReadByte() == 0) { }
					ow.Reset();
					ow.WriteByte((byte)Command.MatchROM);
					ow.Write(ow_address, 0, ow_address.Length);
					ow.WriteByte((byte)Command.ReadScratchPad);
					ow.Read(scratchpad, 0, 9);
					tempLow = scratchpad[0];
					tempHigh = scratchpad[1];
					countremain = scratchpad[6];
					countc = scratchpad[7];
					Int16 rawTemperature = (Int16)((tempHigh << 8) | tempLow);
					TemperatureC = (float)(rawTemperature >> 1) - 0.25f + ((float)(countc - countremain) / (float)countc);
					break;
				case (byte)Model.DS18B20:
					ow.Reset();
					ow.WriteByte((byte)Command.MatchROM);
					ow.Write(ow_address, 0, ow_address.Length);
					ow.WriteByte((byte)Command.StartTemperatureConversion);
					while (ow.ReadByte() == 0) { }
					ow.Reset();
					ow.WriteByte((byte)Command.MatchROM);
					ow.Write(ow_address, 0, ow_address.Length);
					ow.WriteByte((byte)Command.ReadScratchPad);
					ow.Read(scratchpad, 0, 9);
					tempLow = scratchpad[0];
					tempHigh = scratchpad[1];
					byte config = scratchpad[4];
					bool crc = OneWire.CalculateCRC(scratchpad, 0, 8) == scratchpad[8];
					temp = tempLow;
					temp |= (ushort)(tempHigh << 8);
					temptemp = (((int)(tempHigh) << 8) | tempLow);
					TemperatureC = temptemp * 0.0625f;
					break;
				case (byte)Model.DS2438:
					ow.Reset();
					ow.WriteByte((byte)Command.MatchROM);
					ow.Write(ow_address, 0, ow_address.Length);
					ow.WriteByte((byte)Command.StartTemperatureConversion);
					while (ow.ReadByte() == 0) { }
					ow.Reset();
					ow.WriteByte((byte)Command.MatchROM);
					ow.Write(ow_address, 0, ow_address.Length);
					ow.WriteByte((byte)Command.RecallEEPROM);
					ow.WriteByte((byte)Command.ScratchPadPage0);
					ow.Reset();
					ow.WriteByte((byte)Command.MatchROM);
					ow.Write(ow_address, 0, ow_address.Length);
					ow.WriteByte((byte)Command.ReadScratchPad);
					ow.WriteByte((byte)Command.ScratchPadPage0);
					ow.Read(scratchpad, 0, 9);
					tempLow = scratchpad[1];
					tempHigh = scratchpad[2];


					// temperature is negative if sign bit set
					negative = ((tempHigh & 0x80) == 0) ? false : true;

					// construct complete temp value
					t = (short)((tempHigh << 8) + tempLow);

					// 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
					TemperatureC = (negative) ? -result : result;


					break;
				default:
					break;
			}
			return TemperatureC;
		}

		private float GetHumidity(byte[] ow_address, double temp)
		{
			byte[] scratchpad = new byte[9];
			ow.Reset();
			ow.WriteByte((byte)Command.MatchROM);
			ow.Write(ow_address, 0, ow_address.Length);
			ow.WriteByte((byte)Command.WriteScratchPad);
			ow.WriteByte((byte)Command.ScratchPadPage0);
			ow.WriteByte((byte)0x0);
			//while (ow.ReadByte() == 0) { }
			Thread.Sleep(10);

			ow.Reset();
			ow.WriteByte((byte)Command.MatchROM);
			ow.Write(ow_address, 0, ow_address.Length);
			ow.WriteByte((byte)Command.StartTemperatureConversion);
			while (ow.ReadByte() == 0) { }

			ow.Reset();
			ow.WriteByte((byte)Command.MatchROM);
			ow.Write(ow_address, 0, ow_address.Length);
			ow.WriteByte((byte)Command.StartVoltageConversion);
			//Thread.Sleep(10);
			while (ow.ReadByte() == 0) { }

			ow.Reset();
			ow.WriteByte((byte)Command.MatchROM);
			ow.Write(ow_address, 0, ow_address.Length);
			ow.WriteByte((byte)Command.ReadScratchPad);
			ow.WriteByte((byte)Command.ScratchPadPage0);
			ow.Read(scratchpad, 0, 9);

			short t;
			float result;

			t = (short)((scratchpad[4] << 8) | scratchpad[3]);

			result = (float)(((t * 0.01f) - 0.958) / 0.0307f);
			result = (float)result / (1.0546f - (0.00216f * (float)temp));
			return result;
		}

		private float GetLightLevel(byte[] ow_address)
		{
			byte[] scratchpad = new byte[9];

			ow.Reset();
			ow.WriteByte((byte)Command.MatchROM);
			ow.Write(ow_address, 0, ow_address.Length);
			ow.WriteByte((byte)Command.WriteScratchPad);
			ow.WriteByte((byte)Command.ScratchPadPage0);
			ow.WriteByte((byte)0x0);
			//while (ow.ReadByte() == 0) { }
			Thread.Sleep(10);

			ow.Reset();
			ow.WriteByte((byte)Command.MatchROM);
			ow.Write(ow_address, 0, ow_address.Length);
			ow.WriteByte((byte)Command.StartVoltageConversion);
			//Thread.Sleep(10);
			while (ow.ReadByte() == 0) { }

			ow.Reset();
			ow.WriteByte((byte)Command.MatchROM);
			ow.Write(ow_address, 0, ow_address.Length);
			ow.WriteByte((byte)Command.ReadScratchPad);
			ow.WriteByte((byte)Command.ScratchPadPage0);
			ow.Read(scratchpad, 0, 9);

			short t;
			float result;

			t = (short)((scratchpad[4] << 8) | scratchpad[3]);

			result = (float)((t / 100f) / 5.0f) * 100.0f;
			return result;
		}

	}
}


@ EriSan500 - Thanks. It looks like the forum inserted some cool.gif tags. What are those supposed to be?

hehe, lol, more work for Josh :slight_smile:

Replace “<img src=”/img/forum/smilies/cool.gif"" with “8 )”