[solved] Drive 4-Channel SPDT Relay via I2C/smbus2 python

I just got one of these boards and came across this so figured I would share. See below for a python example where I have replicated the Adruino C++ example so that you can leverage it more easily.

Hope this helps.

import time
import smbus

class GroveRelay(object):
    def __init__(self):
        self.channel_state      = 0
        self.cmd_channel_ctrl   = None
        self.save_i2c_addr      = None
        self.read_i2c_addr      = None
        self.read_firmware_ver  = None
        
    def begin(self, i2c_port, cmd_channel_ctrl, save_i2c_addr, read_i2c_addr, read_firmware_ver):
        self.channel_state      = 0
        self.cmd_channel_ctrl   = cmd_channel_ctrl
        self.save_i2c_addr      = save_i2c_addr
        self.read_i2c_addr      = read_i2c_addr
        self.read_firmware_ver  = read_firmware_ver
        
        self.bus = smbus.SMBus(i2c_port)
        self.bus.write_byte_data(self.save_i2c_addr, self.cmd_channel_ctrl, self.channel_state)
        
    def change_i2c_address(self, new_addr):
        self.bus.write_byte_data(self.save_i2c_addr, self.save_i2c_addr, new_addr)
        self.save_i2c_addr = new_addr;
        
    def get_channel_state(self):
        return self.channel_state
    
    def get_firmware_version(self):
        self.bus.write_byte(self.save_i2c_addr, self.read_firmware_ver)
        return self.bus.read_byte(self.save_i2c_addr)
        
    def channel_ctrl(self, state):
        self.channel_state = state
        self.bus.write_byte_data(self.save_i2c_addr, self.cmd_channel_ctrl, self.channel_state)
        
    def turn_on_channel(self, channel):
        self.channel_state |= (1 << (channel - 1))
        self.bus.write_byte_data(self.save_i2c_addr, self.cmd_channel_ctrl, self.channel_state)

    def turn_off_channel(self, channel):
        self.channel_state &= ~(1 << (channel - 1))
        self.bus.write_byte_data(self.save_i2c_addr, self.cmd_channel_ctrl, self.channel_state)

if __name__ == "__main__":
    I2C_PORT = 1

    CMD_CHANNEL_CTRL        = 0x10
    CMD_SAVE_I2C_ADDR		= 0x11
    CMD_READ_I2C_ADDR		= 0x12
    CMD_READ_FIRMWARE_VER	= 0x13
    
    CHANNLE1_BIT = 0x01
    CHANNLE2_BIT = 0x02
    CHANNLE3_BIT = 0x04
    CHANNLE4_BIT = 0x08
    CHANNLE5_BIT = 0x10
    CHANNLE6_BIT = 0x20
    CHANNLE7_BIT = 0x40
    CHANNLE8_BIT = 0x80

    relay = GroveRelay()
    relay.begin(1, 0x10, 0x11, 0x12, 0x13)
    
    print ("Firmware version:" + str(relay.get_firmware_version()))

    #/* Begin Controlling Relay */
    print("Channel 1 on");
    relay.turn_on_channel(1);
    time.sleep(1);
    print("Channel 2 on");
    relay.turn_off_channel(1);
    relay.turn_on_channel(2);
    time.sleep(1);
    print("Channel 3 on");
    relay.turn_off_channel(2);
    relay.turn_on_channel(3);
    time.sleep(1);
    print("Channel 4 on");
    relay.turn_off_channel(3);
    relay.turn_on_channel(4);
    time.sleep(1);
    relay.turn_off_channel(4);

    relay.channel_ctrl(CHANNLE1_BIT |
                      CHANNLE2_BIT |
                      CHANNLE3_BIT |
                      CHANNLE4_BIT);
    print("Turn all channels on, State: ");
    print(relay.get_channel_state());

    time.sleep(1);

    relay.channel_ctrl(CHANNLE1_BIT |
                      CHANNLE3_BIT);
    print("Turn 1 3 channels on, State: ");
    print(relay.get_channel_state());

    time.sleep(1);

    relay.channel_ctrl(CHANNLE2_BIT |
                      CHANNLE4_BIT);
    print("Turn 2 4 channels on, State: ");
    print(relay.get_channel_state());

    time.sleep(1);

    relay.channel_ctrl(0);
    print("Turn off all channels, State: ");
    print(relay.get_channel_state());

    time.sleep(1);
1 Like