Main Site Documentation

DS2482-800 1 Wire Setup using I2C


#1

Anyone have experience with the DS2482-800 1wire master?

It has a I2C interface and i cannot get it to work. I have a couple MCP23017 on the same bus that work fine but i cannot be able to communicate to the DS2482-800 chip.

        I2CDevice.I2CTransaction[] writeTrans = new I2CDevice.I2CTransaction[1];
        I2CDevice.I2CTransaction[] readTrans = new I2CDevice.I2CTransaction[2];


        public Init(byte address, OutputPort resetPin)
        {
            this._Device = new I2CDevice(new I2CDevice.Configuration(address, 100));
        }

         public void Write(byte reg, byte val)
        {
            int written;
            writeBuffer[0] = (byte)reg;
            writeBuffer[1] = val;
            writeTrans[0] = I2CDevice.CreateWriteTransaction(writeBuffer);
            written = _Device.Execute(writeTrans, 100);

            if (written != writeBuffer.Length)
            {
                    //failed
            }
            else
            {
                         //success
            }

        }


            I2C = new I2C.Init(0x60, null);//DS2482 ....A

            I2C = new I2C.Init(0x23, null);//MCP23017 .......B

            I2C.Write(0x7, 0xff);//get a response if i use A but fails with B

#2

You are using the same variable for both devices at the same time?


#3

I have simplied the code to show you what i tried…i haven’t used the same variable…i comment one out at a time to test


#4

Ok. so which one do you have problem with? You description and comment in the code are different.


#5
            MCP23017 = new I2C.Init(0x23, null);.// Works fine
            MCP23017 .Write(0x7, 0xff);// Works fine


       DS2482 = new I2C.Init(0x60, null);// No response from 
       DS2482 .Write(0x7, 0xff);//  No response from 

#6

Can you show how do you wire address pins (AD0, AD1, AD2) on the DS2482?

These pins will define the address to use in I2C communication. In most cases I2C problems are address related.

I can tell you for sure that it can’t be 0x60.


#7

I’d hazard a guess at saying 100% of I2C issues are address issues :slight_smile:

The netmf I2C setup requires a 7-bit attdress. Many people use code that provides an 8-bit address that doesn’t work.

By default, that device’s address will be 0x18 (address lines all 0). As Architect says, it’ll never be 0x60. If all address lines were high, it’d be 0x1f.


#8

Here is how the address is formed for reference.


#9

Ao,a1,a2 are all low. Since they are all low…how do i address chip using 7bit instead of 8 bits? Using 8bits the address is 0x60 as the LSB is 0 for read and 1 for write

Ok…i understand how you got 0x18 but what do i do with the R/W bit?

As usual, appreciate your help


#10

@ anthonys - Good! 0x18 it is. R/W bit will be taken care for you. So don’t worry about it.


#11

@ Architect Thanks! Again i appreciate your help…this is the main reason why i’m using G120 instead of open source version which can be an issue for a commercial product if you need support.


#12

The I2C device addresses are ALWAYS 7 bits, you never need to take into account the 8th bit in your code. So we’ve kept up the 100% rule :slight_smile:


#13

Thanks Brett.


#14

Question…i don’t know if its me but some datasheets are not always initiative.

Anyway, using the DS2482…how do i search for 1wire devices on a channel. I know how to select a channel but how do i search for device on it?

I apparently need to use 1-Wire Triplet …command but i not sure how this works. Using dome code i found in codeshare…i’m not sure how it works…

BTW, trying to read the temperature from a DS18B20 device


main()
{
                iCount += 1;
                status = oneWireBridge.Status;  // status
                loginfo(LoggingLevel.info, "Channel IO0", "Channel IO0");
                oneWireBridge.ChannelSelect(0xF0);
                loginfo(LoggingLevel.info, byte2binary.Byte2BinStringLSBF(status), byte2binary.Byte2BinStringLSBF(status));
                oneWireBridge.OneWireSingleBit(0x00); // top-most bit decides on single 1-Wire time slot.  i.e. 0x00 or 0x80)
                oneWireBridge.OneWireWriteByte(0x00); // single byte
                readByte = oneWireBridge.OneWireReadByte();
                loginfo(LoggingLevel.info, readByte.ToString(), readByte.ToString());
                oneWireBridge.OneWireTriplet(true); // Search direction true - don't know what this means yet.
                oneWireBridge.OneWireTriplet(false); // Search direction
                Thread.Sleep(1000);
}


        public void OneWireTriplet(bool searchDirection)
        {
            WaitFreeGetStatus();
            _writeTrans = I2CDevice.CreateWriteTransaction(new byte[2] { (byte)DeviceCommand.oneWT, searchDirection ? (byte)0x80 : (byte)0x00 });
            // should there be a read transaction here?
            _transactions = new I2CDevice.I2CTransaction[] { _writeTrans };
            _Device.Execute(_transactions, DELAY);
        }


#15

You’ll need to share your other code too, at least ChannelSelect and OneWireSingleBit and OneWireWriteByte and OneWireReadByte.


#16

Actually I take that back, a little.

The reason this is more complex than normal is because you’re using two complex chips when you could avoid it. And that’s actually what I would suggest you do first up, avoid it and test and understand the way one-wire works so you knwow hat kind of interactions you need to make to use a DS18B20, then you can figure out how that then translates to using it all via the DS2482. In other words, you’re going to need to focus on the DS18B20 command set first up, then figure out how to make that work in DS2482 I2C transactions.

Have you checked app notes? Dallas are usually pretty good at documenting use-cases. Which ones have you seen?


#17

My code

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

namespace zigbox.fezcobra2.OneWire
{




    public enum Pin
    {
        GP0A = 0x01,
        GP1A = 0x02,
        GP2A = 0x04,
        GP3A = 0x08,
        GP4A = 0x10,
        GP5A = 0x20,
        GP6A = 0x40,
        GP7A = 0x80,
        GP0B = 0x01,
        GP1B = 0x02,
        GP2B = 0x04,
        GP3B = 0x08,
        GP4B = 0x10,
        GP5B = 0x20,
        GP6B = 0x40,
        GP7B = 0x80,
        ALL = 0xFF,
    }

    public enum ConfigRegister
    {
        /// <summary>
        /// Sequential Operation
        /// 0 = enabled(default)
        /// 1 = disabled
        /// </summary>
        SEQOP = 0x20,

        /// <summary>
        /// SDA Slew Rate
        /// 0 = enabled(default)
        /// 1 = disabled
        /// </summary>
        DISSLW = 0x10,

        /// <summary>
        /// Hardware Address Enable for MCP23S08 SPI version only
        /// 0 = disabled(default)
        /// 1 = enabled
        /// </summary>
        HAEN = 0x08,

        /// <summary>
        /// INT pin as open-drain
        /// 0 = Active driver output(default)
        /// 1 = Open-drain output
        /// </summary>
        ODR = 0x04,

        /// <summary>
        /// INT polarity
        /// 0 = Active-low(default)
        /// 1 = Active-high
        /// </summary>
        INTPOL = 0x02,
    }

    /// <summary>
    /// MCP23017 pin expander
    /// </summary>
    public class Mcp23017
    {
        #region "Contructor"
        /// <summary>
        /// Reference to the I�C bus
        /// </summary>
        private I2CDevice _Device;
        const ushort DS2482_ADDRESS = 0x18; // 7 bit address from data sheet, default address
        const int CLOCK_FREQ = 100; // 100kHz, will also work at 400kHz
        const int DELAY = 60; // not sure, might be the number of clock cycles?
        const int POLL_LIMIT = 200; // limit for polling of status
        const byte ONE_WIRE_BUSY = 0x01; // final bit of status is 1, indicating 1-Wire is busy

        private enum DeviceCommand : byte  // size of storage, still needs explicit cast when used.
        {
            ADDRESS = 0x18, // assuming both add pins are either left open or low.  Change if they aren't.
            DRST = 0xF0, // Command Device Reset
            SRP = 0xE1, // Command Set Read Pointer
            WCFG = 0xD2, // Command Write Configuration
            CHANNELSELECT = 0xC3, // Command Write Configuration

            oneWRS = 0xB4, // Command 1-Wire Reset
            oneWSB = 0x87, // Command 1-Wire Single Bit
            oneWWB = 0xA5, // Command 1-Wire Write Byte
            oneWRB = 0x96, // Command 1-Wire Read Byte
            oneWT = 0x78, // Command 1-Wire Triplet
        }

        public enum ReadPointer : byte
        {
            Status = 0xF0, // Status Register F0h
            Read = 0xE1, // Read Data Register E1h
            Configuration = 0xC3, // Configuration Register C3h
        }

        // Registers for port A
        private const byte _IODIRA = 0x00;
        private const byte _IPOLA = 0x02;
        private const byte _GPINTENA = 0x04;
        private const byte _DEFVALA = 0x06;
        private const byte _INTCONA = 0x08;
        private const byte _IOCONA = 0x0a;
        private const byte _GPPUA = 0x0c;
        private const byte _INTFA = 0x0e;
        private const byte _INTCAPA = 0x10;
        private const byte _GPIOA = 0x12;
        private const byte _OLATA = 0x14;

        OutputPort resetPin;
        byte[] singleCommand = new byte[1];
        byte[] writeBuffer = new byte[2];
        byte[] readBuffer = new byte[1];

        I2CDevice.I2CTransaction[] writeTrans = new I2CDevice.I2CTransaction[1];
        I2CDevice.I2CTransaction[] readTrans = new I2CDevice.I2CTransaction[2];

        I2CDevice.I2CWriteTransaction _writeTrans;
        I2CDevice.I2CReadTransaction _readTrans;
        I2CDevice.I2CTransaction[] _transactions;


        public Mcp23017(byte address, OutputPort resetPin)
        {
            //this._Device = new I2CDevice(new I2CDevice.Configuration(address, 100));
            //Init();
            _Device = new I2CDevice(new I2CDevice.Configuration(DS2482_ADDRESS, CLOCK_FREQ));
            DeviceReset();
        }
        #endregion
        private void Init()
        {
            Reset();
            Write((byte)DeviceCommand.DRST, 0x0);
            WaitFreeGetStatus();
        }

        private byte WaitFreeGetStatus()
        {
            // Wait until the 1-Wire is not busy or polling limit is reached.
            byte[] _status = new byte[1];
            _writeTrans = I2CDevice.CreateWriteTransaction(new byte[2] { (byte)DeviceCommand.SRP, (byte)ReadPointer.Status });
            _readTrans = I2CDevice.CreateReadTransaction(_status);
            _transactions = new I2CDevice.I2CTransaction[] { _writeTrans, _readTrans };
            _Device.Execute(_transactions, DELAY);

            I2CDevice.I2CTransaction[] readTransaction = new I2CDevice.I2CTransaction[] { _readTrans };  // used to read status if 1-wire bus busy.
            int i = 0;  // used with POLL_LIMIT to make sure we don't wait forever for status byte.
            while (((_status[0] & ONE_WIRE_BUSY) != 0x00) && i < POLL_LIMIT) // if the 1-Wire bus is busy
            {
                _Device.Execute(readTransaction, DELAY);
                i++;
            }

            return _status[0];
        }

        public byte Configuration
        {
            get
            {
                // read the current configuration
                /* Configuration Register Bit Assignment bit 7 to 0: 1WS SPU 1 APU 1WS SPU 0 APU
                 * Active Pullup (APU)
                 * Strong Pullup (SPU)
                 * 1-Wire Speed (1WS)
                 */
                byte[] _config = new byte[1];
                WaitFreeGetStatus();
                _writeTrans = I2CDevice.CreateWriteTransaction(new byte[2] { (byte)DeviceCommand.SRP, (byte)ReadPointer.Configuration });  // change pointer to config register
                _readTrans = I2CDevice.CreateReadTransaction(_config);  // single byte configuraiton, as above
                _transactions = new I2CDevice.I2CTransaction[] { _writeTrans, _readTrans };

                _Device.Execute(_transactions, DELAY);

                return _config[0];
            }
            set
            {
                // write configuration.  Top 4 bits, desired config, lower 4 bits 1's compliment of the top 4.  So 0xF0 would work.  or 0xE1 for APU only.
                /* Configuration Register Bit Assignment bit 7 to 0: 1WS SPU 1 APU 1WS SPU 0 APU
                 * Active Pullup (APU) // 1 unless there is a single device on the line.
                 * Strong Pullup (SPU) // for some devices (e.g. EEPROM) can be set to 1
                 * 1-Wire Speed (1WS) // 0 for standard speed
                 */
                byte[] _config = new byte[1];
                WaitFreeGetStatus();

                _writeTrans = I2CDevice.CreateWriteTransaction(new byte[2] { (byte)DeviceCommand.WCFG, value });  // change the configuration
                _readTrans = I2CDevice.CreateReadTransaction(_config);  // single byte configuraiton, as above
                _transactions = new I2CDevice.I2CTransaction[] { _writeTrans, _readTrans };

                _Device.Execute(_transactions, DELAY);

                if (!(_config[0] == value))
                {
                    WaitFreeGetStatus();
                    _Device.Execute(_transactions, DELAY);
                }
            }
        }

        public void OneWireReset()
        {
            int written;
            _writeTrans = I2CDevice.CreateWriteTransaction(new byte[1] { (byte)DeviceCommand.oneWRS });
            _transactions = new I2CDevice.I2CTransaction[] { _writeTrans };

            written = _Device.Execute(_transactions, DELAY);

            WaitFreeGetStatus();
        }




        public byte[] ReadData(int bytes)
        {
            int written;
            // Read one or more bytes from the read register
            _writeTrans = I2CDevice.CreateWriteTransaction(new byte[2] { (byte)DeviceCommand.SRP, (byte)ReadPointer.Read });
            byte[] data = new byte[bytes];
            _readTrans = I2CDevice.CreateReadTransaction(data);  // is this right?
            _transactions = new I2CDevice.I2CTransaction[] { _writeTrans, _readTrans };

            written = _Device.Execute(_transactions, DELAY);

            return data;  // should we return this?
        }



        public void OneWireSingleBit(byte slot)
        {
            int written;
            /*
             * Generates a single 1-Wire time slot.   If bit 7 is: 
             * 0 then it generates a write-zero time slot 
             * 1 then it generates a write-one time slot, which also functions as a read-data time slot 
             * In either case, the logic level at the 1-Wire line is tested at tMSR and SBR is updated.
             * */
            WaitFreeGetStatus();
            _writeTrans = I2CDevice.CreateWriteTransaction(new byte[2] { (byte)DeviceCommand.oneWSB, slot });
            _transactions = new I2CDevice.I2CTransaction[] { _writeTrans };
            written = _Device.Execute(_transactions, DELAY);
        }

        public void OneWireWriteByte(byte dataByte)
        {
            int written;
            WaitFreeGetStatus();
            _writeTrans = I2CDevice.CreateWriteTransaction(new byte[2] { (byte)DeviceCommand.oneWWB, dataByte });
            _transactions = new I2CDevice.I2CTransaction[] { _writeTrans };
            written = _Device.Execute(_transactions, DELAY);
        }

        public byte OneWireReadByte()
        {
            int written;
            WaitFreeGetStatus();
            byte[] _data = new byte[1];
            _writeTrans = I2CDevice.CreateWriteTransaction(new byte[1] { (byte)DeviceCommand.oneWRB });
            _readTrans = I2CDevice.CreateReadTransaction(_data);
            _transactions = new I2CDevice.I2CTransaction[] { _writeTrans, _readTrans };

            // shouldn't there be a read tx here?
            written = _Device.Execute(_transactions, DELAY);
            return _data[0];
        }

        public void DeviceReset()
        {
            int written;
            _writeTrans = I2CDevice.CreateWriteTransaction(new byte[1] { (byte)DeviceCommand.DRST });
            _transactions = new I2CDevice.I2CTransaction[] { _writeTrans };
            written = _Device.Execute(_transactions, DELAY);

            if (written != writeBuffer.Length)
            {
                if (Program.DebugLevel >= 1) Debug.Print(singleCommand.ToString() + " has NOT been written to  I2C device[" + _Device.Config.Address + "].");
            }
            else
            {
                if (Program.DebugLevel >= 4) Debug.Print(singleCommand.ToString() + " has been written to    I2C device[" + _Device.Config.Address + "].");
            }



            WaitFreeGetStatus();
        }

        /// <summary>
        /// Hardware or software reset
        /// </summary>
        public void Reset()
        {
            int written;
            //singleCommand[0] = (byte)DeviceCommand.DRST;
            _writeTrans = I2CDevice.CreateWriteTransaction(new byte[1] { (byte)DeviceCommand.DRST });


            writeTrans = new I2CDevice.I2CTransaction[] { _writeTrans };
            written = _Device.Execute(writeTrans, 100);

            if (written != writeBuffer.Length)
            {
                if (Program.DebugLevel >= 1) Debug.Print(singleCommand.ToString() + " has NOT been written to  I2C device[" + _Device.Config.Address + "].");
            }
            else
            {
                if (Program.DebugLevel >= 4) Debug.Print(singleCommand.ToString() + " has been written to    I2C device[" + _Device.Config.Address + "].");
            }
        }



        public void OneWireTriplet(bool searchDirection)
        {
            int written = 0;
            WaitFreeGetStatus();
            _writeTrans = I2CDevice.CreateWriteTransaction(new byte[2] { (byte)DeviceCommand.oneWT, searchDirection ? (byte)0x80 : (byte)0x00 });
            // should there be a read transaction here?
            _transactions = new I2CDevice.I2CTransaction[] { _writeTrans };
            written = _Device.Execute(_transactions, DELAY);
        }

        public void SetReadPointer(byte readPointer)
        {
            int written = 0;
            //
            WaitFreeGetStatus();
            _writeTrans = I2CDevice.CreateWriteTransaction(new byte[2] { (byte)DeviceCommand.SRP, readPointer });
            _transactions = new I2CDevice.I2CTransaction[] { _writeTrans };
            written = _Device.Execute(_transactions, DELAY);
        }

        public void ChannelSelect(byte readPointer)
        {
            int written;

            WaitFreeGetStatus();
            _writeTrans = I2CDevice.CreateWriteTransaction(new byte[2] { (byte)DeviceCommand.CHANNELSELECT, readPointer });
            _transactions = new I2CDevice.I2CTransaction[] { _writeTrans };
            written = _Device.Execute(_transactions, DELAY);


            if (written != writeBuffer.Length)
            {
                if (Program.DebugLevel >= 1) Debug.Print(singleCommand.ToString() + " has NOT been written to  I2C device[" + _Device.Config.Address + "].");
            }
            else
            {
                if (Program.DebugLevel >= 4) Debug.Print(singleCommand.ToString() + " has been written to    I2C device[" + _Device.Config.Address + "].");
            }

        }

        // property
        public byte Status
        {
            get
            {
                // read the current status
                /* Status Register Bit Assignment 7 to 0: DIR TSB SBR RST LL SD PPD 1WB
                 * Branch Direction Taken (DIR)
                 * Triplet Second Bit (TSB)
                 * Single Bit Result (SBR)
                 * Device Reset (RST)
                 * Logic Level (LL)
                 * Short Detected (SD)
                 * Presence-Pulse Detect (PPD)
                 * 1-Wire Busy (1WB)
                */
                return WaitFreeGetStatus();
            }
        }

        /// <summary>
        /// Write single register
        /// </summary>
        /// <param name="reg">Register name</param>
        /// <param name="val">Register value</param>
        public void Write(byte reg, byte val)
        {
            int written;
            writeBuffer[0] = (byte)reg;
            writeBuffer[1] = val;
            writeTrans[0] = I2CDevice.CreateWriteTransaction(writeBuffer);
            written = _Device.Execute(writeTrans, 100);

            if (written != writeBuffer.Length)
            {
                if (Program.DebugLevel >= 1) Debug.Print(val + " has NOT been written to " + reg + "  I2C device[" + _Device.Config.Address + "].");
            }
            else
            {
                if (Program.DebugLevel >= 4) Debug.Print(val + " has been written to " + reg + "  I2C device[" + _Device.Config.Address + "].");
            }

        }

        /// <summary>
        /// Read single register
        /// </summary>
        /// <param name="reg">Register name</param>
        /// <returns>Register value</returns>
        public byte Read(byte reg)
        {
            singleCommand[0] = (byte)reg;
            readTrans[0] = I2CDevice.CreateWriteTransaction(singleCommand);
            readTrans[1] = I2CDevice.CreateReadTransaction(readBuffer);
            int resylt = _Device.Execute(readTrans, 100);

            if (resylt > 0)
            {
                if (Program.DebugLevel >= 4) Debug.Print(" Read " + reg + "  I2C device[" + _Device.Config.Address + "] Result[" + readBuffer[0] + "]");
            }
            else
            {
                if (Program.DebugLevel >= 1) Debug.Print(" Read " + reg + "  I2C device[" + _Device.Config.Address + "] No data returned");
            }

            return readBuffer[0];
        }

        /// <summary>
        /// Write GPIO pin(s)
        /// </summary>
        /// <param name="pin">pin</param>
        /// <param name="value">value</param>
        public void WritePinA(Pin pinMask, bool value)
        {
            SetRegisterForPin(_GPIOA, pinMask, value);
        }

        /// <summary>
        /// Read single GPIO pin
        /// </summary>
        /// <param name="pin">pin</param>
        /// <returns>pin value</returns>
        public bool ReadPin(Pin pin)
        {
            byte current_GPIO = Read(_GPIOA);
            if ((current_GPIO & (byte)pin) > 0)
            {
                return true;
            }
            else
            {
                return false;
            }
        }

        /// <summary>
        /// Read GPIO pin(s)
        /// </summary>
        /// <param name="pin">pin mask</param>
        /// <returns>masked value</returns>
        public byte ReadPinsA(Pin pinMask)
        {
            byte current_GPIOA = Read(_GPIOA);
            current_GPIOA &= (byte)pinMask;

            return current_GPIOA;
        }






        /// <summary>
        /// Set pin value mask
        /// </summary>
        /// <param name="reg">register</param>
        /// <param name="pin">pin</param>
        /// <param name="value">value</param>
        private void SetRegisterForPin(byte reg, Pin pinMask, bool value)
        {
            byte current = Read(reg);
            if (value)
            {
                current |= (byte)pinMask;
            }
            else
            {
                current &= (byte)((int)~pinMask);
            }
            Write(reg, current);
        }





        /// <summary>
        /// Set configuration
        /// </summary>
        /// <param name="cr">config</param>
        public void SetConfigRegister(ConfigRegister cr)
        {
            Write(_IOCONA, (byte)cr);
        }

        /// <summary>
        /// Clear INTF by reading INTCAP
        /// </summary>
        public void ClearInterruptA()
        {
            Read(_INTCAPA);
        }

    }
}

#18

Awesome, so now where are all your debug.print statements and your output that tells us what it’s actually calling and responding? :slight_smile:

You did see my suggestion about getting the 1-wire set up directly, yeah? :slight_smile:


#19

Whats the namespace to use the onewire libarry from g120 device?

ir OneWire ow = new OneWire(myPin);


#20

namespace and assembly name is Microsoft.SPOT.Hardware.OneWire