← Back to Lab Hub RP2040 JHS Lab

I2C Bus & Proximity Sensor Simulator

2-Wire Serial Protocol (SDA Data / SCL Clock), Device Addressing & Sensor Readings

📡 I2C Protocol Basics: Microcontrollers talk to sensors using just 2 wires: SCL (Serial Clock) keeps timing, while SDA (Serial Data) transfers bits. The RP2040 Master sends the target device address (e.g., 0x39), requests Register 0x1C (Proximity Data), and the Sensor responds with an ACK bit followed by the 8-bit distance byte!
RP2040 MASTER SDA (GP4) SCL (GP5) 4.7kΩ Pull-ups (3.3V) APDS-9960 SLAVE ADDR: 0x39
I2C BUS LOGIC ANALYZER SCL SDA
Sensor 8-bit Raw Value: 215 (0xD7)
Binary Transmitted on SDA: 1101 0111
Bus State: TRANSMISSION OK (ACK RECEIVED)
📦 I2C Frame Packet Breakdown
Start Slave Addr (7-bit) R/W ACK Sensor Data Byte Stop
S 0x39 (0111001) 1 (READ) 0 (ACK) 11010111 P
🐍 MicroPython Master Code Inspector
from machine import Pin, I2C
import utime

# Initialize I2C Bus on RP2040 (SDA=GP4, SCL=GP5, 100kHz)
i2c = I2C(0, sda=Pin(4), scl=Pin(5), freq=100000)

# APDS-9960 I2C Slave Address = 0x39
SENSOR_ADDR = 0x39
PROX_REG = 0x1C # Proximity Data Register

def read_proximity():
  # Request 1 byte of proximity data from register 0x1C
  data = i2c.readfrom_mem(SENSOR_ADDR, PROX_REG, 1)
  val = data[0] # Raw value: 215
  return val

# Continuously query sensor over I2C bus
while True:
  prox = read_proximity()
  print("Proximity Raw:", prox)
  utime.sleep_ms(200)
📝 Concept Check Quiz
Why are 4.7kΩ pull-up resistors required on both SDA and SCL lines in an I2C bus setup?