I2C I/O error, or timeout

I’m unable to communicate with my external I2C sensor inside balena container. With the same hardware setup communication works: on Raspbian OS, on Raspbian OS inside docker container (python3 image).

I’ve tried running the balenaOS container as single container and as multi-container (in privileged mode). Inside the container, I’m able to use i2cdetect -y 1 to verify my sensor is available.

I’m using smbus2 for communcation.

Every write command returns one of the following:
OSError: [Errno 5] Input/output error
OSError: [Errno 121] Remote I/O error
TimeoutError: [Errno 110] Connection timed out

hardware: raspberry pi 4
base image: balenalib/raspberrypi4-64-debian-python:3
OS: balenaOS 2.48.0+rev1

FROM balenalib/raspberrypi4-64-debian-python:3

RUN pip install --upgrade pip

Set our working directory

WORKDIR /usr/src/app

Copy requirements.txt first for better cache on later pushes

COPY requirements.txt requirements.txt

pip install python deps from requirements.txt on the resin.io build server

RUN pip install setuptools AWSIoTPythonSDK pyHS100 googlemaps sixfab-power-python-api smbus2 crc16 Rpi.GPIO

This will copy all files in our root to the working directory in the container

COPY . ./

Enable udevd so that plugged dynamic hardware devices show up in our container.

ENV UDEV=1

#CMD modprobe i2c-dev
CMD python src/queryTPLINK.py

Just out of curiosity, can you try to run it on a Pi3, with a 32-bit OS, and 32-bit containers? I’m wondering if this is a compatibility issue with a 64-bit OS (all of our Pi 4 builds are 64-bit), and I see you are using 64-bit containers as well.

Raspbian testing that you performed earlier would automatically indicate 32-bit host operating system, so I’m curious to see if there is some issue between the move from 32 to 64 bit.

thanks @dtischler I’ll give it a try.

Are you thinking the python I2C library is incompatible with 64-bit OS?

Also, can balenaEngine 64-bit run 32-bit containers?

That’s certainly a possibility as far as a I2C library incompatibility, but let’s see what your testing bears out. Also, yes the 64 bit OS can run 32 bit containers.

tested with RPI3 32-bit but got the same IO error.

is there a I2C library that has been tested in balenaOS container?

balenaEngine
Client:
Version: 18.09.10-dev
API version: 1.39
Go version: go1.10.8
Git commit: 7cb464a406748016f2df0c31a9851d20456a3d31
Built: Mon Jan 27 17:17:28 2020
OS/Arch: linux/arm
Experimental: false

Server:
Engine:
Version: 18.09.10-dev
API version: 1.39 (minimum version 1.12)
Go version: go1.10.8
Git commit: 7cb464a406748016f2df0c31a9851d20456a3d31
Built: Mon Jan 27 17:17:28 2020
OS/Arch: linux/arm
Experimental: true

Hi, can you make sure you are following https://www.balena.io/docs/learn/develop/hardware/i2c-and-spi/#raspberry-pi-family ?

I added CMD modprobe i2c-dev to dockerfile and the library is now working.

So, as of now I don’t know the root cause of I2C issue on raspberry pi 4

  1. smbus2 library incompatibility with 64-bit OS
  2. proper configuration of I2C inside balenaOS container on raspberry pi 4 (64-bit)

The next test I can do is to build a 32-bit container on 64-bit OS. This example shows I should use balenalib/raspberry-pi-python:3 as the base image. Can anyone confirm?

So just to be clear, you’re running the code inside a 32-bit userspace container? The i2c-dev module should be loaded by default (I just checked one of my 64-bit balenaOS pi 4’s and it is). The only thing you should have to do to enable i2c is set "i2c_arm=on" in the Define DT parameters option in the device configuration screen. If you don’t mind continuing to troubleshoot can you try the following steps:

  1. Revert your modprobe i2c-dev change.
  2. Reboot your device.
  3. Open a shell to the host OS either through the web interface or via balena ssh and run the command lsmod | grep i2c and paste the output here?

Thanks,
James.

@jimsynz
on the raspberry pi 3 I copied the balenaEngine version printout in an above post, the OS/ARCH is linux/arm which is 32-bit?

on the raspberry pi 4, I’m attempting to run a 32-bit userspace container by building from a balena base image balenalib/raspberry-pi-python:3

inside running container I ran uname -a
Linux f92c08a 4.19.75 #1 SMP PREEMPT Mon Mar 23 11:50:49 UTC 2020 aarch64 GNU/Linux

on balenaOS host terminal, uname -a
Linux f92c08a 4.19.75 #1 SMP PREEMPT Mon Mar 23 11:50:49 UTC 2020 aarch64 aarch64 aarch64 GNU/Linux

I aslo ran lsmod | grep i2c inside the container
i2c_dev 20480 2

the aarch64 machine hardware platform shows 64-bit, is there a different command to find the container OS/arch?

Sorry, I’m having trouble following along with what’s been done before. Regarding the OS/arch of a container - it’s the same as the host OS. It’s not a virtual machine with it’s own kernel, etc. The reason you can run a 32 bit container on a 64 bit OS is because the kernel supports both userspaces and can run either 32 bit or 64 bit binaries. However, the container will contain binaries and dynamic libraries which were compiled to target a specific architecture. If you’re running one of our base images then you can use the balena-info command from the container shell. If you’re not running one of our images then probably the safest way to find out is to run file -L /lib/ld-linux.so* to see what dynamic linker is being used (you may have to install the file package). For example on a 32bit container I see the following:

root@a851c24e0707:/# file -L /lib/ld-linux.so*
/lib/ld-linux.so.3: ELF 32-bit LSB pie executable, ARM, EABI5 version 1 (SYSV), dynamically linked, BuildID[sha1]=80442130c1faa9e99d4162d266dc011b99b52500, stripped

just backing up: my goal is to run a python I2C library to query a sensor on raspberry pi 4. As of now, this library does not work on balenaOS host running balenalib base image container on raspberry pi 4 (64-bit arch).

I was also able to get the library running on raspberry pi 4 on the default Raspbian build (latest) and inside a docker container on Raspbian (base image python3). The docker container OS/ARCH is linux/arm

I was able to get the python library working on balenaOS host running a balenalib base image container on raspberry pi 3 (32-bit arch).

So, I think my I2C communication issues could be:

  1. incompatibility between python smbus2 library and 64-bit balenaOS
  2. I’m not configuring I2C correctly in the balenaOS build

So, without having to change raspberry pi 4 hardware I was going to try to run a 32-bit container on the balenaOS (64-bit). Please let me know if that’s an invalid path.

$ balena-info
Architecture: ARM v7
OS: Debian Buster
Variant: build variant
Default variable(s): UDEV=off
The following software stack is preinstalled:
Python v3.8.3, Pip v20.0.2, Setuptools v46.1.3

That sound like a reasonable path to me. The only surprising thing for me is that i2c isn’t working in a 64 bit container for you. I have used the pi 4 with a sense hat and various other i2c devices from python without issue.

I’m also confused why I2C is not working on balenaOS rpi4 build.

Can you elaborate on your software setup when using I2C devices?

@rcalderon did you try the 32 bit container on the Pi 4? It might be worth taking a look at the balenaSense project as an example of a configuration where this works. We’re using smbus there with I2C sensors in a 32 bit container on the Pi 4 without any problems at all. Here’s the repo: https://github.com/balenalabs/balena-sense/tree/master/sensor

I just tried updating this script to install smbus2 via pip and then import smbus2 as smbus and it works great. Maybe take a look at this project and try to modify it to work with your sensor. It may help to know what sensor you’re working with, in case someone else has tried it or is using one and can share their setup.

@chrisys thanks for the reference.

Looking at balena sense respository, would Dockerfile.aarch64 would be used on the raspberry pi 4? The file specifies FROM balenalib/raspberrypi3-python:3-build base image.

I tried that base image but got the same error.

I’m using the SixFab power management HAT
with their python API

Yes, the suffix is detected and used if the arch type is aarch64 :+1:

The base image is just the image; it defines a starting point, and the file in the image ^^ are compiled to work on a Raspberry Pi 3 in 32bit mode. A Pi 4 in 64bit mode can still use those binaries.