I am looking for a python library, or code snippets, that can detect which channels/ports are active (have a device on it) and which do not on I2C. If anyone has advice or links, that would help. Thanks!
One thought I had was running sudo I2c-detect -y 1 and reading the input in. But could not figure out how to run the command and read input in python.
- DougieLawson
- Posts: 42215
- Joined: Sun Jun 16, 2013 11:19 pm
- Location: A small cave in deepest darkest Basingstoke, UK
Re: Python code for detecting I2C ports?
This should get you started
Code: Select all
#!/usr/bin/python3
import os
import subprocess
import re
p = subprocess.Popen(['i2cdetect', '-y','1'],stdout=subprocess.PIPE,)
#cmdout = str(p.communicate())
for i in range(0,9):
line = str(p.stdout.readline())
for match in re.finditer("[0-9][0-9]:.*[0-9][0-9]", line):
print (match.group())
Languages using left-hand whitespace for syntax are ridiculous
DMs sent on https://twitter.com/DougieLawson or LinkedIn will be answered next month.
Fake doctors - are all on my foes list.
The use of crystal balls and mind reading is prohibited.
DMs sent on https://twitter.com/DougieLawson or LinkedIn will be answered next month.
Fake doctors - are all on my foes list.
The use of crystal balls and mind reading is prohibited.
Re: Python code for detecting I2C ports?
Thanks dude, I will give it a go tonight and give you feedback.
Re: Python code for detecting I2C ports?
Worked! Now I just need to parse for numbers.
Do you think you can give me a step through explanation of the code so I can learn what it's exactly doing and why?
Plus It'll help me in the future
Do you think you can give me a step through explanation of the code so I can learn what it's exactly doing and why?
Plus It'll help me in the future

Re: Python code for detecting I2C ports?
Here's some code which does pretty much what i2cdetect is doing under the hood.
It just tries to talk to every possible I2C device and prints the ids of those which respond.
It just tries to talk to every possible I2C device and prints the ids of those which respond.
Code: Select all
#!/usr/bin/env python
# 2015-06-30
# i2c_detect.py
# Public Domain
import pigpio
pi = pigpio.pi() # connect to local Pi
for device in range(128):
h = pi.i2c_open(1, device)
try:
pi.i2c_read_byte(h)
print(hex(device))
except: # exception if i2c_read_byte fails
pass
pi.i2c_close(h)
pi.stop # disconnect from Pi
Code: Select all
$ /code/i2c_detect.py
0x1e
0x53
0x68
- DougieLawson
- Posts: 42215
- Joined: Sun Jun 16, 2013 11:19 pm
- Location: A small cave in deepest darkest Basingstoke, UK
Re: Python code for detecting I2C ports?
I get from running i2cdetect
So the regex that's looking for number, number, colon, anything, number, number ([0-9][0-9]:.*[0-9][0-9]) gets two matches
The next step would be to parse those lines looking beyond the first three characters and ignoring the '--' blocks.
I like Joan's pigpio solution better because it's not relying on parsing output (which could change if someone updates the i2c-tools).
Code: Select all
0 1 2 3 4 5 6 7 8 9 a b c d e f
00: -- -- -- -- -- -- -- -- -- -- -- -- --
10: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
20: 20 -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
30: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
40: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
50: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
60: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
70: -- -- -- -- -- -- -- 77
So the regex that's looking for number, number, colon, anything, number, number ([0-9][0-9]:.*[0-9][0-9]) gets two matches
Code: Select all
Match#1 == "20: 20 -- -- -- -- -- -- -- -- -- -- -- -- -- -- --"
Code: Select all
Match#2 == "70: -- -- -- -- -- -- -- 77"
I like Joan's pigpio solution better because it's not relying on parsing output (which could change if someone updates the i2c-tools).
Languages using left-hand whitespace for syntax are ridiculous
DMs sent on https://twitter.com/DougieLawson or LinkedIn will be answered next month.
Fake doctors - are all on my foes list.
The use of crystal balls and mind reading is prohibited.
DMs sent on https://twitter.com/DougieLawson or LinkedIn will be answered next month.
Fake doctors - are all on my foes list.
The use of crystal balls and mind reading is prohibited.
Re: Python code for detecting I2C ports?
I will try his method later tonight. I tried yours and added some parsing to pull just the port numbers. Worked perfectly.
Re: Python code for detecting I2C ports?
It's even simpler if you have the Python smbus module installed.
Code: Select all
#!/usr/bin/env python
import smbus
bus = smbus.SMBus(1) # 1 indicates /dev/i2c-1
for device in range(128):
try:
bus.read_byte(device)
print(hex(device))
except: # exception if read_byte fails
pass
Re: Python code for detecting I2C ports?
I do. I will give that snippet a try then. I'm a .net developer and I've always read documentation on libraries and frameworks while using them. Python seems to be more difficult to find such information. I was looking into Smbus and didn't find any functions to use to do this. But seems you have, so thanks!
Re: Python code for detecting I2C ports?
Python code example that reads a data from the bus, can lockup or change the i2C bus, such that it slows down or freezes.
For example... The exception result of Errno 5 does not cause and issue but once Errno 110 returned the i2C bus is hung or slows way down.
No Device At 55, [Errno 5] Input/output error
Device At 56, Data 56
No Device At 57, [Errno 5] Input/output error
No Device At 58, [Errno 5] Input/output error
No Device At 59, [Errno 5] Input/output error
No Device At 60, [Errno 5] Input/output error
No Device At 61, [Errno 5] Input/output error
No Device At 62, [Errno 5] Input/output error
No Device At 63, [Errno 5] Input/output error
No Device At 64, [Errno 5] Input/output error
No Device At 65, [Errno 5] Input/output error
No Device At 66, [Errno 5] Input/output error
No Device At 67, [Errno 5] Input/output error
No Device At 68, [Errno 110] Connection timed out
No Device At 69, [Errno 110] Connection timed out
No Device At 70, [Errno 110] Connection timed out
No Device At 71, [Errno 110] Connection timed out
No Device At 72, [Errno 110] Connection timed out
No Device At 73, [Errno 110] Connection timed out
No Device At 74, [Errno 110] Connection timed out
No Device At 75, [Errno 110] Connection timed out
No Device At 76, [Errno 110] Connection timed out
No Device At 77, [Errno 110] Connection timed out
No Device At 78, [Errno 5] Input/output error
No Device At 79, [Errno 5] Input/output error
No Device At 80, [Errno 5] Input/output error
No Device At 81, [Errno 5] Input/output error
No Device At 82, [Errno 5] Input/output error
Even i2cdetect bogs down once this happens, powering down all the i2c slaves seems to reset the bus, but it can happen again.
For example... The exception result of Errno 5 does not cause and issue but once Errno 110 returned the i2C bus is hung or slows way down.
No Device At 55, [Errno 5] Input/output error
Device At 56, Data 56
No Device At 57, [Errno 5] Input/output error
No Device At 58, [Errno 5] Input/output error
No Device At 59, [Errno 5] Input/output error
No Device At 60, [Errno 5] Input/output error
No Device At 61, [Errno 5] Input/output error
No Device At 62, [Errno 5] Input/output error
No Device At 63, [Errno 5] Input/output error
No Device At 64, [Errno 5] Input/output error
No Device At 65, [Errno 5] Input/output error
No Device At 66, [Errno 5] Input/output error
No Device At 67, [Errno 5] Input/output error
No Device At 68, [Errno 110] Connection timed out
No Device At 69, [Errno 110] Connection timed out
No Device At 70, [Errno 110] Connection timed out
No Device At 71, [Errno 110] Connection timed out
No Device At 72, [Errno 110] Connection timed out
No Device At 73, [Errno 110] Connection timed out
No Device At 74, [Errno 110] Connection timed out
No Device At 75, [Errno 110] Connection timed out
No Device At 76, [Errno 110] Connection timed out
No Device At 77, [Errno 110] Connection timed out
No Device At 78, [Errno 5] Input/output error
No Device At 79, [Errno 5] Input/output error
No Device At 80, [Errno 5] Input/output error
No Device At 81, [Errno 5] Input/output error
No Device At 82, [Errno 5] Input/output error
Even i2cdetect bogs down once this happens, powering down all the i2c slaves seems to reset the bus, but it can happen again.
Re: Python code for detecting I2C ports?
What code?Schorschi wrote:Python code example that reads a data from the bus, can lockup or change the i2C bus, such that it slows down or freezes.
...
Re: Python code for detecting I2C ports?
The code posted by joan works well for most devices however I was receiving an error when it attempted to read the device at 0x44, which is a SHT31-D from adafruit (https://www.adafruit.com/product/2857). The code also showed a device at 0x28 which does not exist.
I found that changing bus.read_byte(device) to bus.write_byte(device, 0) worked all of the time.
Here is the output from i2cdetect on my Raspberry Pi zero.
Here is the modified code.
The output after running the above code.
I know this thread is a few years old now but I'm posting this update so it may help others if they run across this thread.
BTW: The run with joan's code, modified with capturing the error on device 0x44, was the following.
After running into this error, i2cdetect showed that no devices were connected to the I2C bus. The only way to recover was to shut down the Raspberry Pi, turn the power off, then turn the power back on.
I found that changing bus.read_byte(device) to bus.write_byte(device, 0) worked all of the time.
Here is the output from i2cdetect on my Raspberry Pi zero.
Code: Select all
pi@ussdakota:~ $ sudo i2cdetect -y 1
0 1 2 3 4 5 6 7 8 9 a b c d e f
00: -- -- -- -- -- -- -- -- -- -- -- -- --
10: -- -- -- -- -- -- -- -- -- 19 -- -- -- -- 1e --
20: -- -- -- -- -- -- -- -- -- 29 -- -- -- -- -- --
30: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
40: 40 -- -- -- 44 -- -- -- -- -- -- -- -- -- -- --
50: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
60: 60 -- -- -- -- -- -- -- -- -- -- 6b -- -- -- --
70: -- -- -- -- -- -- -- 77
pi@ussdakota:~ $
Code: Select all
#!/usr/bin/env python3
import smbus
import errno
if __name__ == "__main__":
bus_number = 1 # 1 indicates /dev/i2c-1
bus = smbus.SMBus(bus_number)
device_count = 0
for device in range(3, 128):
try:
bus.write_byte(device, 0)
print("Found {0}".format(hex(device)))
device_count = device_count + 1
except IOError as e:
if e.errno != errno.EREMOTEIO:
print("Error: {0} on address {1}".format(e, hex(address)))
except Exception as e: # exception if read_byte fails
print("Error unk: {0} on address {1}".format(e, hex(address)))
bus.close()
bus = None
print("Found {0} device(s)".format(device_count))
Code: Select all
pi@ussdakota:~ $ python3 i.py
Found 0x19
Found 0x1e
Found 0x29
Found 0x40
Found 0x44
Found 0x60
Found 0x6b
Found 0x77
Found 8 device(s)
pi@ussdakota:~ $
BTW: The run with joan's code, modified with capturing the error on device 0x44, was the following.
Code: Select all
pi@ussdakota:~ $ python3 i.py
Found 0x19
Found 0x1e
Found 0x28
Found 0x29
Found 0x40
Error: [Errno 5] Input/output error on address 0x44
Found 5 device(s)
pi@ussdakota:~ $
Code: Select all
pi@ussdakota:~ $ sudo i2cdetect -y 1
0 1 2 3 4 5 6 7 8 9 a b c d e f
00: -- -- -- -- -- -- -- -- -- -- -- -- --
10: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
20: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
30: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
40: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
50: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
60: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
70: -- -- -- -- -- -- -- --
pi@ussdakota:~ $