0
\$\begingroup\$

I have two identical I2C devices that I need to use with a single MCU (arduino nano). I have read here on EE that an I2C multiplexer can be used to switch between multiple I2C buses. But I find them too expensive. A single pca9540 multiplexer costs at least $5, which is too much. (A complete 40pin pic MCU would costs less...) My idea is to use a digital output pin of the mcu to switch between two different scl lines. Would that work? Is it possible to do it with a few transistors? (2n2222 or BC547 etc.) That would keep costs down.

\$\endgroup\$
  • 1
    \$\begingroup\$ You could try using a CD4066 analog switch -- they're about 40¢. \$\endgroup\$ – tcrosley Jan 1 '16 at 19:12
  • \$\begingroup\$ Good idea, but at 5V it has about 1Kohm on-state resistance. Isn't it a problem for the I2C devices to have an 1K series resistor on the line? \$\endgroup\$ – nagylzs Jan 1 '16 at 19:27
  • \$\begingroup\$ Yes -- if you had a 1k pull-up and a 1k series resistance, when pulling down on the line, you'd end up just sitting at 0.5Vcc instead of a logic low. \$\endgroup\$ – Krunal Desai Jan 1 '16 at 19:46
  • 1
    \$\begingroup\$ @nagylzs I didn't realize the 4066 had such a high on-resistance. The TS5A4624 SPDT switch has an on resistance of 1Ω and costs 59¢ at Digi-Key. It only comes in a SMT package (SC-70), but it's easy enough to solder. \$\endgroup\$ – tcrosley Jan 1 '16 at 20:00
  • 1
    \$\begingroup\$ can't set them to different I2C addresses by jumpers? \$\endgroup\$ – Jasen Jan 1 '16 at 23:14
1
\$\begingroup\$

Here is the transistor solution. You need to make sure SEL_1 and SEL_2 are not high at the same time. You need to make sure that one of them is high all the time (because the pullups are on the other side of the FET). If you are not confident of managing that in software, maybe use an inverter. The input to the inverter will be a GPIO, and will also be SEL_1. The output of the inverter will be SEL_2.

schematic

simulate this circuit – Schematic created using CircuitLab

I2C_DA is the I2C data line from the processor. SEL_1 is a GPIO. When high, it selects slave 1. This means that slave 1 will be able to see data sent by the bus master. When SEL_1 is low, slave 1 will only see the data line being high, so it will never respond.

SEL2 is a different GPIO. When SEL_2 is high, it selects slave 2. You should avoid having them both be high. It will not create contention (open collector data line) but if you send out a read on the slave address, and both selects are high, you will get the type of bus collision you are trying to avoid. And you might not realize it right away. The data would not appear obviously corrupted.

| improve this answer | |
\$\endgroup\$
  • \$\begingroup\$ The body diodes of those MOSFETs will allow voltage to leak across them even when off -- I really hate CircuitLab's transistor symbol. Even if both are off, you'll get the voltage on I2C_DA -0.7V on the slaves, if for some reason the slave is driving low. \$\endgroup\$ – Krunal Desai Jan 2 '16 at 7:43
  • 1
    \$\begingroup\$ Hey, @KrunalDesai, that is not a mistake. I did it that way on purpose. Those are NMOS. The drain is connected to the slaves. When the FET's are off, the drains will be high (pulled up by the resistor). If the select lines are used correctly, the slaves will never drive the data line when they are not supposed to. But you are right that they cannot prevent the slave from driving the line low, even when they are off. \$\endgroup\$ – mkeith Jan 2 '16 at 7:50
  • \$\begingroup\$ The idea is to set the select lines correctly before you query the device. Since the de-selected device does not see data toggling, it will never respond. Only the selected device will respond. \$\endgroup\$ – mkeith Jan 2 '16 at 7:53
  • \$\begingroup\$ Would this also work with 2n7000 mosfets? They are available in TO92 package and I can buy 100pcs for less than $4. \$\endgroup\$ – nagylzs Jan 2 '16 at 9:03
  • \$\begingroup\$ I'm accepting this solution because it is cheaper, but the other one is a good one too. \$\endgroup\$ – nagylzs Jan 2 '16 at 13:09
1
\$\begingroup\$

Assuming you're in a single-master situation, using an IC like the TS12A12511, a single SPDT switch would let you do this with one extra I/O pin:

TS12A12511 Sample

MCU_GPIO controls which one you talk too -- I assume you don't need a 'float / no-connect mode'. The on-state resistance of this switch is ~5 ohms, which is virtually nothing for I2C. I assume that your I2C bus runs at the MCU voltage, so you should tie that to the V+ pin on the switch. The part can slew rail-to-rail, so there should be no problems there.

I would then also place my I2C pull-up resistors on both SLAVE_0_SCL and SLAVE_1_SCL -- this prevents floating input pins at the slaves which can cause undesired behavior, which would be the case if you left the SCL pull-up on the 'MCU_SCL' side of the switch.

I don't know what your quantities are, but this drops to about $1 at 100 pieces.

| improve this answer | |
\$\endgroup\$
  • \$\begingroup\$ Whoops, that's a 10-pin DFN. Hold on, I'll change it to a more suitable part -- DONE. \$\endgroup\$ – Krunal Desai Jan 1 '16 at 19:29

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.