Notes About Working with Various Arduino & Netduino Microcontroller Boards

Monday, January 21, 2013

Multiple OneWire (1-Wire) Devices with a Netduino Plus 2

Previously, I posted a quick example of using the Netduino Plus 2's 1-Wire support with a single device. Here is an example with multiple devices (DS18B20 temperature sensors). You can find the DS18B20 datasheet here.

This example assumes that you have Netduino firmware version 4.2. As in the one device example, I have use I used godfroi's  OneWireBus and DS18B20 classes (posted at TinyCLR). Just add the code for these classes to your project. Be sure to add the reference to Microsoft.SPOT.Hardware.OneWire in your project's references section.

Important note: I have gotten multiple 1-Wire devices to work with the Netduino in normal or "non-parasitic" power mode. This means that each device has its own connection to ground and voltage. The data line is shared among the devices, so only one pin is needed for data on the Netduino.  When I have tried parasitic power mode, all sensors report the same invalid temperature. For more information on 1-wire power modes, see the OneWire page at the Arduino Playground.

Note (March 29, 2013): When working with temperatures below freezing, see this post.

Connections:

1. Looking at the flat side of the sensor, the left pin is connected to GND.
2. The right pin on the sensor is connected to 5V.
3. The center (data) pin of each connects to the center pin of the previous sensor.
4. There is a pull-up resistor (4k7) at the head of the data line where it connects to the Netduino (to pin D0). 

This code queries the 1-wire bus to get a list of devices and then cycles through the devices to get the temperature and convert it to Fahrenheit. The results are printed to the debug console in Visual Studio.

Code:

using ThreelnDotOrg.NETMF.Hardware;
using Microsoft.SPOT.Hardware;
using Microsoft.SPOT;
using System.Threading;
using SecretLabs.NETMF.Hardware.Netduino;
using System;


namespace OneWireMultDev
{
    public class Program
    {
        private static OneWireBus.Device[] devs;

        public static void Main()
        {
            // Data line connected to D0 - but couldn be any digital pin
            OutputPort pin = new OutputPort(Pins.GPIO_PIN_D0, false);
            OneWire bus = new OneWire(pin);
            // Get list of devices (just in DS18B20 family)
            devs = OneWireBus.Scan(bus, OneWireBus.Family.DS18B20);
            // Create array to hold DS18B20 references
            DS18B20[] ds = new DS18B20[devs.Length];
            // Instantiate DS18B20 objects
            for (int i = 0; i < devs.Length; i++)
            {
                ds[i] = new DS18B20(bus, devs[i]);
            }
            while (true)
            {
                for (int i = 0; i < devs.Length; i++)
                {
                    float temp = ds[i].ConvertAndReadTemperature();
                    temp = temp / 5 * 9 + 32;
                    Debug.Print(i.ToString() + ": " + temp.ToString());
                }
                Thread.Sleep(1000);
                Debug.Print(" ");
            } 
        }
    }


Note (March 29, 2013): When working with temperatures below freezing, see this post.

17 comments:

  1. excellent program, a query need to measure negative temperatures when going below zero indicates 4093,, 4091, you can help me, thank you very much.

    Marcelo Panizzi

    ingmp143@gmail.com

    ReplyDelete
    Replies
    1. Hi Marcelo -

      Thanks for posting. It looks like the issue has to do with Godfroi's DS18B20 class. The DS18B20 sensor returns negative values as 2s compliments (pp 3 - 4 of the datasheet), but the temperature conversion in the DS18B20 class doesn't take this into account. I'll see if I can work out how to do this.

      Delete
    2. Oops - so much for spelling! I meant "2s complement"

      Delete
  2. Brad
    thanks for your quick response, I was reading the data sheet, I see that the sign is given one of the bit 11 to bit 15, I hope you can make changes in Godfroi's OneWireBus and DS18B20
    pd:I understand you two perfect complement two ajajjaja!!!
    thanks Marcelo

    ReplyDelete
    Replies
    1. Hi Marcelo -

      I've got a modification to the ConvertAndReadTemperature() method in the DS18B20 class that does the trick. The first couple lines are comments in the original code so you can find the location where I've made the changes.

      // returns C
      // F would be: (float)((1.80 * (data / 16.00)) + 32.00);
      //return (float)data / 16f;
      if (data < 2048)
      {
      // Positive temp.
      return (float)data / 16f;
      }
      else
      {
      // Negative temp.
      return (float)(-(~(data-1) & 4095) / 16f);
      }

      Delete
  3. Brad
    this modification works perfect!,
    I'm still working with my temperature measurement project, I have to resolve other issues,
    1) the sensors are 15 meters between them, and 30 meters from the netduino plus 2
    2) upload the data to cosm

    thanks you

    ReplyDelete
  4. Awesome snippet and implementation! Thank you. Do you know how I can get the unique ID of each sensor. I want to database them along with the temperatures and don't want to have to worry about what sensor goes where when running in parallel. Thank you again!

    ReplyDelete
    Replies
    1. Hi Anthony -

      Try inserting this code before the line that prints out the temperature. It converts each byte of the device's address to hex digits and concatenates them -

      String addr = "";
      foreach (Byte a in devs[i].Address)
      {
      addr += a.ToString("X");
      }
      Debug.Print(addr);

      Delete
    2. Worked Perfectly! I did add the below property to the DS18B20 class so I can call it easily. Thanks again!

      public string GetSerial()
      {
      String addr = "";
      foreach (Byte a in m_dev.Address)
      {
      addr += a.ToString("X");
      }

      return addr;
      }

      Delete
  5. I ran into an issue and could not find any other place to post the resolution. It appears that the code created by godfroi has a datatype issue; it casts the value to ushort which does not accept negative values. You only see the issue when you go below 32 deg F or 0 deg C, I had a sensor in the mine in the freezer. It will start to register in the 7k range. It is easily fixed by changing the cast to short instead. Hope this helps anyone else who runs into the same issue. Thanks!

    ReplyDelete
    Replies
    1. Hi Anthony -

      Thanks for passing this along. I was aware of the problem with temps below freezing and had published a correction to Godfroi's code in a comment and in a post on March 29th that worked for me and another person. Changing the cast may make things even simpler...I'll check into it. Thanks again.

      Delete
  6. Have you seen any issues with these sensors simply disappearing? I've got 8 of them, 1 data wire and "normal" power (not parasitic). They work for a while, then without warning the bus is simply empty. I haven't found anything predictable to get them to start responding again.

    ReplyDelete
    Replies
    1. Hi Brian -

      No, I didn't run into that issue when using multiple sensors, but I have to say that I haven't been running this setup with a Netduino 2 for a while. My Netduino 2 developed (or more likely, I caused) some sort of electrical issues a few months back and it hasn't worked since. I plan on getting a Netduino 3 when the Ethernet version comes out, but I haven't replaced my Netduino 2 at this point.

      --Brad

      Delete
    2. ok, thanks. i was very happy to find this article when i started trying to figure out how to do this with the netduino :) when they work, it's great. at first i thought i'd built one of the cables wrong (they're 2 per cable, with the cables joined at the 'duino end)... but i tore apart that junction and tested each one separately, and they were fine. joined them back together, and it worked again. then moved the whole assembly from my workbench back to my coding chair... and it quit again. i'm thinking there must be something positional involved, but i'm at a complete loss. ah well, will try taking them apart again.

      brian

      Delete
    3. seems that at least in my case, the scan function doesn't always return everything that's actually there. if i call it repeatedly i'll get a wide range of values - often finding 0, 1, or 2 devices, sometimes finding all 8. Once it finds them, it seems that they're there consistently after that, so at the moment i'm retrying the scan until it succeeds.

      Delete
  7. Hello,
    I got two of the sensors working in PAR mode. Trick, IMHO, is this:

    //Konversion befehlen
    myOneWire.TouchReset();
    myOneWire.WriteByte(0x55); //Match ROM
    writeAddress(deviceAddress);
    myOneWire.WriteByte(0x44);
    Thread.Sleep(800); //Energie liefern!!!

    //Lesen
    myOneWire.TouchReset();
    myOneWire.WriteByte(0x55);
    writeAddress(deviceAddress);
    myOneWire.WriteByte(0xBE);

    The sensors really need power during the convert phase...

    Tam

    ReplyDelete
    Replies
    1. Hi Tam -

      Thanks for passing this along. I don't have a functioning Netduino Plus 2 at present, but I'll give this a try when I have a replacement.

      --Brad

      Delete