{"id":13802296,"url":"https://github.com/mcauser/micropython-mcp23017","last_synced_at":"2025-07-28T05:32:44.752Z","repository":{"id":50424416,"uuid":"226629483","full_name":"mcauser/micropython-mcp23017","owner":"mcauser","description":"MicroPython driver for MCP23017 16-bit I/O Expander","archived":false,"fork":false,"pushed_at":"2024-02-05T19:55:10.000Z","size":844,"stargazers_count":76,"open_issues_count":5,"forks_count":21,"subscribers_count":6,"default_branch":"master","last_synced_at":"2025-04-04T15:50:42.051Z","etag":null,"topics":["esp32","esp8266","io-expander","mcp23017","micropython"],"latest_commit_sha":null,"homepage":null,"language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/mcauser.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE.txt","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2019-12-08T07:15:23.000Z","updated_at":"2025-01-06T14:12:02.000Z","dependencies_parsed_at":"2024-11-18T17:44:27.626Z","dependency_job_id":"ce5ec1a6-c663-4b59-bb33-94e65329f23f","html_url":"https://github.com/mcauser/micropython-mcp23017","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/mcauser/micropython-mcp23017","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mcauser%2Fmicropython-mcp23017","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mcauser%2Fmicropython-mcp23017/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mcauser%2Fmicropython-mcp23017/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mcauser%2Fmicropython-mcp23017/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/mcauser","download_url":"https://codeload.github.com/mcauser/micropython-mcp23017/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mcauser%2Fmicropython-mcp23017/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":267468371,"owners_count":24092330,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","status":"online","status_checked_at":"2025-07-28T02:00:09.689Z","response_time":68,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["esp32","esp8266","io-expander","mcp23017","micropython"],"created_at":"2024-08-04T00:01:41.430Z","updated_at":"2025-07-28T05:32:44.472Z","avatar_url":"https://github.com/mcauser.png","language":"Python","readme":"# MicroPython MCP23017 16-bit I/O Expander\n\nA MicroPython library for the MCP23017 16-bit I/O Expander with I2C Interface.\n\n![demo](docs/demo.jpg)\n\n## Examples\n\n```python\nfrom machine import Pin, I2C\nimport mcp23017\ni2c = I2C(scl=Pin(22), sda=Pin(21))\nmcp = mcp23017.MCP23017(i2c, 0x20)\n\n# list interface\nmcp[0].input()\nmcp[1].input(pull=1)\nmcp[1].value()\nmcp[2].output(1)\nmcp[3].output(0)\n\n# method interface\nmcp.pin(0, mode=1)\nmcp.pin(1, mode=1, pullup=True)\nmcp.pin(1)\nmcp.pin(2, mode=0, value=1)\nmcp.pin(3, mode=0, value=0)\n\nmcp.config(interrupt_polarity=0, interrupt_mirror=1)\n\n# property interface 16-bit\nmcp.mode = 0xfffe\nmcp.gpio = 0x0001\n\n# property interface 8-bit\nmcp.porta.mode = 0xfe\nmcp.portb.mode = 0xff\nmcp.porta.gpio = 0x01\nmcp.portb.gpio = 0x02\n```\n\nFor more detailed examples, see [examples](/examples).\n\n\n## Pins\n\nPin   | Type | Description\n:----:|:----:|:----------------------------------------\nA0    | I    | Address select 1, connect to VCC or GND\nA1    | I    | Address select 2, connect to VCC or GND\nA2    | I    | Address select 3, connect to VCC or GND\nINTA  | O    | Interrupt output for port A\nINTB  | O    | Interrupt output for port B\nRESET | I    | Reset, active LOW\nGPA0  | IO   | Port A, Pin 0\nGPA1  | IO   | Port A, Pin 1\nGPA2  | IO   | Port A, Pin 2\nGPA3  | IO   | Port A, Pin 3\nGPA4  | IO   | Port A, Pin 4\nGPA5  | IO   | Port A, Pin 5\nGPA6  | IO   | Port A, Pin 6\nGPA7  | IO   | Port A, Pin 7\nGPB0  | IO   | Port B, Pin 0\nGPB1  | IO   | Port B, Pin 1\nGPB2  | IO   | Port B, Pin 2\nGPB3  | IO   | Port B, Pin 3\nGPB4  | IO   | Port B, Pin 4\nGPB5  | IO   | Port B, Pin 5\nGPB6  | IO   | Port B, Pin 6\nGPB7  | IO   | Port B, Pin 7\nVDD   | P    | Power (3V3 or 5V)\nVSS   | P    | Ground\nCS    | I    | Not used - SPI Chip Select (CS) on the SPI version (MCP23S17)\nSCK   | I    | I2C Serial Clock - SPI Serial Clock (SCK) on the SPI version\nSI    | I    | I2C Serial Data - SPI Serial Data In (MOSI) on the SPI version\nSO    | O    | Not used - SPI Serial Data Out (MISO) on the SPI version\n\n\n## Methods\n\n### __init__(i2c, address=0x20)\n\nConstruct with a reference to I2C and set the device address (0x20-0x27).\nIf are you not sure what it is, run an `i2c.scan()`.\n\n### init()\n\nInitialises the device.\n\n### config(interrupt_polarity=None, interrupt_open_drain=None, sda_slew=None, sequential_operation=None, interrupt_mirror=None, bank=None)\n\nConfigures the device by writing to the iocon register.\n\n### pin(pin, mode=None, value=None, pullup=None, polarity=None, interrupt_enable=None, interrupt_compare_default=None, default_value=None)\n\nMethod for getting, setting or configuring a single pin.\nIf no value is provided, the port will read the value from the GPIO register and return for the current pin.\nIf a value is provided, the port will write the value to the GPIO register.\nValid pin range 0-15.\nAll of the other optional arguments are booleans.\n\n### interrupt_triggered_gpio(port)\n\nAfter an interrupt fires, this method tells you which pin triggered it and clears the interrupt so it can fire again.\nIt's port specific as there are port specific interrupts.\n\n### interrupt_captured_gpio(port)\n\nThis method tells you the state of the GPIO register at the time the interrupt fired.\n\n### _flip_bit(value, condition, bit)\n\nPrivate method for toggling a bit in a value based on a condition.\n\n### __getitem__(pin)\n\nProvides the list interface for interacting with \"virtual pins\".\n\n\n## Virtual pin methods\n\n### __init__(pin, port)\n\nConstructed with a specific pin (0-7) and the port it belongs to.\n\n### _flip_bit(value, condition)\n\nPrivate method for toggling a bit in a value based on a condition.\n\n### _get_bit(value)\n\nPrivate method for getting a single bit from the given value based on the current pin\n\n### value(val=None)\n\nReads or writes the current pins value (0-1).\n\n### input(pull=None)\n\nConfigures the pin as input and optionally configures it to be pulled up.\n\n### output(val=None)\n\nConfigures the pin to be output and optionally sets it's value (0-1).\n\n\n## Port methods\n\n### __init__(port, mcp)\n\nConstructed with the port number (0-1) and a reference to the main class.\n\n### _which_reg(reg)\n\nPrivate method for calculating which register to write to as their address\ncan change when configured to use different addressing scheme (iocon.bank).\n\n### _flip_property_bit(reg, condition, bit)\n\nPrivate method for toggling a bit in a register based on a condition.\n\n### _read(reg)\n\nPrivate method for reading the register over I2C.\n\n### _write(reg, val)\n\nPrivate method for writing to the register over I2C.\n\n\n## Properties\n\nThere are two sets of properties, one on the main class and one on each port class.\n\nProperties on the main class wrap the properties in each port.\n\nYou can get and set on the main class properties with a 16-bit integer and it splits\nit into two 8-bit integers and forwards to each port.\n\nYou can also get and set on the ports a and b directly with 8-bit integers.\n\nThe registers accessible using the property interface are:\n\nProperty                  | Register | Type | Description\n:------------------------ |:-------- |:---- |:-----------------------------------------------\nmode                      | iodir    | R/W  | Direction 0=output, 1=input\ninput_polarity            | ipol     | R/W  | Input polarity 0=normal, 1=invert\ninterrupt_enable          | gpinten  | R/W  | Interrupt enable 0=disabled, 1=enabled\ndefault_value             | defval   | R/W  | Interrupt default value\ninterrupt_compare_default | intcon   | R/W  | Interrupt config\nio_config                 | iocon    | R/W  | IO config\npullup                    | gppu     | R/W  | Pull-up\ninterrupt_flag            | intf     | R    | Interrupt flag 1=this pin triggered interrupt\ninterrupt_captured        | intcap   | R    | Interrupt captured - state of pins at interrupt\ngpio                      | gpio     | R/W  | General purpose IO\noutput_latch              | olat     | R/W  | Output latch - which output pins are high\n\n\nGetter on the main class reads the GPIO register and returns a 16-bit integer.\nThe lower 8 bits represent port a.\n```python\ngpio\n```\n\nGetter on the nested port classes reads their GPIO registers and returns 8-bit integers.\n```python\nporta.gpio\nportb.gpio\n```\n\nSetter on the main class writes to the both of the GPIO registers in port a and b.\nThe lower 8 bits represent port a.\n```python\ngpio = 0xffee\n```\n\nSetter on the nested port classes writes to their GPIO registers.\n```python\nporta.gpio = 0xee\nportb.gpio = 0xff\n```\n\nYou can use bitwise assignment operators to toggle specific pins, which performs a read, modify, write.\n\n```python\n# set all pins low\nporta.gpio = 0\n# set the first 4 pins high\nporta.gpio |= 0x0f\n# set the first 2 pins low\nporta.gpio \u0026= ~0x03\n# invert the first 4 pins\nporta.gpio ^= 0x0f\n```\n\n## Ports\n\nFeaturing a 16-bit bidirectional I/O port where each pin can be configured as active-high, active-low or open-drain.\nPolarity can be inverted on any of the pins.\nWork on both 3V3 or 5V logic.\n\n* A0-A7\n* B0-B7\n\n## Interrupts\n\nTwo independent interrupts, one for each 8-bit port, which can be linked/mirrored using `interrupt_mirror` config, so that any pin change triggers both.\n\nInterrupt can be configured to watch any specific pins and fire on pin change or when the pin differs from the defaults you set.\n\n* INTA - for pins A0-A7\n* INTB - for pins B0-B7\n\nOnce an interrupt fires, you need to read either the interrupt_flag (INTCAP) or gpio (GPIO) registers to clear it.\n\n## I2C Interface\n\nThere are three address select pins (A0,A1,A2) providing addresses 0x20-0x27 for up to 8 of these devices on the I2C bus.\n\nRequires 10k pull-up resistors on the SCL + SDA lines.\n\nA0  | A1  | A2  | I2C Address\n:---|:----|:----|:-----------\nGND | GND | GND | 0x20\n3V3 | GND | GND | 0x21\nGND | 3V3 | GND | 0x22\n3V3 | 3V3 | GND | 0x23\nGND | GND | 3V3 | 0x24\n3V3 | GND | 3V3 | 0x25\nGND | 3V3 | 3V3 | 0x26\n3V3 | 3V3 | 3V3 | 0x27\n\n## Parts\n\n* [MCP23017 black board](https://www.aliexpress.com/item/32957655097.html) $1.40 AUD\n* [MCP23017 green board](https://www.aliexpress.com/item/32945601544.html) $1.99 AUD\n* [MCP23017 char lcd board](https://www.aliexpress.com/item/32885659482.html) $2.16 AUD\n* [MCP23017 DIP-28](https://www.aliexpress.com/item/32665631086.html) $1.58 AUD\n* [TinyPICO](https://www.tinypico.com/) $20.00 USD\n* [Wemos D1 Mini](https://www.aliexpress.com/item/32529101036.html) $5.20 AUD\n\n## Connections\n\n### TinyPICO ESP32\n\n```python\nfrom machine import Pin, I2C\nimport mcp23017\ni2c = I2C(scl=Pin(22), sda=Pin(21))\nmcp = mcp23017.MCP23017(i2c, 0x20)\n```\n\nMCP23017 | TinyPICO (ESP32)\n-------- | ----------------\nVCC      | 3V3\nGND      | GND\nSCL      | 22 (SCL)\nSDA      | 21 (SDA)\nINTA     | 4 (Optional)\n\n### Wemos D1 Mini (ESP8266)\n\n```python\nfrom machine import Pin, I2C\nimport mcp23017\ni2c = I2C(scl=Pin(5), sda=Pin(4))\nmcp = mcp23017.MCP23017(i2c, 0x20)\n```\n\nMCP23017 | Wemos D1 Mini (ESP8266)\n-------- | -----------------------\nVCC      | 3V3\nGND      | GND\nSCL      | D1 (GPIO5)\nSDA      | D2 (GPIO4)\nINTA     | D5 (GPIO14 Optional)\n\n## Links\n\n* [micropython.org](http://micropython.org)\n* [MCP23017 product page](https://www.microchip.com/wwwproducts/en/MCP23017)\n* [MCP23017 datasheet](docs/mcp23017.pdf)\n* [TinyPICO Getting Started](https://www.tinypico.com/gettingstarted)\n* [Wemos D1 Mini](https://wiki.wemos.cc/products:d1:d1_mini)\n\n## License\n\nLicensed under the [MIT License](http://opensource.org/licenses/MIT).\n\nCopyright (c) 2019 Mike Causer\n","funding_links":[],"categories":["Libraries"],"sub_categories":["IO"],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmcauser%2Fmicropython-mcp23017","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fmcauser%2Fmicropython-mcp23017","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmcauser%2Fmicropython-mcp23017/lists"}