A Python application that maps button presses from a Yamaha T-420 tuner's front panel (via TCA8418 I2C matrix) to Plexamp playback actions. Includes a web-based configuration interface for managing presets and a 1602A LCD display for showing now-playing information.
- Hardware Integration: Reads button presses from TCA8418 I2C keypad matrix
- LCD Display: 1602A LCD via I2C shows now-playing information with marquee scrolling
- Plexamp Control: Controls Plexamp playback via HTTP API
- Web Configuration UI: Flask-based web interface at
http://localhost:5000for managing presets - Preset Management: Save and load 8 presets (artists, albums, playlists, tracks)
- Now Playing Display: Real-time track information (song - artist - album) with automatic scrolling
- Preset Feedback: LCD displays preset name when activated
- Python 3.7 or higher
- Raspberry Pi or Linux system with I2C support
- TCA8418 I2C keypad matrix connected to I2C bus 1 at address 0x34
- 1602A LCD with PCF8574 I2C backpack (optional, but recommended)
- Plexamp running and accessible on your network
- Plex server with music library
- Connect the TCA8418 to your Raspberry Pi:
- SDA → GPIO 2 (Pin 3)
- SCL → GPIO 3 (Pin 5)
- VCC → 3.3V
- GND → Ground
-
Connect the 1602A LCD with PCF8574 I2C backpack to your Raspberry Pi:
- SDA → GPIO 2 (Pin 3) - shared with TCA8418
- SCL → GPIO 3 (Pin 5) - shared with TCA8418
- VCC → 5V (Pin 2 or 4)
- GND → Ground
Note: The LCD and TCA8418 can share the same I2C bus since they use different addresses.
How I2C Addressing Works: Each I2C device has a unique, hardware-determined address:
- TCA8418: Always uses address
0x34(fixed by the chip design) - PCF8574 (LCD backpack): Uses
0x27or0x3F(determined by address pins A0/A1/A2 on the chip)
The software automatically identifies devices by their addresses - you don't need to configure which address is which. When the code communicates with address
0x34, it's talking to the TCA8418. When it uses0x27or0x3F, it's talking to the LCD. -
Enable I2C on Raspberry Pi:
sudo raspi-config # Navigate to: Interface Options → I2C → Enable -
Verify I2C connections:
sudo apt-get install i2c-tools sudo i2cdetect -y 1 # Should show: # - TCA8418 at address 0x34 # - LCD at address 0x27 or 0x3F (depending on your module)
The LCD address is automatically detected by the application. Common addresses are:
0x27- Most common PCF8574 backpack address (A0/A1/A2 pins connected to GND)0x3F- Alternative PCF8574 backpack address (varies by manufacturer/module)
Important: If you have multiple PCF8574 modules, you can change their addresses by connecting the A0, A1, A2 pins differently (see PCF8574 datasheet). However, for this project, we only need one LCD, so the default address is fine.
Run the automated setup script:
chmod +x setup.sh
./setup.shThis will:
- Create a Python virtual environment
- Install all dependencies
- Set up the project structure
-
Create a virtual environment:
python3 -m venv venv source venv/bin/activate # On Windows: venv\Scripts\activate
-
Install dependencies:
pip install -r requirements.txt
-
Install system dependencies (for I2C on Raspberry Pi):
sudo apt-get update sudo apt-get install python3-dev i2c-tools
Before running the application, you need to configure Plex connection settings. The code currently references several variables that need to be set:
PLEX_SERVER_URL: Your Plex server URL (e.g.,https://your-plex-server.com)PLEX_TOKEN: Your Plex authentication tokenPLEX_MACHINE_ID: Your Plex server machine identifierMUSIC_SECTION_ID: Your Plex music library section IDPLEX_DEVICE_NAME: Device name for Plex API callsPLEXAMP_BASE_URL: Plexamp base URL (e.g.,http://192.168.68.92:32500)
Note: You may need to add these as environment variables or modify plex_tuner.py to include them. Consider creating a .env file or config.py for these settings.
- Log into your Plex server web interface
- Open browser developer tools (F12)
- Go to Network tab
- Make a request in Plex web UI
- Look for requests containing
X-Plex-Tokenin headers - Copy the token value
Check your Plex server's Preferences.xml file or use the Plex API.
-
Activate the virtual environment:
source venv/bin/activate # On Windows: venv\Scripts\activate
-
Run the application:
python3 plex_tuner.py
Or use the convenience script:
./run.sh
-
Access the web configuration UI:
Open your browser and navigate to:
http://localhost:8888(Port may vary - check the console output)
To automatically start the application when the Raspberry Pi boots:
-
Install the systemd service:
sudo ./install-service.sh
-
The service will:
- Start automatically on boot
- Restart automatically if it crashes
- Log output to systemd journal
-
Service management:
# Start the service sudo systemctl start plex-tuner # Stop the service sudo systemctl stop plex-tuner # Restart the service sudo systemctl restart plex-tuner # Check service status sudo systemctl status plex-tuner # View logs sudo journalctl -u plex-tuner -f # Disable auto-start at boot (keeps service installed) sudo systemctl disable plex-tuner # Uninstall the service completely sudo ./uninstall-service.sh
-
Configure presets:
- Use the search box to find artists, albums, playlists, or tracks
- Select a preset number (1-8)
- Click on a search result to assign it to that preset
- Presets are automatically saved to
presets.json
-
Use the hardware buttons:
- Press the configured buttons on your T-420 front panel
- The application will trigger the corresponding Plexamp actions
The LCD display (if connected) provides visual feedback:
-
Now Playing Display:
- Top row shows: "song - artist - album"
- Automatically scrolls (marquee) if text is longer than 16 characters
- Updates every 3 seconds with current playback information
- Shows "No signal" when nothing is playing
-
Preset Feedback:
- When a preset is activated (via hardware button or web UI), the LCD displays the preset name
- Preset name is shown for 3 seconds, then returns to now-playing display
- Format: "Preset: [name]"
-
Graceful Degradation:
- If the LCD is not connected, the application continues to work normally
- All functionality remains available via the web UI
plex-tuner/
├── plex_tuner.py # Main application file
├── requirements.txt # Python dependencies
├── setup.sh # Automated setup script
├── run.sh # Convenience script to run the app
├── install-service.sh # Install systemd service for auto-start
├── uninstall-service.sh # Remove systemd service
├── plex-tuner.service # Systemd service file
├── README.md # This file
├── presets.json # Preset configuration (auto-generated)
└── public/
└── index.html # Web UI template
- Verify I2C is enabled:
sudo i2cdetect -y 1 - Check device addresses:
- TCA8418 should be at 0x34
- LCD should be at 0x27 or 0x3F
- Ensure proper wiring and power supply
- LCD requires 5V power (not 3.3V like TCA8418)
-
LCD not detected:
- Check wiring connections (SDA, SCL, VCC, GND)
- Verify LCD is powered (5V)
- Run
sudo i2cdetect -y 1to see if LCD appears at 0x27 or 0x3F - Application will continue to work without LCD (graceful degradation)
-
LCD shows garbled text:
- Check contrast potentiometer on LCD module (if present)
- Verify I2C address is correct (check console output for detected address)
- Try power cycling the LCD module
-
Text not scrolling:
- Marquee scrolling only activates when text exceeds 16 characters
- Short text will be displayed statically
- Verify Plexamp is running and accessible
- Check network connectivity to Plex server
- Verify Plex token is valid and has proper permissions
- Check firewall settings
- Ensure virtual environment is activated
- Reinstall dependencies:
pip install -r requirements.txt - For
smbus2on Raspberry Pi, ensurepython3-devis installed
To modify button mappings, edit the KEYMAP dictionary in plex_tuner/hardware/tca8418.py:
KEYMAP = {
(row, col): "action_name",
# ...
}LCD settings can be modified in plex_tuner/hardware/lcd1602.py:
LCD_I2C_BUS: I2C bus number (default: 1)LCD_I2C_ADDRESSES: List of addresses to try (default: [0x27, 0x3F])- Marquee scroll speed: Adjust
marquee_update_intervalinLCDDisplayclass - Preset display duration: Modify
durationparameter inshow_preset()calls
[Add your license here]
[Add contribution guidelines here]
