RP2040: I2C on PIO statemachines?!

Hi, I’ve seen in a Github repo, that there is a PIO based I2C implementation for the Earle_Philhower Arduino core. That would greatly reduce MCU-interrupt hassle.
I tried to understand how to use it, but it’s way over my head.
Is there a way to implement it in sFOC for AS5600 sensors?

The RP2040 already has an I2C peripheral, so there is not really much reason to implement this in PIO (e.g. it’s not bitbanging, it’s handled by a specific on-chip peripheral). I think it’s provided in this repo as an example of how to use the PIO.

The problem with I2C is the low speed, which this does not solve, the transactions will still be the bottleneck for the FOC loop.

The problem is not so much the low speed but the latency and the way it’s used in arduino. Others have posted code although it’s kind of hard to find, that did some stuff where they separated the sending and receiving. The problem is arduino simply sends a message and blocks while waiting for a reply, but you don’t have to do that. You can send the message and then get the reply at 1 million baud or something and time for actual communication is not a problem. Also the peripheral buffers the info, and handles everything, the cpu doesn’t actually have to wait for anything. That’s just the way the arduino library is written.

You can get a >1 khz update rate in any case which is enough for a lot of situations, but it makes a buzzing noise because the system stops modulating the sine wave etc for that period.

I have pushed a new driver for the AS5600 to the drivers library, dev branch:

It is not yet tested, its on my list to test it out…

But in theory it should support the “ultra-fast mode” as discovered by one of our users here, with up to 9kHz update rates by not closing the I2C transactions properly between reads.

#include <Arduino.h>
#include <SimpleFOC.h>
#include <SimpleFOCDrivers.h>
#include "encoders/as5600/MagneticSensorAS5600.h"

MagneticSensorAS5600 sensor;

void setup() {
    sensor.closeTransactions = false;


I can confirm that it compiles and runs without problems.
But the loop time is still 1kHz, except I use motor.motion_downsample.

I also tried to set sensor.closeTransactions to true, but that ended in a screaming motor.
ATM, it would be better to make this variable static.

I only replaced the driver folder, maybe that’s the problem?

Oh no! Well if it’s working ok in normal mode, then that’s at least a partial success. In this mode you would not expect more than the 1kHz you normally get, so that’s fine.
I’ll investigate the fast mode and get it working eventually…

May I ask which MCU you tested this on?

no, that should be fine, if it finds the code and it compiled fine then that should work.

I have a different understanding of closeTransactions.
I thought, when set to false it would be the fast mode, because it wouldn’t waste time with closing and re-establishing the connection?

I’ve tested it on a rp2040 with mbed_i2c. Should I try Earl_philhowers library instead?

It’s probably still buggy - I didn’t have a chance to test it yet…

I thought the way I implemented it, closeTransactions = true is the normal, default behaviour, and closeTransactions = false is the fast version.
But you’re indicating that doesn’t work.

TBH the Arduino Support for RP2040 isn’t the greatest, it would not be my first choice for testing this. Especially not with mbed, so, yes, maybe EarleHillPower will work better :slight_smile:

Don’t spend too much time on it though, like I said I could not yet test so its probably still buggy.

1 Like