Close

Validating I2C Communications

A project log for SigCore UC - Universal Controller

Universal industrial I/O controller with relays, analog/digital I/O, Modbus & OPC-UA support. Powered by Raspberry Pi.

edwardEdward 07/31/2025 at 17:540 Comments

Got I²C up and running today between the Raspberry Pi 4 and an MCP23017-based GPIO expander. The goal: drive a handful of LEDs via I²C instead of burning Pi GPIOs.

Here’s the rundown:

Lesson learned: don’t trust DIP switch markings, and always verify with i2cdetect before debugging your code. Total time burned due to wrong I²C address: ~3 hours. Worth it.

Code

using System;
using System.Device.I2c;
using System.Threading;
using Iot.Device.Mcp23xxx;

class Program {
    static void Main() {
        I2cConnectionSettings settings = new I2cConnectionSettings(1, 0x27);
        I2cDevice device = I2cDevice.Create(settings);
        Mcp23017 mcp = new Mcp23017(device);

        // Set all Port A pins as output (lower byte = 0x00 = all output)
        mcp.WriteUInt16(Register.IODIR, 0xFF00);  // Port B = input (0xFF), Port A = output (0x00)

        const byte PA7 = 1 << 7;
        ushort output = PA7;

        // Turn on PA7 initially
        mcp.WriteUInt16(Register.OLAT, output);

        for (int i = 0; i < 10; i++) {
            for (int bit = 0; bit <= 2; bit++) {
                byte ledMask = (byte)(1 << bit);
                output = (ushort)(PA7 | ledMask);
                mcp.WriteUInt16(Register.OLAT, output);
                Thread.Sleep(1000);
            }
        }

        // Leave PA7 on
        mcp.WriteUInt16(Register.OLAT, PA7);

        Console.WriteLine("Done. PA7 remains ON.");
    }
}

Discussions