Question: How to Write a Python I2C Library

Hello All!

I hope my question is not too ambiguous, I already had an idea on how to do this BUT it would use another library author’s code as a template, and I did not think that was fair to the author. Although I would be happy to credit him.

This is for an embedded system, and perhaps I should ask this in a MicroPython or CircuitPython forum, but I need to start somewhere.

I have an older piece of I2C sensor hardware. I cannot find a library for it anywhere but I want to use it. Out of the gate, I thought of taking a library for a similar piece of hardware, pull up the datasheet for the devices used on my hardware, and make changes to suit the requirements.

It does not seem right though, so I am asking if anyone can direct me to a DOs and DON’Ts faq for creating libraries for I2C components. I thought I would ask this first before I go after reverse engineering, say, a library in python that allows access to a MPU4060 accelerometer. It looks like there are base components of the library that handle communication, as in memory or register reads and writes by address.

Is there a template for such a thing? Creating a I2C device library for Python, MicroPython, or CircuitPython?

My piece of hardware is a GY-80 Accelerometer board. It has 4 devices on it and I have the datasheet for each. ALL are tied to the same I2C bus on the board and have different addresses of course, which I can see when I scan it. But I am fairly new to libraries, especially ones that touch hardware for a specific platform. In my case, it is the RPI Pico 2040 W.

I just want to do it right, and not cannibalize someone’s hard work. There is too much of that already. And I have to learn somewhere, which is why I asked. To be honest, I would LOVE to be able to write libraries for all my legacy I2C (and other) hardware spanning the last 10-15 years.

I hope someone can point me in the right direction. I do not want it done for me, just a bread-crumb trail to follow to learn, practice, and achieve.

THANKS so much for your valuable time. I appreciate it!

Hop

If this other library uses an open source license, you do not need to feel bad about modifying it for your own purposes. In that case, the original author has given you explicit permission to do just that.

If not, you should indeed think twice before using it as a template, since you would not legally own the resulting program. Technically, you would need the original author’s permission to even run it.

First, a point of clarification: An “I2C library” could refer to either

  1. A driver for the I2C bus itself.
  2. A driver for a device connected to said bus.

(1) is a low-level bit shuffler that pushes bits in and out of the necessary hardware registers to make the SCL and SDA lines go up and down at the appropriate times. This is not possible to implement in Python, because it requires real-time hardware access.

If you use Micro- or CircuitPython with supported hardware (such as the RPi Pico), you get this part for free, via the machine.I2C (micropython) or busio.I2C (circuitpython) modules.

There is also smbus2, which is a high-level I2C driver implemented in Python. However, it still depends on something else providing the low-level bit shuffling, and it only works in Unix.

(2), which is what I think you want to do, is possible to do in Python given that you already have (1). There is no “template” for such drivers, because I2C devices are sufficiently different from each other that the greatest common denominator is just that you can read and write bytes to them.

However, there exists a very large number of open source implementations of such drivers, which you can use as inspiration even if your particular device is not supported. Adafruit (the company behind CircuitPython) maintains hundreds of such drivers on their github. They depend on CircuitPython, but if you want to use something else you can just replace busio.I2C with machine.I2C or whatever low-level driver you prefer; they will all be more-or-less interchangeable.

1 Like

I agree with Alexander, but want to add that you can write your own low level stuff in C and provide bindings to python. That way you get the performance needed for communication and easy to use API in your library, to build higher level drivers for devices.

As a bonus you can test device drivers without any physical hardware (you just mock bytes you should receive from it)

1 Like

Thank you guys for the replies and the info. I appreciate it! This certainly gets me started and clears up quite a few questions I had. I am so glad I posted my question!!