Ability to use alternate I2C pins on RP2040

Issue #479 resolved
Ludo Joris created an issue

Can't use the Kitronik Pico Robotics Board (5329) with MicroBlocks.

The board has a PCA9685 chip to control the board. Micro:bit and PCA9685 communicate via I2C. Easy enough but yet it doesn't work.

A Pico has 24 pins available for I2C (12 pairs of SDA and SDC). MicroBlocks uses the default I2C pins: pin 4 for SDA and pin 5 for SCL. The Kitronik board uses pin 8 for SDA and pin 9 for SCL, you can't change that.

The MicroBlocks Comm library has no blocks to assign pins for I2C.

I have not tried it but I'm afraid this will also be the case for SPI.

Any plans on blocks that let you select non-default pins for I2C interfacing?

Comments (10)

  1. John Maloney repo owner

    It's unfortunate that there is not one standard I2C pin assignment for the RP2040. MicroBlocks is using the default pins, but other vendors use different pins.

    Will explore the possibility of switching to alternate pins. It's a bit tricky because some pin pairs are on I2C0 and some on I2C1 and those use different interrupt vectors.

  2. John Maloney repo owner

    I've added a system primitive that allows the I2C pins to be switched on the RP2040. You can only use the pins associated with IC20:

    SDA: 0, 4, 8, 12, 16, 20, 24, or 28 SCL: 1, 5, 9, 13, 17, 21, or 25

    This should allow you to use the Kitronik Pico Robotics Board (SDA 8, SCL 9).

    This special primitive can be found in the Other/System/sensorPrims library. It is not in the main palette because many microcontrollers have fixed pins for I2C which cannot be changed. If you run this primitive on boards that don't support changing I2C pins, you will get an error.

  3. Ludo Joris reporter

    Thank you!

    The image got cropped.

    It’s a primitive and clumsy test.

    I know how to set up the PCA9685 for register sequential write. Now figuring out how to make such a list of bytes in MicroBlocks.

    module main
    author unknown
    version 1 0
    description ''
    variables addr reg nr

    script 40 40 {
    whenStarted
    sayIt 'started'
    '[sensors:i2cSetPins]' 8 9
    '[sensors:i2cSetClockSpeed]' 100000
    sayIt 'i2c ready'
    addr = 108
    sayIt 'registers'
    i2cSet addr 0 16
    i2cSet addr 254 121
    i2cSet addr 0 0
    i2cSet addr 250 0
    i2cSet addr 251 0
    i2cSet addr 252 0
    i2cSet addr 253 0
    sayIt 'PCA9685 done'
    waitMillis 1000
    sayIt ''
    nr = 1
    reg = (38 + ((nr - 1) * 8))
    i2cSet addr reg 0
    i2cSet addr (reg + 1) 0
    i2cSet addr (reg + 2) 0
    i2cSet addr (reg + 3) 0
    i2cSet addr (reg + 4) 0
    i2cSet addr (reg + 5) 0
    i2cSet addr (reg + 6) 100
    i2cSet addr (reg + 7) 10
    }

    module 'Sensor Primitives' Input
    author MicroBlocks
    version 1 1

  4. John Maloney repo owner

    Did this work? You can use the "i2c get device _ register _" block to read back a register value to see if it is what you set it to.

  5. Ludo Joris reporter

    Yes, I could read back the PRE_SCALE (254) register.

    Program has been modified, the motor now stops. Added these blocks to the end:

    sayIt (i2cGet addr 254)
    waitMillis 3000

    Microblocks says 121, which is correct.

  6. Log in to comment