exzile
Posts: 132
Joined: Sun Jul 20, 2014 5:33 am

Python code for detecting I2C ports?

Mon Jun 29, 2015 3:07 am

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.

User avatar
DougieLawson
Posts: 32687
Joined: Sun Jun 16, 2013 11:19 pm
Location: Basingstoke, UK
Contact: Website

Re: Python code for detecting I2C ports?

Mon Jun 29, 2015 9:47 am

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())
Microprocessor, Raspberry Pi & Arduino Hacker
Mainframe database troubleshooter
MQTT Evangelist
Twitter: @DougieLawson

2012-18: 1B*5, 2B*2, B+, A+, Z, ZW, 3Bs*3, 3B+

Any DMs sent on Twitter will be answered next month.

exzile
Posts: 132
Joined: Sun Jul 20, 2014 5:33 am

Re: Python code for detecting I2C ports?

Mon Jun 29, 2015 1:13 pm

Thanks dude, I will give it a go tonight and give you feedback.

exzile
Posts: 132
Joined: Sun Jul 20, 2014 5:33 am

Re: Python code for detecting I2C ports?

Tue Jun 30, 2015 5:27 am

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 ;)

User avatar
joan
Posts: 13364
Joined: Thu Jul 05, 2012 5:09 pm
Location: UK

Re: Python code for detecting I2C ports?

Tue Jun 30, 2015 8:00 am

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.

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

User avatar
DougieLawson
Posts: 32687
Joined: Sun Jun 16, 2013 11:19 pm
Location: Basingstoke, UK
Contact: Website

Re: Python code for detecting I2C ports?

Tue Jun 30, 2015 8:29 am

I get

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
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

Code: Select all

Match#1 == "20: 20 -- -- -- -- -- -- -- -- -- -- -- -- -- -- --"

Code: Select all

Match#2 == "70: -- -- -- -- -- -- -- 77"
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).
Microprocessor, Raspberry Pi & Arduino Hacker
Mainframe database troubleshooter
MQTT Evangelist
Twitter: @DougieLawson

2012-18: 1B*5, 2B*2, B+, A+, Z, ZW, 3Bs*3, 3B+

Any DMs sent on Twitter will be answered next month.

exzile
Posts: 132
Joined: Sun Jul 20, 2014 5:33 am

Re: Python code for detecting I2C ports?

Tue Jun 30, 2015 1:21 pm

I will try his method later tonight. I tried yours and added some parsing to pull just the port numbers. Worked perfectly.

User avatar
joan
Posts: 13364
Joined: Thu Jul 05, 2012 5:09 pm
Location: UK

Re: Python code for detecting I2C ports?

Tue Jun 30, 2015 1:32 pm

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

exzile
Posts: 132
Joined: Sun Jul 20, 2014 5:33 am

Re: Python code for detecting I2C ports?

Tue Jun 30, 2015 1:37 pm

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!

Schorschi
Posts: 202
Joined: Thu Nov 22, 2012 9:38 pm

Re: Python code for detecting I2C ports?

Sun May 07, 2017 6:21 pm

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.

User avatar
joan
Posts: 13364
Joined: Thu Jul 05, 2012 5:09 pm
Location: UK

Re: Python code for detecting I2C ports?

Sun May 07, 2017 7:14 pm

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.
...
What code?

User avatar
richteel
Posts: 2
Joined: Thu Sep 01, 2016 2:24 pm
Location: US

Re: Python code for detecting I2C ports?

Mon Dec 11, 2017 2:12 pm

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.

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:~ $
Here is the modified code.

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))
The output after running the above code.

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:~ $
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.

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:~ $ 
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.

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:~ $

Return to “Python”

Who is online

Users browsing this forum: No registered users and 10 guests