NeoPixel Integration - griffingilreath/Punch-Card-Project GitHub Wiki
This document outlines the technical specifications and implementation plan for integrating physical NeoPixel LED arrays with the Punch Card Display System. The goal is to create a synchronized experience where the physical LEDs mirror what's shown in the terminal display.
-
LED Grid
- NeoPixel grid with 12 rows Γ 80 columns (960 LEDs)
- Alternative: Multiple smaller NeoPixel strips arranged in a grid formation
- Estimated power requirements: 5V, ~20A at full brightness (white)
-
Controller Options
- Primary Controller: Mac Mini running the main Python application
-
Secondary Controller: One of the following:
- Raspberry Pi (3B+ or 4)
- Arduino Mega
- Teensy 4.1 (preferable due to high pin count and speed)
-
Power Supply
- 5V power supply with sufficient current capacity (minimum 20A for full grid)
- Power distribution board to handle the current requirement
- Optional: Multiple smaller power supplies with proper ground connections
-
Connectivity
- USB connection between Mac Mini and secondary controller
- Alternatively: Network connection via Ethernet or WiFi (for Raspberry Pi)
-
LED Grid Mounting
- Grid dimensions: Approximately 12cm Γ 80cm (based on standard NeoPixel density)
- Mounting backplate: Rigid, non-conductive material (acrylic/wood)
- Diffuser layer: Semi-transparent material to blend individual LED points
-
Controller Housing
- Weather-resistant enclosure for electronics
- Ventilation for heat dissipation
- Cable management for power and data connections
βββββββββββββββββββββββββββββββββββββββββββββββββββββΊ
β βββββΊ
βββββββββββββββββββββββββββββββββββββββββββββββββ β
β βββββΊ
βββββββββββββββββββββββββββββββββββββββββββββββββ β
β βββββΊ
βββββββββββββββββββββββββββββββββββββββββββββββββ β
β βββββΊ
βββββββββββββββββββββββββββββββββββββββββββββββββ β
β βββββΊ
βββββββββββββββββββββββββββββββββββββββββββββββββ β
βββββββββββββββββββββββββββββββββββββββββββββββββββββΊ
-
Advantages:
- Minimizes wiring complexity
- Requires only one data connection from controller
- Simplified power injection points
-
Challenges:
- Mapping (x,y) coordinates to LED index requires calculations
- Potential for signal degradation over distance
- Requires careful power injection every 1-1.5 meters
βββββββββββββββββββββββββββββββββββββββββββββββββββΊ
β
βββββββββββββββββββββββββββββββββββββββββββββββββββΊ
β
βββββββββββββββββββββββββββββββββββββββββββββββββββΊ
β
βββββββββββββββββββββββββββββββββββββββββββββββββββΊ
β
βββββββββββββββββββββββββββββββββββββββββββββββββββΊ
β
βββββββββββββββββββββββββββββββββββββββββββββββββββΊ
-
Advantages:
- Each row can be controlled separately (potentially by different pins)
- Simple mapping of coordinates to physical LEDs
- Can run multiple data lines in parallel for faster updates
-
Challenges:
- Requires multiple data pins from controller
- More complex wiring between controller and grid
- Synchronization between rows requires careful timing
Power Supply
β
ββββ Row 1 βββ¬βββ Row 1 Middle βββ¬βββ Row 1 End
β β β
ββββ Row 2 βββΌβββ Row 2 Middle βββΌβββ Row 2 End
β β β
ββββ Row 3 βββΌβββ Row 3 Middle βββΌβββ Row 3 End
β β β
ββββ Row 4 βββΌβββ Row 4 Middle βββΌβββ Row 4 End
β β β
ββββ Ground connections to all rows and controller
- Power should be injected at both ends of each row for strips longer than 1m
- For the full 80-column grid, power injection recommended at the start, middle, and end
- All ground lines must connect to create a common ground plane
- Capacitors (1000ΞΌF) recommended at each power injection point to stabilize voltage
- Data line requires a 300-500 Ohm resistor at the first LED to protect against voltage spikes
- For long runs, consider using a logic level converter if controller uses 3.3V logic
- Maintain short, direct wiring for data lines with proper shielding
- Maximum recommended distance from controller to first LED: 2m with proper shielding
ββββββββββββββββββ βββββββββββββββββββ βββββββββββββββββ
β β β β β β
β Mac Mini ββββββββββββΊβ Secondary ββββββββββββΊβ NeoPixel β
β Main App β Serial/ β Controller β Data β LED Grid β
β β Network β (Pi/Arduino/ β Signal β β
β β β Teensy) β β β
ββββββββββββββββββ βββββββββββββββββββ βββββββββββββββββ
β β β
β β β
βΌ βΌ βΌ
ββββββββββββββββββ βββββββββββββββββββ βββββββββββββββββ
β Terminal β β Hardware β β Web Server/ β
β Display β β Diagnostics β β API β
β β β β β β
ββββββββββββββββββ βββββββββββββββββββ βββββββββββββββββ
β
βΌ
βββββββββββββββββ
β Website β
β Integration β
β β
βββββββββββββββββ
-
LEDController Class
- Python class that abstracts the LED grid control
- Includes methods for setting individual LEDs and patterns
- Handles communication with the secondary controller
-
Hardware Abstraction Layer
- Allows the application to run with or without physical hardware
- Provides diagnostic information about connected hardware
- Implements fallback behavior when hardware is unavailable
-
Communication Protocol
- Serial communication (USB) or network protocol (TCP/IP)
- Binary protocol for efficient data transfer
- Heartbeat mechanism to detect disconnections
-
Secondary Controller Firmware
- Arduino/Teensy: Custom firmware using FastLED or Adafruit NeoPixel libraries
- Raspberry Pi: Python script using rpi_ws281x library
- Implements buffer for smoother animations
-
Web Integration Module
- REST API for external access to statistics and control
- WebSocket connection for real-time updates
- Authentication system for secure access
-
Acquire Development Hardware
- Purchase 8x8 NeoPixel Matrix from Adafruit (~$35)
- Arduino Nano/Uno for initial testing (~$10-20)
- Small breadboard and jumper wires
- 5V/2A power supply
-
Proof of Concept
- Implement basic communication protocol
- Create adapter function to map 12x80 punch card to 8x8 display (scaled representation)
- Verify signal timing and basic functionality
-
Documentation
- Document wiring connections
- Create schematic for reference
- Establish baseline power consumption metrics
-
Scale to Larger Test Grid
- Expand to 16Γ16 or 8x32 NeoPixel matrix/strip
- Upgrade to development board with more capabilities (Teensy or Pi)
- Design expandable power distribution system
-
Create Hardware Abstraction Layer
- Implement
LEDController
class with simulation mode - Add configuration options for hardware presence
- Create visualization for physical setup in terminal
- Implement
-
Grid Mapping Optimization
- Implement coordinate mapping for both serpentine and row layouts
- Test transition between simulation and physical hardware
- Create diagnostic pattern routines
-
Implement Communication Protocol
- Develop serial/network communication between Mac and controller
- Create command set for LED control
- Implement error handling and reconnection logic
-
Synchronize Display States
- Link terminal display grid state to physical LEDs
- Implement brightness controls
- Create testing utility to verify synchronization
-
Initial Web Interface
- Develop basic web server functionality
- Create REST endpoints for status and control
- Implement simple statistics dashboard
-
Optimize Update Rate
- Implement frame buffering to reduce communication overhead
- Optimize animation sequences for physical display
- Add performance monitoring
-
Implement Power Management
- Create power usage estimation
- Implement brightness limits and power-saving modes
- Add overheating protection
-
Expand Web Capabilities
- Add historical data storage
- Implement interactive control features
- Create user management system
-
Scale to Full Grid
- Adapt code for full 12Γ80 grid (or modular segments)
- Optimize for performance with large LED count
- Implement zoning for partial updates
-
Create Calibration Utilities
- Color calibration tool
- LED testing sequence
- Diagnostics and troubleshooting tools
-
Complete Web Integration
- Finalize website integration
- Implement public/private view options
- Create data export capabilities
Mac Mini Controller
ββββββββββββββββ ββββββββββββββββ
β β β β
β Python β β β
β Applicationβ β Firmware β
β β β β
β βββββββββββ β Serial β βββββββββββ β
β β Serial β β Protocol β β Serial β β
β β Handler ββββββββββββββββββββββββββββββββββββ€βΊβ Handler β β
β βββββββββββ β 115200 baud β βββββββββββ β
β β 8N1 format β β
ββββββββββββββββ ββββββββββββββββ
-
Protocol Details:
- Baud Rate: 115200
- Format: 8 data bits, no parity, 1 stop bit
- Flow Control: None
- Maximum packet size: 256 bytes
- Acknowledgment required for all commands
-
Implementation:
import serial class SerialCommunicator: def __init__(self, port='/dev/ttyUSB0', baudrate=115200): self.port = port self.baudrate = baudrate self.connection = None def connect(self): try: self.connection = serial.Serial( port=self.port, baudrate=self.baudrate, bytesize=serial.EIGHTBITS, parity=serial.PARITY_NONE, stopbits=serial.STOPBITS_ONE, timeout=1 ) return True except serial.SerialException as e: print(f"Error connecting to serial port: {e}") return False def send_command(self, command, data=None): if not self.connection: return False # Format: [Command][Data Length][Data...] payload = bytearray([command, len(data) if data else 0]) if data: payload.extend(data) try: self.connection.write(payload) # Wait for acknowledgment ack = self.connection.read(1) return ack and ack[0] == 0x06 # ACK except Exception as e: print(f"Error sending command: {e}") return False
Mac Mini Raspberry Pi
ββββββββββββββββ ββββββββββββββββ
β β β β
β Python β β Python β
β Applicationβ β Service β
β β β β
β βββββββββββ β TCP/IP β βββββββββββ β
β β Network β β ZeroMQ β β Network β β
β β Client ββββββββββββββββββββββββββββββββ€βΊβ Server β β
β βββββββββββ β JSON or β βββββββββββ β
β β Binary Protocol β β
ββββββββββββββββ ββββββββββββββββ
-
Protocol Options:
- ZeroMQ (recommended): For efficient binary communication
- WebSockets: For web integration compatibility
- JSON-RPC: For human-readable debugging
-
Implementation:
import zmq import json class NetworkCommunicator: def __init__(self, server_address="tcp://192.168.1.100:5555"): self.server_address = server_address self.context = zmq.Context() self.socket = None def connect(self): try: self.socket = self.context.socket(zmq.REQ) self.socket.connect(self.server_address) return True except zmq.ZMQError as e: print(f"Error connecting to server: {e}") return False def send_command(self, command, params=None): if not self.socket: return False message = { "command": command, "params": params or {} } try: self.socket.send_json(message) response = self.socket.recv_json() return response.get("status") == "success" except Exception as e: print(f"Error sending command: {e}") return False
ββββββββββββββββ ββββββββββββββββ ββββββββββββββββ
β β β β β β
β Punch Card β API β Backend β Databaseβ Website β
β Application ββββββββββΊβ Server ββββββββββΊβ Frontend β
β β Requestsβ (Flask/ β Queries β β
β β β FastAPI) β β β
ββββββββββββββββ ββββββββββββββββ ββββββββββββββββ
β β²
β β
βΌ β
ββββββββββββββββ β
β β β
β Database β β
β (SQLite/ β β
β PostgreSQL)β β
β β β
ββββββββββββββββ β
β β
βββββββββββββββββββββββββ
-
Technology Stack:
- Flask or FastAPI (Python-based)
- SQLAlchemy for database abstraction
- JWT for authentication
- Redis for caching (optional)
-
Key Endpoints:
-
/api/v1/status
- Get system status -
/api/v1/statistics
- Get usage statistics -
/api/v1/history
- Get message history -
/api/v1/display
- Get current display state -
/api/v1/config
- Get/update configuration (authenticated)
-
-
Implementation Timeline:
- Phase 2: Basic status and statistics endpoints
- Phase 3: Complete API with authentication
- Phase 4: Advanced features and optimizations
-
New Tables:
-
web_users
- User authentication and permissions -
punch_card_images
- Captured display states -
system_logs
- Detailed operation logs -
api_access_logs
- API usage tracking
-
-
Schema Example:
CREATE TABLE web_users ( id INTEGER PRIMARY KEY AUTOINCREMENT, username TEXT UNIQUE NOT NULL, password_hash TEXT NOT NULL, role TEXT NOT NULL, created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, last_login TIMESTAMP ); CREATE TABLE punch_card_images ( id INTEGER PRIMARY KEY AUTOINCREMENT, message_id INTEGER, image_path TEXT NOT NULL, created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, FOREIGN KEY (message_id) REFERENCES messages(id) );
-
Technology Options:
- React.js for single-page application
- Vue.js for component-based design
- Simple server-rendered templates for MVP
-
Key Features:
- Live status dashboard
- Historical statistics visualization
- Message archive with search functionality
- System configuration interface (admin only)
- LED grid simulator/mirror
-
Implementation Timeline:
- Phase 3: Basic dashboard with statistics
- Phase 4: Complete website with all features
- Implement proper authentication using JWT
- Use HTTPS for all API communications
- Rate limiting to prevent abuse
- Input validation on all API endpoints
- Separation of public/private endpoints
- Regular security audits
class LEDController:
def __init__(self,
rows=12,
columns=80,
hardware_enabled=True,
controller_type='pi',
connection_string='/dev/ttyUSB0',
brightness=0.5):
"""Initialize the LED controller."""
self.rows = rows
self.columns = columns
self.hardware_enabled = hardware_enabled
self.connection = None
self.brightness = brightness
self.led_buffer = [[0 for _ in range(columns)] for _ in range(rows)]
if hardware_enabled:
self._connect_hardware(controller_type, connection_string)
def _connect_hardware(self, controller_type, connection_string):
"""Establish connection to hardware controller."""
# Implementation varies based on controller_type
pass
def set_led(self, row, column, state):
"""Set the state of a single LED."""
# Update buffer
self.led_buffer[row][column] = state
# If hardware connected, send update
if self.hardware_enabled and self.connection:
self._send_update(row, column)
def update_grid(self, grid):
"""Update the entire LED grid at once."""
# Update buffer
self.led_buffer = grid
# If hardware connected, send full update
if self.hardware_enabled and self.connection:
self._send_full_update()
def _send_update(self, row, column):
"""Send single LED update to hardware."""
# Implementation details for communication protocol
pass
def _send_full_update(self):
"""Send complete grid update to hardware."""
# Optimization for full grid updates
pass
def test_pattern(self, pattern='chase'):
"""Display a test pattern on the LEDs."""
# Various test patterns implementation
pass
def set_brightness(self, brightness):
"""Set the overall brightness of the LED grid."""
self.brightness = max(0.0, min(1.0, brightness))
if self.hardware_enabled and self.connection:
self._send_brightness()
def _send_brightness(self):
"""Send brightness update to hardware."""
pass
def shutdown(self):
"""Safely shut down the LED grid."""
# Turn off all LEDs
# Close connection
pass
# New method for web integration
def get_status_for_web(self):
"""Get current status as JSON for web API."""
return {
"hardware_enabled": self.hardware_enabled,
"connected": self.connection is not None,
"grid_dimensions": {
"rows": self.rows,
"columns": self.columns
},
"brightness": self.brightness,
"power_estimate_watts": self._estimate_power_usage()
}
def _estimate_power_usage(self):
"""Estimate current power usage in watts."""
# Power calculation based on active LEDs and brightness
pass
class WebAPIIntegrator:
def __init__(self,
base_url='https://your-website.com/api',
api_key=None,
auto_sync=True,
sync_interval=60):
"""Initialize Web API integration."""
self.base_url = base_url
self.api_key = api_key
self.auto_sync = auto_sync
self.sync_interval = sync_interval
self.last_sync = 0
self.sync_thread = None
if auto_sync:
self._start_sync_thread()
def _start_sync_thread(self):
"""Start background thread for periodic syncing."""
import threading
import time
def sync_worker():
while self.auto_sync:
if time.time() - self.last_sync >= self.sync_interval:
self.sync_statistics()
self.last_sync = time.time()
time.sleep(1)
self.sync_thread = threading.Thread(target=sync_worker)
self.sync_thread.daemon = True
self.sync_thread.start()
def sync_statistics(self):
"""Sync statistics to web API."""
import requests
import json
try:
stats = self._gather_statistics()
response = requests.post(
f"{self.base_url}/statistics",
json=stats,
headers={
"Authorization": f"Bearer {self.api_key}",
"Content-Type": "application/json"
}
)
return response.status_code == 200
except Exception as e:
print(f"Error syncing statistics: {e}")
return False
def _gather_statistics(self):
"""Gather system statistics for sync."""
# Implement to collect statistics from different modules
pass
-
Command Format
<Command><Data Length><Data>
-
Command Types
-
0x01
: Set single LED -
0x02
: Set multiple LEDs -
0x03
: Set full grid -
0x04
: Set brightness -
0x05
: Run test pattern -
0x06
: Ping/heartbeat -
0x07
: Reset controller -
0x08
: Get status -
0x09
: Web sync status (new) -
0x0A
: Capture display image (new)
-
-
Example: Setting Multiple LEDs
0x02 0x07 <row1> <col1> <state1> <row2> <col2> <state2> <row3> <col3> <state3>
Component | Specification | Quantity | Est. Cost |
---|---|---|---|
NeoPixel Matrix | 8x8 (64 LEDs) | 1 | $35 |
Arduino Nano | ATmega328P | 1 | $10 |
DC Power Supply | 5V/2A | 1 | $10 |
Breadboard | Half-size | 1 | $5 |
Jumper Wires | Pack of 40 | 1 | $5 |
Resistor | 470 ohm | 1 | $1 |
Capacitor | 1000ΞΌF | 1 | $2 |
Total | $68 |
Component | Specification | Quantity | Est. Cost |
---|---|---|---|
NeoPixel Matrix | 16x16 (256 LEDs) | 1 | $90 |
Teensy 4.0 | ARM Cortex-M7 | 1 | $20 |
DC Power Supply | 5V/5A | 1 | $15 |
Logic Level Shifter | 3.3V to 5V | 1 | $4 |
Prototyping Board | Large | 1 | $10 |
Capacitors | 1000ΞΌF | 3 | $6 |
Resistors | 470 ohm | 2 | $1 |
Total | $146 |
Component | Specification | Quantity | Est. Cost |
---|---|---|---|
NeoPixel Strips | WS2812B 60 LED/m | 20m | $400 |
Teensy 4.1 | ARM Cortex-M7 | 1 | $30 |
Power Supplies | 5V/20A | 2 | $140 |
Power Distribution Board | Custom | 1 | $50 |
Logic Level Shifter | 3.3V to 5V | 2 | $8 |
Enclosure | Custom | 1 | $100 |
Mounting Hardware | Assorted | 1 kit | $40 |
Cooling Fans | 80mm | 2 | $20 |
Wiring & Connectors | Assorted | 1 kit | $60 |
Diffuser Material | Acrylic | 1mΒ² | $50 |
Total | $898 |
-
Hardware Testing
- LED grid functionality test (all on, all off, checkerboard)
- Communication latency testing
- Power consumption measurement
-
Software Testing
- Synchronization between terminal and physical display
- Error handling for disconnection/reconnection
- Performance testing with animations
-
Integration Testing
- Full system test with all components
- Stress testing with rapid updates
- Long-duration stability testing
-
Web Integration Testing
- API endpoint validation
- Authentication testing
- Performance under load
-
Libraries
-
Hardware References
-
Communication Protocols
-
Web Development
This technical specification provides a comprehensive plan for integrating NeoPixel LEDs with the Punch Card Display System. By following this approach, the physical LED grid will accurately reflect the terminal display while maintaining flexibility for future enhancements.
The modular architecture allows for different hardware configurations while maintaining a consistent software interface. This approach ensures that the system can evolve as hardware components are upgraded or changed.
Implementation should proceed in phases, starting with a small-scale prototype before scaling to the full 12Γ80 grid. This incremental approach will allow for testing and refinement at each stage.
The addition of web integration capabilities will enable remote monitoring and sharing of punch card statistics, expanding the project's reach and functionality.