Overview
BaseConfig manages dynamic PCF8574 I/O expander configuration with intelligent channel distribution strategies, I2C scanning, and configuration validation.
Quick Start
#define ENABLE_ADDONS_AUTOLIGHT_V3
#include "Kinematrix.h"
using namespace AutoLight;
BaseConfig config;
void setup() {
// Automatic distribution across 2 PCF8574s
config.setDynamicConfig(12, 2);
// Validate configuration
if (config.validateConfiguration()) {
Serial.println("Configuration valid!");
config.printDistribution();
}
}
Constructor
Create BaseConfig instance
Initialization
Initialize configuration system
Dynamic Configuration
Automatic channel distribution across PCF8574 expanders:
Configure channels with automatic distribution
Auto-calculate optimal PCF count
Specify PCF count, auto-distribute
With strategy
total_channels, num_pcf, strategy
Specify distribution strategy
Distribution Strategies
typedef enum {
DISTRIBUTE_BALANCED = 0, // Even distribution across all PCFs
DISTRIBUTE_SEQUENTIAL = 1, // Fill PCFs sequentially
DISTRIBUTE_OPTIMIZED = 2, // Minimize PCF usage
DISTRIBUTE_CUSTOM = 3 // Manual configuration
} distribution_strategy_t;
Examples
Balanced Distribution
config.setDynamicConfig(24, 3, DISTRIBUTE_BALANCED);
// Result: PCF1=8ch, PCF2=8ch, PCF3=8ch
Sequential Distribution
config.setDynamicConfig(20, 3, DISTRIBUTE_SEQUENTIAL);
// Result: PCF1=8ch, PCF2=8ch, PCF3=4ch
Optimized Distribution
config.setDynamicConfig(20, 5, DISTRIBUTE_OPTIMIZED);
// Result: Uses only 3 PCFs (20 channels)
Custom Configuration
Configure with specific addresses and channel counts
Array of channels per PCF
Set fully custom PCF distribution
Array of PCFDistribution structures
Custom Distribution Example
PCFDistribution custom[3] = {
{0x27, 8, 0, 0, true}, // PCF at 0x27: channels 0-7
{0x38, 8, 8, 0, true}, // PCF at 0x38: channels 8-15
{0x45, 4, 16, 0, true} // PCF at 0x45: channels 16-19
};
config.setCustomDistribution(custom, 3);
Manual Configuration
Set channel sequence manually
Set PCF I2C addresses
I2C addresses (0x20-0x27)
EEPROM Operations
Set and save channel count to EEPROM
Read channel count from EEPROM
Returns saved channel count
Set configuration version
Read configuration version
Returns version number
Getters
Get configuration data pointer
Returns pointer to ConfigData structure
Get config instance
Returns this pointer
Get configuration version
Get number of I/O expanders
Get pin mapping array
Returns array of pin numbers
Get current distribution data
Returns pointer to DynamicConfigData
Validation
Validate entire configuration
Returns true if configuration is valid
Validate PCF distribution
Returns true if distribution is valid
Calculate optimal PCF count for channels
Returns recommended PCF count
Debugging
Print PCF distribution to Serial
Print complete configuration debug info
I2C Scanner
BaseConfig includes an I2C scanner class:
I2CScanner scanner;
scanner.beginTransmission();
scanner.scanI2CAddress(); // Prints found devices
scanner.endTransmission();
PCFDistribution Structure
struct PCFDistribution {
uint8_t address; // I2C address (0x20-0x27)
uint8_t used_pins; // Number of allocated pins (1-8)
uint8_t start_channel; // Starting channel number
uint8_t pin_offset; // Pin offset within PCF
bool is_active; // PCF active status
};
ConfigData Structure
typedef struct {
ConfigHeader header; // Channel count, pin pointers, I2C addresses
ConfigTable table; // Address and version tables
} ConfigData;
Complete Example
#define ENABLE_ADDONS_AUTOLIGHT_V3
#include "Kinematrix.h"
using namespace AutoLight;
BaseConfig config;
void setup() {
Serial.begin(115200);
// Method 1: Simple auto-configuration
config.setDynamicConfig(12); // Auto-optimizes PCF count
// Method 2: Specify PCF count and strategy
config.setDynamicConfig(24, 3, DISTRIBUTE_BALANCED);
// Method 3: Custom addresses and distribution
uint8_t addresses[] = {0x27, 0x38, 0x45};
uint8_t channels[] = {8, 8, 8};
config.setDynamicWithAddresses(24, 3, addresses, channels);
// Method 4: Full custom control
PCFDistribution custom[2] = {
{0x27, 6, 0, 0, true},
{0x38, 6, 6, 0, true}
};
config.setCustomDistribution(custom, 2);
// Validate and debug
if (config.validateConfiguration()) {
Serial.println("Configuration OK!");
config.printDistribution();
} else {
Serial.println("Configuration error!");
}
}
void loop() {
// Configuration is static after setup
}
Best Practices
Auto Distribution
Use setDynamicConfig(channels) for automatic optimization
Validation
Always call validateConfiguration() before use
I2C Scan
Use I2CScanner to verify PCF addresses before configuration
Debug Output
Use printDistribution() to verify channel mapping
ESP32
Full support with hardware I2C