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:
-
Hardware: MCP23017 breakout powered at 5V, connected to Pi’s I²C bus 1 (
/dev/i2c-1) -
I²C address: Detected at
0x27viai2cdetect -y 1(DIP switches were not what they seemed) -
Pull-ups: Not initially present — but breakout board had them onboard, so no manual resistors needed
-
Voltage levels: MCP running at 5V, Pi at 3.3V. Thankfully the board didn’t pull SDA/SCL past safe limits
-
Code: .NET 8 app using
System.Device.I2candIot.Device.Mcp23xxx. ManualWriteUInt16(Register.OLAT, 0x0080)controls Port A directly — no guesswork, just register writes -
Outcome: LEDs on PA0–PA2 flash sequentially with PA7 staying on as an indicator. Blinks exactly as intended
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.");
}
}
Edward
Discussions
Become a Hackaday.io Member
Create an account to leave a comment. Already have an account? Log In.