树莓派Genset监控项目问题:如何中断计时并返回待机提示
Hey there! I see exactly the problem you're stuck with—using time.sleep() locks up your entire program, so even if the genset switches back to standby early, you can't interrupt the timer until it finishes counting down. Let's fix this with a non-blocking approach using Python's threading module, which lets us cancel the timer the second the genset's state changes.
What's Wrong with the Original Code?
The time.sleep() call (I noticed you used 20 seconds for testing, smart move!) blocks your main loop completely. While the program is sleeping, it can't check the GPIO pin for state changes. So even if the genset goes back to standby after 30 minutes, the program won't notice until the sleep finishes—frustrating, right?
Solution: Use threading.Timer for Cancelable Timers
We'll use a Timer object that runs in a background thread. When the genset starts, we kick off the timer. If the genset switches back to standby before the timer finishes, we cancel the timer immediately and print the standby message.
Step-by-Step Modified Code
First, let's fix the typo in your original code (you used DOOR_SENSOR_PIN instead of GENSET_SENSOR_PIN in GPIO.setup()—that would throw an error!). Then add the threading logic:
import RPi.GPIO as GPIO import time import threading GPIO.setmode(GPIO.BCM) GENSET_SENSOR_PIN = 23 GPIO.setup(GENSET_SENSOR_PIN, GPIO.IN, pull_up_down=GPIO.PUD_UP) # Global variable to hold our active timer object running_timer = None def print_running_alert(): """Function that triggers when the timer finishes""" print("Genset is still Running!") try: old_is_open = GPIO.input(GENSET_SENSOR_PIN) while True: current_is_open = GPIO.input(GENSET_SENSOR_PIN) # Check if the genset's state has changed if current_is_open != old_is_open: old_is_open = current_is_open if current_is_open: # Genset switched to standby print("Genset is Ok") # Cancel the timer if it's still running if running_timer is not None: running_timer.cancel() running_timer = None else: # Genset switched to running print("Genset is Running!") # Cancel any existing timer first (in case of rapid state flips) if running_timer is not None: running_timer.cancel() # Start a new 1-hour timer (use 20 seconds for testing) running_timer = threading.Timer(3600, print_running_alert) running_timer.start() time.sleep(0.01) # Small delay to keep CPU usage low finally: # Clean up GPIO and cancel timer when exiting the program GPIO.cleanup() if running_timer is not None: running_timer.cancel()
How This Works
threading.Timer: This creates a background thread that waits the specified time (3600 seconds for 1 hour) before running theprint_running_alert()function. Your main loop keeps running normally, so it can keep checking the GPIO pin for state changes.- Instant Cancel on State Change: When the genset switches back to standby, we call
running_timer.cancel()to stop the timer immediately. This prevents the "still running" message from printing if the genset didn't stay on for the full hour. - Cleanup: The
finallyblock ensures GPIO is properly reset and the timer is canceled when you exit the program—good practice for Raspberry Pi projects to avoid pin lockups.
Testing Tips
For quick testing, replace 3600 with a smaller number like 20 (as you did before). Try switching the genset to standby before the timer finishes—you'll see the standby message right away, and the "still running" message won't print at all.
内容的提问来源于stack exchange,提问作者Aries Galang

