-
Notifications
You must be signed in to change notification settings - Fork 7.6k
Changing I2C pins on the fly (Question/suggestion, not a bug) #5669
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Comments
I can say it is good or bad idea, because i didnt test it, but some time ago i found that you can call as many times as you want with |
Interesting! I'm more surprised that works reliably since i2cInit (called internally by Wire.begin) does lots of things, including "checking the i2c line state" and failing completely if the line states are low, so that would seem risky to me. :) Very good to know it did work for you though. |
@leifclaesson , please check PR #5664 As @chegewara already said, you can call TwoWire::begin(sda, scl, clock) with new pins or new i2c bus clock at any time, and doing so, reset it to the pins and values you need on the fly. This same functionality (changing pins on the fly with begin) will work in this refactoring new i2c version as well. I've tested it and it works fine as well in the PR code. On any Core Version (1.0.6 to 2.0.1), the methods TwoWire::setSDA (v2.01 only), TwoWire::setSCL (v2.01 only), TwoWire::setPins and TwoWire::setClock can only be used before calling TwoWire::begin. |
@leifclaesson , could you please check if the code in the PR #5664 works "with the line states in low"? Just curious... Another option is to use IDF function: You can use it directly with Arduino code. Thanks. |
Hi!
On an already finished custom PCB based on the WROOM-32U module, I realized I needed another I2C bus.
I'm already using one high-speed I2C bus locally on the PCB for an OLED display, and the second I2C bus is brought out to headers for use to interface with external I/O expander boards with relays, also custom.
It's not a matter of running out of addresses -- with too many external boards the signalling just became unreliable -- the fact that these boards live in an electrical box around lots of 240 volt wiring might have something to do with it.
I have plenty of other pins brought out to headers, so I looked for a way to change TwoWire(0) or TwoWire(1) pins on the fly, and was rather surprised that there wasn't a way!
So, I dug into the Arduino Core source code and found esp32-hal-i2c.c and after some analysis, I wrote the following new function into the aforementioned file:
With this function, I can change the I2C pins before calling the normal Wire functions, and change them back again afterwards.
Let me make absolutely clear, it works perfectly and it solved my problem.
My questions are:
As the code is written now, although you could call the i2cAttach/Detach functions from your own code, you don't have access to the
i2c_dev_t *
pointer unless you subclass TwoWire and save it from the i2cInit return value, and even if you do that, thei2c_dev_t
and related definition such as enums are all private so you still couldn't change the sda/scl pins in the structure.So, I tried simply modifying my copy, and it works beautifully. The lack of access to the i2c_dev_t pointer is why I simply used the i2c_num value (0 or 1), if I'm hacking the core code anyway why bother making it pretty.
Is there a better way? I'd be surprised if I was the last/only person to need more i2c buses by pin reassignment even if it's probably not all that common.
The text was updated successfully, but these errors were encountered: