{"id":20989814,"url":"https://github.com/robtillaart/max14661","last_synced_at":"2026-04-19T19:07:01.733Z","repository":{"id":45322961,"uuid":"373277929","full_name":"RobTillaart/MAX14661","owner":"RobTillaart","description":"Arduino library for MAX14661 16 channel I2C multiplexer","archived":false,"fork":false,"pushed_at":"2024-04-13T09:06:13.000Z","size":573,"stargazers_count":4,"open_issues_count":0,"forks_count":1,"subscribers_count":2,"default_branch":"master","last_synced_at":"2024-08-07T18:27:17.978Z","etag":null,"topics":["arduino","i2c","multiplexer"],"latest_commit_sha":null,"homepage":"","language":"C++","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/RobTillaart.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":".github/FUNDING.yml","license":"LICENSE","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},"funding":{"github":"RobTillaart","custom":"https://www.paypal.me/robtillaart"}},"created_at":"2021-06-02T19:14:45.000Z","updated_at":"2023-10-13T20:18:01.000Z","dependencies_parsed_at":"2023-12-07T17:44:35.571Z","dependency_job_id":null,"html_url":"https://github.com/RobTillaart/MAX14661","commit_stats":null,"previous_names":[],"tags_count":7,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/RobTillaart%2FMAX14661","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/RobTillaart%2FMAX14661/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/RobTillaart%2FMAX14661/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/RobTillaart%2FMAX14661/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/RobTillaart","download_url":"https://codeload.github.com/RobTillaart/MAX14661/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":225305683,"owners_count":17453429,"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","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":["arduino","i2c","multiplexer"],"created_at":"2024-11-19T06:26:18.402Z","updated_at":"2026-04-19T19:07:01.724Z","avatar_url":"https://github.com/RobTillaart.png","language":"C++","funding_links":["https://github.com/sponsors/RobTillaart","https://www.paypal.me/robtillaart"],"categories":[],"sub_categories":[],"readme":"\n[![Arduino CI](https://github.com/RobTillaart/MAX14661/workflows/Arduino%20CI/badge.svg)](https://github.com/marketplace/actions/arduino_ci)\n[![Arduino-lint](https://github.com/RobTillaart/MAX14661/actions/workflows/arduino-lint.yml/badge.svg)](https://github.com/RobTillaart/MAX14661/actions/workflows/arduino-lint.yml)\n[![JSON check](https://github.com/RobTillaart/MAX14661/actions/workflows/jsoncheck.yml/badge.svg)](https://github.com/RobTillaart/MAX14661/actions/workflows/jsoncheck.yml)\n[![GitHub issues](https://img.shields.io/github/issues/RobTillaart/MAX14661.svg)](https://github.com/RobTillaart/MAX14661/issues)\n\n[![License: MIT](https://img.shields.io/badge/license-MIT-green.svg)](https://github.com/RobTillaart/MAX14661/blob/master/LICENSE)\n[![GitHub release](https://img.shields.io/github/release/RobTillaart/MAX14661.svg?maxAge=3600)](https://github.com/RobTillaart/MAX14661/releases)\n[![PlatformIO Registry](https://badges.registry.platformio.org/packages/robtillaart/library/MAX14661.svg)](https://registry.platformio.org/libraries/robtillaart/MAX14661)\n\n\n# MAX14661\n\nArduino library for MAX14661 multiplexer with I2C interface.\n\n\n## Description\n\n**Experimental**\n\nThe MAX14661 multiplexer is a sort of 16 x 2 channel multiplexer.\nThe device has 16 ABxx lines which can be connected to COM-A and/or COM-B.\n\nThe library provides four interfaces (details see below)\n- **PAIR** switch A and B in pairs\n- **SHADOW** use a shadow register to prepare and set all simultaneously.\n- **MUX** open channels exclusively.\n- **FULL** control all as you like.\n\nMixing these interfaces is allowed in theory but definitely not advised as\nespecially the **PAIR** interface assumes that A and B selections\nare kept in sync.\nSo depending on your application choose the interface you want to use.\n\n**Warning**\n\nBe aware that by switching on both the A and B switch for any\nline ABxx will short-circuit the COM-A and COM-B. such short-circuit would\nalso connect any ABxx line to any other if one of their switches is switched on.\nThere might be projects when such short-circuit is no problem and if\nintended it can be done, but be careful.\n\nFeedback as always is welcome, please open an issue on GitHub.\n\n\n### SPI vs I2C\n\nThe MAX14661 device can be controlled by SPI or I2C.\nThis library implements only the I2C interface.\nIf you need a SPI library for the MAX14661, feel free to contact me.\n\n\n### 0.3.0 Breaking change\n\nVersion 0.3.0 introduced a breaking change.\n\nThe PAIR interface got a **complete rewrite** so its functionality matches\nthe intention to work as a multiplexer for 2-wire based protocols like\nI2C and Serial.\nThe PAIR functions of pre-0.3.0 version are all removed and new functions\nhave been added to replace them, see below.\n\nThe FULL CONTROL interface got a **complete rewrite**.\nThe FULL CONTROL functions of pre-0.3.0 version are all removed and new functions\nhave been added to replace them, see below.\n\n\n### 0.2.0 Breaking change\n\nVersion 0.2.0 introduced a breaking change.\nYou cannot set the pins in **begin()** any more.\nThis reduces the dependency of processor dependent Wire implementations.\nThe user has to call **Wire.begin()** and can optionally set the Wire pins\nbefore calling **begin()**.\n\n### Related\n\n- https://github.com/RobTillaart/TCA9548 specific I2C multiplexer.\n- https://github.com/RobTillaart/HC4067 1x16 channel multiplexer.\n- https://github.com/RobTillaart/HC4051 1x8 channel multiplexer.\n- https://github.com/RobTillaart/HC4052 2x4 channel multiplexer.\n- https://github.com/RobTillaart/HC4053 2x3 channel multiplexer.\n- https://github.com/RobTillaart/I2C_HC4067 (1x16 mux - using I2C PCF8574)\n\n\n##I2C\n\n### I2C address\n\nThe I2C address can be adjusted by 2 address lines A0 and A1.\nAddresses go from 0x4C (76) .. 0x4F (79). See table 3 datasheet.\nThis implies you may have up to 4 MAX14661 multiplexers on one I2C bus.\nIf you need more, consider a TCA9548, see below.\n\nAccording to the datasheet the I2C Serial-Clock Frequency is max 400 kHz.\nThis needs to be tested.\n(SPI can do 10 MHz)\n\n\n### I2C multiplexing\n\nSometimes you need to control more devices than possible with the default\naddress range the device provides.\nThis is possible with an I2C multiplexer e.g. TCA9548 which creates up\nto eight channels (think of it as I2C subnets) which can use the complete\naddress range of the device.\n\nDrawback of using a multiplexer is that it takes more administration in\nyour code e.g. which device is on which channel.\nThis will slow down the access, which must be taken into account when\ndeciding which devices are on which channel.\nAlso note that switching between channels will slow down other devices\ntoo if they are behind the multiplexer.\n\n- https://github.com/RobTillaart/TCA9548\n\n\n## Interface\n\n```cpp\n#include \"MAX14661.h\"\n```\n\n\n### Constructor\n\n- **MAX14661(uint8_t deviceAddress, TwoWire \\*wire = \u0026Wire)** Constructor with device address,\nand optional the Wire interface as parameter.\n- **bool begin()** initializes the wire interface.\nReturns true if device address is seen on I2C bus.\n- **bool isConnected()** checks if the device address is visible on the I2C bus.\n\n\n### PAIR interface\n\n(note the PAIR interface is completely rewritten in 0.3.0)\n\nThe ABxx lines are considered to form 8 pairs { (0,1), (2,3), (4,5), ... (14,15) }.\nThe functions in this interface manage the switches in pairs, so when e.g. pair 3\nis connected, AB06 connects with COM-A and AB07 connects with COM-B.\nThis allows one to multiplex an I2C bus, a Serial TX/RX pair, or any 2 wires based protocol.\n\n|  pair  |  COM-A  |  COM-B  |  notes  |\n|:------:|:-------:|:-------:|:--------|\n|   0    |    0    |    1    |\n|   1    |    2    |    3    |\n|   2    |    4    |    5    |\n|   3    |    6    |    7    |\n|   4    |    8    |    9    |\n|   5    |   10    |   11    |\n|   6    |   12    |   13    |\n|   7    |   14    |   15    |\n\nThe PAIR interface allows to have multiple pairs to be connected in parallel.\n\n- **bool connectPair(uint8_t pair)** connects a pair of lines to COM-A, COM-B.\n- **bool disconnectPair(uint8_t pair)** disconnects a pair of lines from COM-A, COM-B.\n- **bool isConnectedPair(uint8_t pair)** returns true if pair is connected to COM-A, COM-B.\n- **void disconnectAllPairs()** disconnects all pairs.\n\n\n### SHADOW interface\n\nThe SHADOW interface allows one to prepare which switches should be set,\nand activate them all (nearly) simultaneously.\n\n- **bool shadowClear()** clears all shadow registers.\n- **void activateShadow()** write all shadow registers to the direction\nregisters of COM-A and COM-B at once.\n\nPrepare multiple channels at once. This is way faster than per channel.\n\n- **bool setShadowChannelMaskA(uint16_t mask)** prepare all channels at once.\n- **uint16_t getShadowChannelMaskA()** read the COM-A shadow registers.\n- **bool setShadowChannelMaskB(uint16_t mask)** prepare all channels at once.\n- **uint16_t getShadowChannelMaskB()** read COM-B shadow registers.\n\nPrepare per channel for COM-A.\n\n- **bool isOpenShadowChannelA(uint8_t channel)** read status of specific channel in COM-A shadow registers.\n- **void openShadowChannelA(uint8_t channel)** prepare a specific channel to open.\n- **void closeShadowChannelA(uint8_t channel)** prepare a specific channel to close.\n\nPrepare per channel for COM-B.\n\n- **bool isOpenShadowChannelB(uint8_t channel)** read status of specific channel in COM-B shadow registers.\n- **void openShadowChannelB(uint8_t channel)** prepare a specific channel to open.\n- **void closeShadowChannelB(uint8_t channel)** prepare a specific channel to close.\n\nNote: there is no command that sets both A and B exactly simultaneously.\n\n\n### MUX interface\n\nThe MUX interface allows one channel (0..15) to be open at a time.\n\n- **void MUXA(uint8_t channel)** if channel \u003c 16 only that channel will be selected.\nIt will disconnect previous selected channels.\nAll values \u003e 15 will select no channel.\n- **uint8_t getMUXA()** returns the selected channel.\n255 means no channel is selected (all switches off)\n- **void MUXB(uint8_t channel)** if channel \u003c 16 only that channel will be selected.\nIt will disconnect previous selected channels.\nAll values \u003e 15 will select no channel.\n- **uint8_t getMUXB()** returns the selected channel.\n255 means no channel is selected (all switches off)\n\n\n### FULL CONTROL interface\n\nFull control per channel, any combination of switches is possible.\nUse with care as these can interfere e.g. with the PAIR interface,\nor one can connect COM-A to COM-B, causing all pins to be connected to each other.\n\nAll functions return false if the channel \u003e 15.\n\n- **bool connectA(uint8_t channel)** idem\n- **bool connectB(uint8_t channel)** idem\n- **bool disconnectA(uint8_t channel)** idem\n- **bool disconnectB(uint8_t channel)** idem\n- **bool disconnectAll()** fast disconnect of all ABxx lines\n\n\n### LOW LEVEL CONTROL interface\n\nCheck datasheet for the meaning of and the values in the registers.\n\n- **uint8_t readRegister(uint8_t reg)** read low level device register.\n- **int writeRegister(uint8_t reg, uint8_t value)** write value to device register.\n\n\n### Error handling\n\n- **int lastError()** returns the last error, resets the internal error flag.\n\n|  Define                    |  value  |  notes  |\n|:---------------------------|:-------:|:-------:|\n|  MAX14661_OK               |  0x00   |\n|  MAX14661_ERR_I2C_READ     |  0x80   |\n|  MAX14661_ERR_I2C_REQUEST  |  0x81   |\n|  MAX14661_ERR_CHANNEL      |  0x90   |\n|  MAX14661_ERR_ADDRESS      |  0x91   |\n\nNote: here are also low level Wire errors possible. (how to handle them).\n\n\n## Future\n\n#### Must\n\n- improve documentation\n- get hardware for testing.\n\n#### Should\n\n- test behaviour.\n\n#### Could\n\n- optimizations\n  - low level bit set/clear/get\n  - read/write 2 bytes at once.\n  - cache direct registers. (faster, but possible incorrect).\n  - only write register if changed.\n- **ShutDown()** SD pin. For low power datasheet p.15\n  - document it.\n  - implement it.\n\n#### Wont\n\n- SPI interface.\n  - separate (derived ?) class, upon request maybe\n- initial values parameter for begin()?\n  - depends on interface (PAIR MUX SHADOW FULL) used, so ambiguous.\n  - ==\u003e user task.\n- use an internal mode to see which of the three interfaces is used\n    consequently or not?  performance penalty\n    ==\u003e user responsibility\n- write unit tests.\n  - needs full mock,\n- redo functions signature void() =\u003e bool() so more detail or even int()?\n  =\u003e affects performance.\n  =\u003e user can check lastError();\n\n\n## Support\n\nIf you appreciate my libraries, you can support the development and maintenance.\nImprove the quality of the libraries by providing issues and Pull Requests, or\ndonate through PayPal or GitHub sponsors.\n\nThank you,\n\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Frobtillaart%2Fmax14661","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Frobtillaart%2Fmax14661","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Frobtillaart%2Fmax14661/lists"}