Code Example - PCA9531 8-bit I2C LED dimmer

The PCA9531 is an 8-bit I/O expander that you can interface with via I2C. It is intended for driving LEDs, but the pins can be use for input as well. It supports a maximum of 25 mA sink current per pin and 100 mA per package. The one I’m working with is in a SO-16 package, which is quite small and surface mount. It has three address input pins, so you can have a maximum of 8 of these on a single I2C bus. Each pin can be set in four different states. Off (high-impedance), On (low), PWM0, or PWM1. Each of the PWMs can be set at a user-defined PWM rate and prescaler frequency.

When hooking LEDs to this chip, keep in mind that it has to pull the pin low to supply any useful amount of current. You’ll want to connect your LED and resistor between the positive rail and the pin on the chip.

$2.06 at Mouser:,118virtualkey66800000virtualkey771-PCA9531D-T
$2.28 at Digikey:,112/568-3369-5-ND/1125682

local i2c = hardware.i2c89;
local Addr = 0xC0; //Address of the chip with all address inputs tied low
i2c.write(Addr, “\x11\x06\x80”); //Configure PSC0 and PWM0
i2c.write(Addr, “\x13\x80\x40”); //Configure PSC1 and PWM1

local i = 0;

function loop() {
i2c.write(Addr, “\x15\x02\x00”);

//The state of each LED output uses two bits.
if (i == 0) i2c.write(Addr, "\\x15\\x01\\x00"); //LED 0 = on (01)
if (i == 1) i2c.write(Addr, "\\x15\\x04\\x00"); //LED 1 = on (01)
if (i == 2) i2c.write(Addr, "\\x15\\x10\\x00"); //LED 2 = on (01)
if (i == 3) i2c.write(Addr, "\\x15\\x40\\x00"); //LED 3 = on (01)
if (i == 4) i2c.write(Addr, "\\x15\\x00\\x02"); //LED 4 = PWM0 (10)
if (i == 5) i2c.write(Addr, "\\x15\\x00\\x08"); //LED 5 = PWM0 (10)
if (i == 6) i2c.write(Addr, "\\x15\\x00\\x30"); //LED 6 = PWM1 (11)
if (i == 7) i2c.write(Addr, "\\x15\\x00\\xC0"); //LED 7 = PWM1 (11)

if (i == 8) i = 0; //Reset count
imp.wakeup(1, loop);


imp.configure(“PCA9531 Example”, [], []);

Note that you could use an array of strings here to simplify the code, eg:

config[] = { "\\x15\\x01\\x00" , "\\x15\\x04\\x00", "\\x15\\x10\\x00" ... (etc) }; i2c.write(Addr, config[i]);

The other useful thing about that device is that you can run LEDs from a 5v supply into the drive pins of the PCA even when the PCA is powered by 3.3v :slight_smile: