metronome/pico/README.md
Me Here 111702222b PM_K-1 docs: make the two-step flash explicit (main.py is not drag-and-drop)
A user dropped main.py onto the RPI-RP2 BOOTSEL drive (which only accepts a .uf2)
and it vanished on reboot. Clarify in pico/README.md and info-kit.html that
flashing is two distinct steps: (1) drag-and-drop the MicroPython .uf2, then
(2) copy main.py over USB serial with Thonny/mpremote — the Pico is not a USB
drive once MicroPython is running.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-28 16:42:18 -05:00

94 lines
5.1 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# PM_K1 "Kit" — VARASYS PolyMeter firmware for the Raspberry Pi Pico
MicroPython firmware that turns a **Raspberry Pi Pico** on the **52Pi EP0172 "Pico
Breadboard Kit Plus"** into a touchscreen polymeter metronome. It runs the *same program
strings* as <https://metronome.varasys.io> — design a groove in the web editor, copy its
program string, paste it into `PROGRAMS` in `main.py`, and it plays here.
Everything is in one file: `main.py` (ST7796 display driver, GT911 touch, WS2812 RGB,
buzzer, joystick, the polymeter engine — no external libraries).
## The board (EP0172) — fixed pinout
| Component | Pico pins |
|---|---|
| 3.5″ ST7796 320×480 display | SPI0 — SCK `GP2`, MOSI `GP3`, CS `GP5`, DC `GP6`, RST `GP7` |
| GT911 capacitive touch | I2C0 — SDA `GP8`, SCL `GP9` (addr 0x5D) |
| WS2812 RGB LED | `GP12` |
| Buzzer | `GP13` |
| Button A / Button B | `GP15` / `GP14` |
| PSP joystick | X = `ADC0`/`GP26`, Y = `ADC1`/`GP27` |
The components are wired on the board — you don't breadboard anything; just seat the Pico.
## Flash it — TWO separate steps
> ⚠️ **`main.py` is NOT a drag-and-drop file.** The `RPI-RP2` drive that appears in BOOTSEL mode
> is the bootloader, and it *only* accepts a `.uf2` firmware file — anything else (like `main.py`)
> is silently discarded on the next reboot. You first flash MicroPython with a `.uf2` (drag-and-drop),
> and *then* copy `main.py` over the USB serial link with Thonny or mpremote. Two different steps.
### Step 1 — install MicroPython (drag-and-drop a `.uf2`, one time)
1. Download the MicroPython firmware **`.uf2`** for your board:
- Pico / Pico W → <https://micropython.org/download/RPI_PICO/> (or `RPI_PICO_W`)
- Pico 2 / Pico 2 W → <https://micropython.org/download/RPI_PICO2/>
2. Hold **BOOTSEL**, plug into USB → the `RPI-RP2` drive appears.
3. **Drag the `.uf2` file onto that drive.** It copies, the Pico reboots on its own, and the drive
**disappears** — that's correct and means MicroPython is installed. (Don't use BOOTSEL again unless
you're reinstalling the firmware.)
### Step 2 — copy `main.py` (over USB serial, NOT to a drive)
After step 1 the Pico runs MicroPython and **no longer shows up as a USB drive** — so you can't drag
files to it. Use a tool that talks to it over USB serial:
- **Thonny (easiest):** install [Thonny](https://thonny.org), plug the Pico in normally, then
bottom-right click the interpreter selector → **MicroPython (Raspberry Pi Pico)** (you should see
a `>>>` prompt in the Shell). Open `main.py`, then **File ▸ Save as… ▸ Raspberry Pi Pico** and save
it as exactly **`main.py`**.
- **mpremote (command line):** `pip install mpremote` then `mpremote cp main.py :main.py`
Reset (replug) and it boots straight into the metronome.
## Controls
- **Touch:** onscreen `<<` / `>||` / `>>` (prev · play/stop · next) and `` / `TAP` / `+`.
- **Joystick:** up/down = tempo (push far for ±5), left/right = previous/next groove.
- **Button A (GP15):** play / stop. **Button B (GP14):** tap tempo.
- **RGB LED** flashes each beat (amber = accent, cyan = normal, violet = ghost); the
**buzzer** clicks with matching pitch.
## Add your own grooves
Edit the `PROGRAMS` list near the top of `main.py` — each entry is `("Name", "program string")`.
Get program strings from the web editor's program box (e.g. `v1;t120;kick:4;snare:4=.X.X;hat:4/2`).
Supported: tempo `t<bpm>`, lanes `sound:grouping[/sub][=pattern][~][!]`, pattern chars
`X` accent · `x` normal · `g` ghost · `.` `-` `_` rest, grouped meters like `3+3+2`, polymeter `~`.
(Perlane dB gain `@n` is parsed but ignored — the buzzer is mono.)
## If something looks off — calibration
All the knobs are flags in the `CONFIG` block at the top of `main.py`:
- **Colours look negative / washed out:** toggle `INVERT_COLORS`.
- **Red and blue swapped:** set `SWAP_RB = True`.
- **Taps land in the wrong place:** set `TOUCH_DEBUG = True`, reset, watch the raw
coordinates over the USB serial (Thonny shell) as you tap the corners, then set
`TOUCH_SWAP_XY` / `TOUCH_INVERT_X` / `TOUCH_INVERT_Y` to match.
- **Joystick reversed:** toggle `JOY_INVERT_X` / `JOY_INVERT_Y`; widen `JOY_DEADZONE` if it drifts.
- **Screen stays black:** the backlight is hardwired on, so this usually means the SPI init
didn't take — drop `SPI_BAUD` to `24_000_000` and retry.
- **Garbled / wrong size image:** your panel lot may be a 240×320 ILI9341 instead of the
320×480 ST7796. This firmware targets the ST7796 you have (you said 320×480); if a unit
ever ships ILI9341, set `WIDTH,HEIGHT = 240,320` and use an ILI9341 init sequence.
## Notes
- Audio is a single passive buzzer, so coincident lane hits play one click at the highest
priority (accent > normal > ghost); the RGB + screen still show the combined activity.
- The scheduler is nonblocking and timed off `time.ticks_us()`, so tempo stays steady while
the screen and inputs update.
Hardware reference: [52Pi EP0172 wiki](https://wiki.52pi.com/index.php?title=EP-0172) ·
[vendor code](https://github.com/geeekpi/pico_breakboard_kit). VARASYS — Simplifying Complexity.