diff --git a/CHANGELOG.md b/CHANGELOG.md index 205cc5e..35eba39 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,4 +4,12 @@ - Feature A added - FIX: nasty bug #1729 fixed +- ADD: Raspberry Pi LG-07 lift control implementation + - Created lift_driver.py with GPIO control for FLTCON remote + - Added hardware test script (test_hardware.py) + - Added command-line application (app.py) + - Added configuration file (config.yaml) + - Added Raspberry Pi setup script (setup-pi.sh) + - Added Pi-specific requirements (requirements-pi.txt) + - Added comprehensive hardware setup documentation - add your changes here! diff --git a/find_pi.ps1 b/find_pi.ps1 new file mode 100644 index 0000000..aec3ee3 --- /dev/null +++ b/find_pi.ps1 @@ -0,0 +1,71 @@ +# PowerShell script to find Raspberry Pi on network +# Run this from PowerShell: .\find_pi.ps1 + +param( + [string]$Network = "172.20.10", + [int]$StartIP = 2, + [int]$EndIP = 14 +) + +Write-Host "๐Ÿ” Scanning for Raspberry Pi on network $Network.0/28..." -ForegroundColor Cyan +Write-Host "Testing IPs from $Network.$StartIP to $Network.$EndIP" -ForegroundColor Yellow +Write-Host "" + +$found = $false + +for ($i = $StartIP; $i -le $EndIP; $i++) { + $ip = "$Network.$i" + Write-Host "Testing $ip..." -NoNewline + + try { + $ping = Test-Connection -ComputerName $ip -Count 1 -Quiet -TimeoutSeconds 1 + if ($ping) { + Write-Host " โœ“ ALIVE" -ForegroundColor Green + + # Try to get hostname + try { + $hostname = [System.Net.Dns]::GetHostEntry($ip).HostName + Write-Host " Hostname: $hostname" -ForegroundColor Green + + # Check if it looks like a Raspberry Pi + if ($hostname -like "*raspberry*" -or $hostname -eq "pi") { + Write-Host " ๐ŸŽ‰ Found Raspberry Pi at $ip ($hostname)" -ForegroundColor Green -BackgroundColor Black + $found = $true + } + } catch { + Write-Host " Could not resolve hostname" -ForegroundColor Yellow + } + + # Try SSH connection test + try { + $sshTest = Test-NetConnection -ComputerName $ip -Port 22 -WarningAction SilentlyContinue + if ($sshTest.TcpTestSucceeded) { + Write-Host " ๐Ÿ” SSH port open" -ForegroundColor Green + } else { + Write-Host " โŒ SSH port closed" -ForegroundColor Red + } + } catch { + Write-Host " Could not test SSH" -ForegroundColor Yellow + } + + } else { + Write-Host " โŒ No response" -ForegroundColor Red + } + } catch { + Write-Host " โŒ Error testing $ip" -ForegroundColor Red + } +} + +Write-Host "" +if (-not $found) { + Write-Host "โŒ No Raspberry Pi found in the scanned range." -ForegroundColor Red + Write-Host "" + Write-Host "Troubleshooting steps:" -ForegroundColor Yellow + Write-Host "1. Make sure Raspberry Pi is powered on" -ForegroundColor White + Write-Host "2. Check Ethernet cable is connected" -ForegroundColor White + Write-Host "3. Try different IP ranges if your network is different" -ForegroundColor White + Write-Host "4. Check router admin panel for connected devices" -ForegroundColor White + Write-Host "5. Try connecting Pi directly to computer via Ethernet" -ForegroundColor White +} else { + Write-Host "โœ… Raspberry Pi found! Use the IP address above for SSH/scp commands." -ForegroundColor Green +} \ No newline at end of file diff --git a/requirements-pi.txt b/requirements-pi.txt new file mode 100644 index 0000000..ca049b0 --- /dev/null +++ b/requirements-pi.txt @@ -0,0 +1,6 @@ +# Raspberry Pi specific requirements for LG-07 lift control +# Install with: pip install -r requirements-pi.txt + +RPi.GPIO>=0.7.0 +# Note: RPi.GPIO is only available on Raspberry Pi +# On other systems, use the test_basic.py script with mocked GPIO \ No newline at end of file diff --git a/setup-pi.sh b/setup-pi.sh new file mode 100644 index 0000000..c0505e3 --- /dev/null +++ b/setup-pi.sh @@ -0,0 +1,55 @@ +#!/bin/bash +# Setup script for Raspberry Pi LG-07 Lift Control +# Run this script on your Raspberry Pi to set up the environment + +set -e # Exit on any error + +echo "๐Ÿ› ๏ธ Setting up LG-07 Lift Control on Raspberry Pi" +echo "=================================================" + +# Check if running on Raspberry Pi +if ! grep -q "Raspberry Pi" /proc/cpuinfo; then + echo "โŒ This script must be run on a Raspberry Pi" + exit 1 +fi + +echo "โœ… Running on Raspberry Pi" + +# Update package list +echo "๐Ÿ“ฆ Updating package list..." +sudo apt update + +# Install Python and pip if not present +echo "๐Ÿ Installing Python and pip..." +sudo apt install -y python3 python3-pip python3-dev + +# Install RPi.GPIO +echo "๐Ÿ”Œ Installing RPi.GPIO..." +sudo apt install -y python3-rpi.gpio + +# Install the package in development mode +echo "๐Ÿ“š Installing progressive-automations-python..." +cd "$(dirname "$0")" +pip3 install -e . + +# Install additional dependencies if any +if [ -f "requirements-pi.txt" ]; then + echo "๐Ÿ“‹ Installing Raspberry Pi specific requirements..." + pip3 install -r requirements-pi.txt +fi + +# Make scripts executable +echo "๐Ÿ”ง Making scripts executable..." +chmod +x src/progressive_automations_python/pi/lg07_lift/test_hardware.py +chmod +x src/progressive_automations_python/pi/lg07_lift/app.py + +echo "" +echo "๐ŸŽ‰ Setup completed successfully!" +echo "" +echo "Next steps:" +echo "1. Connect your relays to GPIO pins 17 (UP) and 27 (DOWN)" +echo "2. Connect relays to FLTCON UP/DOWN buttons" +echo "3. Test with: python3 src/progressive_automations_python/pi/lg07_lift/test_hardware.py" +echo "4. Or run: python3 src/progressive_automations_python/pi/lg07_lift/app.py up" +echo "" +echo "โš ๏ธ Safety note: Test with short movements first and ensure emergency stop works!" \ No newline at end of file diff --git a/src/progressive_automations_python/pi/lg07_lift/README.md b/src/progressive_automations_python/pi/lg07_lift/README.md new file mode 100644 index 0000000..0caa490 --- /dev/null +++ b/src/progressive_automations_python/pi/lg07_lift/README.md @@ -0,0 +1,132 @@ +# LG-07 Lift Control - Raspberry Pi Setup + +This directory contains the Raspberry Pi implementation for controlling an LG-07 lifting column via FLTCON remote. + +## Hardware Requirements + +- Raspberry Pi (any model with GPIO pins) +- Relay board/module (2 relays minimum) +- FLTCON remote control unit +- LG-07 lifting column +- Jumper wires for connections + +## Hardware Connections + +### GPIO Pin Assignments (BCM numbering) +- **GPIO 17 (Pin 11)**: UP relay control +- **GPIO 27 (Pin 13)**: DOWN relay control +- **GND (Pin 6)**: Common ground for relays + +### Relay Connections +1. Connect relay board to Raspberry Pi GPIO pins +2. Connect relay outputs to FLTCON remote buttons: + - Relay 1 (GPIO 17) โ†’ FLTCON UP button + - Relay 2 (GPIO 27) โ†’ FLTCON DOWN button +3. Ensure relays are configured as **ACTIVE-LOW** (closed when GPIO is LOW) + +## Software Setup + +### Option 1: Automated Setup (Recommended) +```bash +# Copy project to Raspberry Pi +scp -r progressive-automations-python pi@raspberrypi.local:~/ + +# SSH to Raspberry Pi +ssh pi@raspberrypi.local + +# Run setup script +cd progressive-automations-python +chmod +x setup-pi.sh +./setup-pi.sh +``` + +### Option 2: Manual Setup +```bash +# Update system +sudo apt update +sudo apt install -y python3 python3-pip python3-rpi.gpio + +# Install package +pip3 install -e . + +# Install Pi-specific requirements +pip3 install -r requirements-pi.txt +``` + +## Testing + +### Hardware Test (Recommended First Step) +```bash +cd progressive-automations-python +python3 src/progressive_automations_python/pi/lg07_lift/test_hardware.py +``` + +This will run an automated test sequence: +1. Small UP movement (0.5s) +2. Small DOWN movement (0.5s) +3. Quick UP nudge (0.2s) +4. Quick DOWN nudge (0.2s) +5. Emergency stop test + +### Manual Testing +```bash +# Move up for 1 second +python3 src/progressive_automations_python/pi/lg07_lift/app.py up + +# Move down for 2 seconds +python3 src/progressive_automations_python/pi/lg07_lift/app.py down --time 2.0 + +# Quick nudge up +python3 src/progressive_automations_python/pi/lg07_lift/app.py nudge up --time 0.3 +``` + +### Interactive Manual Test +```bash +python3 src/progressive_automations_python/pi/lg07_lift/test_hardware.py +# Choose option 2 for manual testing +``` + +## Safety Precautions + +โš ๏ธ **Important Safety Notes:** + +1. **Test with short movements first** - Start with 0.2-0.5 second movements +2. **Have emergency stop ready** - Ctrl+C will trigger emergency stop +3. **Monitor the lift** - Ensure it moves in expected direction +4. **Check relay polarity** - Verify relays activate when GPIO goes LOW +5. **Secure connections** - Loose wires can cause intermittent operation + +## Troubleshooting + +### Lift doesn't move +- Check relay connections to FLTCON buttons +- Verify FLTCON has power and is paired with LG-07 +- Test relays independently (they should click when activated) + +### Wrong direction +- Swap relay connections between UP/DOWN buttons +- Check GPIO pin assignments in `lift_driver.py` + +### GPIO errors +- Ensure you're running as a user with GPIO access (usually `pi`) +- Check that RPi.GPIO is installed: `python3 -c "import RPi.GPIO"` + +### Import errors +- Run `pip3 install -e .` from project root +- Check Python path includes the src directory + +## Configuration + +Edit `config.yaml` to customize: +- GPIO pin assignments +- Default timing values +- Safety settings + +## Next Steps + +Once basic control works, consider adding: +- Position feedback sensors +- Web interface for remote control +- Automated movement sequences +- Safety limit switches +- Logging and monitoring \ No newline at end of file diff --git a/src/progressive_automations_python/pi/lg07_lift/app.py b/src/progressive_automations_python/pi/lg07_lift/app.py new file mode 100644 index 0000000..ec28159 --- /dev/null +++ b/src/progressive_automations_python/pi/lg07_lift/app.py @@ -0,0 +1,77 @@ +#!/usr/bin/env python3 +""" +Basic application for controlling LG-07 lift via FLTCON on Raspberry Pi. + +This provides a simple command-line interface for lift control. +For production use, consider adding: +- Web API (Flask/FastAPI) +- Configuration file support +- Position feedback +- Safety limits +- Logging +""" + +import sys +import signal +import argparse +from progressive_automations_python.pi.lg07_lift.lift_driver import ( + press_up, press_down, nudge, emergency_stop, cleanup +) + +def signal_handler(signum, frame): + """Handle Ctrl+C gracefully.""" + print("\nโน๏ธ Received signal, stopping lift and cleaning up...") + emergency_stop() + cleanup() + sys.exit(0) + +def main(): + """Main application entry point.""" + # Set up signal handlers for clean shutdown + signal.signal(signal.SIGINT, signal_handler) + signal.signal(signal.SIGTERM, signal_handler) + + parser = argparse.ArgumentParser(description='LG-07 Lift Control') + parser.add_argument('command', choices=['up', 'down', 'nudge'], + help='Movement command') + parser.add_argument('direction', nargs='?', choices=['up', 'down'], + help='Direction for nudge command') + parser.add_argument('-t', '--time', type=float, default=1.0, + help='Movement time in seconds (default: 1.0)') + parser.add_argument('--test', action='store_true', + help='Run hardware test instead of single command') + + args = parser.parse_args() + + try: + if args.test: + # Run the hardware test + print("๐Ÿงช Running hardware test...") + from test_hardware import test_sequence + test_sequence() + elif args.command == 'up': + print(f"โฌ†๏ธ Moving UP for {args.time} seconds...") + press_up(args.time) + print("โœ… UP movement completed") + elif args.command == 'down': + print(f"โฌ‡๏ธ Moving DOWN for {args.time} seconds...") + press_down(args.time) + print("โœ… DOWN movement completed") + elif args.command == 'nudge': + if not args.direction: + print("โŒ Direction required for nudge command") + sys.exit(1) + print(f"โฌ†๏ธ Nudging {args.direction.upper()} for {args.time} seconds...") + nudge(args.direction, args.time) + print("โœ… Nudge completed") + + except Exception as e: + print(f"โŒ Error: {e}") + emergency_stop() + sys.exit(1) + + finally: + cleanup() + +if __name__ == "__main__": + main() diff --git a/src/progressive_automations_python/pi/lg07_lift/config.yaml b/src/progressive_automations_python/pi/lg07_lift/config.yaml new file mode 100644 index 0000000..da29529 --- /dev/null +++ b/src/progressive_automations_python/pi/lg07_lift/config.yaml @@ -0,0 +1,22 @@ +# Configuration for LG-07 Lift Control +# GPIO pin assignments (BCM numbering) +gpio: + pin_up: 17 # GPIO pin for UP relay + pin_down: 27 # GPIO pin for DOWN relay + +# Timing settings (seconds) +timing: + default_press_time: 1.0 # Default movement time + nudge_time: 0.2 # Default nudge time + min_press_time: 0.1 # Minimum allowed press time + max_press_time: 10.0 # Maximum allowed press time + +# Safety settings +safety: + enable_emergency_stop: true + auto_cleanup: true + +# Debug settings +debug: + enable_logging: false + log_level: INFO diff --git a/src/progressive_automations_python/pi/lg07_lift/lift_driver.py b/src/progressive_automations_python/pi/lg07_lift/lift_driver.py new file mode 100644 index 0000000..80d397f --- /dev/null +++ b/src/progressive_automations_python/pi/lg07_lift/lift_driver.py @@ -0,0 +1,100 @@ +# lift_driver.py +# +# Low-level driver for controlling the LG-07 lifting column +# using Raspberry Pi GPIO pins connected to a relay board. +# +# Each relay simulates a button press on the FLTCON remote. +# Relays are assumed to be ACTIVE-LOW: +# GPIO LOW -> relay ON -> button pressed +# GPIO HIGH -> relay OFF -> button released + +import time +import threading +import RPi.GPIO as GPIO + +# Default GPIO pin assignments (BCM numbering) +PIN_UP = 17 +PIN_DOWN = 27 + +_initialized = False +_lock = threading.Lock() + + +def _init_gpio(): + """Initialize GPIO pins once.""" + global _initialized + if _initialized: + return + + GPIO.setmode(GPIO.BCM) # use BCM numbering (GPIO17 = pin 11) + GPIO.setup(PIN_UP, GPIO.OUT, initial=GPIO.HIGH) + GPIO.setup(PIN_DOWN, GPIO.OUT, initial=GPIO.HIGH) + + _initialized = True + + +def _release_all(): + """Release all relays (set all GPIO HIGH).""" + GPIO.output(PIN_UP, GPIO.HIGH) + GPIO.output(PIN_DOWN, GPIO.HIGH) + + +def press_up(seconds: float): + """ + Press the UP button for a given number of seconds. + """ + _init_gpio() + with _lock: + _release_all() + GPIO.output(PIN_UP, GPIO.LOW) + time.sleep(seconds) + _release_all() + + +def press_down(seconds: float): + """ + Press the DOWN button for a given number of seconds. + """ + _init_gpio() + with _lock: + _release_all() + GPIO.output(PIN_DOWN, GPIO.LOW) + time.sleep(seconds) + _release_all() + + +def nudge(direction: str, seconds: float = 0.2): + """ + Move UP or DOWN for a small time increment. + """ + direction = direction.lower() + if direction not in ("up", "down"): + raise ValueError("direction must be 'up' or 'down'") + + if seconds <= 0: + raise ValueError("seconds must be > 0") + + if direction == "up": + press_up(seconds) + else: + press_down(seconds) + + +def emergency_stop(): + """ + Immediately release all relays. + """ + if not _initialized: + return + with _lock: + _release_all() + + +def cleanup(): + """ + Cleanup GPIO state. Call this when shutting down the script. + """ + if _initialized: + emergency_stop() + GPIO.cleanup() + \ No newline at end of file diff --git a/src/progressive_automations_python/pi/lg07_lift/test_hardware.py b/src/progressive_automations_python/pi/lg07_lift/test_hardware.py new file mode 100644 index 0000000..3462633 --- /dev/null +++ b/src/progressive_automations_python/pi/lg07_lift/test_hardware.py @@ -0,0 +1,162 @@ +#!/usr/bin/env python3 +""" +Hardware test script for LG-07 lift control on Raspberry Pi. +Run this script directly on your Raspberry Pi to test the FLTCON connection. + +Usage: + python test_hardware.py + +Make sure: +1. Relays are connected to GPIO pins 17 (UP) and 27 (DOWN) +2. Relays are connected to FLTCON UP/DOWN buttons +3. FLTCON is powered and connected to LG-07 lift +4. Run with: python test_hardware.py +""" + +import sys +import os +import time + +# Add the package to path +sys.path.insert(0, os.path.dirname(__file__)) + +from progressive_automations_python.pi.lg07_lift.lift_driver import ( + press_up, press_down, nudge, emergency_stop, cleanup +) + +def test_sequence(): + """Run a test sequence of movements.""" + print("๐Ÿงช Starting LG-07 Lift Hardware Test") + print("=" * 40) + + try: + # Test 1: Small up movement + print("Test 1: Small UP movement (0.5 seconds)") + print("Watch the lift - it should move UP slightly") + input("Press Enter to start test 1...") + press_up(0.5) + print("โœ… UP movement completed") + time.sleep(2) + + # Test 2: Small down movement + print("\nTest 2: Small DOWN movement (0.5 seconds)") + print("Watch the lift - it should move DOWN slightly") + input("Press Enter to start test 2...") + press_down(0.5) + print("โœ… DOWN movement completed") + time.sleep(2) + + # Test 3: Nudge up + print("\nTest 3: Quick UP nudge (0.2 seconds)") + input("Press Enter to start test 3...") + nudge('up', 0.2) + print("โœ… UP nudge completed") + time.sleep(1) + + # Test 4: Nudge down + print("\nTest 4: Quick DOWN nudge (0.2 seconds)") + input("Press Enter to start test 4...") + nudge('down', 0.2) + print("โœ… DOWN nudge completed") + time.sleep(1) + + # Test 5: Emergency stop + print("\nTest 5: Emergency stop test") + print("This should immediately stop any movement") + emergency_stop() + print("โœ… Emergency stop activated") + + print("\n๐ŸŽ‰ All hardware tests completed successfully!") + print("If the lift moved as expected, your FLTCON connection is working!") + + except KeyboardInterrupt: + print("\nโน๏ธ Test interrupted by user") + emergency_stop() + + except Exception as e: + print(f"\nโŒ Error during testing: {e}") + emergency_stop() + + finally: + print("\n๐Ÿงน Cleaning up GPIO...") + cleanup() + print("โœ… GPIO cleanup completed") + +def manual_test(): + """Allow manual testing of individual functions.""" + print("๐Ÿ”ง Manual Test Mode") + print("Commands:") + print(" u - Move UP for specified seconds") + print(" d - Move DOWN for specified seconds") + print(" nu - Nudge UP for specified seconds") + print(" nd - Nudge DOWN for specified seconds") + print(" stop - Emergency stop") + print(" quit - Exit manual mode") + print() + + try: + while True: + cmd = input("Command: ").strip().lower() + + if cmd == 'quit': + break + elif cmd == 'stop': + emergency_stop() + print("โน๏ธ Emergency stop") + elif cmd.startswith('u '): + try: + seconds = float(cmd.split()[1]) + print(f"โฌ†๏ธ Moving UP for {seconds} seconds...") + press_up(seconds) + print("โœ… UP movement completed") + except (ValueError, IndexError): + print("โŒ Invalid command. Use: u ") + elif cmd.startswith('d '): + try: + seconds = float(cmd.split()[1]) + print(f"โฌ‡๏ธ Moving DOWN for {seconds} seconds...") + press_down(seconds) + print("โœ… DOWN movement completed") + except (ValueError, IndexError): + print("โŒ Invalid command. Use: d ") + elif cmd.startswith('nu '): + try: + seconds = float(cmd.split()[1]) + print(f"โฌ†๏ธ Nudging UP for {seconds} seconds...") + nudge('up', seconds) + print("โœ… UP nudge completed") + except (ValueError, IndexError): + print("โŒ Invalid command. Use: nu ") + elif cmd.startswith('nd '): + try: + seconds = float(cmd.split()[1]) + print(f"โฌ‡๏ธ Nudging DOWN for {seconds} seconds...") + nudge('down', seconds) + print("โœ… DOWN nudge completed") + except (ValueError, IndexError): + print("โŒ Invalid command. Use: nd ") + else: + print("โŒ Unknown command") + + except KeyboardInterrupt: + print("\nโน๏ธ Manual test interrupted") + emergency_stop() + + finally: + cleanup() + +if __name__ == "__main__": + print("LG-07 Lift Hardware Test Script") + print("Choose test mode:") + print("1. Automated test sequence") + print("2. Manual testing") + print() + + choice = input("Enter choice (1 or 2): ").strip() + + if choice == '1': + test_sequence() + elif choice == '2': + manual_test() + else: + print("โŒ Invalid choice") \ No newline at end of file diff --git a/src/progressive_automations_python/pi/lg07_lift/tests/test_driver.py b/src/progressive_automations_python/pi/lg07_lift/tests/test_driver.py new file mode 100644 index 0000000..e69de29