Coursework / GE1501 / Pico-0

Pico-0: Getting Started with Raspberry Pi Pico

Exploring how a few lines of MicroPython can control light, read a sensor, and connect code to a physical circuit.

By
Yi Qiao (Joe) Lin
Course
GE1501 · Northeastern University
Term
Fall 2026
Instructor
Professor Baskaran

01 / Overview

What is this project?

Pico-0 introduces the Raspberry Pi Pico through four breadboard tasks: blinking an external LED, responding to a light sensor, controlling brightness with pulse-width modulation, and mixing colors with an RGB LED.

The challenges build on each other, moving from digital output to analog sensing and then to continuous brightness control. Thonny provides the programming environment, and MicroPython’s built-in machine module connects the code to the hardware.

02 / Goals

Four circuits. Four challenges.

  1. Blink an external LED

    Extend the basic blink circuit to two LEDs that alternate like a police siren.

  2. An LED that responds to light

    Use the light sensor to blink an LED in darkness and keep it off in bright light.

  3. Dimming an LED with light

    Reverse the starter dimmer so the LED becomes brighter as the room becomes brighter.

  4. Mixing RGB colors

    Modify the RGB sequence to display only the rainbow colors: red, orange, yellow, green, blue, indigo, and violet.

03 / How it was made

The breadboard builds

The four task photos document the circuits at the workbench. Open any image to inspect the wiring at full size.

Platform setup

The setup procedure is to connect the Pico in BOOTSEL mode, install the matching MicroPython firmware through Thonny, and select the Pico interpreter. The programs use Pin, ADC, and PWM; no additional Python library is needed.

Disconnect USB power before changing wiring. Keep each LED’s current-limiting resistor in series and use the 3V3(OUT) supply, not the adjacent 3V3_EN pin, for the LDR divider.

Raspberry Pi Pico on a breadboard connected to an illuminated external red LED and resistor
Single-LED circuit, with the external red LED illuminated.

Task 01 / Digital output

Blink an external LED

The Pico is connected over USB and mounted on the breadboard. An external red LED, a series resistor, and jumper wires form the first output circuit. The challenge adds a second LED with its own resistor and GPIO connection.

Challenge goal

Extend the basic blink circuit to two LEDs that alternate like a police siren.

Wiring and pin assignments

  • GP15 → series resistor → red LED anode; cathode → GND.
How the code works
Pico, external red LED, and light-sensor wiring on a breadboard with a hand shading the sensor area
The LED and light-sensor circuit during a hand-shading test.

Task 02 / Analog input + digital output

An LED that responds to light

A light-dependent resistor (LDR) and a fixed resistor form a voltage divider alongside the LED circuit. A hand over the sensor changes the amount of light reaching it.

Challenge goal

Use the light sensor to blink an LED in darkness and keep it off in bright light.

Wiring and pin assignments

  • 3V3(OUT), physical pin 36 → LDR → divider junction.
  • Divider junction → GP27 and a 10 kΩ resistor; the resistor’s other end → GND.
  • GP15 → series resistor → LED anode; cathode → GND.
How the code works
Close-up of a photoresistor and fixed resistor beside an external red LED, with a hand above the sensor
A close-up of the LDR, fixed resistor, and LED circuit used for the dimming task.

Task 03 / Analog input + PWM

Dimming an LED with light

The LED and LDR wiring from Task 2 is reused. The change is in software: the LED output becomes PWM, allowing intermediate brightness levels instead of just on and off.

Challenge goal

Reverse the starter dimmer so the LED becomes brighter as the room becomes brighter.

Wiring and pin assignments

  • Reuse the GP27 light-sensor divider from Task 2.
  • The corrected copy uses GP15 for the LED, matching Tasks 1 and 2. The uploaded original does not define its LED output pin.
How the code works
Common-cathode RGB LED glowing purple on a breadboard connected to a Raspberry Pi Pico
The RGB circuit illuminated with a purple-toned color, with separate channel wiring and resistors visible.

Task 04 / Three PWM outputs

Mixing RGB colors

A common-cathode RGB LED replaces the single-color LED. Its red, green, and blue channels each have a separate series resistor and GPIO connection, while the common cathode connects to ground.

Challenge goal

Modify the RGB sequence to display only the rainbow colors: red, orange, yellow, green, blue, indigo, and violet.

Wiring and pin assignments

  • GP13 → series resistor → red channel.
  • GP12 → separate series resistor → green channel.
  • GP11 → separate series resistor → blue channel; common cathode → GND.
How the code works

04 / How it works

Reading inputs. Controlling outputs.

These are the four uploaded MicroPython programs, available to read and download unchanged. The explanations describe their logic; the challenge notes identify what still differs from the assignment’s extension goals. Hardware behavior has not been independently verified.

Task 01 / Uploaded source

Blink an external LED

The uploaded program configures GP15 as a digital output. Its loop turns one external LED on for half a second, then off for half a second, repeating continuously.

Expected behavior: One LED blinks with a one-second cycle: 0.5 seconds on and 0.5 seconds off.

Challenge extension: The two-LED challenge requires a second GPIO output and alternating states; the uploaded file controls one LED.

View blink_external_led.py
from machine import Pin
import time

LED_PIN = 15                 # GP number: change to match your wiring
led = Pin(LED_PIN, Pin.OUT)  # set the pin as an output

while True:
    led.value(1)             # LED on
    time.sleep(0.5)          # wait half a second
    led.value(0)             # LED off
    time.sleep(0.5)          # wait half a second
Download original .py

Task 02 / Uploaded source

An LED that responds to light

The program reads the LDR on GP27 and prints the value every 0.2 seconds. When the reading is below the configured DARK threshold of 35,000, it sets the LED on GP15 high. At 35,000 or above, it turns the LED off.

Expected behavior: The LED stays on below the threshold and stays off at or above it.

Challenge extension: The challenge adds a warning blink in darkness. The uploaded file holds the LED steadily on instead.

View ldr_on_off.py
from machine import Pin, ADC
import time

# GP numbers: change to match your wiring
LED_PIN = 15
LDR_PIN = 27                 # must be GP26, GP27, or GP28 (analog pins)

led = Pin(LED_PIN, Pin.OUT)
ldr = ADC(LDR_PIN)

DARK = 35000                 # threshold: set this from your own readings

while True:
    light = ldr.read_u16()   # 0 (dark) to 65535 (bright)
    print(light)
    if light < DARK:         # dark: turn the LED on
        led.value(1)
    else:                    # bright: turn the LED off
        led.value(0)
    time.sleep(0.2)
Download original .py

Task 03 / Uploaded source

Dimming an LED with light

The uploaded file calculates brightness as (50,000 − light) / (50,000 − 35,000), clamps it to 0–1, and scales it to a PWM duty value from 0–65535. This is night-light behavior: less ambient light produces a brighter LED. It specifies 1 kHz PWM and a 0.1-second sampling interval.

Expected behavior: When run on its own in a fresh interpreter, the original file stops with a NameError because LED_PIN is not defined. The corrected copy uses GP15: a reading of 50,000 gives 0% brightness, 42,500 gives 50%, and 35,000 gives 100%.

Challenge extension: The challenge reverses this mapping so brighter ambient light produces a brighter LED. Both the original formula and the corrected copy retain the night-light mapping.

View ldr_dimmer.py
from machine import Pin, PWM, ADC
import time

# GP numbers: change to match your wiring
RED_PIN = 13
GREEN_PIN = 12
BLUE_PIN = 11
LDR_PIN = 27                 # must be GP26, GP27, or GP28 (analog pins)

led = PWM(Pin(LED_PIN))
led.freq(1000)               # 1000 on/off cycles per second
ldr = ADC(LDR_PIN)

# Readings from Task 6: set these from your own room
BRIGHT_ROOM = 50000          # reading in normal room light
DARK_ROOM = 35000            # reading with the LDR covered

while True:
    light = ldr.read_u16()   # 0 (dark) to 65535 (bright)

    # 0.0 in a bright room, 1.0 in a dark room
    level = (BRIGHT_ROOM - light) / (BRIGHT_ROOM - DARK_ROOM)
    level = max(0, min(1, level))     # keep between 0 and 1

    led.duty_u16(int(level * 65535))  # darker room -> brighter LED
    print(light, round(level * 100), "%")
    time.sleep(0.1)
Download original .py

Task 04 / Uploaded source

Mixing RGB colors

Three 1 kHz PWM outputs control red on GP13, green on GP12, and blue on GP11. The set_color function multiplies each 0–255 channel value by 257 to reach the 16-bit duty range. A loop prints and displays each color for one second, then turns all channels off.

Expected behavior: One sequence of red, green, blue, yellow, cyan, magenta, white, purple, and orange, followed by off.

Challenge extension: The challenge requires only rainbow colors in order. The uploaded sequence includes cyan, magenta, and white and is not in rainbow order.

View rgb_led.py
from machine import Pin, PWM
import time

# GP numbers: change to match your wiring
RED_PIN = 13
GREEN_PIN = 12
BLUE_PIN = 11

red = PWM(Pin(RED_PIN))
green = PWM(Pin(GREEN_PIN))
blue = PWM(Pin(BLUE_PIN))

for channel in (red, green, blue):
    channel.freq(1000)       # 1000 on/off cycles per second

def set_color(r, g, b):
    """Set brightness of each color from 0 (off) to 255 (full)."""
    red.duty_u16(r * 257)    # 255 * 257 = 65535 (full brightness)
    green.duty_u16(g * 257)
    blue.duty_u16(b * 257)

colors = [
    ("red",     (255, 0, 0)),
    ("green",   (0, 255, 0)),
    ("blue",    (0, 0, 255)),
    ("yellow",  (255, 255, 0)),
    ("cyan",    (0, 255, 255)),
    ("magenta", (255, 0, 255)),
    ("white",   (255, 255, 255)),
    ("purple",  (128, 0, 128)),
    ("orange",  (255, 128, 0)),
]

for name, (r, g, b) in colors:
    print(name)
    set_color(r, g, b)
    time.sleep(1)

set_color(0, 0, 0)           # turn the LED off
Download original .py