- src/main.cpp: Add serial command interface (A/B/C values, s=status, 0=off) - src/main.cpp: Serial control disables MIDI timeout for persistent values - serial_control.py: Streamlit GUI with sliders and quick action buttons - serial_control.py: Filter out ttyS* ports, prioritize USB serial - test_midi.py: Update for new CC control mapping (CC 20/21/22) - README.md: Complete project documentation
MIDI PWM Controller
Arduino-based PWM controller with MIDI and Serial input support. Controls three PWM channels on pins 9, 10, and 11 via MIDI Control Change messages or direct serial commands.
Hardware
- Arduino (Uno, Nano, or compatible)
- MIDI Input: Pin 4 (via optocoupler circuit, 31250 baud)
- PWM Outputs: Pins 9, 10, 11
See fritzing/ directory for circuit diagrams.
Features
- MIDI Control: CC messages for direct PWM control
- Serial Control: Simple text commands via USB serial
- Smooth Ramping: Gradual PWM transitions for smooth motor/LED control
- Safety Timeout: Auto-shutoff when MIDI signal is lost (disabled for serial control)
MIDI Mapping
| Control Change | PWM Channel | Arduino Pin |
|---|---|---|
| CC 20 | Channel 1 | Pin 9 |
| CC 21 | Channel 2 | Pin 10 |
| CC 22 | Channel 3 | Pin 11 |
CC values 0-127 map to PWM 0-255.
Note Control (Optional)
Note-based control is enabled by default:
| Note | PWM Channel | Arduino Pin |
|---|---|---|
| C4 (60) | Channel 1 | Pin 9 |
| D4 (62) | Channel 2 | Pin 10 |
| E4 (64) | Channel 3 | Pin 11 |
Velocity maps to PWM intensity.
Serial Commands
Connect via USB at 115200 baud. Commands are case-insensitive.
| Command | Description | Example |
|---|---|---|
A<0-255> |
Set PWM channel 1 (pin 9) | A255 = full on |
B<0-255> |
Set PWM channel 2 (pin 10) | B128 = 50% |
C<0-255> |
Set PWM channel 3 (pin 11) | C64 = 25% |
s |
Show status | |
0 |
All channels off |
Note: Serial control disables the MIDI timeout, so values persist until explicitly changed.
Building
This project uses PlatformIO.
# Build
pio run
# Upload
pio run --target upload
# Monitor serial
pio device monitor
Testing Tools
MIDI Test Script
Python script for testing MIDI control:
# Run all demos (requires uv or install mido + python-rtmidi)
./test_midi.py
# Interactive mode
./test_midi.py -m interactive
# Available modes: sweep, individual, wave, notes, interactive, all
./test_midi.py -m wave -d 10
Serial Control GUI (Streamlit)
Web-based GUI for serial control:
# Run with uvx (recommended - isolated environment)
uvx --with pyserial streamlit run serial_control.py
# Or install dependencies globally and run
pip install streamlit pyserial
streamlit run serial_control.py
Configuration
Edit constants in src/main.cpp:
// MIDI CC numbers
#define CC_PWM_1 20
#define CC_PWM_2 21
#define CC_PWM_3 22
// Note control (set to false to disable)
#define ENABLE_NOTE_CONTROL true
// Safety timeout (ms) - set to 0 to disable
static const uint16_t MIDI_TIMEOUT_MS = 400;
// Ramping (for smooth transitions)
static const uint8_t RAMP_STEP = 3; // PWM change per tick
static const uint16_t RAMP_PERIOD_MS = 2; // tick period
License
MIT
Description
Languages
Python
62.6%
C++
37.4%