Sensors & I2C on Raspberry Pi Pico W
Sensors & I2C on Raspberry Pi Pico W
Use I2C to read temperature, humidity, and OLED displays.
I2C on the Pico W
I2C (Inter-Integrated Circuit) is a two-wire bus for connecting sensors and displays to a microcontroller. You only need two wires regardless of how many devices are connected:
- SDA ߀” Serial Data
- SCL ߀” Serial Clock
The Pico W has two I2C controllers. Common pin assignments:
| I2C | SDA pins | SCL pins |
|---|---|---|
| I2C0 | GPIO 0, 4, 8, 12, 16, 20 | GPIO 1, 5, 9, 13, 17, 21 |
| I2C1 | GPIO 2, 6, 10, 14, 18, 26 | GPIO 3, 7, 11, 15, 19, 27 |
Always add 4.7 k?© pull-up resistors to both SDA and SCL lines (many breakout boards include them).
Setting Up I2C
from machine import I2C, Pin
i2c = I2C(0, sda=Pin(0), scl=Pin(1), freq=400000) # 400 kHz fast mode
Scanning for I2C Devices
devices = i2c.scan()
for addr in devices:
print("Found I2C device at address:", hex(addr))
Common addresses:
0x3C/0x3D߀” SSD1306 OLED display0x76/0x77߀” BME280 / BMP280 temperature/pressure sensor0x40߀” SHT31 humidity sensor0x68߀” MPU6050 accelerometer/gyro
Reading a BME280 (Temperature, Humidity, Pressure)
First, install the MicroPython BME280 library ߀” copy bme280.py to the Pico W.
from machine import I2C, Pin
import bme280
i2c = I2C(0, sda=Pin(0), scl=Pin(1), freq=400000)
bme = bme280.BME280(i2c=i2c)
temp, pressure, humidity = bme.read_compensated_data()
print(f"Temp: {temp/100:.1f} ?°C")
print(f"Pressure: {pressure/25600:.1f} hPa")
print(f"Humidity: {humidity/1024:.1f} %")
Reading a DHT22 (Temperature & Humidity)
DHT sensors use a single-wire protocol, not I2C:
import dht
from machine import Pin
sensor = dht.DHT22(Pin(15))
sensor.measure()
print("Temperature:", sensor.temperature(), "?°C")
print("Humidity:", sensor.humidity(), "%")
DHT11 and DHT22 need at least 2 seconds between measurements.
SSD1306 OLED Display
The SSD1306 is a popular 128G—64 pixel OLED display. Install ssd1306.py on the Pico W.
from machine import I2C, Pin
import ssd1306
i2c = I2C(0, sda=Pin(0), scl=Pin(1))
oled = ssd1306.SSD1306_I2C(128, 64, i2c)
oled.fill(0) # Clear screen (black)
oled.text("Hello, Pico W!", 0, 0) # Text at x=0, y=0
oled.text("Temp: 22.5 C", 0, 16)
oled.show() # Push buffer to display
SPI Communication
For faster sensors or displays using SPI:
from machine import SPI, Pin
spi = SPI(0,
baudrate=1000000,
polarity=0,
phase=0,
sck=Pin(2),
mosi=Pin(3),
miso=Pin(4)
)
cs = Pin(5, Pin.OUT)
cs.value(0) # Select device
spi.write(b"\x00\x01") # Send bytes
data = spi.read(2) # Receive 2 bytes
cs.value(1) # Deselect
Combining Sensors with WiFi
A common pattern: read sensors and POST to a server.
import network, urequests, dht, ujson
from machine import Pin
from time import sleep
# Connect WiFi
wlan = network.WLAN(network.STA_IF)
wlan.active(True)
wlan.connect("SSID", "Password")
while wlan.status() != 3:
sleep(0.5)
sensor = dht.DHT22(Pin(15))
while True:
sensor.measure()
payload = ujson.dumps({
"temperature": sensor.temperature(),
"humidity": sensor.humidity()
})
r = urequests.post("https://yourserver.com/data",
data=payload,
headers={"Content-Type": "application/json"})
r.close()
sleep(60)