IO Expander Interface (PCAL6408A)
Contents
Introduction
PCAL6408A Features
MicroPython Interface
Complete Example
C/C++ Interface
Hardware Connection
Troubleshooting
Register Map
Introduction
The IO Expander interface provides access to the PCAL6408A 8-bit I2C GPIO expander available on SGW3501-F1-StarterKit boards. This component extends the available GPIO pins and provides interrupt-capable I/O expansion.
I2C Bridge Architecture
The IO expander implementation uses MicroPython I2C Bridge architecture for ESP-IDF v5.4+ compatibility:
Driver: PCAL6408A 8-bit I2C GPIO expander
Bridge:
mp_i2c_bridgecomponent provides C interface to MicroPython I2CBenefits: Unified I2C management, modern ESP-IDF compatibility, future-proof
Implementation Details
Device Address: 0x20 (7-bit I2C address)
I2C Pins: SCL=20, SDA=21 (configurable)
Frequency: 100kHz I2C bus frequency
Integration: Uses
ioexp_mp.cwith I2C bridge for MicroPython builds
PCAL6408A Features
8-bit I2C-bus GPIO with interrupt and weak pull-up
5V tolerant inputs
Polarity inversion register
Low current consumption
Interrupt output for pin change detection
Compatible with standard GPIO operations
MicroPython Interface
Initialization
import ioexp
# Initialize the IO expander
ioexp.init()
Pin Configuration
# Set pin direction (1 = input, 0 = output)
ioexp.set_direction(pin_number, direction)
# Example: Set pin 0 as output, pin 1 as input
ioexp.set_direction(0, 0) # Output
ioexp.set_direction(1, 1) # Input
Digital I/O Operations
# Write to output pin
ioexp.write_pin(pin_number, value)
# Example: Set pin 0 high
ioexp.write_pin(0, 1)
# Read from input pin
value = ioexp.read_pin(pin_number)
# Example: Read pin 1 state
state = ioexp.read_pin(1)
print(f"Pin 1 state: {state}")
Port Operations
# Write entire 8-bit port at once
ioexp.write_port(0b10101010) # Set pins 1,3,5,7 high
# Read entire port
port_state = ioexp.read_port()
print(f"Port state: 0x{port_state:02X}")
Pull-up Configuration
# Enable/disable weak pull-up resistors
ioexp.set_pullup(pin_number, enable)
# Example: Enable pull-up on pin 2
ioexp.set_pullup(2, 1)
Polarity Inversion
# Configure polarity inversion
ioexp.set_polarity(pin_number, inverted)
# Example: Invert polarity on pin 3
ioexp.set_polarity(3, 1)
Complete Example
import ioexp
import time
# Initialize the IO expander
ioexp.init()
# Configure pins: 0-3 as outputs, 4-7 as inputs with pull-ups
for pin in range(4):
ioexp.set_direction(pin, 0) # Output
for pin in range(4, 8):
ioexp.set_direction(pin, 1) # Input
ioexp.set_pullup(pin, 1) # Enable pull-up
# Blink LEDs on output pins
while True:
# Set outputs high
for pin in range(4):
ioexp.write_pin(pin, 1)
# Read and display input states
for pin in range(4, 8):
state = ioexp.read_pin(pin)
print(f"Input pin {pin}: {state}")
time.sleep(0.5)
# Set outputs low
for pin in range(4):
ioexp.write_pin(pin, 0)
time.sleep(0.5)
C/C++ Interface
For native C/C++ applications, the same functionality is available through the header interface:
#include "ioexp.h"
// Initialize
esp_err_t err = ioexp_init();
// Configure pin direction
ioexp_set_direction(0, IOEXP_OUTPUT);
ioexp_set_direction(4, IOEXP_INPUT);
// Digital operations
ioexp_write_pin(0, 1); // Set pin 0 high
int state = ioexp_read_pin(4); // Read pin 4
Hardware Connection
The PCAL6408A is typically connected as follows on SGW3501-F1-StarterKit:
VCC: 3.3V power supply
GND: Ground
SCL: I2C clock line (GPIO 20)
SDA: I2C data line (GPIO 21)
INT: Interrupt output (optional, board-dependent)
ADDR: Address select pin (determines I2C address)
Troubleshooting
Common Issues
I2C Communication Errors
Verify I2C connections (SCL, SDA, power, ground)
Check I2C address (0x20 default)
Ensure proper pull-up resistors on I2C lines
Pin State Issues
Verify pin direction configuration
Check for polarity inversion settings
Ensure proper voltage levels (5V tolerance)
Initialization Failures
Confirm device presence with I2C scan
Verify power supply stability
Check for I2C bus conflicts
Debug Commands
# Test I2C communication
import machine
i2c = machine.I2C(0, scl=20, sda=21)
devices = i2c.scan()
print(f"I2C devices found: {[hex(d) for d in devices]}")
# Expected output should include 0x20 for PCAL6408A
Register Map
For advanced users, the PCAL6408A register map:
Register |
Address |
Function |
|---|---|---|
Input Port |
0x00 |
Read input levels |
Output Port |
0x01 |
Write output levels |
Polarity Inversion |
0x02 |
Configure input polarity |
Configuration |
0x03 |
Set pin direction |
Output Drive Strength |
0x40 |
Configure drive strength |
Input Latch |
0x42 |
Input latch control |
Pull-up/Pull-down Enable |
0x43 |
Pull resistor enable |
Pull-up/Pull-down Select |
0x44 |
Pull resistor direction |
Interrupt Mask |
0x45 |
Interrupt enable |
Interrupt Status |
0x46 |
Interrupt status |
Output Port Configuration |
0x4F |
Output port configuration |