Raspberry Pi and I2C devices of different voltage

After my recent posts on using the MCP23017 I/O expander with the Raspberry Pi several people have queried the connection of an I2C device running at 5v to the Raspberry Pi’s 3v3 I/O. The reason why this is safe in this case is that on an I2C bus the clock and data lines are open-drain lines that are pulled high and devices on the I2C bus pull them low to communicate, in this case the Pi is pulling the lines to 3v3 and it and the MCP23017 pull them low, this means the Pi is never exposed to the 5v supplying the MCP23017. As long as the slave device is happy to register the 3v3 as a high then everything will work fine.

In my testing the Pi has worked flawlessly with the MCP23017 like this although as Selsinork pointed out in the comments on this post it is strictly speaking out of spec, a high shouldn’t really be any lower than 4v for the MCP23017 so in theory using 3v3 could cause reliability problems, it’s perfectly safe as far as the possibility of causing damage to the Pi is concerned though. That said, it does work in practice although YMMV and I suspect if you tried adding more MCP23017s or distanced it from the Pi that reliability would drop off rapidly.

One way I had thought of to fix this had it been a problem was to use a bi-directional buffer IC such as the P82B96 at a cost of a few pounds but Selsinork tipped me off to a very cheap way to do this with just a couple of n-channel FETs, I looked it up and found this document which contains a diagram (page 43) showing how easily it can be done:

This would certainly be an easy and cheap fix if reliability became a problem.

Another thing that has come to light is the eLinux site is wrong when it says that the available current on the Raspberry Pi’s 5V pin with a 1A USB power supply is typically 300mA (1A-700mA). The link to the citation for that claim has been lost in the update to the forums but it probably originates from the schematics stating that a 1.1A polyfuse would be fitted for the microUSB input, the production units only have a 700mA version fitted though so that’s actually the upper limit, I’ve not measured the current draw of the Pi myself but from what I’ve read it seems to be somewhere in the region of 450-550mA depending on the devices plugged in so something like 150-250mA available from the 5v pin might be more realistic, maybe much less (and of course, you don’t want to push that 700mA ceiling). That certainly makes running the MCP23017 from the Pi’s 5v pin less attractive than before but it’s still better than the measly 50mA available from the 3v3 pin.

As I’ve mentioned before it’s easy enough to run the MCP23017 from an external source so that may be more sensible in some cases and if you use 3v3 it would of course negate the need for any level shifting of the I2C lines. This would be as simple as connecting the MCP23017’s Vcc and reset lines to a 3v3 supply instead of the Pi’s 5v line as shown below. This will allow the expander to source as much current as your external supply can deliver, up to the MCP23017’s maximum of 25mA per output of course. If you need 5v I/O and more current than the Pi can provide then an external 5v supply could be used but as above you might then find it necessary to do some level shifting if it proves unreliable.

11 thoughts on “Raspberry Pi and I2C devices of different voltage

  1. Great article!

    Another option, specially if you want to use GPIOS with 5V without using shift-level, is to use the MCP23018 instead of the MCP23017. The main advantage of MCP23018 is that it has GPIOs inputs 5V tolerant, the MCP23017 hasn’t when running at 3.3V (the specification says Vcc+0.6V).

    An important different between both ICs is that the 23018 model use open collector to set the high output.

  2. Thank you for this article.I actually trying to use external supply for mcp23017, when connected to raspi. Using your schema, the mcp23017 detection is unstable. I have to connect the Ground of external supply, to the ground of raspi to get stability. I’m not really confident using this solution. I’m trying using a diode between the 2 grounds, as we can see on some website, but nothing better, maybe a problem a diode speed ?. What do you think about this problem ?

  3. Hi Fleo, The grounds should be connected together, perhaps it isn’t clear in my diagram but the blue line is also connected to the GND pin on the Slice of Pi which is effectively joining the external supplys ground and the Pis ground.

    Milan’s diagram is essentially the same as the one in this post and while it might be required in some cases for the reasons mentioned I don’t think that is your problem if it is working OK once the grounds are common.


  4. Hi Milan, Hi Nathan
    Thank you for your quick answers, as you said, by now, joining the ground should be enough to me, but for future project, i keep the fet solution preciously.

    Thank you for your help.

  5. Thanks for the nice post. I am wonderin if it is ok to run the 23017 with 5v and then connect one of the interrupt pins back to a GPiO pin of the pi to receive the io expander change interrupts. Will the pi die or is there a similar pull up pull down logic so that there is no problem (see also slice of pi/o which offers this interrupt line link).

    Any hints, example code etc. would be welcomed


  6. Can’t we simply use voltage divider on VDD line to reduce input voltage to around 4V so that signal from RPi (3.3v) is > 80% of VDD? Just a thought.

  7. If you’re using the PCF9548, you’ll catch two birds with one stone: voltage level shifter and a huge extention of the I2c bus (up to 8 separate I2c buses)…

Leave a Reply

Your email address will not be published. Required fields are marked *

Notify me of followup comments via e-mail. You can also subscribe without commenting.