# Mausefalle
# by (c) 2023 Frank Schürmann / www.schuermann.ws
from machine import Pin, Timer
from time import sleep
from picozero import pico_led
from picozero import Servo # importing Servo class to easily control the servo motor
# Hardware and connections used:
# Servo GND to Raspberry Pi Pico GND
# Servo V+ to Raspberry Pi Pico 3.3 V
# Servo PWM pin to GPIO Pin 15
from machine import Pin, I2C # importing Display SSD1306 class
from ssd1306 import SSD1306_I2C
import framebuf, sys
import utime
# Pins LEDs
led_green = Pin(14, Pin.OUT, value=0)
led_red = Pin(13, Pin.OUT, value=0)
led_blue = Pin(12, Pin.OUT, value=0)
# Pins Buttons und Kontakte
button1 = Pin(1, Pin.IN, Pin.PULL_UP)
contact1 = Pin(5, Pin.IN, Pin.PULL_UP)
contact2 = Pin(9, Pin.IN, Pin.PULL_UP)
# Pin Servo / bzw. Magnetschalter / Auslösung Falle
servo_gate = Servo(15)
# Pins Ansteuerung und Auflösung Display SSD1306
display_scl_pin = 27
display_sda_pin = 26
display_res_x = 128
display_res_y = 64
# Globale Variablen
catch_status = 0
maingate_passed = 0
countdown_max = 12 # Countdown bis Falle nicht mehr aktiv ist in Stunden - Sicherheitsfunktion
# FUNKTIONEN ----------------------------------------------------------------
# FUNKTION INITIALISISERUNG DISPLAY
def display_init():
# Initialize I2C device
global display_scl_pin
global display_sda_pin
i2c_dev = I2C(1, scl=Pin(display_scl_pin), sda=Pin(display_sda_pin), freq=200000)
i2c_addr = [hex(ii) for ii in i2c_dev.scan()]
if not i2c_addr:
print('No I2C Display Found')
sys.exit()
else:
print("I2C Address : {}".format(i2c_addr[0]))
print("I2C Configuration: {}".format(i2c_dev))
return i2c_dev
#FUNKTION DISPLAY LÖSCHEN
def display_clear():
global display
display.fill(0)
display.show()
#FUNKTION SUESSES VIECH ANZEIGEN
def display_picture(motiv,xpos,ypos):
global display
# Bytearray generiert bei: https://www.digole.com/tools/PicturetoC_Hex_converter.php und https://www.donskytech.com/micropython-interfacing-with-ssd1306-oled-display/
# Motiv 1: Süße Maus anzeigen
if motiv == 1:
# Bytearray der Maus-Grafik
buffer = bytearray(b"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x20\x00\x00\x00\x00\x00\x00\x00\x00\x00\x80\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x00\x00\x00\x03\xfc\x00\x00\x00\x06\x00\x00\x00\x00\x0f\xfe\x00\x00\x00\x04\x00\x00\x00\x00\x1f\xff\x40\x00\x00\x08\x00\x00\x00\x00\x3f\xff\xb0\x00\x00\x18\x00\x00\x00\x00\x3f\xff\xf8\x00\x00\x18\x00\x00\x00\x00\x7f\xff\xd8\x00\x00\x30\x00\x00\x03\x00\x7f\xff\xdc\x00\x00\x30\x00\x01\xff\xfe\x7f\xff\xdc\x00\x00\x30\x00\x0f\xff\xff\x7f\xff\xdc\x00\x00\x30\x00\x3f\xff\xff\x7f\xff\xde\x00\x00\x60\x00\x7f\xff\xff\x7f\xff\xde\x00\x00\x60\x00\xff\xff\xff\x7f\xff\xdc\x00\x00\x60\x01\xff\xff\xff\xbf\xff\xfc\x00\x00\x60\x03\xff\xff\xff\xbf\xff\xbc\x00\x00\x60\x07\xfe\x3f\xff\xdf\xff\x78\x00\x00\x60\x07\xff\x8f\xff\xef\xff\xd8\x00\x00\x70\x0f\xff\xc7\xff\xfb\xff\xe0\x00\x00\x70\x0f\xff\xe7\xff\xff\xff\xf0\x00\x00\x30\x1f\xff\xe7\xff\xff\xff\xf8\x00\x00\x38\x1f\xff\xe7\xff\xff\xff\xfe\x00\x00\x38\x1f\xff\xf7\xff\xff\xff\xff\x00\x00\x1c\x1f\xff\xe7\xff\xff\xff\xdf\x80\x00\x1e\x1f\xff\xe7\xff\xff\xff\x8f\xc0\x00\x0f\x3f\xff\xef\xff\xff\xff\x8f\xe0\x00\x07\xff\xff\xde\x07\xff\xff\xff\xe0\x00\x01\xff\xff\xc1\xe1\xff\xff\xff\xe0\x00\x00\xff\xff\xff\xfc\xff\xff\xff\xde\x00\x00\x3f\xff\xff\xfe\xff\xff\xff\xde\x00")
# Framebuffer Class https://docs.micropython.org/en/latest/library/framebuf.html
fb = framebuf.FrameBuffer(buffer, 73, 32, framebuf.MONO_HLSB)
# Motiv 2: Käse anzeigen
elif motiv == 2:
# Bytearray der Käse-Grafik
buffer = bytearray(b"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x3f\xc0\x00\x00\x00\x00\x00\x00\x00\x00\xff\xfc\x00\x00\x00\x00\x00\x00\x00\x01\xfe\x0f\x80\x00\x00\x00\x00\x00\x00\x03\xfc\x07\xf0\x00\x00\x00\x00\x00\x00\x07\xfc\x07\xfc\x00\x00\x00\x00\x00\x00\x1c\x3e\x0f\xfe\x00\x00\x00\x00\x00\x00\x38\x3f\xff\x80\x00\x00\x00\x00\x00\x00\x7c\x3f\xe0\x03\x00\x00\x00\x00\x00\x01\xff\xfc\x00\x7f\x00\x00\x00\x00\x00\x03\xff\x80\x1f\xff\x00\x00\x00\x00\x00\x07\xf0\x03\xff\xff\x00\x00\x00\x00\x00\x1e\x00\x7f\xff\x1f\x00\x00\x00\x00\x00\x00\x0f\xff\xfe\x0f\x00\x00\x00\x00\x00\x01\xff\xff\xfe\x07\x00\x00\x00\x00\x00\x3f\xff\xff\xfc\x07\x00\x00\x00\x00\x00\x3f\xf8\x7f\xfe\x07\x00\x00\x00\x00\x00\x7f\xf8\x3f\xfe\x0f\x00\x00\x00\x00\x00\x3f\xf8\x3f\xff\x1f\x00\x00\x00\x00\x00\x1f\xf8\x3f\x1f\xff\x00\x00\x00\x00\x00\x0f\xf8\x7e\x1f\xff\x00\x00\x00\x00\x00\x0f\xfe\xfe\x0f\xff\x00\x00\x00\x00\x00\x0f\xff\xfe\x0f\xff\x00\x00\x00\x00\x00\x1f\x3f\xfe\x1f\xff\x00\x00\x00\x00\x00\x3e\x1f\xff\x3f\xfe\x00\x00\x00\x00\x00\x3c\x1f\xff\xff\xc0\x00\x00\x00\x00\x00\x3e\x1f\x9f\xf8\x00\x00\x00\x00\x00\x00\x3e\x3e\x0f\x00\x00\x00\x00\x00\x00\x00\x3f\xfe\x00\x00\x00\x00\x00\x00\x00\x00\x3f\xf8\x00\x00\x00\x00\x00\x00\x00\x00\x3f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x20\x00\x00\x00\x00\x00\x00\x00")
# Framebuffer Class https://docs.micropython.org/en/latest/library/framebuf.html
fb = framebuf.FrameBuffer(buffer, 73, 32, framebuf.MONO_HLSB)
# Motiv 3: Maus und Käse anzeigen
elif motiv == 3:
# Bytearray der Maus-Käse-Grafik
buffer = bytearray(b"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x3e\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\xe0\x00\x00\x00\x00\x00\x00\x00\x00\xf8\x38\x00\x00\x00\x00\x00\x00\x00\x03\xf8\x3f\x00\x00\x00\x00\x00\x00\x00\x06\x3c\xf0\x00\x00\x00\x00\x3f\x80\x00\x0e\x3f\x00\x00\x00\x00\x00\x3f\xd0\x00\x1f\xc0\x1f\x80\x20\x00\x00\x7f\xd0\x00\x78\x03\xff\x80\x40\x00\x20\x7f\xc8\x00\x00\x7f\xe3\x80\x40\x0f\xfe\x7f\xc8\x00\x0f\xff\xc1\x80\x40\x1f\xfe\x7f\xc8\x01\xfe\x7f\xc1\x80\x00\x3f\xff\x7f\xc8\x01\xfc\x3f\xe1\x80\x00\x7d\xff\x3f\x98\x00\xfc\x3c\xf7\x80\x00\xfc\x7f\x9f\x80\x00\xfe\x38\x7f\x80\x41\xfe\x3f\xcf\xe0\x00\x7f\xf8\x7f\x80\x41\xff\x3f\xff\xf0\x00\xef\xf8\x7f\x80\x61\xff\x3f\xff\xfc\x01\xc7\xfc\xfe\x00\x21\xff\x3f\xff\xce\x01\xc7\x9f\xc0\x00\x13\xfe\x63\xff\xcf\x01\xe7\x08\x00\x00\x0f\xfe\x00\xff\xff\x01\xfe\x00\x00\x00\x03\xff\xbc\xff\xfe\x41\xc0\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00")
# Framebuffer Class https://docs.micropython.org/en/latest/library/framebuf.html
fb = framebuf.FrameBuffer(buffer, 73, 32, framebuf.MONO_HLSB)
# Motiv 4: Sanduhr / Warte-Symbol anzeigen
elif motiv == 4:
# Bytearray der Sanduhr-Grafik
buffer = bytearray(b"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\xff\xff\xff\xe0\x00\x00\x00\x00\x00\x01\xff\xff\xff\xe0\x00\x00\x00\x00\x00\x00\x38\x00\x07\x00\x00\x00\x00\x00\x00\x00\x30\x00\x07\x00\x00\x00\x00\x00\x00\x00\x30\x00\x07\x00\x00\x00\x00\x00\x00\x00\x38\x00\x07\x00\x00\x00\x00\x00\x00\x00\x3f\xff\xff\x00\x00\x00\x00\x00\x00\x00\x3f\xff\xfe\x00\x00\x00\x00\x00\x00\x00\x1f\xff\xfe\x00\x00\x00\x00\x00\x00\x00\x1c\x00\x1e\x00\x00\x00\x00\x00\x00\x00\x0e\x00\x1c\x00\x00\x00\x00\x00\x00\x00\x0f\x00\x38\x00\x00\x00\x00\x00\x00\x00\x07\xc0\xf0\x00\x00\x00\x00\x00\x00\x00\x01\xe1\xe0\x00\x00\x00\x00\x00\x00\x00\x01\xe1\xe0\x00\x00\x00\x00\x00\x00\x00\x07\xc0\xf0\x00\x00\x00\x00\x00\x00\x00\x0f\x00\x38\x00\x00\x00\x00\x00\x00\x00\x0e\x00\x1c\x00\x00\x00\x00\x00\x00\x00\x1c\x1c\x1e\x00\x00\x00\x00\x00\x00\x00\x1c\x1e\x0e\x00\x00\x00\x00\x00\x00\x00\x38\x3f\x06\x00\x00\x00\x00\x00\x00\x00\x38\x7f\x87\x00\x00\x00\x00\x00\x00\x00\x38\xff\x87\x00\x00\x00\x00\x00\x00\x00\x31\xff\xc7\x00\x00\x00\x00\x00\x00\x00\x31\xff\xe7\x00\x00\x00\x00\x00\x00\x00\x73\xff\xf7\x00\x00\x00\x00\x00\x00\x01\xff\xff\xff\xe0\x00\x00\x00\x00\x00\x01\xff\xff\xff\xe0\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00")
# Framebuffer Class https://docs.micropython.org/en/latest/library/framebuf.html
fb = framebuf.FrameBuffer(buffer, 73, 32, framebuf.MONO_HLSB)
# Motiv 5: Error-Symbol anzeigen
elif motiv == 5:
# Bytearray der Error-Grafik
buffer = bytearray(b"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\x3e\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7e\x00\x00\x00\x00\x00\x00\x00\x00\x00\x77\x00\x00\x00\x00\x00\x00\x00\x00\x00\xe7\x00\x00\x00\x00\x00\x00\x00\x00\x00\xe3\x80\x00\x00\x00\x00\x00\x00\x00\x01\xc3\xc0\x00\x00\x00\x00\x00\x00\x00\x03\xc1\xc0\x00\x00\x00\x00\x00\x00\x00\x03\x81\xe0\x00\x00\x00\x00\x00\x00\x00\x07\x00\xe0\x00\x00\x00\x00\x00\x00\x00\x07\x18\x70\x00\x00\x00\x00\x00\x00\x00\x0e\x3c\x78\x00\x00\x00\x00\x00\x00\x00\x1e\x3e\x38\x00\x00\x00\x00\x00\x00\x00\x1c\x3c\x3c\x00\x00\x00\x00\x00\x00\x00\x3c\x3c\x1c\x00\x00\x00\x00\x00\x00\x00\x38\x3c\x0e\x00\x00\x00\x00\x00\x00\x00\x70\x1c\x0e\x00\x00\x00\x00\x00\x00\x00\x70\x1c\x07\x00\x00\x00\x00\x00\x00\x00\xe0\x1c\x07\x80\x00\x00\x00\x00\x00\x01\xe0\x1c\x03\x80\x00\x00\x00\x00\x00\x01\xc0\x1c\x03\xc0\x00\x00\x00\x00\x00\x03\xc0\x08\x01\xc0\x00\x00\x00\x00\x00\x03\x80\x1c\x00\xe0\x00\x00\x00\x00\x00\x07\x00\x1c\x00\xe0\x00\x00\x00\x00\x00\x07\x00\x18\x00\x70\x00\x00\x00\x00\x00\x0e\x00\x00\x00\x78\x00\x00\x00\x00\x00\x1c\x00\x00\x00\x38\x00\x00\x00\x00\x00\x1f\xff\xff\xff\xf8\x00\x00\x00\x00\x00\x0f\xff\xff\xff\xf8\x00\x00\x00\x00\x00\x0f\xff\xff\xff\xf0\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00")
# Framebuffer Class https://docs.micropython.org/en/latest/library/framebuf.html
fb = framebuf.FrameBuffer(buffer, 73, 32, framebuf.MONO_HLSB)
# Motiv 6: Alarmclock-Symbol anzeigen
elif motiv == 6:
# Bytearray der Wecker-Grafik
buffer = bytearray(b"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x60\x00\x03\x00\x00\x00\x00\x00\x00\x00\xe0\x00\x07\x80\x00\x00\x00\x00\x00\x01\xc0\x7f\x03\xc0\x00\x00\x00\x00\x00\x03\x83\xff\xc1\xe0\x00\x00\x00\x00\x00\x03\x07\xff\xf0\xc0\x00\x00\x00\x00\x00\x00\x1f\x00\x78\x00\x00\x00\x00\x00\x00\x00\x3c\x00\x3c\x00\x00\x00\x00\x00\x00\x00\x78\x00\x0e\x00\x00\x00\x00\x00\x00\x00\x70\x18\x07\x00\x00\x00\x00\x00\x00\x00\xe0\x1c\x07\x80\x00\x00\x00\x00\x00\x00\xc0\x18\x03\x80\x00\x00\x00\x00\x00\x01\xc0\x18\x01\x80\x00\x00\x00\x00\x00\x01\xc0\x18\x01\xc0\x00\x00\x00\x00\x00\x01\x80\x18\x01\xc0\x00\x00\x00\x00\x00\x01\x80\x1c\x00\xc0\x00\x00\x00\x00\x00\x01\x80\x1f\xf0\xc0\x00\x00\x00\x00\x00\x01\x80\x1f\xf0\xc0\x00\x00\x00\x00\x00\x01\x80\x00\x01\xc0\x00\x00\x00\x00\x00\x01\x80\x00\x01\xc0\x00\x00\x00\x00\x00\x01\xc0\x00\x01\xc0\x00\x00\x00\x00\x00\x01\xc0\x00\x03\x80\x00\x00\x00\x00\x00\x00\xe0\x00\x03\x80\x00\x00\x00\x00\x00\x00\xe0\x00\x07\x00\x00\x00\x00\x00\x00\x00\x70\x00\x0f\x00\x00\x00\x00\x00\x00\x00\x78\x00\x1e\x00\x00\x00\x00\x00\x00\x00\x3c\x00\x3c\x00\x00\x00\x00\x00\x00\x00\x0f\x00\xf8\x00\x00\x00\x00\x00\x00\x00\x07\xff\xf0\x00\x00\x00\x00\x00\x00\x00\x01\xff\xc0\x00\x00\x00\x00\x00\x00\x00\x00\x3c\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00")
# Framebuffer Class https://docs.micropython.org/en/latest/library/framebuf.html
fb = framebuf.FrameBuffer(buffer, 73, 32, framebuf.MONO_HLSB)
display.blit(fb, xpos, ypos)
display.show()
# FUNKTION SERVO UND LEDs ZURÜCKSETZEN
def reset():
global maingate_passed
global catch_status
servo_gate.mid()
led_green.off()
led_blue.off()
led_red.off()
catch_status = 0
maingate_passed = 0
# FUNKTION SHOW STANDBY & EINWANDFREIE FUBKTION ANZEIGEN
def standby():
print ("Warten auf Aktivierung der Falle")
global display
error = True
while button1.value() == 1:
# Bereitschaft - grüne LED blinkt
if contact1.value() == 1 and contact2.value() == 1:
if error == True:
error = False
# Display Text ausgeben
display_clear()
display.text("OK - Warte", 5, 5)
display.text("auf Aktivierung", 5, 15)
display.show()
display_picture(4,25,31) # Sanduhr-Bild darstellen: Motivnummer, X-Position, Y-Position
led_green.on()
sleep(0.5)
led_green.off()
sleep(0.5)
# Bei Störung von contact1 Fehlercode 1 x rot blinken
elif contact1.value() == 0 and contact2.value() == 1:
error = True
# Display Text ausgeben
display_clear()
display.text("ERROR", 5, 5)
display.text("Sensor 1", 5, 15)
display.show()
display_picture(5,25,31) # Error-Bild darstellen: Motivnummer, X-Position, Y-Position
led_red.on()
sleep(0.5)
led_red.off()
sleep(0.5)
# Bei Störung von contact2 Fehlercode 2 x rot blinken
elif contact1.value() == 1 and contact2.value() == 0:
error = True
# Display Text ausgeben
display_clear()
display.text("ERROR", 5, 5)
display.text("Sensor 2", 5, 15)
display.show()
display_picture(5,25,31) # Error-Bild darstellen: Motivnummer, X-Position, Y-Position
led_red.on()
sleep(0.2)
led_red.off()
sleep(0.2)
led_red.on()
sleep(0.2)
led_red.off()
sleep(0.5)
# FUNKTION FALLE SCHARF
def trap_armed():
global maingate_passed
global catch_status
global start_time
global countdown_max
led_green.on()
print ("Falle scharf gestellt")
# Display Texte ausgeben
global display
display_clear()
display.text("FALLE SCHARF", 5, 5)
display.text("GESTELLT!", 5, 15)
display.show()
display_picture(2,70,31) # Käse-Bild darstellen: Motivnummer, X-Position, Y-Position
# Warten auf Maus - Alarmkontakte-Auswertung
while catch_status == 0:
if contact1.value() == 0 and contact2.value() == 1 and maingate_passed == 0:
led_green.off()
led_red.off()
led_blue.on()
maingate_passed = 1
print ("Falle betreten")
# Display Texte ausgeben
global display
display_clear()
display.text("FALLE BETRETEN", 5, 5)
display.text("", 5, 15)
display.show()
display_picture(3,25,31) # Maus-Käse-Bild darstellen: Motivnummer, X-Position, Y-Position
elif contact1.value() == 1 and contact2.value() == 0 and maingate_passed == 1:
led_green.off()
led_blue.off()
led_red.on()
print ("AUSLÖSUNG")
catch_status = 1
else: #Sicherheits-Timer
trap_countdown = (utime.ticks_diff(utime.ticks_ms(), start_time) // 1000) + 1 # Sekunden seitdem Falle aktiv ist
trap_countdown = (countdown_max * 60 * 60) - trap_countdown # Countdown Rückwärts
if trap_countdown <= 0: # Wenn der Countdown abgezählt ist, dann Abbruch und Falle sichern!
catch_status = 2
else:
# Vorherige Zeit im Grafikcache löschen indem ein schwarzes Rechteck über die Zeit gelegt wird
display.fill_rect(5, 25, display.width - 5, 8, 0)
# Neue Zeit / Countdown anzeigen
trap_min, trap_sec = divmod(trap_countdown, 60)
trap_hour, trap_min = divmod(trap_min, 60)
display.text(str(trap_hour) + ":" + str(trap_min) + ":" + str(trap_sec), 5, 25)
display.show()
# FUNKTION MAUS GEFANGEN
def guest_catched():
servo_gate.max()
print ("GEFANGEN!")
# Display Texte ausgeben
global display
display_clear()
display.text("FALLE", 5, 5)
display.text("AUSGELOEST!", 5, 15)
display.show()
display_picture(1,25,31) # Maus-Bild darstellen: Motivnummer, X-Position, Y-Position
print ("Email send")
# FUNKTON NEUSTART
def restart():
print ("Warten auf Neustart")
while button1.value() == 1:
sleep(3)
while button1.value() == 0:
sleep(1)
print ("Neustart")
# MAIN PROGRAM --------------------------------------------------------------
# Display initialisieren
i2c_dev = display_init()
display = SSD1306_I2C(display_res_x, display_res_y, i2c_dev)
# Hauptprogramm
while True:
# Globaler Reset
reset()
# Warten auf Aktivierung
standby()
# Falle scharf gestellt & Warten auf Maus
start_time = utime.ticks_ms() # Zeitpunkt des Startes sichern
trap_armed()
# Gefangen!
guest_catched()
# Warten auf Neustart - 3 Sekunden Status-Button drücken!
restart()