Arduino-side companion to the cuewire Python package.
Implements all nineteen commands referenced in cuewire.constants.COMMAND_IDS.
Provenance: this is the Huepfburg_SophieVersion sketch from
zerotonin/arduinosketchbook,
folded back into the cuewire repo so the two sides ship together.
| Feature | Value |
|---|---|
| MCU | ATmega32U4 |
| Board (arduino-cli FQBN) | arduino:avr:leonardo |
| Clock | 16 MHz |
| Required library | FlexiTimer2 (Arduino IDE Library Manager or arduino-cli lib install FlexiTimer2) |
Pin numbering for 18, 19, 20 as digital outputs confirms a
Leonardo / Pro Micro target (analogue pins doubled as digitals).
| Function | Pin(s) |
|---|---|
| LED bar (12 single-colour LEDs) | 0, 1, 4, 12, 6, 8, 10, 5, 13, 18, 19, 20 |
| Camera TTL outputs (× 3) | A3, A4, 7 |
| Bottom strip | 20 (shares slot with LEDPins[11], but switched separately by the botStripOn/Off commands) |
| Hall sensor (analogue) | A5 |
The "LED strip" is not addressable — it is twelve individual
single-colour LEDs animated by shifting a 16-bit Stripes pattern.
Patterns load Stripes; modes rotate it over time. No FastLED /
NeoPixel libraries are involved.
The firmware speaks two kinds of lines:
- Telemetry (~50 Hz when
writeOutFlag == true):>clockVar,boxPos,LEDpattern,LEDmode,LEDrelPos,LEDsinPer,LEDfreePer,LEDhallFactor,experimentRunning,duringPre,camFlag<— leading>and trailing<distinguish telemetry from command responses. - Command responses:
50 1337— reply to comm-test (1337).>>pre,exp,pattern,mode,free,sin,hall<<— reply toEXPgetParameter_return(13372999).end— emitted once whenclockVar >= endOfExperiment(no trailing newline; the host treats it as a sentinel).
The full 19-command table lives in
src/cuewire/constants.py.
| Mode | Integer | Behaviour |
|---|---|---|
NO_MOVEMENT |
0 | Static; whatever Stripes was last loaded with stays put. |
OPPOSITE_BOX |
1 | On each platform zero-crossing, animation direction flips opposite to platform motion (LEDhall_factor ticks per crossing). |
FOLLOW_BOX |
2 | Same, but animation direction matches platform motion. |
DOWN_CYCLE |
3 | Free-running rotation downward at LEDfree_periodeSec. |
UP_CYCLE |
4 | Free-running rotation upward at LEDfree_periodeSec. |
SINE |
5 | Period modulated sinusoidally with LEDsin_factor / LEDsin_periodeSec. |
| Pattern | Integer | Stripes value |
|---|---|---|
DARK |
0 | 0b0000000000000000 |
LIGHT |
1 | 0b1111111111111111 |
ALTERNATING |
2 | 0b1010101010101010 |
STRIPES |
3 | 0b0110111000110111 |
With arduino-cli (recommended for reproducibility):
# One-time setup
arduino-cli core update-index
arduino-cli core install arduino:avr
arduino-cli lib install FlexiTimer2
# Compile (creates firmware/PARROTard/build/)
arduino-cli compile --fqbn arduino:avr:leonardo firmware/PARROTard
# Flash (set PORT to your device, e.g. /dev/ttyACM0)
arduino-cli upload --fqbn arduino:avr:leonardo --port "$PORT" firmware/PARROTardThe Arduino IDE works too — open firmware/PARROTard/PARROTard.ino,
install FlexiTimer2 from Library Manager, select board "Arduino
Leonardo", and upload.
cuewire.testing.FirmwareSimulator is a Python class that mirrors
this firmware's protocol behaviour over a pty. The CI suite drives
it from tests/test_integration.py, so the host-side experiment
runners are exercised end-to-end without a physical Arduino.
If you have arduino-cli installed locally and want to compile the
real .ino (just to verify it builds), the GitHub Actions workflow
tests.yml includes an optional
firmware-compile job on Ubuntu.
FlexiTimer2::set(1, control) fires the control() ISR every 1 ms.
That ISR ticks clockVar, advances the sine-mode phase, and triggers
writeOutFunc() every writeOutCmax (= 20) ticks, i.e. at 50 Hz.
experimentControl() walks the pre-exp → exp → done phase machine on
the same tick.
The integer-command protocol described in
src/cuewire/constants.py is shared
across rigs. Firmware sketches that speak it (and their Python
companions) include:
| Firmware | Python host | Subsystems |
|---|---|---|
firmware/PARROTard/ (this directory) |
cuewire.huepfburg |
13371xxx LED, 13373xxx strip, cameras |
zerotonin/shinto (Arduino Uno) |
cuewire.shinto |
13374xxx shock, 13375xxx mode, 13376xxx timetable, 13377xxx stim-train, 13378xxx pattern |
All firmware shares 13370xxx (write-out & clock), 13372xxx
(experiment flow), and the 1337 → 50 1337 comm-test handshake.