110 lines
3.8 KiB
Python
110 lines
3.8 KiB
Python
#!/usr/bin/env python3
|
||
"""
|
||
GPIO‑monitor.py
|
||
|
||
* Sets every usable BCM pin as an input (pull‑down default)
|
||
* Saves the last read state of each pin
|
||
* In an infinite loop it polls the pins (≈10 ms per pass)
|
||
* When one or more pins change it prints:
|
||
- Which pins changed and old→new values
|
||
- The full 32‑bit snapshot as a binary string (MSB = highest pin)
|
||
|
||
Run as root (or a user in the *gpio* group):
|
||
sudo python3 GPIO‑monitor.py
|
||
Press Ctrl‑C to stop – the script cleans up the GPIO pins.
|
||
"""
|
||
|
||
import sys
|
||
import time
|
||
import signal
|
||
import RPi.GPIO as GPIO
|
||
|
||
# ----------------------------------------------------------------------
|
||
# 1️⃣ Pin list – all BCM pins that exist on the 40‑pin header
|
||
# ----------------------------------------------------------------------
|
||
GPIO_PINS = [
|
||
2, 3, 4, 5, 6, 7, 8, 9,
|
||
10, 11, 12, 13, 14, 15, 16, 17,
|
||
18, 19, 20, 21, 22, 23, 24, 25,
|
||
26, 27
|
||
]
|
||
|
||
# ----------------------------------------------------------------------
|
||
# 2️⃣ Initialise GPIO
|
||
# ----------------------------------------------------------------------
|
||
GPIO.setmode(GPIO.BCM)
|
||
|
||
# keep only those pins we can actually configure
|
||
active_pins = []
|
||
failed = []
|
||
|
||
for pin in GPIO_PINS:
|
||
try:
|
||
GPIO.setup(pin, GPIO.IN, pull_up_down=GPIO.PUD_DOWN)
|
||
active_pins.append(pin)
|
||
except Exception as e:
|
||
failed.append((pin, str(e)))
|
||
|
||
if failed:
|
||
sys.stderr.write("⚠️ Could not initialise the following pins (they will be ignored):\n")
|
||
for p, msg in failed:
|
||
sys.stderr.write(f" Pin {p}: {msg}\n")
|
||
|
||
# ----------------------------------------------------------------------
|
||
# 3️⃣ Helper to read the current snapshot (dict pin→0/1)
|
||
# ----------------------------------------------------------------------
|
||
def read_all():
|
||
return {pin: GPIO.input(pin) for pin in active_pins}
|
||
|
||
# ----------------------------------------------------------------------
|
||
# 4️⃣ Signal handling – graceful exit on Ctrl‑C / SIGTERM
|
||
# ----------------------------------------------------------------------
|
||
keep_running = True
|
||
|
||
def _handle_exit(signum, frame):
|
||
global keep_running
|
||
keep_running = False
|
||
|
||
signal.signal(signal.SIGINT, _handle_exit) # Ctrl‑C
|
||
signal.signal(signal.SIGTERM, _handle_exit)
|
||
|
||
# ----------------------------------------------------------------------
|
||
# 5️⃣ Main monitoring loop
|
||
# ----------------------------------------------------------------------
|
||
prev_state = read_all() # initial snapshot
|
||
|
||
print("🔎 Monitoring {} GPIO pins – press Ctrl‑C to stop".format(len(active_pins)))
|
||
while keep_running:
|
||
cur_state = read_all()
|
||
|
||
# Find pins whose value differed from the previous snapshot
|
||
changed = [(pin, prev_state[pin], cur_state[pin])
|
||
for pin in active_pins
|
||
if prev_state[pin] != cur_state[pin]]
|
||
|
||
if changed:
|
||
# Build a readable change list e.g. "4:0→1, 17:1→0"
|
||
changes_txt = ", ".join(f"{pin}:{old}→{new}" for pin, old, new in changed)
|
||
|
||
# Build a compact binary view – 32‑bit with pins sorted ascending
|
||
# (higher pins become more significant bits)
|
||
bits = "".join(str(cur_state[p]) for p in sorted(active_pins, reverse=True))
|
||
# Pad to a multiple of 4 for readability
|
||
pad_len = (4 - len(bits) % 4) % 4
|
||
bits = "0" * pad_len + bits
|
||
|
||
print(f"[{time.strftime('%H:%M:%S')}] Change detected – {changes_txt}")
|
||
print(f" Current snapshot: 0b{bits}")
|
||
|
||
# Update reference for the next iteration
|
||
prev_state = cur_state
|
||
|
||
# Polling interval – adjust if you need faster/slower response
|
||
time.sleep(0.01) # 10 ms
|
||
|
||
# ----------------------------------------------------------------------
|
||
# 6️⃣ Cleanup
|
||
# ----------------------------------------------------------------------
|
||
GPIO.cleanup()
|
||
print("\n✅ Monitoring stopped – GPIO pins released.")
|