Gone Fishin'- a Simple Fishing Game
by carbonmk in Circuits > Raspberry Pi
129 Views, 1 Favorites, 0 Comments
Gone Fishin'- a Simple Fishing Game
This build is a simple fishing game powered by a Raspberry Pi Pico W that uses a proximity sensor and a continuous servo to play the game. It is connected to Adafruit IO, so it can easily be controlled from your computer. A user first presses the "Cast" button which spins the servo, releasing some slack so the fishing line can drop toward the proximity sensor. When the hook gets close enough, you will hear a bubbling noise, and at that point click on the "Reel" button. This means you have caught a fish, and will hear Mikey the Angler tell you what fish you just caught. Depending on the temperature of the room, the kind of fish you can potentially catch also changes!
Supplies
Electronics:
Pico W
Speaker
Adafruit APDS9960- proximity sensor
Adafruit mcp9808- temperature sensor
A continuous servo motor
A speaker that has an audio plug
2 Alligator to pin clips
9 Pin wires
Stemma QT plug with pins on the end
Stemma QT to Stemma QT wire
An Adafruit microSD SPI reader (pins already soldered on).
An SD card (32 gigabytes or less)
A USB cable (to power the microcontroller)
1 Battery pack
Other materials:
Wooden Box to hold our components
Some sort of tank on the top (here I used laser cut acrylic and glued them together)
A miniature fishing rod
Some sort of strong string like a fishing wire
SD Card reader for your computer
Additional ocean themed decorations of your choice (optional)
Some sort of weight that can be attached to your fishing wire
A spool to help wind and unwind the string.
Wire the Pico W and Speaker
1- Take one of the alligator to pin clips and connect the pin to any ground on the Pico.
2- Connect the alligator clip to the base of the audio jack cable.
3- Take the other alligator to pin clips and connect the pin to GP16 (or your preferred pin) on the Pico.
4- Connect the alligator clip to the tip of the audio jack cable.
5- If applicable, make sure to turn on the speaker.
The speaker will play the audio files which are needed for the game and tells you what fish you caught.
Wire the Pico W and Adafruit SD Card Reader
1- Using the SD card reader for your computer, make a new folder on the SD card and load any sounds you want into that folder. Make sure to remember the name of the folder as this will be the path for your sounds in the code.
2- If applicable, make sure to solder the pins onto your Adafruit SD card reader.
3- Take a pin-to-pin wire and connect it to 3.3 Volts on the Pico W and the 3V slot on the SD Card reader.
4- Using another pin-to-pin wire, connect it to any ground on the Pico W and the ground slot on the SD card reader.
5- Connect a pin-to-pin wire to GP10, which is SCK, to CLK slot on the SD Card reader.
6- Connect a pin-to-pin wire to GP11, which is SI or TX, to the “DO SO” slot on the SD card reader.
7- Connect a pin-to-pin wire to GP12, which is SO or RX, to the “CMD SI” slot on the SD card reader.
8- Connect a pin-to-pin wire to GP13, which is CS, to the “DE CS” slot on the SD card reader.
9- Finally, insert the SD card into the slot, you will hear a click when the SD Card is properly inserted.
Wire the Pico W, Mcp9808, and APDS9960
1- Plug the Stemma QT side of the Stemma QT-to-pins wire into the mcp9808.
2- The yellow wire is SCL which is connected to GP5 on the Pico.
3- The blue wire is SDA and is connected to GP4 on the Pico.
4- The red wire is power which is connected to 3.3 Volts out, not VBUS!
5- The black wire is ground which is connected to any ground on the Pico W.
6- Now that the Stemma QT is connected to the Pico, using the Stemma QT-to-Stemma QT wire, connect the mcp9808 and APDS9960
Wire the Pico W and Servo
1- Connect a pin-to-pin wire to the red wire on the servo then connect that to VBUS.
2- Connect a pin-to-pin wire to the brown wire on the servo then connect that to any ground
3- Connect a pin-to-pin wire to the orange wire on the servo then connect that to GP15 (or any other signal pin you wish)
The finished wiring should like something the image shows.
Assembling the Box and Tank
There is no specific way how to do this, just make sure the bottom of your tank has a hole that the APDS9960 can be able to read proximity from. Make sure this hole is the same size as the one in the top of your box so you can line them up, then APDS9960 can be taped to face out of both holes.
Code
I have pasted the code and also attached a file for convenience:
import time, board, digitalio, pwmio, adafruit_mcp9808, random, os, ssl, socketpool, wifi, mount_sd
from adafruit_motor import servo
import adafruit_minimqtt.adafruit_minimqtt as MQTT
from adafruit_apds9960.apds9960 import APDS9960
from audiopwmio import PWMAudioOut as AudioOut
from audiomp3 import MP3Decoder
# Configure the servo
servo_pin = board.GP15
pwm = pwmio.PWMOut(servo_pin, frequency=50)
my_servo = servo.ContinuousServo(pwm)
# Configure the prox sensor
i2c = board.STEMMA_I2C()
multi_sensor = APDS9960(i2c)
multi_sensor.enable_proximity = True
# Configure the temp sensor
temp_sensor = adafruit_mcp9808.MCP9808(i2c)
# Confgigure the speaker:
audio = AudioOut(board.GP16) # assuming tip of Audio pin to GP16
path = "/sd/fish_sounds/"
sound_playing = False
# set up the mp3 decoder
filename = "boat.mp3"
mp3_file = open(path + filename, "rb")
decoder = MP3Decoder(mp3_file)
# function to play an mp3 file
def play_mp3(filename):
global sound_playing
try:
decoder.file = open(path + filename, "rb")
audio.play(decoder)
sound_playing = True
except OSError as e:
if e.errno != 2: # If the error is not related to the file not being found, print it
print(f"Error: {e}")
# Temperature is returned in degrees celsius. Formula for conversion to degrees fahrenheit also shown below:
tempC = temp_sensor.temperature
tempF = tempC * 9 / 5 + 32
def move_servo(throttle):
my_servo.throttle = throttle
# variables
is_reeling = False
last_button_press_time = 0
warm = 72
warm_fish = ["Mahi-Mahi", "Tuna", "Marlin", "Sailfish", "Barracuda"]
cool_fish = ["Salmon", "Trout", "Cod", "Mackerel", "Tilapia"]
def get_random_fish(tempF, warm, warm_fish, cool_fish):
if tempF >= warm:
return random.choice(warm_fish)
elif tempF < warm:
return random.choice(cool_fish)
else:
return None
caught_fish = None
bubbling_start_time = None
caught_fish_during_bubbling = False
def is_proximity_minimal():
proximity_value = multi_sensor.proximity
print(f"Proximity value: {proximity_value}") # Debug print for distance sensor
minimal_distance_threshold = 230 # You can change this value based on your requirements
minimal_proximity = proximity_value >= minimal_distance_threshold
if minimal_proximity:
play_mp3("bubbling.mp3")
return minimal_proximity
# Get adafruit io username and key from settings.toml
aio_username = os.getenv('AIO_USERNAME')
aio_key = os.getenv('AIO_KEY')
# Setup a feed: This may have a different name than your Dashboard
fish_feed = aio_username + "/feeds/fish-feed"
# Setup functions to respond to MQTT events
def connected(client, userdata, flags, rc):
# Connected to broker at adafruit io
print("Connected to Adafruit IO! Listening for topic changes in feeds I've subscribed to")
# Subscribe to all changes on the feed.
client.subscribe(fish_feed)
def disconnected(client, userdata, rc):
# Disconnected from the broker at adafruit io
print("Disconnected from Adafruit IO!")
def message(client, topic, message):
global sound_playing, bubbling_start_time, caught_fish_during_bubbling
print(f"topic: {topic}, message: {message}")
if topic == fish_feed:
if message == "cast":
move_servo(-1.0)
time.sleep(3) # Wait for 3 seconds
move_servo(0) # Stop the servo
proximity_value = multi_sensor.proximity
if proximity_value > 230: # Check if the proximity is close
play_mp3("bubbling.mp3")
bubbling_start_time = time.monotonic() # Set the bubbling_start_time
sound_playing = True
elif message == "reel" and sound_playing:
move_servo(1.0)
time.sleep(3) # Wait for 3 seconds
move_servo(0) # Stop the servo
if sound_playing and (time.monotonic() - bubbling_start_time) <= 6.43: # Check if the sound is playing and if the reel button was pressed within the sound duration
tempF = temp_sensor.temperature * 9 / 5 + 32 # Update the temperature value
caught_fish = get_random_fish(tempF, warm, warm_fish, cool_fish)
if caught_fish:
audio.stop()
print(f"You caught a {caught_fish}!")
play_mp3(f"{caught_fish}.mp3")
else:
print("No fish caught this time. Keep trying!")
sound_playing = False # Reset the sound_playing variable
bubbling_start_time = None
elif message == "0":
move_servo(0)
# Connect to WiFi
# Connect to wifi
print("Connecting to wifi")
wifi.radio.connect(os.getenv("WIFI_SSD"), os.getenv("WIFI_PASSWORD"))
print("COnnected")
# Create a socket pool
pool = socketpool.SocketPool(wifi.radio)
# Set up a MiniMQTT Client - this is our current program that subscribes or "listens")
mqtt_client = MQTT.MQTT(
broker=os.getenv("BROKER"),
port=os.getenv("PORT"),
username=aio_username,
password=aio_key,
socket_pool=pool,
ssl_context=ssl.create_default_context(),
)
# Setup the "callback" mqtt methods above
mqtt_client.on_connect = connected
mqtt_client.on_disconnect = disconnected
mqtt_client.on_message = message
broker=os.getenv("BROKER")
port=os.getenv("PORT")
username=aio_username
password=aio_key
socket_pool=pool
ssl_context=ssl.create_default_context()
print(f"{aio_username}, {aio_key}, {pool}, {port}, {broker}")
# Setup the "callback" mqtt methods above
mqtt_client.on_connect = connected
mqtt_client.on_disconnect = disconnected
mqtt_client.on_message = message
# Connect to the MQTT broker (adafruit io for us)
print("Connecting to Adafruit IO...")
mqtt_client.connect()
while True:
mqtt_client.loop()