[mcp23016] Migrate to CachedGpioExpander to reduce I2C bus usage - #10581
Conversation
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## dev #10581 +/- ##
=======================================
Coverage 60.43% 60.43%
=======================================
Files 51 51
Lines 10482 10482
Branches 1400 1400
=======================================
Hits 6335 6335
Misses 3789 3789
Partials 358 358 ☔ View full report in Codecov by Sentry. 🚀 New features to boost your workflow:
|
|
To use the changes from this PR as an external component, add the following to your ESPHome configuration YAML file: external_components:
- source: github://pr#10581
components: [mcp23016]
refresh: 1h(Added by the PR bot) |
There was a problem hiding this comment.
Pull Request Overview
This PR migrates the MCP23016 I/O expander component to use the CachedGpioExpander base class to reduce I2C bus traffic by eliminating redundant reads when multiple pins from the same bank are accessed within a single loop cycle.
- Inherits from
CachedGpioExpander<uint8_t, 16>to implement caching for 2 banks of 8 pins each - Implements required virtual methods for hardware reads/writes and cache management
- Adds loop-based cache invalidation to ensure fresh data each cycle
Reviewed Changes
Copilot reviewed 3 out of 3 changed files in this pull request and generated 2 comments.
| File | Description |
|---|---|
| esphome/components/mcp23016/mcp23016.h | Adds CachedGpioExpander inheritance, new virtual methods, and input cache member variable |
| esphome/components/mcp23016/mcp23016.cpp | Implements caching logic, replaces direct digital_read/write methods, and adds loop method |
| esphome/components/mcp23016/init.py | Adds gpio_expander as auto-loaded dependency |
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
|
thanks |
What does this implement/fix?
This PR migrates the MCP23016 I/O expander component to use the
CachedGpioExpanderbase class, eliminating redundant I2C reads when multiple pins from the same bank are accessed in a single loop cycle.The MCP23016 component was performing one I2C read transaction for every
digital_read()call, even when reading multiple pins from the same 8-bit bank. Since the MCP23016 reads an entire 8-bit bank at once via I2C, this created unnecessary bus traffic when multiple pins from the same bank were read in the same loop cycle.Types of changes
Related issue or feature (if applicable):
CachedGpioExpanderbase class that's already proven with MCP23008/MCP23017Pull request in esphome-docs with documentation (if applicable):
Test Environment
Note: I don't have MCP23016 hardware available for physical testing. The changes follow the same pattern successfully used in MCP23008/MCP23017 (which already use CachedGpioExpander) and the code compiles successfully. Testing assistance from the community would be appreciated.
Example entry for
config.yaml:Checklist:
tests/folder).If user exposed functionality or configuration variables are added/changed:
Changes Made
Migrated MCP23016 to CachedGpioExpander base class:
gpio_expander::CachedGpioExpander<uint8_t, 16>AUTO_LOAD = ["gpio_expander"]to Python configurationImplemented required virtual methods:
digital_read_hw(uint8_t pin)- Reads the relevant 8-bit bank (GP0 or GP1) based on pin number, returns true/false for success/failuredigital_read_cache(uint8_t pin)- Returns cached pin value frominput_mask_digital_write_hw(uint8_t pin, bool value)- Updates output latch register via existingupdate_reg_()methodCache management:
loop()method that callsreset_pin_cache_()to invalidate cache at start of each loopPreserved existing functionality:
Expected Performance Impact
Based on similar optimizations in other I/O expander components:
The optimization is particularly beneficial when:
Technical Details
The MCP23016 reads its GPIO banks separately:
Using
CachedGpioExpander<uint8_t, 16>with 2 banks perfectly matches this hardware pattern:This approach is identical to the already-proven MCP23017 implementation, which uses the same 2-bank architecture.