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 numberNameDescription
1SSignal (connect to GPIO port)
2VCCPower supply (3.3v or 5v)
3Ground (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:

Keypad pinout
Pin numberNameDescription
1C2Keypad column 2 (keys 2, 5, 8 and 0)
2R1Keypad row 1 (keys 1, 2 and 3)
3C1Keypad column 1 (keys 1, 4, 7 and *)
4R4Keypad row 4 (keys *, 0 and #)
5R3Keypad row 3 (keys 7, 8 and 9)
6C3Keypad column 3 (keys 3, 6, 9 and #)
7R2Keypad row 2 (keys 4, 5 and 6)

The circuit

Tilt sensor and keypad car alarm with a raspberry pi pico
Tilt sensor and keypad car alarm with a raspberry pi pico

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.