Pi Pico I2C not working.

Issue #533 open
Matthew Barulic created an issue

I have the attached Arduino sketch working on a Pi Pico to talk to another Pico over I2C. I’m trying to port it to MicroBlocks, but the attached program is not producing any activity on the I2C lines. I’ve also noticed that when I press the stop button with this program loaded to the board, it seems to lock up the VM. The IDE is no longer able to connect to the board. I have to use the flash nuke UF2 and re-install the VM firmware to get the board working with the IDE again.

Am I missing something about using I2C communication in MicroBlocks, or is there potentially a bug in the Pico support?

Comments (4)

  1. John Maloney repo owner

    The MicroBlocks I2C communication functions do work on the Pico. We use them I2C heavily with Robotistan's PicoBricks product, which is based on the Pico board.

    As you may know, to use I2C to communicate between boards, one board must act as the I2C peripheral ("slave") while the other acts as the controller ("master"). However, MicroBlocks only supports the controller/master role so you'll need to implement the other role in Arduino C++. There is an example here:

    https://wiki-content.arduino.cc/en/Tutorial/LibraryExamples/MasterWriter

    The Arduino sketch you provided appears to be the controller/master role. You'll need to run a Arduino sketch for the other role on the Pico board with which MicroBlocks communicates.

    Assuming you've got a sketch for the peripheral/slave role on the other board, here are a couple of possible issues:

    1. Lack of pullup resistors on the I2C pins. Both SDA and SCL should have a pullup resistor of about 10k to 3.3v.

    2. Incorrect I2C pins. MicroBlocks uses pins GP4 (SDA) and GP5 (SCL) on the Wire (not Wire1) device. Those are physical pins 6 and 7. In an Arduino sketch those pins would be:

    Wire.setSDA(4); // physical pin 6 Wire.setSCL(5); // physical pin 7

    As you can see, this is a fairly advanced topic and MicroBlocks does not support the I2C peripheral/slave role. If your goal is to explore I2C in depth, I encourage you to continue to work on this project and let us know how it goes. If your goal is simply to communicate between two boards, I'd suggest using the serial (UART) blocks. They are easier to use and both sides can be written in MicroBlocks.

  2. Matthew Barulic reporter

    Thanks for the quick and thorough response. Looks like my issue was using the wrong pins. I misunderstood the VM source code. I thought it was referencing physical pins 4/5 instead of GP4/5.

    Do I understand this comment from another issue correctly that I would not be able to switch to physical pins 4/5 even with the recently added pin changing primitive because they are part of I2C1? https://bitbucket.org/john_maloney/smallvm/issues/479/ability-to-use-alternate-i2c-pins-on#comment-66834096

  3. John Maloney repo owner

    Changing the I2C pins is not supported at all by many microcontrollers, which have hardwired pins for I2C.

    The Raspberry Pi Pico actually does allow the pins to be changed but only to a limited number of options. In particular, you must stick to the pins marked for "I2C0" on the pinout:

    https://www.raspberrypi.com/documentation/microcontrollers/raspberry-pi-pico.html

    SDA: GP0, GP4, GP8, GP16, GP20

    SCL: GP1, GP5, GP9, GP17, GP21

    Because it does not work on all boards, the block to change the i2c pins is tucked away in a system library. Unless there is no other option, I encourage users to stick with the MicroBlocks standard I2C pins (which are also the Raspberry Pi Pico default I2C pins) since will make your code portable across boards.

  4. Log in to comment