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:

  1. search wokwi pico, micropython in your browser of choice
  2. click the first link that pops up
  3. the Wokwi micropython simulation environment appears!
Wokwi Environment

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. !

LEDs

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!

Circuit with Servo

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.

Full Circuit

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:

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:

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:

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:

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:

Technical Details

PWM Calculations

Button Debouncing

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()

LED by Pico