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.