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 third project in our adventure in electronics. It uses an push button sensor as a reaction timer game with a Lego compatible servo connected to a trap door that could send a minifig plunging down into a shark infested piranha pool.
The pico explorer screen says “Get ready” for a random amount of time. As soon as the screen goes red, you have to press the button as soon as you can. If you’re fast enough, the minifig lives to play another round. If you’re too slow (or too fast and try to cheat) the servo opens the trapdoor and the minifigure slides down to meet a sticky end.
About the sensor
The push 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)* |
* Whilst the breakout board labels the + and – pins as shown in the table above, I had more success when swapping the power and ground round as shown in the schematic below and the video above. When the push button is pressed, a connection is made between pins 1 and 3. The middle pin is connected to a resistor that can be a pull up or pull down resistor depending on whether you connect up the switch as shown in the table above or in the schematic below.
The circuit
The servo is connected to a Lego trap door as shown below:
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 it says “Get ready” for a random amount of time (between 1 and 3 seconds) then the edge of the screen goes red to indicate that you need to press the button. If you press the button too soon (before the screen goes red) or too late (or not at all) then the servo opens the trapdoor and the Lego minifig falls to its watery doom.
"""
Adventures in Electronics
* Firmware:
- CircuitPython v9.2.1
* Hardware:
- Raspberry pi pico in pico explorer board
- Servo
Pin1 (Orange => GP1)
Pin2 (Red => 3v3)
Pin3 (Brown => GND)
- Push switch (note inverse polarity)
Pin1 (GND => 3v3)
Pin2 (VCC => GND)
Pin3 (S => GP0)
* Description:
Reaction timer trap door of doom:
Pico explorer board will display "Get ready" for a random amount of time
As soon as the screen goes red, you have to press the button. If you're too slow the servo will
open a Lego trapdoor
"""
import picoexplorer
import time
import random
import board
import pwmio
from digitalio import DigitalInOut, Direction, Pull
from adafruit_motor import servo
TIME_TOO_SLOW = 2
TIME_MAX_WAIT = 5
# Set up button
btn = DigitalInOut(board.GP0)
btn.direction = Direction.INPUT
btn.pull = Pull.UP
# Set up servo
pwm = pwmio.PWMOut(board.GP1, duty_cycle=2 ** 15, frequency=50)
trapdoor_servo = servo.Servo(pwm)
# Open Lego servo trapdoor of doom
def open_trapdoor():
trapdoor_servo.angle = 0
time.sleep(1)
trapdoor_servo.angle = 90
# Make sure trapdoor is closed
def close_trapdoor():
trapdoor_servo.angle = 180
time.sleep(2)
trapdoor_servo.angle = 90
picoexplorer.init()
close_trapdoor()
while True:
picoexplorer.set_line(3, "Get ready")
picoexplorer.set_line(4, "")
# random delay before pressing button
delay = random.randint(10,30) / 10
start_time = time.monotonic()
duration = 0
# make sure button isn't pressed too soon
while duration < delay:
time.sleep(0.05)
duration = time.monotonic() - start_time
if btn.value:
picoexplorer.set_line(4, "Cheat!")
open_trapdoor()
# Go!
picoexplorer.set_color(picoexplorer.COLORS_BACKGROUND_OUTER, 0xFF0000)
picoexplorer.set_line(3, "Press button!")
# Time how long it takes to press button
start_time = time.monotonic()
while not btn.value:
time.sleep(0.05)
duration = time.monotonic() - start_time
# don't wait for too long
if duration > TIME_MAX_WAIT:
break
# display time
picoexplorer.set_color(picoexplorer.COLORS_BACKGROUND_OUTER, 0x000000)
picoexplorer.set_line(3, "Time: {:.2f}s".format(duration))
# open the trapdoor if they take too long
if duration > TIME_TOO_SLOW:
picoexplorer.set_line(4, "Too slow!")
open_trapdoor()
close_trapdoor()
# if button is pressed soon enough, keep the trapdoor closed for another try
else:
picoexplorer.set_line(4, "Well done!")
time.sleep(2)
Link to code (including the picoexplorer module and other required libraries) here.
There’s also some micropython code just to read from the sensor here.