Adventures with Electronics is a father and son project to learn how to connect up and code 37 different electronic sensors using a Raspberry Pi Pico.
After setting up the software and firmware needed to write python code on a Raspberry Pi Pico, this is the forth project in our adventure in electronics. It uses a tilt sensor as a car alarm for a Lego vehicle with a 4×3 keypad to enable or disable the alarm.
About the sensor
The tilt sensor button breakout has three pins.
Pin number | Name | Description |
1 | S | Signal (connect to GPIO port) |
2 | VCC | Power supply (3.3v or 5v) |
3 | – | Ground (0v) |
The keypad had an unusual pinout and may well be different to one that you have. I got mine from AliExpress for around £1:
Pin number | Name | Description |
1 | C2 | Keypad column 2 (keys 2, 5, 8 and 0) |
2 | R1 | Keypad row 1 (keys 1, 2 and 3) |
3 | C1 | Keypad column 1 (keys 1, 4, 7 and *) |
4 | R4 | Keypad row 4 (keys *, 0 and #) |
5 | R3 | Keypad row 3 (keys 7, 8 and 9) |
6 | C3 | Keypad column 3 (keys 3, 6, 9 and #) |
7 | R2 | Keypad row 2 (keys 4, 5 and 6) |
The circuit
Note that on the pico explorer board the piezo speaker was connected to GP8 which is also used by the motor controller (labelled Motor 1+ on the pico explorer board). This is because there weren’t enough unused general purpose input and output pins available.
The servo we should have used is a GeekServo Lego Compatible servo but we don’t have one of those yet. That would allow us to control the exact angle of the trap door. Instead, we used a continuous rotation servo which runs more like a motor, continuously rotating as the name would suggest. Using a servo rather than a motor means we don’t have to use a h bridge motor driver to protect the pico as you would for a motor but the continuous rotation means that the only way of opening or closing the trap door is to make the servo on for a set amount of time and hope that it rotates fully. The Lego model restricts the trapdoor from opening or closing too much so the timings set in code should be plenty of time to allow for this.
The code
When the program starts the alarm is active so any vibration detected by the tilt sensor will set off the alarm.
To disable the alarm you can enter the pin (1234) on the keypad. Any other pin (re)enables the alarm.
"""
* Firmware:
- CircuitPython 9.2.1
* Hardware:
- Raspberry Pi Pico v1
- Piezo speaker
GP21 => Speaker
- Keypad
Pin 1 (Col 2) => GP1
Pin 2 (Row 1) => GP2
Pin 3 (Col 1) => GP3
Pin 4 (Row 4) => GP4
Pin 5 (Row 3) => GP5
Pin 6 (Col 3) => GP6
Pin 7 (Row 2) => GP7
- Hit sensor
Pin 1 (Signal) => GP0
Pin 2 (VCC) => Power
Pin 3 (GND) => Ground
* Description:
Asks user to enter a 4 digit pin to disable alarm (correct pin is 1234)
If alarm is enabled it sounds if the tilt sensor detects vibrations
"""
import pwmio
import board
import time
import picoexplorer
import keypad
import digitalio
picoexplorer.init()
picoexplorer.i2c.deinit()
""" Pins for Keypad:
GP1 GP2 GP3 GP4 GP5 GP6 GP7
C2, R1, C1, R4, R3, C3, R2
"""
rows_pins = (board.GP2, board.GP7, board.GP5, board.GP4)
cols_pins = (board.GP3, board.GP1, board.GP6)
keys = keypad.KeyMatrix(row_pins=rows_pins, column_pins=cols_pins)
KEYS = "123456789*0#"
# Replace with your own pin
pin_correct = "1234"
# Set up tilt switch
switch = digitalio.DigitalInOut(board.GP0)
switch.direction = digitalio.Direction.INPUT
switch.pull = digitalio.Pull.DOWN
# mario tune in musical notes and rests
tune = "E E _ E _ C E _ G"
# Create piezo buzzer PWM output.
buzzer = pwmio.PWMOut(board.GP21, variable_frequency=True)
picoexplorer.play_tune(buzzer, tune, duty_cycle=5)
pin = ""
alarm_set = True
previous_switch_value = switch.value
while True:
# check if keypad key is pressed
e = keys.events.get()
if e and e.pressed:
pin += KEYS[e.key_number]
# Assume pin has 4 digits - check if correct
if len(pin) == 4:
if pin == pin_correct:
alarm_set = False
picoexplorer.play_tune(buzzer, "C G")
else:
alarm_set = True
picoexplorer.play_tune(buzzer, "G C")
pin = ""
else:
picoexplorer.play_tune(buzzer, "C")
previous_switch_value = switch.value
# Update alarm status
if alarm_set:
picoexplorer.set_line(3, "Alarm active")
if switch.value != previous_switch_value:
picoexplorer.set_line(3, "ALARM!")
picoexplorer.play_tune(buzzer, "B " * 20)
previous_switch_value = switch.value
else:
picoexplorer.set_line(3, "Alarm disabled")
previous_switch_value = switch.value
pin_masked = "*" * len(pin)
picoexplorer.set_line(4, "Pin: [{:4}]".format(pin_masked))
time.sleep(0.1)
Code language: PHP (php)
Link to code (including the picoexplorer module and other required libraries) here.