reed_switch.py 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112
  1. """
  2. Reed switch monitoring module for Raspberry Pi GPIO.
  3. Used for angular homing to detect home position.
  4. """
  5. import logging
  6. import platform
  7. logger = logging.getLogger(__name__)
  8. class ReedSwitchMonitor:
  9. """Monitor a reed switch connected to a Raspberry Pi GPIO pin."""
  10. def __init__(self, gpio_pin=18, invert_state=False):
  11. """
  12. Initialize the reed switch monitor.
  13. Args:
  14. gpio_pin: GPIO pin number (BCM numbering) for the reed switch
  15. invert_state: If True, invert the logic (triggered = LOW instead of HIGH)
  16. """
  17. self.gpio_pin = gpio_pin
  18. self.invert_state = invert_state
  19. self.gpio = None
  20. self.is_raspberry_pi = False
  21. # Try to import and initialize GPIO
  22. try:
  23. import RPi.GPIO as GPIO
  24. self.gpio = GPIO
  25. # Set up GPIO mode (BCM numbering)
  26. self.gpio.setmode(GPIO.BCM)
  27. # Set up the pin as input with pull-up resistor
  28. # Reed switch should connect pin to ground when triggered
  29. self.gpio.setup(self.gpio_pin, GPIO.IN, pull_up_down=GPIO.PUD_UP)
  30. self.is_raspberry_pi = True
  31. logger.info(f"Reed switch initialized on GPIO pin {self.gpio_pin} (invert_state={self.invert_state})")
  32. except ImportError:
  33. logger.warning("RPi.GPIO not available. Reed switch monitoring disabled.")
  34. except Exception as e:
  35. logger.error(f"Error initializing reed switch: {e}")
  36. logger.info("Reed switch monitoring disabled.")
  37. def is_triggered(self):
  38. """
  39. Check if the reed switch is currently triggered.
  40. Returns:
  41. bool: True if reed switch is triggered, False otherwise
  42. Notes:
  43. - If invert_state=False: triggered when pin is HIGH (1)
  44. - If invert_state=True: triggered when pin is LOW (0)
  45. """
  46. if not self.is_raspberry_pi or not self.gpio:
  47. return False
  48. try:
  49. # Read the GPIO pin state
  50. pin_state = self.gpio.input(self.gpio_pin)
  51. # Apply inversion if configured
  52. if self.invert_state:
  53. # Inverted: triggered when LOW (0)
  54. return pin_state == 0
  55. else:
  56. # Normal: triggered when HIGH (1)
  57. return pin_state == 1
  58. except Exception as e:
  59. logger.error(f"Error reading reed switch: {e}")
  60. return False
  61. def wait_for_trigger(self, timeout=None):
  62. """
  63. Wait for the reed switch to be triggered.
  64. Args:
  65. timeout: Maximum time to wait in seconds (None = wait indefinitely)
  66. Returns:
  67. bool: True if triggered, False if timeout occurred
  68. """
  69. if not self.is_raspberry_pi or not self.gpio:
  70. logger.warning("Reed switch not available, cannot wait for trigger")
  71. return False
  72. try:
  73. # Wait for rising edge (pin goes from LOW to HIGH)
  74. channel = self.gpio.wait_for_edge(
  75. self.gpio_pin,
  76. self.gpio.RISING,
  77. timeout=int(timeout * 1000) if timeout else None
  78. )
  79. return channel is not None
  80. except Exception as e:
  81. logger.error(f"Error waiting for reed switch trigger: {e}")
  82. return False
  83. def cleanup(self):
  84. """Clean up GPIO resources."""
  85. if self.is_raspberry_pi and self.gpio:
  86. try:
  87. self.gpio.cleanup(self.gpio_pin)
  88. logger.info(f"Reed switch GPIO pin {self.gpio_pin} cleaned up")
  89. except Exception as e:
  90. logger.error(f"Error cleaning up reed switch GPIO: {e}")
  91. def __del__(self):
  92. """Destructor to ensure GPIO cleanup."""
  93. self.cleanup()