The Raspberry Pi Pico is a small microcontroller board with two SPI controllers, two I2C controllers, two UARTs, and 16 PWMs.
The Raspberry Pi Pico is mainly used to control multiple devices as a master.
In fact, Raspberry Pi Pico also has a mode of slave operation.
This article shows how to set up Raspberry Pi Pico as I2C slave.
Contents
- Parts required to use the Raspberry Pi Pico
- Connection of each part
- Python sample code
sponsored link
Parts required to use the Raspberry Pi Pico
In the beginning, I show parts required to use the Raspberry Pi Pico reflective optical sensor.
Raspberry Pi Pico
Breadboard
This breadboard is a best seller on Amazon.
Jumper wire
This product is a set of male-male, male-female, and female-female.
sponsored link
Connection of each part
I show the wiring of Raspberry Pi and Raspberry Pi Pico.
SDA and SCL required for I2C communication are only connected.
Raspberry Pi GPIO Pinout
Here is the pinout of the Raspberry Pi.
quotation : Raspberry Pi Documentation
Raspberry Pi Pico GPIO Pinout
Here is the pinout of the Raspberry Pi Pico.
quotation : Raspberry Pi Pico Documentation
Connection of Raspberry Pi and Raspberry Pi Pico
This is a schematic of Raspberry Pi and Raspberry Pi Pico.
SDA and SCL required for I2C communication are only connected.
Since the input voltage of Raspberry Pi Pico is 1.8 ~ 5.5 V, 5 V power is supplied from Raspberry Pi.
sponsored link
Python sample code
I show sample code to run Raspberry Pi Pico in slave mode.
There are a few things to note.
【UF2】
In order to use the Raspberry Pi Pico, the MicroPython UF2 file must be installed.
Please install the UF2 file by referring to this site.
【Thonny】
For writing code to Raspberry Pi Pico, I recommend "Thonny" environment.
Thonny is Python Integrated development environment that makes it easy to write code to Raspberry Pi Pico.
MicroPython code to write to Raspberry pi pico
Prepare the following three files and write them to Raspberry Pi Pico.
- i2cSlave.py
- led.py
- main.py
Files stored in Raspberry Pi Pico can be viewed in Thonny.
As soon as Raspberry Pi Pico is turned on, main.py starts up and calls led.py and i2cSlave.py.
The description of i2cSlave.py is based on this site.
Thanks to danjperron for creating this code.
--- i2cSlave.py ---
### i2cSlave.py
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 #I2C Control Register
IC_TAR = 4 #I2C Target Address Register
IC_SAR = 8 #I2C Slave Address Register
IC_DATA_CMD = 0x10 #I2C Rx/Tx Data Buffer and Command Register
IC_RAW_INTR_STAT = 0x34 # I2C Raw Interrupt Status Register
IC_RX_TL = 0x38 #I2C Receive FIFO Threshold Register
IC_TX_TL = 0x3C #I2C Transmit FIFO Threshold Register
IC_CLR_INTR = 0x40 #Clear Combined and Individual Interrupt Register
IC_CLR_RD_REQ = 0x50
IC_CLR_TX_ABRT = 0x54
IC_ENABLE = 0x6c #I2C ENABLE Register
IC_STATUS = 0x70 #I2C STATUS Register
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
--- led.py ---
### led.py
import utime
import time
from machine import Pin, Timer
led = Pin(25, Pin.OUT)
def led_power_on() :
for i in range(5) :
led.value(1)
time.sleep(0.5)
led.value(0)
time.sleep(0.5)
led.value(1)
time.sleep(0.5)
led.value(0)
time.sleep(1.0)
def led_on() :
led.value(1)
def led_off() :
led.value(0)
--- main.py ---
### main.py
import utime
import time
from machine import mem32,Pin
import led
from i2cSlave import i2c_slave
### --- check pico power on --- ###
led.led_power_on()
### --- pico connect i2c as slave --- ###
s_i2c = i2c_slave(0,sda=0,scl=1,slaveAddress=0x41)
try:
while True:
data = s_i2c.get()
print(data)
data_int = int(data)
for i in range(data_int):
led.led_on()
time.sleep(0.5)
led.led_off()
time.sleep(0.5)
except KeyboardInterrupt:
pass
Save above codes to the Raspberry Pi Pico.
I2C address of Raspberry Pi Pico
When main.py is loaded, I2C address of the Raspberry Pi Pico is recognized.
In the example in this article, I2C address is set to 0x41 in main.py.
Check if I2C address of Raspberry Pi Pico is really set to 0x41.
Enter the following command in Raspberry Pi terminal.
$ sudo i2cdetect -y 1
I2C address of Raspberry Pi Pico is 0x41.
Python code to write to Raspberry pi
Next, on the Raspberry Pi side, prepare the code for I2C communication.
--- pi_pico_i2c_test.py ---
### pi_pico_i2c_test.py
import time
import smbus
bus = smbus.SMBus(1)
bus.write_byte(0x41,3) #"3" is the data sent to Raspberry Pi Pico
When the above code is executed, LED of Raspberry Pi Pico blinks according to transmitted data.
sponsored link