
LaserHarp3 - V1
amonbenson/laserharp
Setup a virtual environment and install the dependencies:

Setup a virtual environment and install the dependencies:
LaserHarp3 - Rev3.1 is an open-source printed circuit board by amonbenson, from the amonbenson/laserharp repository on GitHub. It is a 2-layer board of 99.1 × 59.7 mm with 134 parts on 122 nets, routed with 708 tracks and 146 vias.
It is built around the STM32F103C8T6, 74HC595 and AMS1117-3.3, with the 1N4148WS, AO3401A and ZMM5V6 among its other parts. Its parts include 38 resistors, 25 transistors, 15 capacitors, 11 connectors and 6 ICs. It belongs with the STM32 boards of this library.
Setup a virtual environment and install the dependencies:
python3 -m venv .venv --system-site-packages
source .venv/bin/activate
pip install -r requirements.txtRun the server in development mode:
source .venv/bin/activate
python -m laserharp.serverInstall node js and yarn:
wget -qO- https://raw.githubusercontent.com/nvm-sh/nvm/v0.40.1/install.sh | bash
nvm install --lts
nvm use --lts
npm install -g yarnInstall all dependencies:
cd frontend
yarn installRun the development server:
yarn devsee https://wiki.linuxaudio.org/wiki/raspberrypi
for cpu in /sys/devices/system/cpu/cpu[0-9]*; do echo -n performance \
| sudo tee $cpu/cpufreq/scaling_governor; donesee https://www.jeffgeerling.com/blog/2023/reducing-raspberry-pi-5s-power-consumption-140x
# sudo rpi-eeprom-config -e
[all]
BOOT_UART=1
WAKE_ON_GPIO=0
POWER_OFF_ON_HALT=1rpi-update to get the latest kernel firmware/boot/firmware/config.txt:dtoverlay=uart2-pi5
dtoverlay=midi-uart2-pi5http://blog.dddac.com/wp-content/uploads/Flash-RPi5-and-adding-5000mA-Line-tutorial.pdf
sudo chmod u+s /sbin/poweroff /sbin/reboot /sbin/shutdownRoot note: C3 (midi note 48, one octave below middle C)
Global transpose setting
Modes:
The harp is divided into three horizontal sections resulting in 3 different octave ranges
:heavy_check_mark: – Implemented
:x: – Not implemented
Laserharp -> Host: 0x90 <note> <velocity>Sent when a laser is intercepted. The note value is determined by the diode and section that was intercepted. The velocity is fixed at 127.
Laserharp -> Host: 0x80 <note> <velocity>Sent immediately after a laser was plucked. The velocity is fixed at 127.
Laserharp -> Host: 0xe0 <pitch_bend_msb> <pitch_bend_lsb>Sent during interception when the hand is moved along the laser beam.
:heavy_check_mark: – Implemented
:x: – Not implemented
Host -> Laserharp: 0x80 <note> <velocity>Turn off the laser corresponding to the note. A note value of 127 will turn off all lasers at once.
Host -> Laserharp: 0x90 <note> <velocity>Turn on the laser corresponding to the note. A note value of 127 will turn on all lasers at once. The velocity determines the brightness of the laser.
The brightness is restored automatically after 1s. Note that interceptions will not be detected when the laser is turned off or too dim.
Host -> Laserharp: 0xb0 102 <value>Restores the laser brightness to the previous value immediately. Value must be ≥ 64.
Host -> Laserharp: 0xb0 103 <brightness>Set the brightness for unplucked lasers.
Host -> Laserharp: 0xb0 104 <brightness>Set the brightness when a laser is plucked.
Host -> Laserharp: 0xb0 105 <brightness>Sets the brightness when a laser is muted.
Host -> Laserharp: 0xb0 <pedal_cc> <position>Sets the position and mute of a pedal. The pedals are mapped as follows:
The value is divided into the ranges:
:heavy_check_mark: – Implemented
:x: – Not implemented
Bidirectional: 0x0N <byte0> <byte1> <byte2>These packets are equivalent to the USB Midi Protocol with CN = 1.
Bidirectional: 0x1N <byte0> <byte1> <byte2>Note: With the current version, Din Midi is handled directly by the Raspberry Pi, so this message won't be used.
These packets are equivalent to the USB Midi Protocol with CN = 1.
RPi -> STM: 0x80 <diode_index> <brightness> <fade_duration>Set the brightness of a single laser diode. The fade duration is given in tenths of a second. E.g. a value of 20 will fade the laser to the new brightness over 2 seconds. A duration of 0 will set the brightness immediately.
RPi -> STM: 0x81 <brightness> <fade_duration> <unused>Set the brightness of all laser diodes. The fade duration is given in tenths of a second. E.g. a value of 20 will fade the lasers to the new brightness over 2 seconds. A duration of 0 will set the brightness immediately.
RPi -> STM: 0x82 <diode_index> <unused> <unused>
STM -> RPi: 0x82 <diode_index> <brightness> <unused>RPi -> STM: 0x83 <animation_id> <duration> <follow_action>Play one of the predefined animations.
Animation Ids:
0 – Boot animation – Played during powerup of the Raspberry Pi
1 – Flip animation – Played when flipping the harp view
2 – Test animation – Used for internal testing, alternates between diodes 4 and 5
Duration: Given in tenths of a second. E.g. a value of 20 will play the animation for 2 seconds.
Follow Actions:
0 – Loop – Loop the animation indefinitely
1 – Freeze – Play the animation once and stop on the last frame
2 – Off – Play the animation once and stop with all lasers off
3 – Restore – Play the animation once and restore the laser brightnesses
RPi -> STM: 0x84 <unused> <unused> <unused>Stop the current animation from playing and execute the follow action immediately. If the follow action was set to 0 (loop indefinitely), the animation will stop and the lasers will remain in their current state.
STM -> RPi: 0x90 <state_0> <state_1> <state_2>Sent when the calibration button is pressed. The states are given as follows:
0 – released
1 – short press
2 – long press
For example, if the button is short-pressed, then long-pressed, and then released, the states will be 0x01 0x02 0x00.
RPi -> STM: 0x91 <00> <unused> <unused>
STM -> RPi: 0x91 <00> <voltage_int> <voltage_frac>Returns the current voltage. Currently only the Laser Diode voltage (index 0) can be measured. The result is given as a decimal number with a resolution of 0.01V and can be calculated as follows:
voltage = voltage_int + voltage_frac / 100RPi -> STM: 0xf0 <unused> <unused> <unused>
STM -> RPi: 0xf0 <major> <minor> <patch>RPi -> STM: 0xf1 <unused> <unused> <unused>RPi -> STM: 0xf2 <fade_delay> <fade_duration> <unused>Starts by playing the boot animation, waits for the fade delay, and then fades the lasers to black over the fade duration. Both delay and duration are given in tenths of a second.
Important: This is intended to be used when the harp is turned off. It will block any further IPC commands and the STM will not respond until it is power cycled.
Each predefined scale controls the pedal positions and mutes for each note.
Can be selected using Bank Change Messages (CC 0).
Additional custom scales can be defined and stored internally.
For each scale, choose:
C C# D D# E F F# G G# A A# B1 2 3 #4 5 6 b7| Qty | Value | Footprint | References |
|---|---|---|---|
| 25 | 10k | Resistor_SMD:R_0603_1608Metric | R12, R13, R14, R15, R16, R17, R18, R19, R20, R21, R22, R23, R24, R25, R26, R27 +9 |
| 24 | 2N7002 | Package_TO_SOT_SMD:SOT-23 | Q2, Q10, Q11, Q12, Q13, Q14, Q15, Q16, Q17, Q18, Q19, Q20, Q21, Q22, Q23, Q24 +8 |
| 24 | Laser_Diode | LED_THT:LED_D5.0mm | LD1, LD2, LD10, LD11, LD12, LD13, LD14, LD15, LD16, LD17, LD18, LD19, LD20, LD21, LD22, LD23 +8 |
| 8 | 100n | Capacitor_SMD:C_0603_1608Metric | C4, C5, C7, C8, C9, C10, C15, C16 |
| 4 | 10p | Capacitor_SMD:C_0603_1608Metric | C11, C12, C13, C14 |
| 4 | MountingHole | MountingHole:MountingHole_2.7mm | H1, H2, H3, H4 |
| 3 | 100k | Resistor_SMD:R_0603_1608Metric | R3, R10, R11 |
| 3 | 74HC595 | Package_SO:SO-16_3.9x9.9mm_P1.27mm | U4, U5, U6 |
| 2 | 1N5819 | Diode_SMD:D_SOD-323 | D1, D3 |
| 2 | 22u | Capacitor_THT:C_Radial_D6.3mm_H5.0mm_P2.50mm | C1, C2 |
| 2 | 47 | Resistor_SMD:R_0603_1608Metric | R6, R7 |
| 2 | 5.1k | Resistor_SMD:R_0603_1608Metric | R1, R2 |
| 1 | 1.5k | Resistor_SMD:R_0603_1608Metric | R36 |
| 1 | 10u | Capacitor_THT:C_Radial_D6.3mm_H5.0mm_P2.50mm | C3 |
| 1 | 1N4148WS | Diode_SMD:D_SOD-323 | D4 |
| 1 | 1k | Resistor_SMD:R_0603_1608Metric | R8 |
| 1 | 220 | Resistor_SMD:R_0603_1608Metric | R4 |
| 1 | 220k | Resistor_SMD:R_0603_1608Metric | R37 |
| 1 | 32.768 KHz | Crystal:Crystal_SMD_3215-2Pin_3.2x1.5mm | Y2 |
| 1 | 330k | Resistor_SMD:R_0603_1608Metric | R38 |
| 1 | 3V3 Power | Connector_PinHeader_2.54mm:PinHeader_1x02_P2.54mm_Vertical | J6 |
| 1 | 470 | Resistor_SMD:R_0603_1608Metric | R5 |
| 1 | 6N137 | Package_SO:SSO-8_6.7x9.8mm_P2.54mm_Clearance8mm | U3 |
| 1 | 8 MHz | Crystal:Crystal_SMD_HC49-SD | Y1 |
| 1 | AMS1117-3.3 | Package_TO_SOT_SMD:SOT-223-3_TabPin2 | U2 |
| 1 | AO3401A | Package_TO_SOT_SMD:SOT-23 | Q1 |
| 1 | Boot | Button_Switch_THT:SW_PUSH_6mm | SW3 |
| 1 | Cal | Button_Switch_THT:SW_Tactile_SPST_Angled_PTS645Vx39-2LFS | SW1 |
| 1 | Debug | Connector_PinHeader_2.54mm:PinHeader_1x04_P2.54mm_Vertical | J9 |
| 1 | GPIO | Connector_PinHeader_2.54mm:PinHeader_2x02_P2.54mm_Vertical | J11 |
| 1 | Midi_In | w_conn_av:din-5 | J4 |
| 1 | Midi_Out | w_conn_av:din-5 | J5 |
| 1 | Power | Connector_BarrelJack:BarrelJack_CUI_PJ-102AH_Horizontal | J2 |
| 1 | Raspberry Pi | Connector_PinHeader_2.54mm:PinHeader_1x04_P2.54mm_Vertical | J8 |
| 1 | Reset | Button_Switch_THT:SW_PUSH_6mm | SW2 |
| 1 | STM32F103C8T6 | Package_QFP:LQFP-48_7x7mm_P0.5mm | U1 |
| 1 | STM_Midi_In | Connector_PinHeader_2.54mm:PinHeader_1x02_P2.54mm_Vertical | JP3 |
| 1 | STM_Midi_Out | Connector_PinHeader_2.54mm:PinHeader_1x02_P2.54mm_Vertical | JP4 |
| 1 | UART | Connector_PinHeader_2.54mm:PinHeader_1x02_P2.54mm_Vertical | J7 |
| 1 | USB Power | Connector_PinHeader_2.54mm:PinHeader_1x04_P2.54mm_Vertical | J10 |
| 1 | USB Type C | Connector_USB:USB_C_Receptacle_Palconn_UTC16-G | J1 |
| 1 | VIN Power | Connector_PinHeader_2.54mm:PinHeader_1x04_P2.54mm_Vertical | J3 |
| 1 | ZMM5V6 | Diode_SMD:D_MiniMELF | D2 |

amonbenson/laserharp
Setup a virtual environment and install the dependencies:



swayerloren/KICAD_ENGINE
AI-assisted KiCad PCB design workflow for schematics, PCB layouts, DRC, BOM/CPL, and fabrication outputs using Codex or Claude.

MURPHYENGINEERING/STM32F405RGT6-Breakout
Following along with Phil's Lab: https://www.youtube.com/watch?v=t5phi3nT8OU


hackclub/OnBoard
💡 Join 1,000 teenagers and make your first PCB with a $100 grant!


It measures 99.1 × 59.7 mm and has 2 copper layers, 1.6 mm thick.
134 parts, built around the STM32F103C8T6, 74HC595, AMS1117-3.3 and 1N4148WS. The full list of its parts is on this page, with links to each part's symbol and footprint where PCBKit's library has them.
From the amonbenson/laserharp repository on GitHub, at the commit this page was made from: the board is hardware/pcb/LaserHarp3 - Rev3.1.kicad_pcb and its schematic hardware/pcb/Diode_Array.kicad_sch. PCBKit opens the board in the browser, with nothing to install.
Its repository states no licence, so its author keeps all rights: ask amonbenson before reusing the design.