Debugging I2C on a Fez Cerberus...?

OK, I’ve got a Cerberus, and on socket 1 I have a breakout board with a Pimoroni card on it:

Essentially this is an SN3218 on a board.

Borrowed :slight_smile: some code from John Stov WinHill.WinIoT/SN3218 at master · JohnStov/WinHill.WinIoT · GitHub

It seems to write the device OK, but… no LEDs…

Questions:

  • Looking at the SN3218 spec, is there a ‘read’ register that can confirm comms is working?
  • How else would I know that the write is working? Or will the code throw if there’s no device present?
  • Whats the best way to debug I2C? Stick a 'scope on the SDA/clock lines?

Thanks in advance :slight_smile:

1 Like

Unless your scope can decode the bytes you will need to manually read the bits and convert but this will at least show you if there is a reply from the device when it ACKS the bytes. Set your scope on normal trigger with 2 channels for the data and clock. Trigger on the clock. Look or the ACK in the bit stream. The datasheet for the device usually has timing diagrams to assist with this.

A vert handy little gadget I find for I2C is the Bus Pirate. An indispensable gadget to have in your toolbox when wanting to test I2C buses.

http://dangerousprototypes.com/docs/Bus_Pirate

Thanks Dave, I’ll check the ack with my scope tonight. Probably I’ve not sent it the right commands, or I’ve got my LEDs round the wrong way :slight_smile:

1 Like

hi @ adamwynne

Welcome to the forum.

I’ve used I2C on the Cerberus successfully so I know it’s working. What SDK and firmware version are you running, is that all consistent? (sorry, have to ask since you’re new here!).

Hi Brett

It’s running NetMF 4.3. I stuck a 'scope on it last night and saw the data and clock lines as expected. Just not seeing any output from the LED controller (SN3218 ). But am seeing the ACK on the data line so it’s working.
I wired up another SN3218 board (this is the Pimoroni board:
18-Channel 8-bit PWM LED Driver with I2C Interface - Pimoroni)
onto a Raspberry Pi and that works fine, so the theory is sound… I reckon it’s software. Heres the code I’m using:



using Gadgeteer;
using Gadgeteer.SocketInterfaces;

namespace LEDDriver
{
    public class Sn3218
    {
        private const int I2CAddress = 0x54;
        private readonly I2CBus _device;

        public Sn3218()
        {
            var socket = Socket.GetSocket(1, true, null, null);
            _device = I2CBusFactory.Create(socket, I2CAddress, 100, null);
        }

        private enum Command
        {
            EnableOutput = 0x00,
            SetPwmValues = 0x01,
            EnableLeds = 0x13,
            Update = 0x16,
            Reset = 0x17
        }

        public void Enable()
        {
            WriteBlockData(Command.EnableOutput, 0x01);
        }

        public void Disable()
        {
            WriteBlockData(Command.EnableOutput, 0x00);
        }

        public void Reset()
        {
            WriteBlockData(Command.Reset, 0xff);
        }

        public void EnableLeds(int bitmask)
        {
            WriteBlockData(Command.EnableLeds, bitmask & 0x3f, (bitmask >> 6) & 0x3f, (bitmask >> 12) & 0X3f);
            WriteBlockData(Command.Update, 0xff);
        }

        public void Output(params int[] levels)
        {
            WriteBlockData(Command.SetPwmValues, levels);
            WriteBlockData(Command.Update, 0xff);
        }

        private void WriteBlockData(Command command, params int[] data)
        {
            if (_device == null)
                return;

            var buffer = new byte[data.Length + 1];
            buffer[0] = (byte)command;
            for (var idx = 1; idx < data.Length-1; idx++)
            {
                buffer[idx] = (byte)data[idx - 1];
            }
            _device.Write(buffer);
        }
    }
}

...

        void ProgramStarted()
        {
            Debug.Print("Program Started");

            var sn = new Sn3218();
            sn.Reset();
            sn.Enable();
            sn.EnableLeds(0xFFFFF);
            while(true)
            {
                sn.Output(new[]{255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255});
                Thread.Sleep(100);
                sn.Output(new[] { 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128});
                Thread.Sleep(100);
            }
            sn.Disable();
        }


Any thoughts/help gratefully received :slight_smile:

— EDIT —

Oh, now that’s embarrassing. An out by two error.
The old adage of, ask for help, read through the code, facepalm.

Anyway, all working. Coolness!!! :slight_smile:


private void WriteBlockData(Command command, params int[] data)
        {
            if (_device == null)
                return;

            var buffer = new byte[data.Length + 1];
            buffer[0] = (byte)command;
            for (var idx = 1; idx <= data.Length; idx++) // <----- oops
            {
                buffer[idx] = (byte)data[idx - 1];
            }
            _device.Write(buffer);
        }

1 Like