Created
October 13, 2025 03:36
-
-
Save raoulduke/aa4e40fe07e03870e3f93ca88754421e to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| import RPi.GPIO as GPIO | |
| import time | |
| import random | |
| # Setup GPIO | |
| GPIO.setmode(GPIO.BCM) | |
| GPIO.setup(17, GPIO.OUT) | |
| pwm = GPIO.PWM(17, 1000) # 1kHz PWM frequency | |
| pwm.start(100) | |
| def flicker_burst(): | |
| """Rapid on-off flicker like a dying neon tube""" | |
| flicker_count = random.randint(4, 12) | |
| for _ in range(flicker_count): | |
| # Off time (dark) | |
| pwm.ChangeDutyCycle(255 - random.randint(0, 50)) | |
| time.sleep(random.uniform(0.02, 0.08)) | |
| # On time (bright) | |
| pwm.ChangeDutyCycle(255 - random.randint(200, 255)) | |
| time.sleep(random.uniform(0.02, 0.07)) | |
| def slow_dim(): | |
| """Gradually dim from bright to dim""" | |
| for brightness in range(255, 100, -3): | |
| pwm.ChangeDutyCycle(brightness) | |
| time.sleep(random.uniform(0.01, 0.05)) | |
| def slow_brighten(): | |
| """Gradually brighten from dim to bright""" | |
| for brightness in range(100, 255, 3): | |
| pwm.ChangeDutyCycle(brightness) | |
| time.sleep(random.uniform(0.01, 0.05)) | |
| def power_surge(): | |
| """Sudden bright flash then dim""" | |
| pwm.ChangeDutyCycle(0) # Full bright | |
| time.sleep(0.3) | |
| for brightness in range(0, 180, 2): | |
| pwm.ChangeDutyCycle(brightness) | |
| time.sleep(0.01) | |
| def struggling_start(): | |
| """Struggling to turn on - multiple attempts""" | |
| attempts = random.randint(2, 4) | |
| for _ in range(attempts): | |
| # Try to turn on | |
| pwm.ChangeDutyCycle(255 - random.randint(100, 180)) | |
| time.sleep(random.uniform(0.15, 0.4)) | |
| # Failed - turns off | |
| pwm.ChangeDutyCycle(255) | |
| time.sleep(random.uniform(0.1, 0.3)) | |
| # Finally turns on | |
| pwm.ChangeDutyCycle(0) | |
| def intermittent_flicker(): | |
| """Occasional quick flickers while otherwise on""" | |
| base_brightness = random.randint(20, 60) | |
| for _ in range(random.randint(3, 8)): | |
| # Normal on | |
| pwm.ChangeDutyCycle(base_brightness) | |
| time.sleep(random.uniform(0.5, 2)) | |
| # Quick flicker off | |
| pwm.ChangeDutyCycle(220) | |
| time.sleep(random.uniform(0.03, 0.1)) | |
| try: | |
| print("Starting Dying Neon Sign Effect...") | |
| print("Press Ctrl+C to stop") | |
| while True: | |
| effect = random.randint(1, 6) | |
| if effect == 1: | |
| # Rapid death flicker | |
| print("Effect: Rapid flicker burst") | |
| flicker_burst() | |
| time.sleep(random.uniform(0.5, 1.5)) | |
| elif effect == 2: | |
| # Struggling to stay on | |
| print("Effect: Struggling to power on") | |
| struggling_start() | |
| time.sleep(2) | |
| elif effect == 3: | |
| # Dim and brighten cycle | |
| print("Effect: Gradual dim and brighten") | |
| slow_dim() | |
| time.sleep(random.uniform(0.3, 0.8)) | |
| slow_brighten() | |
| time.sleep(1) | |
| elif effect == 4: | |
| # Power surge | |
| print("Effect: Power surge") | |
| power_surge() | |
| time.sleep(random.uniform(1, 2)) | |
| elif effect == 5: | |
| # Intermittent flickers | |
| print("Effect: Intermittent flicker") | |
| intermittent_flicker() | |
| time.sleep(random.uniform(0.5, 1)) | |
| else: # effect == 6 | |
| # Stay bright normally then suddenly flicker | |
| print("Effect: Normal bright then sudden flicker") | |
| pwm.ChangeDutyCycle(255 - random.randint(240, 255)) | |
| time.sleep(random.uniform(1, 4)) | |
| flicker_burst() | |
| time.sleep(random.uniform(0.5, 1)) | |
| # Random pause between effects | |
| time.sleep(random.uniform(0.3, 1)) | |
| except KeyboardInterrupt: | |
| print("\nShutting down...") | |
| pwm.ChangeDutyCycle(255) # Turn off | |
| time.sleep(0.5) | |
| finally: | |
| pwm.stop() | |
| GPIO.cleanup() | |
| print("Goodbye!") |
Author
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Dying Neon Sign Effect - Raspberry Pi LED Controller
A Python script that creates a realistic dying neon sign flicker effect on a 12V LED strip controlled by a Raspberry Pi (4, Zero WH, or Pico). Uses PWM (Pulse Width Modulation) on GPIO pin 17 to simulate the unpredictable behavior of a failing vintage neon sign.
Features:
Hardware Required:
Circuit Details:
The script controls the LED strip through a PWM gate driver circuit that safely amplifies the GPIO signal from 3.3V (16mA) to 12V (5A). This protects the microcontroller while providing full brightness control.
Code Features:
Usage:
python3 dying-neon-sign-effect.py
Press Ctrl+C to stop (if connected to terminal). For headless operation, unplug power or SSH in and kill the process.