-
- Posts: 19
- Joined: Fri Jan 22, 2016 11:43 pm
- Location: El Cerrito, CA USA
Use Pico as an I2C slave?
On Arduino I've used the Wire library, which allows it to be an I2C slave. Is there anything similar for the Pico?
Thanks.
Thanks.
Re: Use Pico as an I2C slave?
+1, this is a really common pattern with a RPx managing peripheral uControllers. It really limits the Pico to a stand alone system if can't slave to a central controller.
Re: Use Pico as an I2C slave?
The Pico can be a slave I2C.
Principal Software Engineer at Raspberry Pi Ltd.
Working in the Applications Team.
Working in the Applications Team.
-
- Posts: 3
- Joined: Sun Feb 07, 2021 3:37 pm
Re: Use Pico as an I2C slave?
The examples I've found for other boards all seem to reference I2C.SLAVE
when I've tried that within I2C.init I get
AttributeError: type object 'I2C' has no attribute 'SLAVE'
is there somewhere I can find an I2C slave exmple in micropython that will work on the Pico.
when I've tried that within I2C.init I get
AttributeError: type object 'I2C' has no attribute 'SLAVE'
is there somewhere I can find an I2C slave exmple in micropython that will work on the Pico.
Re: Use Pico as an I2C slave?
I'm also trying to use the Pico as I2C slave, but from MicroPython.
I maybe wrong, but the machine module only supports the setup as master?
http://docs.micropython.org/en/latest/l ... e.I2C.html
I found some support in the pyb module, but this does not seem relevant for the Pico:
https://docs.micropython.org/en/latest/ ... b.I2C.html
i2c.init(I2C.SLAVE, addr=0x42) # init as a slave with given address
Help appreciated, Thanks!
I maybe wrong, but the machine module only supports the setup as master?
http://docs.micropython.org/en/latest/l ... e.I2C.html
I found some support in the pyb module, but this does not seem relevant for the Pico:
https://docs.micropython.org/en/latest/ ... b.I2C.html
i2c.init(I2C.SLAVE, addr=0x42) # init as a slave with given address
Help appreciated, Thanks!
-
- Posts: 19
- Joined: Fri Jan 22, 2016 11:43 pm
- Location: El Cerrito, CA USA
Re: Use Pico as an I2C slave?
Perhaps you could give us guidance as to how to do that. I've reviewed the documentation of machine.I2C and all it seems to talk about is communicating with a slave device - nothing about being a slave device. What am I missing?
Re: Use Pico as an I2C slave?
Hello,
glad to have found this thread.
@espresso: Have a look at the function list (Pico C SDK) page 114. There you will find infos how to activate the i2c slave mode.
But I am not further yet.
Can someone give an example in C how to activate the slave mode and how to set the receive and reply functions.
Thanks and keep it up
glad to have found this thread.
@espresso: Have a look at the function list (Pico C SDK) page 114. There you will find infos how to activate the i2c slave mode.
But I am not further yet.
Can someone give an example in C how to activate the slave mode and how to set the receive and reply functions.
Thanks and keep it up
-
- Posts: 3
- Joined: Sun Feb 07, 2021 3:37 pm
Re: Use Pico as an I2C slave?
Thing you are overlooking here is that this is posted in the micropython section. Just because you can do it in C doesn't mean it's implemented in the micropython libraries.
-
- Posts: 19
- Joined: Fri Jan 22, 2016 11:43 pm
- Location: El Cerrito, CA USA
Re: Use Pico as an I2C slave?
Thanks, @snugle. I was indeed hoping for a MicroPython solution, however it remains elusive. I'll take a look at the C SDK and see if that's any help.
I've started to read up on the PIO capabilities, in hopes that a solution might be found there. Still early days...
I've started to read up on the PIO capabilities, in hopes that a solution might be found there. Still early days...
-
- Posts: 19
- Joined: Fri Jan 22, 2016 11:43 pm
- Location: El Cerrito, CA USA
Re: Use Pico as an I2C slave?
For anyone following along - section 3.6.7 of the 2040 Datasheet shows an example program using the PIO State Machine to implement an I2C bus master. Just found this a few moments ago. So it must be possible to implement an I2C slave in a similar way ... once I wrap my head around the PIO instruction set, etc. This will be fun! I haven't written in assembly language for about 50 years.
Re: Use Pico as an I2C slave?
If you look at the MicroPython API ( https://docs.micropython.org/en/latest/ ... e.I2C.html
) there does not appear to be a way to make a slave. You would expect this to be an argument in the constructor (where you'd pass the I2C slave address).
While I like Python and Micro/CircuitPython I do tire of limitations like this. It can amazingly handle interrupts so why can't it perform as an I2C slave?
) there does not appear to be a way to make a slave. You would expect this to be an argument in the constructor (where you'd pass the I2C slave address).
While I like Python and Micro/CircuitPython I do tire of limitations like this. It can amazingly handle interrupts so why can't it perform as an I2C slave?
Re: Use Pico as an I2C slave?
These limitations are due to the limited development resources MicroPython and CircuitPython have. It takes time and effort to support everything folks want to do.
In CircuitPython we have an `i2cperipheral` API for this but it hasn't been implemented on the RP2040 yet. We're working on audio playback and UART instead.
-
- Posts: 8210
- Joined: Sat Aug 18, 2012 2:33 pm
Re: Use Pico as an I2C slave?
https://datasheets.raspberrypi.org/rp20 ... asheet.pdf
page 464
4.3.10.1. Slave Mode Operation
This section discusses slave mode procedures.
4.3.10.1.1. Initial Configuration
To use the DW_apb_i2c as a slave, perform the following steps:
1. Disable the DW_apb_i2c by writing a ‘0’ to IC_ENABLE.ENABLE.
2. Write to the IC_SAR register (bits 9:0) to set the slave address. This is the address to which the DW_apb_i2c
responds.
3. Write to the IC_CON register to specify which type of addressing is supported (7-bit or 10-bit by setting bit 3). Enable
the DW_apb_i2c in slave-only mode by writing a ‘0’ into bit six (IC_SLAVE_DISABLE) and a ‘0’ to bit zero
(MASTER_MODE).
.....
-
- Posts: 3
- Joined: Sun Feb 07, 2021 3:37 pm
Re: Use Pico as an I2C slave?
So not from the available micropython libraries. 

-
- Posts: 8210
- Joined: Sat Aug 18, 2012 2:33 pm
Re: Use Pico as an I2C slave?
Code: Select all
import machine
machine.mem32[0x4001c074]=0x42
Re: Use Pico as an I2C slave?
Hello, so do I understand it correctly, that there is no easy way for communication between 2 picos? Because there always must be one master and at least one slave in I2C... I will need it in the future for connecting with Fischertechnik controller. Now I am using for this Arduino, but I wanted to switch to Pico because of the python and because its Raspberry...
Last edited by MirekCZ on Thu Feb 18, 2021 9:33 pm, edited 1 time in total.
-
- Posts: 8210
- Joined: Sat Aug 18, 2012 2:33 pm
Re: Use Pico as an I2C slave?
That is not a way. At my university department we use Fischertechnik to show to students basics ofIndustry 4.0 princip. And because we are not programming department, we use only theyr RoboPro for using it - programming by graphical blocks connecting. And there is only block for I2C communication. That is the reason why we use arudino in some parts - arduino is getting data from models and is sending them over the uart/usb to computer to my C# application. It would be to difficult programming models in C/C++, learn it, teach it - easily there is no time dotation for that. Doesn't matter, good to know now. In a future I believe it will be possible and that will be my time to switch 

-
- Posts: 4504
- Joined: Thu Dec 27, 2012 4:05 am
- Location: Québec, Canada
Re: Use Pico as an I2C slave?
Oops It was to late yesterday . I did post it but not at the right place.
Proof of concept!
Ok I made a small I2C slave class that could read one byte data send to the Pico
From the Raspberry Pi, I connect the I2C to the Pico I2C.
I was able to receive data from the Pi by sending via I2c .
On The Pi.
On the Pico I create a class i2cSlave.py
And I got
So just using micropython to create the slave class is possible.
Proof of concept!
Ok I made a small I2C slave class that could read one byte data send to the Pico
From the Raspberry Pi, I connect the I2C to the Pico I2C.
I was able to receive data from the Pi by sending via I2c .
On The Pi.
Code: Select all
import smbus
bus = smbus.SMBus(1)
bus.write_byte(0x41,12)
bus.write_byte(0x41,15)
Code: Select all
from machine import mem32,Pin
class i2c_slave:
I2C0_BASE = 0x40044000
I2C1_BASE = 0x40048000
IO_BANK0_BASE = 0x40014000
mem_rw = 0x0000
mem_xor = 0x1000
mem_set = 0x2000
mem_clr = 0x3000
IC_CON = 0
IC_TAR = 4
IC_SAR = 8
IC_DATA_CMD = 0x10
IC_RX_TL = 0x38
IC_TX_TL = 0x3C
IC_CLR_INTR = 0x40
IC_ENABLE = 0x6c
IC_STATUS = 0x70
def write_reg(self, reg, data, method=0):
mem32[ self.i2c_base | method | reg] = data
def set_reg(self, reg, data):
self.write_reg(reg, data, method=self.mem_set)
def clr_reg(self, reg, data):
self.write_reg(reg, data, method=self.mem_clr)
def __init__(self, i2cID = 0, sda=0, scl=1, slaveAddress=0x41):
self.scl = scl
self.sda = sda
self.slaveAddress = slaveAddress
self.i2c_ID = i2cID
if self.i2c_ID == 0:
self.i2c_base = self.I2C0_BASE
else:
self.i2c_base = self.I2C1_BASE
# 1 Disable DW_apb_i2c
self.clr_reg(self.IC_ENABLE, 1)
# 2 set slave address
# clr bit 0 to 9
# set slave address
self.clr_reg(self.IC_SAR, 0x1ff)
self.set_reg(self.IC_SAR, self.slaveAddress &0x1ff)
# 3 write IC_CON 7 bit, enable in slave-only
self.clr_reg(self.IC_CON, 0b01001001)
# set SDA PIN
mem32[ self.IO_BANK0_BASE | self.mem_clr | ( 4 + 8 * self.sda) ] = 0x1f
mem32[ self.IO_BANK0_BASE | self.mem_set | ( 4 + 8 * self.sda) ] = 3
# set SLA PIN
mem32[ self.IO_BANK0_BASE | self.mem_clr | ( 4 + 8 * self.scl) ] = 0x1f
mem32[ self.IO_BANK0_BASE | self.mem_set | ( 4 + 8 * self.scl) ] = 3
# 4 enable i2c
self.set_reg(self.IC_ENABLE, 1)
def any(self):
# get IC_STATUS
status = mem32[ self.i2c_base | self.IC_STATUS]
# check RFNE receive fifio not empty
if (status & 8) :
return True
return False
def get(self):
while not self.any():
pass
return mem32[ self.i2c_base | self.IC_DATA_CMD] & 0xff
if __name__ == "__main__":
import utime
from machine import mem32
from i2cSlave import i2c_slave
s_i2c = i2c_slave(0,sda=0,scl=1,slaveAddress=0x41)
try:
while True:
print(s_i2c.get())
except KeyboardInterrupt:
pass
Code: Select all
MicroPython v1.13-290-g556ae7914 on 2021-01-21; Raspberry Pi Pico with RP2040
Type "help()" for more information.
>>> %Run -c $EDITOR_CONTENT
12
15
So just using micropython to create the slave class is possible.
-
- Posts: 4504
- Joined: Thu Dec 27, 2012 4:05 am
- Location: Québec, Canada
Re: Use Pico as an I2C slave?
Now read and write i2c slave
the class
And getting data on the Pi
Now it is to figure out how to make interrupt, add command and multiple transaction
the class
Code: Select all
from machine import mem32,mem8,Pin
class i2c_slave:
I2C0_BASE = 0x40044000
I2C1_BASE = 0x40048000
IO_BANK0_BASE = 0x40014000
mem_rw = 0x0000
mem_xor = 0x1000
mem_set = 0x2000
mem_clr = 0x3000
IC_CON = 0
IC_TAR = 4
IC_SAR = 8
IC_DATA_CMD = 0x10
IC_RAW_INTR_STAT = 0x34
IC_RX_TL = 0x38
IC_TX_TL = 0x3C
IC_CLR_INTR = 0x40
IC_CLR_RD_REQ = 0x50
IC_CLR_TX_ABRT = 0x54
IC_ENABLE = 0x6c
IC_STATUS = 0x70
def write_reg(self, reg, data, method=0):
mem32[ self.i2c_base | method | reg] = data
def set_reg(self, reg, data):
self.write_reg(reg, data, method=self.mem_set)
def clr_reg(self, reg, data):
self.write_reg(reg, data, method=self.mem_clr)
def __init__(self, i2cID = 0, sda=0, scl=1, slaveAddress=0x41):
self.scl = scl
self.sda = sda
self.slaveAddress = slaveAddress
self.i2c_ID = i2cID
if self.i2c_ID == 0:
self.i2c_base = self.I2C0_BASE
else:
self.i2c_base = self.I2C1_BASE
# 1 Disable DW_apb_i2c
self.clr_reg(self.IC_ENABLE, 1)
# 2 set slave address
# clr bit 0 to 9
# set slave address
self.clr_reg(self.IC_SAR, 0x1ff)
self.set_reg(self.IC_SAR, self.slaveAddress &0x1ff)
# 3 write IC_CON 7 bit, enable in slave-only
self.clr_reg(self.IC_CON, 0b01001001)
# set SDA PIN
mem32[ self.IO_BANK0_BASE | self.mem_clr | ( 4 + 8 * self.sda) ] = 0x1f
mem32[ self.IO_BANK0_BASE | self.mem_set | ( 4 + 8 * self.sda) ] = 3
# set SLA PIN
mem32[ self.IO_BANK0_BASE | self.mem_clr | ( 4 + 8 * self.scl) ] = 0x1f
mem32[ self.IO_BANK0_BASE | self.mem_set | ( 4 + 8 * self.scl) ] = 3
# 4 enable i2c
self.set_reg(self.IC_ENABLE, 1)
def anyRead(self):
status = mem32[ self.i2c_base | self.IC_RAW_INTR_STAT] & 0x20
if status :
return True
return False
def put(self, data):
# reset flag
self.clr_reg(self.IC_CLR_TX_ABRT,1)
status = mem32[ self.i2c_base | self.IC_CLR_RD_REQ]
mem32[ self.i2c_base | self.IC_DATA_CMD] = data & 0xff
def any(self):
# get IC_STATUS
status = mem32[ self.i2c_base | self.IC_STATUS]
# check RFNE receive fifio not empty
if (status & 8) :
return True
return False
def get(self):
while not self.any():
pass
return mem32[ self.i2c_base | self.IC_DATA_CMD] & 0xff
if __name__ == "__main__":
import utime
from machine import mem32
from i2cSlave import i2c_slave
s_i2c = i2c_slave(0,sda=0,scl=1,slaveAddress=0x41)
counter =1
try:
while True:
if s_i2c.any():
print(s_i2c.get())
if s_i2c.anyRead():
counter = counter + 1
s_i2c.put(counter & 0xff)
except KeyboardInterrupt:
pass
And getting data on the Pi
Code: Select all
>>> bus.read_byte(0x41)
2
>>> bus.read_byte(0x41)
3
>>> bus.read_byte(0x41)
4
>>> bus.read_byte(0x41)
5
>>> bus.read_byte(0x41)
6
>>> bus.read_byte(0x41)
7
Re: Use Pico as an I2C slave?
Unless it has been implemented then that's the way it is, and always will be, if using MicroPython, CircuitPython or other third-party languages.
For those language providers the RP2040 is a third-party product and it takes time and effort to figure out how to provide what people might like to see, implement it, test it, debug it, release it - as tannewt noted earlier.
Just because a chip supports something doesn't mean a language provider will have provided a means of using that capability with their language. Even where they would like to, want to, that takes time, effort, resources and has cost. All that has to be scheduled and balanced alongside other activities.
And it's not always easy to find the funding for additions or improvements when software is given away for free, if chip developers are not funding third-parties to support their chip or that funding is limited.
If something is lacking then one either needs to provide a solution oneself, wait for the language developers or the user community to figure out a solution, or do without, look in some other direction.
Re: Use Pico as an I2C slave?
Works! Nice
Re: Use Pico as an I2C slave?
Would it make sense (and would it be OK with you) if someone took your proof of concept class, and put it on GitHub as a kind of starting point of a generally available MicroPython I2C slave library for the Raspberry Pi Pico?danjperron wrote: ↑Sat Feb 20, 2021 12:36 pmProof of concept!
Ok I made a small I2C slave class that could read one byte data send to the Pico.
Re: Use Pico as an I2C slave?
Great, thank you very much for solution.
I understand, that Pico is for micropython new and for a lot of things I will have to wait and it's really not a problem for me
I understand, that Pico is for micropython new and for a lot of things I will have to wait and it's really not a problem for me
