Question
How to set up multiple I2C buses on Rpi3B+ and Rpi4B?
Answer
I often read forum discussions on setting I2C buses. I tried all for my Rpi3B+'s but all failed, perhaps my drivers or Rpi stretch was to updated. The guys saying it is OK never specified their os version or driver used.
I tried again for Rpi4B and found that I could use at least 2 buses very
stable, 3 buses more or less stable, depending on length of connecting wires.
i2cdetect shows 5 busses, but only first 4 working, but not stable.
To do - I read that a new buster sep26 version is more stable (2019 june versions were bad.)
This is a summary of the config proved working. More details in Appendix A below
dtoverlay=i2c1,pins_2_3 (board pins 3, 5)
dtoverlay=i2c3,pins_4_5 (board pins 7, 29)
dtoverlay=i2c4,pins_6_7 (board pins 31, 26)
dtoverlay=i2c5,pins_12_13 (board pins 32, 33)
dtoverlay=i2c6,pins_22_23 (board pins 15, 16)
pi@raspberrypi:~ $ ls /dev/i2c*
/dev/i2c-1 /dev/i2c-3 /dev/i2c-4 /dev/i2c-5 /dev/i2c-6
Appendices
Appendix A - Rpi4V raspbian 10 buster Python 3.7.3 Multiple I2C Channel Testing Notes
# fi2c62.py tlfong01 2019aug28hkt1433
from time import sleep
import smbus
import fprint53 as fprint
import ftime53 as ftime
# I2c Bus Setup Notes
# pi@raspberrypi:~ $ date Wed 28 Aug 2019 03:26:24 PM HKT
# pi@raspberrypi:~ $ uname -a
# Linux raspberrypi 4.19.58-v7l+ #1245 SMP Fri Jul 12 17:31:45 BST 2019 armv7l GNU/Linux
# pi@raspberrypi:~ $ sudo nano /boot/config.txt
# dtoverlay=i2c1,pins_2_3 (board pins 3, 5)
# dtoverlay=i2c3,pins_4_5 (board pins 7, 29)
# dtoverlay=i2c4,pins_6_7 (board pins 31, 26)
# dtoverlay=i2c5,pins_12_13 (board pins 32, 33)
# dtoverlay=i2c6,pins_22_23 (board pins 15, 16)
# pi@raspberrypi:~ $ ls /dev/i2c*
# /dev/i2c-1 /dev/i2c-3 /dev/i2c-4 /dev/i2c-5 /dev/i2c-6
# ********************************************************************************
# ********************************************************************************
# *** I2c Bus Config ***
i2cBus1 = smbus.SMBus(1)
i2cBus3 = smbus.SMBus(3)
i2cBus4 = smbus.SMBus(4)
i2cBus5 = smbus.SMBus(5)
i2cBusDict = {'I2cBus1': i2cBus1,
'I2cBus3': i2cBus3,
'I2cBus4': i2cBus4,
'I2cBus5': i2cBus5,
}
# *** Pca9685 I2c Slave Device Congif ***
pca9685DevAddrDict = {
'Dev0': 0x40,
'Dev1': 0x41,
'Dev2': 0x42,
'Dev3': 0x43,
'Dev4': 0x44,
'Dev5': 0x45,
'Dev6': 0x46,
'Dev7': 0x47,
}
pca9685RegAddrDict = { 'Mode1': 0x00,
'Mode2': 0x01,
}
pca9685DataByteDict = {
'Mode1Reset': 0x11,
}
# ********************************************************************************
# ********************************************************************************
# *** Read Write Print Device/Register Functions ***
def writeDevTwoBytes(i2cBus, devAddr, writeByte1, writeByte2):
i2cBus.write_byte_data(devAddr, writeByte1, writeByte2)
return
def writeRegOneByte(i2cBus, devAddrDict, devName, regAddrDict, regName, writeByte):
devAddr = devAddrDict[devName]
regAddr = regAddrDict[regName]
writeDevTwoBytes(i2cBus, devAddr, regAddr, writeByte)
return
def readDevOneByte(i2cBus, devAddr, readByteAddr):
readByte = i2cBus.read_byte_data(devAddr, readByteAddr)
return readByte
def readRegOneByte(i2cBus, devAddrDict, devName, regAddrDict, regName):
devAddr = devAddrDict[devName]
regAddr = regAddrDict[regName]
readByte = i2cBus.read_byte_data(devAddr, regAddr)
return readByte
def printRegOneByte(i2cBus, devAddrDict, devName, regAddrDict, regName):
readByte = readRegOneByte(i2cBusName, devAddrDict, devName, regAddrDict, regName)
print(printTitle, hex(readByte))
return
# *** Main Test Function ***
def testWriteReadPca9685Bus1Dev0RegMode1():
fprint.printBeginExecFunction()
i2cBusName = 'I2cBus1'
devName = 'Dev0'
regName = 'Mode1'
#i2cBus = fi2c.i2cBusDict[i2cBusName]
i2cBus = i2cBusDict[i2cBusName]
devAddrDict = pca9685DevAddrDict
regAddrDict = pca9685RegAddrDict
writeByte = 0x77
writeRegOneByte(i2cBus, devAddrDict, devName, regAddrDict, regName, writeByte)
readByte = readRegOneByte(i2cBus, devAddrDict, devName, regAddrDict, regName)
if readByte == writeByte:
resultsString = 'Good'
else:
resultsString = 'Bad'
devAddr = devAddrDict[devName]
fprint.printTitleOneByteNum('PCA9685 I2C Address', fprint.indentFormat640, devAddr)
fprint.printTitleOneByteNum('PCA9685 MODE1 Register Written', fprint.indentFormat640, writeByte)
fprint.printTitleOneByteNum('PCA9685 MODE1 Register Read', fprint.indentFormat640, readByte)
fprint.printTitleString('Write/Read Results', fprint.indentFormat640, resultsString)
fprint.printEndExecFunction()
return
def testPingPca9685Bus1Dev0RegMode1():
fprint.printBeginExecFunction()
i2cBusName = 'I2cBus1'
devName = 'Dev0'
regName = 'Mode1'
#i2cBus = fi2c.i2cBusDict[i2cBusName]
i2cBus = i2cBusDict[i2cBusName]
devAddrDict = pca9685DevAddrDict
regAddrDict = pca9685RegAddrDict
devAddr = devAddrDict[devName]
readByte = readRegOneByte(i2cBus, devAddrDict, devName, regAddrDict, regName)
compareByte = pca9685DataByteDict['Mode1Reset']
if readByte == compareByte:
resultsString = 'Good'
else:
resultsString = 'Bad'
fprint.printTitleString('PCA9685 I2C Address', fprint.indentFormat640, hex(devAddr))
fprint.printTitleString('PCA9685 MODE1 Register Written', fprint.indentFormat640, hex(compareByte))
fprint.printTitleString('PCA9685 MODE1 Register Read', fprint.indentFormat640, hex(readByte))
fprint.printTitleString('Ping Results', fprint.indentFormat640, resultsString)
fprint.printEndExecFunction()
return
# ********************************************************************************
# ********************************************************************************
# *** Main Tests ***
def mainTests():
#ftime.testPrintDateTime()
testPingPca9685Bus1Dev0RegMode1()
testWriteReadPca9685Bus1Dev0RegMode1()
return
# ********************************************************************************
# ********************************************************************************
# *** Init/Main Functions ***
# *** Init Function ***
def init():
pass
return
#*** Main Function ***
def main():
init()
mainTests()
return
# ********************************************************************************
# ********************************************************************************
# *** Main ***
if __name__ == '__main__':
main()
# *** End of Program ***
# ********************************************************************************
# ********************************************************************************
End of answer