Skip to content

cloudfx is a dual-device sound effect control system using Adafruit MacroPad and the Adafruit FunHouse with CircuitPython for live sound effects and remote command execution.

License

Notifications You must be signed in to change notification settings

wchesher/cloudfx

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

68 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

cloudfx v1.0

A dual-device production control system using Adafruit CircuitPython hardware for live sound effects and remote command execution.

CircuitPython Version License

What Is This?

cloudfx turns two Adafruit devices into a powerful sound effects and macro controller system:

  • MacroPad RP2040: Physical 12-button soundboard with rotary encoder (local control)
  • FunHouse ESP32-S2: Network-connected remote trigger via AdafruitIO (remote control)

Both devices act as USB HID keyboards, sending keystrokes to your computer to trigger sounds via AutoHotKey (or any automation software).


Quick Start

1. Hardware You Need

2. Install CircuitPython 10.0.3

Download and install CircuitPython 10.0.3 on your devices:

FunHouse users: Update TinyUF2 bootloader to 0.33.0+ first! See CircuitPython documentation.

3. Get the Code

Download latest release:

git clone https://github.com/wchesher/cloudfx.git
cd cloudfx

4. Deploy Files

MacroPad

Copy these 3 files to the root of your MacroPad's CIRCUITPY drive:

cp macropad/code.py /Volumes/CIRCUITPY/code.py
cp shared/macros.json /Volumes/CIRCUITPY/macros.json
cp shared/macros_loader.py /Volumes/CIRCUITPY/macros_loader.py

Required Libraries (install to /lib/ on device):

  • adafruit_macropad.mpy
  • adafruit_hid/ (folder)
  • adafruit_display_text/ (folder)
  • adafruit_display_shapes/ (folder)

Download from CircuitPython 10.x Library Bundle.

FunHouse (Optional)

Copy these files to FunHouse's CIRCUITPY drive:

cp funhouse/code.py /Volumes/CIRCUITPY/code.py
cp shared/macros.json /Volumes/CIRCUITPY/macros.json
cp shared/macros_loader.py /Volumes/CIRCUITPY/macros_loader.py
cp funhouse/settings.toml.example /Volumes/CIRCUITPY/settings.toml
# Edit settings.toml with your WiFi and AdafruitIO credentials

Required Libraries (install to /lib/ on device):

  • adafruit_hid/ (folder)
  • adafruit_requests.mpy
  • adafruit_io/ (folder)
  • adafruit_display_text/ (folder)
  • adafruit_dotstar.mpy

Download from CircuitPython 10.x Library Bundle.

5. Configure FunHouse (Optional)

Edit settings.toml on your FunHouse:

# WiFi Configuration
CIRCUITPY_WIFI_SSID = "YourWiFiName"
CIRCUITPY_WIFI_PASSWORD = "YourWiFiPassword"

# AdafruitIO Credentials (get from io.adafruit.com)
AIO_USERNAME = "your_username"
AIO_KEY = "your_aio_key"

# Static IP (optional - comment out for DHCP)
STATIC_IP = "192.168.1.100"
GATEWAY = "192.168.1.1"
NETMASK = "255.255.255.0"
DNS = "8.8.8.8"

# Polling Configuration
POLL_INTERVAL = "2"  # seconds between AdafruitIO checks

6. Add Sound Files

Copy your WAV files to a folder (e.g., C:\fx\ on Windows) and update your AutoHotKey script to play them.

Example sound files are in fx/ folder! Copy them to your sound directory.

7. Setup AutoHotKey (Windows)

Create an AHK v2 script to play sounds when keystrokes are received:

#Requires AutoHotkey v2.0
#SingleInstance Force

SoundDir := "C:\fx\"

; SHIFT+ESCAPE: Stop playback (encoder button)
+Escape:: {
    SoundPlay(SoundDir . "off.wav")
}

; CTRL+ALT+SHIFT+F13: Play dj.wav (example)
^!+F13:: {
    SoundPlay(SoundDir . "dj.wav")
}

; Add more hotkeys for each sound...

See your deployed macros.json for all the key combinations!


How It Works

MacroPad Pages

The MacroPad loads 12 "pages" (apps) from macros.json. Rotate the encoder to switch between pages:

  1. EFFECTS - Sound effects (dj, crickets, dundun, etc.)
  2. UPBEAT - Positive sounds (rimshot, tada, applause, etc.)
  3. DOWNBEAT - Negative sounds (fail, wahwah, nope, etc.)
  4. RANDOM 1 - Random effects (Jetsons, psycho, train, etc.)
  5. RANDOM 2 - More random (Shrek, wilhelm scream, etc.)
  6. RICK 1 - Rick & Morty clips #1
  7. RICK 2 - Rick & Morty clips #2
  8. SONGS - Music clips (circus, imperial march, etc.)
  9. SPONGEBOB - Spongebob sounds
  10. STAR WARS 1 - Star Wars clips #1
  11. STAR WARS 2 - Star Wars clips #2
  12. JEOPARDY - Jeopardy music/effects

Each page has up to 12 buttons mapped to your 12 physical keys.

Encoder Button: Click the encoder to send SHIFT+ESCAPE (stops playback).

Encoder Rotation: Turn left/right to navigate between pages.

FunHouse Remote Control

Send commands to your FunHouse via AdafruitIO:

  1. Create an AdafruitIO account at io.adafruit.com
  2. Create a feed named "macros"
  3. Send command names (like "dj", "rimshot", "intro") to the feed
  4. FunHouse receives the command and triggers the keystroke
  5. Your AutoHotKey script plays the sound

Command List: See macros.json - the "command" field is what you send to AdafruitIO.


Project Structure

cloudfx/
├── README.md                    # This file
├── LICENSE                      # MIT License
│
├── macropad/                    # MacroPad RP2040 code
│   └── code.py                  # Main program
│
├── funhouse/                    # FunHouse ESP32-S2 code
│   ├── code.py                  # Main program
│   └── settings.toml.example    # WiFi/AdafruitIO config template
│
├── shared/                      # Shared between both devices
│   ├── macros.json              # 🎯 SINGLE SOURCE OF TRUTH - all macros defined here
│   └── macros_loader.py         # JSON parser for both devices
│
└── fx/                          # Example WAV sound files
    ├── dj.wav
    ├── rimshot.wav
    └── ... (145+ sound files)

Single Source of Truth: macros.json

Everything is defined in shared/macros.json:

  • MacroPad button labels, colors, and keycodes
  • MacroPad page names and order
  • FunHouse command names and keycodes
  • Encoder button behavior

JSON Structure

{
  "apps": [
    {
      "name": "EFFECTS",
      "buttons": [
        {
          "label": "dj",
          "command": "dj",
          "color": "0x17A398",
          "keycodes": ["LEFT_CONTROL", "LEFT_ALT", "LEFT_SHIFT", "F13"]
        }
      ]
    }
  ]
}
  • label: Button text on MacroPad (5-7 chars max)
  • command: Command name for FunHouse (sent to AdafruitIO)
  • color: LED color in hex (MacroPad only)
  • keycodes: HID keys to send (both devices)

Adding New Sounds

  1. Edit shared/macros.json
  2. Add a new button entry with unique command name and keycodes
  3. Copy updated macros.json to both devices
  4. Add sound file to your sound directory (e.g., C:\fx\newsound.wav)
  5. Add hotkey to AutoHotKey script
  6. Restart devices

Features

MacroPad Features

✅ 12 programmable keys per page ✅ 12 pages (144 total sounds!) ✅ RGB LED indicators per key ✅ Rotary encoder for page switching ✅ Click encoder to stop playback (SHIFT+ESCAPE) ✅ OLED display shows current page name ✅ Screensaver after 30s inactivity (prevents LCD burn-in) ✅ Configurable LED brightness (30% default) ✅ Completely standalone (no WiFi needed) ✅ Symmetric encoder navigation (fixed in v1.0)

FunHouse Features

✅ Remote control via AdafruitIO ✅ 145+ commands available ✅ Fast 2-second polling (configurable) ✅ DotStar LED status indicators ✅ WiFi auto-reconnect (30s health checks) ✅ Display backlight control (turns off when idle) ✅ Synced display and LED timing ✅ Static or DHCP IP configuration ✅ Command queuing system (50 command buffer) ✅ Comprehensive error logging ✅ Memory monitoring and garbage collection ✅ HID error recovery ✅ Network resilience with auto-recovery


LED Indicators

MacroPad

  • Per-button RGB LEDs: Show page colors and button status
  • Dimmed to 5%: During screensaver mode (after 30s idle)
  • Full brightness (30%): When active

FunHouse DotStars (5 LEDs)

  • Blue: Connecting to WiFi
  • Green: Connected (shown during first 2 polls)
  • Off: Normal operation (after startup)
  • Magenta: Command received and executing (1 second flash, synced with display)
  • Red: Error occurred

Architecture

┌─────────────────┐                    ┌──────────────────┐
│    MacroPad     │                    │    FunHouse      │
│   (RP2040)      │                    │   (ESP32-S2)     │
│                 │                    │                  │
│  ┌───────────┐  │                    │  ┌────────────┐  │
│  │ Physical  │  │                    │  │ AdafruitIO │  │
│  │  Buttons  │  │                    │  │  Listener  │  │
│  │ (12 keys) │  │                    │  │  (WiFi)    │  │
│  └─────┬─────┘  │                    │  └──────┬─────┘  │
│        │        │                    │         │        │
│  ┌─────▼─────┐  │                    │  ┌──────▼─────┐  │
│  │   JSON    │  │                    │  │    JSON    │  │
│  │  Loader   │  │                    │  │   Loader   │  │
│  └─────┬─────┘  │                    │  └──────┬─────┘  │
│        │        │                    │         │        │
│  ┌─────▼─────┐  │                    │  ┌──────▼─────┐  │
│  │HID Output │  │                    │  │ HID Output │  │
│  └─────┬─────┘  │                    │  └──────┬─────┘  │
└────────┼────────┘                    └─────────┼────────┘
         │                                       │
         │         USB                           │  USB
         └───────────────────┬───────────────────┘
                             │
                   ┌─────────▼──────────┐
                   │   Host Computer    │
                   │  (AutoHotKey/AHK)  │
                   │   Plays WAV Files  │
                   └────────────────────┘

Both devices:

  1. Read macros.json at startup
  2. Convert keycode strings to HID codes
  3. Send HID keystrokes via USB
  4. Computer receives keystrokes
  5. AutoHotKey plays corresponding sound

They operate independently - no direct communication between them.


Technical Details

CircuitPython 10.0.3 Compatibility

✅ Updated exception handling (traceback.print_exception) ✅ Modern settings.toml config (FunHouse) ✅ Compatible with CP 10.x Library Bundle ✅ JSON-based configuration (no Python import issues) ✅ Aggressive memory management

HID Timing

Both devices hold keys for 50ms before releasing - critical for AutoHotKey detection:

kbd.press(keycodes)
time.sleep(0.05)  # 50ms hold
kbd.release_all()

Memory Management

FunHouse (ESP32-S2):

  • Aggressive garbage collection every 5 seconds
  • Memory monitoring with warnings below 10KB free
  • Loader deleted immediately after use
  • Typical free memory: 30-50KB

MacroPad (RP2040):

  • Simple memory management
  • No aggressive GC needed (more RAM available)
  • Typical free memory: 100-150KB

Error Handling

FunHouse includes comprehensive error handling:

  • Full tracebacks printed to serial console
  • WiFi auto-reconnect with exponential backoff
  • HID error recovery (release all keys on failure)
  • Display/LED operation failures don't crash the program
  • KeyboardInterrupt handler logs diagnostic info
  • Separate error handling for backlight control

MacroPad includes basic error handling:

  • Safe screensaver wake logic
  • Encoder position sync on startup
  • Display refresh protection

Configuration

MacroPad (macropad/code.py):

REGULAR_BRIGHTNESS = 0.3    # Regular LED brightness (30%)
SCREENSAVER_TIMEOUT = 30    # Seconds before screensaver (0 = disable)
DIM_BRIGHTNESS = 0.05       # LED brightness when dimmed

FunHouse (funhouse/settings.toml):

POLL_INTERVAL = "2"         # Seconds between AdafruitIO polls

FunHouse (funhouse/code.py):

DISPLAY_TIMEOUT = 1.0       # Seconds to show command name
GC_INTERVAL = 5             # Seconds between garbage collection
QUEUE_SIZE = 50             # Max commands in queue
WIFI_CHECK_INTERVAL = 30    # Seconds between WiFi health checks

Troubleshooting

MacroPad

"NO MACROS" on display

  • Missing macros.json or macros_loader.py
  • Check serial console for errors

Keys don't work

  • Verify CircuitPython 10.0.3 installed
  • Check all required libraries in /lib/ folder
  • Connect to serial console to see errors

Encoder button doesn't stop playback

  • Check AutoHotKey script has +Escape:: hotkey
  • Verify off.wav exists in sound directory

Encoder navigation is weird

  • Fixed in v1.0 - encoder position now syncs on startup
  • Update to latest code

Screensaver not waking

  • Fixed in v1.0 - screen_active flag set before display activation
  • Update to latest code

FunHouse

Won't connect to WiFi

  • Check credentials in settings.toml
  • FunHouse only supports 2.4GHz WiFi (not 5GHz)
  • Check serial console for detailed error messages
  • WiFi will auto-reconnect every 30 seconds if disconnected

Commands don't trigger sounds

  • Command name must match exactly (case-sensitive!)
  • Check command exists in macros.json
  • Serial console will say "✗ Command not found in macro list"
  • Verify AutoHotKey is running and has matching hotkey

Display stays on all the time

  • v1.0 includes backlight control
  • Backlight turns off after 1 second when idle
  • Update to latest code

Device crashes or freezes

  • v1.0 includes comprehensive error handling
  • Check serial console for error messages and tracebacks
  • Look for memory warnings (below 10KB free)
  • WiFi disconnections are now handled automatically

Verbose logging

  • v1.0 includes detailed logging for all operations
  • Connect to serial console to see:
    • Poll activity and received commands
    • Command execution steps (display, LEDs, HID)
    • WiFi health checks
    • Memory status and garbage collection
    • Full error tracebacks

Version History

v1.0 (2025-01-29)

  • Initial stable release
  • Fixed encoder navigation asymmetry
  • Added FunHouse display backlight control
  • Synced FunHouse DotStar LEDs with display timing
  • Comprehensive error handling and logging
  • WiFi auto-reconnect with health checks
  • Memory monitoring and aggressive garbage collection
  • Improved screensaver wake logic
  • Command queuing system
  • Network resilience with auto-recovery

Use Cases

🎭 Live Production: Sound effects board for theater, podcasts, live streams 🎬 Content Creation: Quick sound effects while recording/editing 🎮 Streaming: Instant reactions and sound bites 📡 Remote Control: Trigger sounds from phone/tablet via AdafruitIO 🎵 DJing: Quick sound drops and effects 🎓 Education: Learn CircuitPython, USB HID, IoT integration


Credits

  • Original MacroPad code: Phillip Burgess (Adafruit Industries)
  • CloudFX modifications: William C. Chesher
  • CircuitPython: Adafruit Industries and contributors
  • Sound effects: Various sources (see individual files for attribution)

License

MIT License - See LICENSE file for details.


Links


Support

Issues? Check the troubleshooting section above first!

Still stuck? Open an issue: https://github.com/wchesher/cloudfx/issues


🎵 Happy sound boarding! 🎵

About

cloudfx is a dual-device sound effect control system using Adafruit MacroPad and the Adafruit FunHouse with CircuitPython for live sound effects and remote command execution.

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Contributors 2

  •  
  •  

Languages