Introduction
This week, I had the opportunity to experiment with the Raspberry Pi Pico. The most significant aspects of this experience were reading Datasheets and understanding how a microcontroller works: what are it's pins used for, what type of pins are there. I also contributed to the group assingment by documenting how to download Thonny, Arduino, and VS Code. I also blinked the LED on Pico and documented it.
This is the link to our group project
Simulation
This week to simulate embedded programming I used the Wokwi simulation environment to control a Raspberry Pi Pico to get the hang working with some of the electronic components. Wokwi is a web based embedded programming environment. Steps to open Wokwi:
- search wokwi pico, micropython in your browser of choice
- click the first link that pops up
- the Wokwi micropython simulation environment appears!
Here, I decided the create a circuit which involved some fundamental electronics components.
Electronics
Bill of Materials (BOM)
| Component | Quantity | Description |
|---|---|---|
| Raspberry Pi Pico | 1 | Microcontroller |
| Red LED | 1 | Visual indicator |
| Yellow LED | 1 | Visual indicator |
| Green LED | 1 | Visual indicator |
| Push Button | 1 | User input trigger |
| Servo Motor (SG90 or similar) | 1 | Servo |
| Jumper Wires | Various | Connections |
| Breadboard | 1 | Circuit assembly |
Wiring
In the environment I firstly decided to wire the LED's and tried to create a system similar to traffic lights. I wired red, yellow, green LED's to GP (general purpose) pins 2,5 and 9 respectively. !
After getting this system to work, I added a Servo into the mix which would rotate from 0-160 and 160-0 in a continuous loop. I connected the servo to GP 28 on the opposite side of the board and LED's!
Lastly, I added a push button in order for it to serve as a initiator to the program so that it wouldn't run at the start every time.
Programming
Code Overivew
from machine import Pin, PWM
import time
# Pin definitions for hardware connections
RED_LED_PIN = 2 # Red LED connected to GPIO 2
YELLOW_LED_PIN = 5 # Yellow LED connected to GPIO 5
GREEN_LED_PIN = 9 # Green LED connected to GPIO 9
SERVO_PIN = 28 # Servo motor signal connected to GPIO 28
BUTTON_PIN = 10 # Push button connected to GPIO 10
# Initialize LED pins as digital outputs
red_led = Pin(RED_LED_PIN, Pin.OUT)
yellow_led = Pin(YELLOW_LED_PIN, Pin.OUT)
green_led = Pin(GREEN_LED_PIN, Pin.OUT)
# Initialize servo with PWM at 50Hz (standard servo frequency)
servo = PWM(Pin(SERVO_PIN))
servo.freq(50)
# Initialize button with internal pull-up resistor
# When button is pressed, it will read LOW (0)
button = Pin(BUTTON_PIN, Pin.IN, Pin.PULL_UP)
def turn_on_led(led_pin):
"""
Turn on specified LED and ensure others are off
Args:
led_pin: GPIO pin number of LED to turn on
"""
red_led.value(led_pin == RED_LED_PIN)
yellow_led.value(led_pin == YELLOW_LED_PIN)
green_led.value(led_pin == GREEN_LED_PIN)
def servo_movement(angle):
"""
Move servo to specified angle
Args:
angle: Desired angle between 0 and 180 degrees
"""
# PWM duty cycle values for 0° and 180°
# These values may need adjustment based on your specific servo
min_duty = 1638 # Duty cycle for 0 degrees (1/20 * 65535)
max_duty = 8192 # Duty cycle for 180 degrees (5/20 * 65535)
# Ensure angle is within valid range
angle = max(0, min(180, angle))
# Calculate duty cycle for desired angle
duty = int(min_duty + (angle / 180) * (max_duty - min_duty))
servo.duty_u16(duty)
# Define movement sequence
# Moves from 0° to 160° and back in 20° increments
ANGLE_SEQUENCE = [0, 20, 40, 60, 80, 100, 120, 140, 160,
160, 140, 120, 100, 80, 60, 40, 20, 0]
# Create LED sequence that cycles through all three LEDs
# Length matches ANGLE_SEQUENCE by repeating pattern
LED_SEQUENCE = [RED_LED_PIN, YELLOW_LED_PIN, GREEN_LED_PIN] * (len(ANGLE_SEQUENCE) // 3)
try:
while True:
# Wait for button press
if button.value() == 0:
time.sleep(0.05) # Debounce delay
# Wait for button release
while button.value() == 0:
pass
# Execute movement sequence
for i in range(len(ANGLE_SEQUENCE)):
turn_on_led(LED_SEQUENCE[i]) # Update LED
servo_movement(ANGLE_SEQUENCE[i]) # Move servo
time.sleep(1) # Wait 1 second
except KeyboardInterrupt:
# Clean up on program exit
servo.duty_u16(0) # Stop servo
red_led.value(0) # Turn off all LEDs
yellow_led.value(0)
green_led.value(0)
Mistakes and What I Learned
MicroPython Code Breakdown: LED and Servo Control System
1. Imports and Pin Definitions
from machine import Pin, PWM import time RED_LED_PIN = 2 YELLOW_LED_PIN = 5 GREEN_LED_PIN = 9 SERVO_PIN = 28 BUTTON_PIN = 10
This section imports necessary modules and defines constants for GPIO pin assignments. The machine module provides hardware control capabilities, while time is used for delays.
2. Hardware Initialization
red_led = Pin(RED_LED_PIN, Pin.OUT) yellow_led = Pin(YELLOW_LED_PIN, Pin.OUT) green_led = Pin(GREEN_LED_PIN, Pin.OUT) servo = PWM(Pin(SERVO_PIN)) servo.freq(50) button = Pin(BUTTON_PIN, Pin.IN, Pin.PULL_UP)
This block initializes the hardware:
- LEDs are set up as digital outputs
- Servo is configured with PWM at 50Hz (standard servo frequency)
- Button is set up with an internal pull-up resistor (reads 1 when not pressed, 0 when pressed)
3. LED Control Function
def turn_on_led(led_pin):
"""
Turn on specified LED and ensure others are off
Args:
led_pin: GPIO pin number of LED to turn on
red_led.value(led_pin == RED_LED_PIN)
yellow_led.value(led_pin == YELLOW_LED_PIN)
green_led.value(led_pin == GREEN_LED_PIN)
"""
This function implements mutually exclusive LED control:
- Takes a pin number as input
- Uses boolean comparisons to ensure only one LED is on at a time
- Elegant implementation avoiding multiple if-statements
4. Servo Control Function
def servo_movement(angle):
"""
Move servo to specified angle
Args:
angle: Desired angle between 0 and 180 degrees
"""
min_duty = 1638 # Duty cycle for 0 degrees (1/20 * 65535)
max_duty = 8192 # Duty cycle for 180 degrees (5/20 * 65535)
angle = max(0, min(180, angle))
duty = int(min_duty + (angle / 180) * (max_duty - min_duty))
servo.duty_u16(duty)
The servo control function:
- Converts angles (0-180°) to appropriate PWM duty cycles
- Includes bounds checking for safety
- Uses linear interpolation to calculate duty cycle
- Works with 16-bit PWM resolution (0-65535)
5. Movement Sequences
ANGLE_SEQUENCE = [0, 20, 40, 60, 80, 100, 120, 140, 160, 160, 140, 120, 100, 80, 60, 40, 20, 0] LED_SEQUENCE = [RED_LED_PIN, YELLOW_LED_PIN, GREEN_LED_PIN] * (len(ANGLE_SEQUENCE) // 3)
Defines the movement patterns:
- ANGLE_SEQUENCE creates a sweep pattern (0° → 160° → 0°)
- LED_SEQUENCE cycles through the LEDs in sync with servo movement
- Multiplication operator creates a pattern matching ANGLE_SEQUENCE length
6. Main Control Loop
while True:
if button.value() == 0:
time.sleep(0.05) # Debounce delay
while button.value() == 0:
pass
for i in range(len(ANGLE_SEQUENCE)):
turn_on_led(LED_SEQUENCE[i])
servo_movement(ANGLE_SEQUENCE[i])
time.sleep(1)
except KeyboardInterrupt:
servo.duty_u16(0)
red_led.value(0)
yellow_led.value(0)
green_led.value(0)
The main program loop:
- Waits for button press with debouncing
- Executes the movement sequence when triggered
- Includes cleanup code for graceful shutdown
- Uses try-except to handle program termination
Technical Details
PWM Calculations
- The servo uses a 50Hz signal (20ms period)
- Duty cycle range: 1638 (2.5%) to 8192 (12.5%)
- These values correspond to typical servo pulse widths:
- 0° position: 0.5ms pulse (2.5% duty)
- 180° position: 2.5ms pulse (12.5% duty)
Button Debouncing
- 50ms delay after button press detection
- Waits for button release before continuing
- Prevents multiple triggers from a single press
Extra Credit: Working with a Development Board
After completing the main assignment of this week I had a chance to experiment with a Raspberry Pi Pico in real life. I decided to try to light the LED on the Pico's board, I used the picozero libraries pico_led class for this below is the code implementations and result:
from picozero import pico_led from time import sleep pico_led.on() sleep(10) pico_led.off()