from machine import Pin, PWM
import time
import random
class LED:
def __init__(self, pin_num, name):
self.name = name
self.led = Pin(pin_num, Pin.OUT)
def on(self):
self.led.value(1)
print(f"{self.name} LED is ON")
def off(self):
self.led.value(0)
print(f"{self.name} LED is OFF")
class UltrasonicSensor:
def __init__(self, trig_pin, echo_pin):
self.trig = Pin(trig_pin, Pin.OUT)
self.echo = Pin(echo_pin, Pin.IN)
def distance_cm(self):
# Send 10us pulse as per HC-SR04 datasheet
self.trig.low()
time.sleep_us(2)
self.trig.high()
time.sleep_us(10)
self.trig.low()
# Wait for echo to start
timeout = 30000
start_time = time.ticks_us()
while self.echo.value() == 0:
if time.ticks_diff(time.ticks_us(), start_time) > timeout:
return 1000
# Measure pulse duration
pulse_start = time.ticks_us()
start_time = time.ticks_us()
while self.echo.value() == 1:
if time.ticks_diff(time.ticks_us(), start_time) > timeout:
return 1000
pulse_end = time.ticks_us()
# HC-SR04 formula: distance = (duration / 2) / 29.1
pulse_duration = time.ticks_diff(pulse_end, pulse_start)
distance = (pulse_duration / 2) / 29.1
return distance
def is_covered(self, threshold=15):
dist = self.distance_cm()
print(f"Distance: {dist:.1f} cm")
return dist < threshold
class ServoController:
def __init__(self, pin_num):
self.pwm = PWM(Pin(pin_num))
self.pwm.freq(50)
def move(self, angle):
# Convert angle to duty cycle for MicroPython
# values below adjusted to servo being used
min_pulse_us = 600 # us for 0 degrees
max_pulse_us = 2400 # us for 180 degrees
# Calculate pulse width based on angle
pulse_us = min_pulse_us + (angle / 180) * (max_pulse_us - min_pulse_us)
# Convert microseconds to 16-bit duty cycle value for a 50Hz PWM
# (65535 / 20000) is the scaling factor for microseconds to duty_u16
duty_value = int(pulse_us * (65535 / 20000))
self.pwm.duty_u16(duty_value)
time.sleep(0.3)
def wave(self):
print("Servo waves! šÆ")
self.move(0)
time.sleep(0.3)
self.move(180)
time.sleep(0.3)
self.move(90)
#time.sleep(0.3)
class GameController:
def __init__(self, leds, sensor, servo):
self.leds = leds
self.sensor = sensor
self.servo = servo
self.score = 0
def turn_all_leds_off(self):
for led in self.leds:
led.off()
def start_game(self, rounds=5, initial_time=3.0, time_decrement=0.3):
print("š® Starting Whack-a-Light Game!")
print("Cover the ultrasonic sensor when an LED lights up!")
reaction_time = initial_time
for r in range(rounds):
print(f"\n--- Round {r+1}/{rounds} ---")
print(f"Reaction time allowed: {reaction_time:.1f}s")
self.play_round(reaction_time)
reaction_time = max(1.0, reaction_time - time_decrement)
print(f"\nšÆ Game Over! Final Score: {self.score}/{rounds}")
if self.score == rounds:
print("š Perfect score! Amazing!")
elif self.score >= rounds * 0.7:
print("ā Great job!")
else:
print("šŖ Keep practicing!")
def play_round(self, allowed_time):
self.turn_all_leds_off()
chosen_led = random.choice(self.leds)
print(f"Quick! Cover the sensor when {chosen_led.name} LED lights up!")
chosen_led.on()
start_time = time.ticks_ms()
success = False
reaction_time = 0
while time.ticks_diff(time.ticks_ms(), start_time) < allowed_time * 1000:
if self.sensor.is_covered(threshold=20):
success = True
reaction_time = time.ticks_diff(time.ticks_ms(), start_time) / 1000.0
break
time.sleep(0.05)
chosen_led.off()
if success:
print(f"ā
Success! Reaction time: {reaction_time:.2f}s")
self.score += 1
self.servo.wave()
else:
print("ā Too slow! No points this round.")
time.sleep(1)
def sensor_calibration():
"""Calibrate the sensor like in the image"""
sensor = UltrasonicSensor(trig_pin=7, echo_pin=8)
print("š§ Sensor Calibration (like the image)")
print("Place object at different distances...")
for i in range(5):
dist = sensor.distance_cm()
print(f"Measurement {i+1}: {dist:.1f} cm")
time.sleep(1)
def main():
# Initialize components (match your wiring)
leds = [
LED(20, "Red"),
LED(19, "Yellow"),
LED(18, "Green"),
LED(17, "Blue"),
LED(16, "White")
]
# MC-SR04 Ultrasonic Sensor (like in the image)
sensor = UltrasonicSensor(trig_pin=22, echo_pin=21)
# Servo motor
servo = ServoController(pin_num=9)
# Calibration test
print("=== MC-SR04 Distance Game ===")
sensor_calibration()
time.sleep(1)
# Start the complete simulation
game = GameController(leds, sensor, servo)
game.start_game(rounds=5)
print("\n" + "="*40)
print("Game finished! Reset to play again.")
if __name__ == "__main__":
main()