code.py
  1  # SPDX-FileCopyrightText: 2018 John Edgar Park for Adafruit Industries
  2  #
  3  # SPDX-License-Identifier: MIT
  4  
  5  # HalloWing Jump Scare Trap
  6  # use PIR sensor, speaker, and servo
  7  import time
  8  import array
  9  import math
 10  import board
 11  import displayio
 12  import pwmio
 13  from adafruit_motor import servo
 14  import digitalio
 15  import touchio
 16  import audioio
 17  import audiocore
 18  # Setup LED and PIR pins
 19  LED_PIN = board.LED  # Pin number for the board's built in LED.
 20  PIR_PIN = board.SENSE   # Pin port connected to PIR sensor output wire.
 21  # Setup digital input for PIR sensor:
 22  pir = digitalio.DigitalInOut(PIR_PIN)
 23  pir.direction = digitalio.Direction.INPUT
 24  # Setup digital output for LED:
 25  led = digitalio.DigitalInOut(LED_PIN)
 26  led.direction = digitalio.Direction.OUTPUT
 27  # Setup servo
 28  # servo = pwmio.PWMOut(board.D4, frequency=50)
 29  pwm = pwmio.PWMOut(board.D4)
 30  servo = servo.Servo(pwm)
 31  
 32  # Setup cap touch button
 33  ready_button = touchio.TouchIn(board.TOUCH1)
 34  
 35  def servo_ready():
 36      servo.angle = 0
 37  def servo_release():
 38      servo.angle = 90
 39  
 40  # Set servo to ready position
 41  servo_ready()
 42  # Function for playing wav file, releasing servo
 43  def play_wave():
 44      wave_file = open("hiss01.wav", "rb")  # open a wav file
 45      wave = audiocore.WaveFile(wave_file)
 46      audio.play(wave)  # play the wave file
 47      led.value = True
 48      servo_release()
 49      print('Motion detected!')
 50      while audio.playing:  # turn on LED, turn servo
 51          pass
 52      wave_file.close()  # close the wav file
 53  # Setup audio out pin
 54  audio = audioio.AudioOut(board.A0)
 55  
 56  # tone player setup for status beeps
 57  tone_volume = 0.1  # Increase this to increase the volume of the tone.
 58  frequency_hz = 880  # Set this to the Hz of the tone you want to generate.
 59  length = 8000 // frequency_hz
 60  sine_wave = array.array("H", [0] * length)
 61  for i in range(length):
 62      sine_wave[i] = int((1 + math.sin(math.pi * 2 * i / length)) * tone_volume * (2 ** 15 - 1))
 63  sine_wave_sample = audiocore.RawSample(sine_wave)
 64  
 65  # Function for beeping, usage: 'beep(3)' will beep 3x
 66  def beep(count):
 67      for _ in range(count):
 68          audio.play(sine_wave_sample, loop=True)
 69          time.sleep(0.1)
 70          audio.stop()
 71          time.sleep(0.05)
 72  
 73  # Function for counting down, usage: 'countdown(5)'
 74  def countdown(count):
 75      for k in range(count):
 76          print(count - k)
 77          led.value = True
 78          time.sleep(0.1)
 79          led.value = False
 80          time.sleep(1)
 81  
 82  # function for blinking, usage: 'blink(5, 0.2)'
 83  def blink(count, speed):
 84      for _ in range(count):
 85          led.value = True
 86          time.sleep(speed)
 87          led.value = False
 88          time.sleep(speed)
 89  
 90  # display setup
 91  backlight = pwmio.PWMOut(board.TFT_BACKLIGHT)
 92  splash = displayio.Group()
 93  board.DISPLAY.show(splash)
 94  max_brightness = 2 ** 15
 95  backlight.duty_cycle = 0
 96  # Image list
 97  images = ["trap_sprung.bmp", "reset_trap.bmp", "please_standby.bmp",
 98            "trap_set.bmp"]
 99  # Function for displaying images on HalloWing TFT screen
100  def show_image(filename):
101      # CircuitPython 6 & 7 compatible
102      image_file = open(filename, "rb")
103      odb = displayio.OnDiskBitmap(image_file)
104      face = displayio.TileGrid(
105          odb,
106          pixel_shader=getattr(odb, 'pixel_shader', displayio.ColorConverter())
107      )
108  
109      # # CircuitPython 7+ compatible
110      # odb = displayio.OnDiskBitmap(filename)
111      # face = displayio.TileGrid(odb, pixel_shader=odb.pixel_shader)
112  
113      backlight.duty_cycle = 0
114      splash.append(face)
115      board.DISPLAY.refresh(target_frames_per_second=60)
116      backlight.duty_cycle = max_brightness
117  
118  beep(1)  # startup beep
119  show_image(images[2])  # waiting display
120  print('Stabilizing')
121  countdown(3)
122  print('Ready')
123  blink(3, 0.2)
124  beep(3)  # ready beeps
125  triggered = False
126  ready = True
127  
128  show_image(images[3])  # ready display
129  
130  while True:
131      # Check PIR sensor
132      pir_value = pir.value
133      # Check touch button
134      ready = ready_button.value
135  
136      if pir_value and triggered is not True:
137          # PIR is detecting movement!
138          play_wave()
139          splash.pop()
140          show_image(images[0])
141          print('Triggered')
142          countdown(8)
143          blink(3, 0.2)
144          beep(1)
145          print('Please reset')
146          led.value = False
147          triggered = True
148          servo_ready()
149          splash.pop()
150          show_image(images[1])
151  
152      if ready:  # touch sensor has been pressed
153          beep(1)
154          splash.pop()
155          show_image(images[2])
156          countdown(8)
157          print('Ready.')
158          blink(3, 0.2)
159          beep(3)
160          splash.pop()
161          show_image(images[3])
162          triggered = False