Project Demo
The document below shows a demo. The microcontrolled used here is STEPico, a pin-to-pin version for Pico 2040 based on Raspberry Pi's RP2040 microcontroller.
Last updated
The document below shows a demo. The microcontrolled used here is STEPico, a pin-to-pin version for Pico 2040 based on Raspberry Pi's RP2040 microcontroller.
Last updated
from machine import Pin, I2C, PWM
from utime import sleep
import sh1106
from dht20 import DHT20
from ws2812 import WS2812
# Initialize I2C for the DHT20 sensor
i2c_dht = I2C(1, sda=Pin(10), scl=Pin(11), freq=100000)
dht20 = DHT20(0x38, i2c_dht)
# Initialize I2C for the SH1106 OLED
i2c_oled = I2C(0, sda=Pin(20), scl=Pin(21), freq=100000)
oled = sh1106.SH1106_I2C(128, 64, i2c_oled, rotate=180)
oled.fill(0)
oled.show()
# Initialize rotary encoder
TRA = Pin(16, Pin.IN, Pin.PULL_UP)
TRB = Pin(17, Pin.IN, Pin.PULL_UP)
# Initialize confirm button
confirm_button = Pin(15, Pin.IN, Pin.PULL_UP)
# Initialize GPIO22 for indicating power range status
status_gpio = Pin(22, Pin.OUT)
# Initialize GPIO0 for PWM output control
pwm_gpio = Pin(0)
pwm = PWM(pwm_gpio)
pwm.freq(20000) # 20kHz PWM frequency
# Initialize WS2812 LEDs
led_pin = 23 # Pin where WS2812 is connected
num_leds = 4
ws2812 = WS2812(led_pin, num_leds, brightness=0.05)
# Default power percentage
target_power = 50.0
target_set = False
# State variables for rotary encoder
last_TRA = TRA.value()
last_TRB = TRB.value()
def update_target_power(pin):
global target_power
global last_TRA
global last_TRB
TRA_state = TRA.value()
TRB_state = TRB.value()
# Determine direction based on TRA and TRB states
if TRA_state != last_TRA:
if TRA_state == 0: # TRA went low
if TRB_state == 0:
# TRA low, TRB low: counterclockwise
target_power -= 5
else:
# TRA low, TRB high: clockwise
target_power += 5
last_TRA = TRA_state
last_TRB = TRB_state
def confirm_button_pressed(pin):
global target_set
if pin.value() == 0: # Button pressed
target_set = True
else: # Button released
target_set = False
# Attach interrupt handlers
TRA.irq(trigger=Pin.IRQ_FALLING | Pin.IRQ_RISING, handler=update_target_power)
TRB.irq(trigger=Pin.IRQ_FALLING | Pin.IRQ_RISING, handler=update_target_power)
confirm_button.irq(trigger=Pin.IRQ_FALLING | Pin.IRQ_RISING, handler=confirm_button_pressed)
def update_leds():
# Calculate intensity proportional to power % (0-255 scale for WS2812)
intensity = int(max(0, min(255, (target_power / 100) * 255))) # Convert percentage to 0-255 range
# Set all LEDs to red with calculated intensity
ws2812.pixels_fill((0, 0, intensity)) # Fill LEDs with red color
ws2812.pixels_show()
while True:
# Read DHT20 measurements
measurements = dht20.measurements
current_temp = measurements['t']
current_humi = measurements['rh']
# Calculate PWM duty cycle based on target power (0-100% range)
duty_cycle = max(0, min(100, target_power)) # Clamp duty cycle between 0% and 100%
pwm.duty_u16(int(duty_cycle * 65535 / 100)) # Convert percentage to 16-bit value
# Check if target power is within Β±5% of current temperature
if abs(target_power - current_temp) <= 5.0:
status_gpio.value(0) # Target power is within range
else:
status_gpio.value(1) # Target power is out of range
# Display on OLED
oled.fill(0) # Clear the display
oled.text("Cur. Temp: {:.1f} C".format(current_temp), 0, 0)
oled.text("Cur. Humi: {:.1f} %".format(current_humi), 0, 16)
oled.text("Power %: {:.1f}".format(target_power), 0, 32)
oled.show()
# Update WS2812 LEDs based on power percentage
update_leds()
sleep(0.1) # Delay for 0.1 seconds
This code is based on the connection set out in the hardware layout given above. The code is written in MicroPython. You may use Thonny IDE to run this code. If you are unsure about setting up the environment for STEPico and MicroPython, check out .