Here’s a Python code that runs on Ubuntu and controls 16 relays connected to MCP23017 via I2C. This code uses the smbus2 library, so make sure to install it first (pip install smbus2).
Code:
import smbus2
import time
# MCP23017 Register definitions
IODIRA = 0x00 # Direction register for Port A
IODIRB = 0x01 # Direction register for Port B
OLATA = 0x14 # Output latch register for Port A
OLATB = 0x15 # Output latch register for Port B
# I2C Device Address
MCP23017_ADDRESS = 0x22
# Initialize I2C bus
bus = smbus2.SMBus(1) # Raspberry Pi CM4 typically uses I2C bus 1
def setup_mcp23017():
# Set Port A and Port B to output mode
bus.write_byte_data(MCP23017_ADDRESS, IODIRA, 0x00) # Set Port A to output
bus.write_byte_data(MCP23017_ADDRESS, IODIRB, 0x00) # Set Port B to output
# Turn off all relays initially
bus.write_byte_data(MCP23017_ADDRESS, OLATA, 0x00) # Turn off all relays on Port A
bus.write_byte_data(MCP23017_ADDRESS, OLATB, 0x00) # Turn off all relays on Port B
def set_relay(relay_num, state):
"""
Controls a specific relay
relay_num: 1-16, corresponding to the 16 relays
state: 1 to turn on, 0 to turn off
"""
if relay_num < 1 or relay_num > 16:
raise ValueError("Relay number must be between 1 and 16")
if relay_num <= 8:
# Control relays 1-8 on Port A
current_state = bus.read_byte_data(MCP23017_ADDRESS, OLATA)
if state == 1:
current_state |= (1 << (relay_num - 1)) # Turn on the relay
else:
current_state &= ~(1 << (relay_num - 1)) # Turn off the relay
bus.write_byte_data(MCP23017_ADDRESS, OLATA, current_state)
else:
# Control relays 9-16 on Port B
relay_num -= 8
current_state = bus.read_byte_data(MCP23017_ADDRESS, OLATB)
if state == 1:
current_state |= (1 << (relay_num - 1)) # Turn on the relay
else:
current_state &= ~(1 << (relay_num - 1)) # Turn off the relay
bus.write_byte_data(MCP23017_ADDRESS, OLATB, current_state)
def test_relays():
# Sequentially turn on and off each relay with a 1-second delay
for i in range(1, 17):
print(f"Turning on relay {i}")
set_relay(i, 1)
time.sleep(1)
print(f"Turning off relay {i}")
set_relay(i, 0)
time.sleep(1)
if __name__ == "__main__":
setup_mcp23017()
test_relays() # Test relays
Before running the script, install the smbus2 library: