Hello,
I wanted to document what I learned on doing this, to make it easier for the next person.
Firstly, I read the opening post of this thread (several times) and quite a few of the replies.
I was able to enable the I2C AO easily.
Then I wanted to try and read the measurements from the BNO055 breakout board, this is where I struggled for some hours.
Firstly was the simple task of installing the python module. The normal methods do not work:
pip3 install adafruit-circuitpython-bno055
error: externally-managed-environment
× This environment is externally managed
╰─> To install Python packages system-wide, try apt install
python3-xyz, where xyz is the package you are trying to
install.
If you wish to install a non-Debian-packaged Python package,
create a virtual environment using python3 -m venv path/to/venv.
Then use path/to/venv/bin/python and path/to/venv/bin/pip. Make
sure you have python3-full installed.
For more information visit http://rptl.io/venv
note: If you believe this is a mistake, please contact your Python installation or OS distribution provider. You can override this, at the risk of breaking your Python installation or OS, by passing --break-system-packages.
hint: See PEP 668 for the detailed specification.
This is the workaround that is functional for me:
pip3 install --break-system-packages adafruit-circuitpython-bno055
I have a thread open here asking how to properly install python modules, but for now this is good enough.
The next part was to write the python that would get the readings from the breakout board. Of course I followed along with the guide on the GitHub repository for the Adafruit_CircuitPython_BNO055 library, and I quickly produced python that looked like this (does not work):
import adafruit_bno055
import board
i2c = board.I2C()
sensor = adafruit_bno055.BNO055_I2C(i2c)
print("Temperature: {} degrees C".format(sensor.temperature))
print("Accelerometer (m/s^2): {}".format(sensor.acceleration))
print("Magnetometer (microteslas): {}".format(sensor.magnetic))
print("Gyroscope (rad/sec): {}".format(sensor.gyro))
print("Euler angle: {}".format(sensor.euler))
print("Quaternion: {}".format(sensor.quaternion))
print("Linear acceleration (m/s^2): {}".format(sensor.linear_acceleration))
print("Gravity (m/s^2): {}".format(sensor.gravity))
This produces a very large error, but the last line in the error is the key:
ValueError: No I2C device at address: 0x28
Reading the Libre Computer How-to and all the replies, this problem is mentioned early in the replies, and a response is given saying to specify the I2C device. This makes sense, because for some reason this i2c = board.I2C()
seems to be using device 0
and I need it to use device 1
, but how? How to do that?
I searched on the internet for a long while, and eventually I found the solution.
Reading this tutorial, it shows that you can specify what devices to use like such:
import board
import busio
i2c = busio.I2C(board.SCL, board.SDA)
This also did not work for me, it produced the same error. However, I seemed to have found how to specify the device at least. The next piece in the tutorial was the golden key. There was a way to print all the items that the board can access, like this:
import board
dir(board)
I did this, and after close reading, I noticed some of the items were numbered. This was the output on my AML-S905X-CC after having enabled the I2C AO device.
['I2C', 'MISO', 'MOSI', 'P10', 'P12', 'P13', 'P15', 'P16', 'P18', 'P19', 'P21', 'P22', 'P23', 'P24', 'P26', 'P27', 'P28', 'P29', 'P2J12', 'P2J13', 'P2J33', 'P2J34', 'P2J35', 'P2J36', 'P3', 'P31', 'P32', 'P33', 'P35', 'P36', 'P37', 'P38', 'P40', 'P5', 'P7', 'P8', 'P9J12', 'SCL', 'SCL0', 'SCL1', 'SCLK', 'SDA', 'SDA0', 'SDA1', 'SPI', 'SPI_CS', '__blinka__', '__builtins__', '__cached__', '__doc__', '__file__', '__loader__', '__name__', '__package__', '__repo__', '__spec__', '__version__', 'ap_board', 'board_id', 'detector', 'it', 'pin', 'sys']
Notice, there is an “SCL”, an “SCL0”, and an “SCL1”. There is also an “SDA”, “SDA0”, and “SDA1”. So I could specify these SCL1 and SDA1 devices. I tried that, and it worked. The below example works:
import adafruit_bno055
import board
import busio
i2c = busio.I2C(board.SCL1, board.SDA1)
sensor = adafruit_bno055.BNO055_I2C(i2c)
print("Temperature: {} degrees C".format(sensor.temperature))
print("Accelerometer (m/s^2): {}".format(sensor.acceleration))
print("Magnetometer (microteslas): {}".format(sensor.magnetic))
print("Gyroscope (rad/sec): {}".format(sensor.gyro))
print("Euler angle: {}".format(sensor.euler))
print("Quaternion: {}".format(sensor.quaternion))
print("Linear acceleration (m/s^2): {}".format(sensor.linear_acceleration))
print("Gravity (m/s^2): {}".format(sensor.gravity))
Sample output:
Temperature: 25 degrees C
Accelerometer (m/s^2): (0.51, 0.12, 9.43)
Magnetometer (microteslas): (-36.75, 33.5, -61.875)
Gyroscope (rad/sec): (0.011999138607461015, -0.001090830782496456, -0.008726646259971648)
Euler angle: (0.0, 0.0, 0.0)
Quaternion: (0.0, 0.0, 0.0, 0.0)
Linear acceleration (m/s^2): (0.0, 0.0, 0.0)
Gravity (m/s^2): (0.0, 0.0, 0.0)
Now, after having figured out how to use device 1, I wanted to persist the I2C AO changes after boot. Simply issuing the command ldto merge
seemed to not work, as the device would no longer appear after reboot and I’d have to enable it again. I found the answer in the replies of that thread. This is the command:
ldto merge i2c-ao
After you perform the above command, device 1 will become device 0 after reboot, thus you don’t need to specify the exact device as this big write-up of mine explains, you can just use the default. That merge command at the end was the real missing piece for me.