from machine import Pin, PWM, Timer
from time import sleep, ticks_ms, ticks_diff
#set up morsecode button
morseButton = Pin(16, Pin.IN, Pin.PULL_UP)
#set up rotatorbutton
rotatorButton = Pin(17, Pin.IN, Pin.PULL_UP)
#set up the buzzer
buzzer = PWM(Pin(28))
frequency = 200
#set up a light
blueLED = Pin(13, Pin.OUT)
redLED = Pin(14, Pin.OUT)
greenLED = Pin(15, Pin.OUT)
#measuring time of the press
start_time = None
end_time = None
#defining the servo
servo1 = PWM(Pin(11))
servo1.freq(50)
#servo1.duty_u16(4850) # Set to 180deg
sleep(0.2)
#defining the stepper motor pins
stepPin = Pin(19, Pin.OUT) #used to control the stepping of the motor.
dirPin = Pin(18, Pin.OUT) #used to set the direction of the stepper motor,
steps_per_revolution = 200 #defines the number of steps the motor should take for a full revolution.
timer = Timer() #timer object used to control the rate of stepping.
#https://how2electronics.com/control-stepper-motor-with-a4988-raspberry-pi-pico/
#practice sequence
sequence = [1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1]
#data structure for storing the morese symbols user inputs
userinput = []
#setting answers to game questions
answer1 = "....- ..---" #42
answerA = ".--. .-. --- --. .-. . ... ..." #Progress
answerB = "-.. --- --- --" #Doom
answerC = ".-. . ... - .- .-. -"
answerD = ".- -.. .- .--. -" #adapt
#function to write the dot or dash into userinput list.
def writeDitOrDash(start_time, end_time, space):
from time import ticks_diff # getting libraries into the function
elapsedTimePress = ticks_diff(end_time, start_time) # setting up the measure for time between press and release.
print("Elapsed time:", elapsedTimePress, "ms")
print("time between presses:", space)
short = 60 # milliseconds 1 second #setting the measure of what time a dot takes
longer = 180 # milliseconds 3 seconds
verylong = 300
toolong = 500 #setting the measure of what time a dash takes
if start_time is None or end_time is None: #if start_time is not started. but it wil be in the while loop in main program. and end time also will have value.
return # if user doesnt press the endtime will start but no startime there this will exit function with no action.
elif elapsedTimePress < short:
print("pressed too short")
return
elif short < elapsedTimePress <= longer: #the measure ,for (pressed for a short time), is 'short'
if space is not None and space >= toolong:
userinput.append(" ")
userinput.append(".")
stop = False
return stop
else:
userinput.append(".")
stop = False
return stop
elif longer < elapsedTimePress <= verylong : #the measure for (pressed for a longer time) is 'longer'
if space is not None and space >= toolong:
userinput.append(" ")
userinput.append("-")
stop = False
return stop
else:
userinput.append("-")
stop = False
return stop
else:
print("pressed too long. end of word") # this held down ends the word.
#this needs to break the whiel true loop
#return a value eg the string STOP
stop = True
space = None
return stop
#function for ditsound
def ditSoundAndLED(buzzer, led):
buzzer.duty_u16(int(20000)) # this wont matter - bnecause its an activatrd buzzer. just needs any signal.
buzzer.freq(200) # this needed for sound to come out.
led.value(1)
sleep(0.06) ## keeps its on
buzzer.duty_u16(0) #turns it off
led.value(0)
sleep(0.06) # keeps it off
#function for dash sound
def dashSoundAndLED(buzzer, led):
# from machine import Pin, PWM
# from time import sleep
buzzer.duty_u16(int(20000))
buzzer.freq(200)
led.value(1)
sleep(0.18)
buzzer.duty_u16(0)
led.value(0)
sleep(0.06)
def message2(buzzer, blueLED):
from machine import Pin, PWM
from time import sleep
def dashSoundAndLED(buzzer, led):
buzzer.duty_u16(int(20000))
buzzer.freq(200)
led.value(1)
sleep(0.18)
buzzer.duty_u16(0)
led.value(0)
sleep(0.06)
def ditSoundAndLED(buzzer, led):
buzzer.duty_u16(int(20000)) # this wont matter - bnecause its an activatrd buzzer. just needs any signal.
buzzer.freq(200) # this needed for sound to come out.
led.value(1)
sleep(0.06) ## keeps its on
buzzer.duty_u16(0) #turns it off
led.value(0)
sleep(0.06) # keeps it off
dashSoundAndLED(buzzer, blueLED)
ditSoundAndLED(buzzer, blueLED)
dashSoundAndLED(buzzer, blueLED)
ditSoundAndLED(buzzer, blueLED)
sleep(0.18)
ditSoundAndLED(buzzer, blueLED)
ditSoundAndLED(buzzer, blueLED)
ditSoundAndLED(buzzer, blueLED)
ditSoundAndLED(buzzer, blueLED)
sleep(0.18)
dashSoundAndLED(buzzer, blueLED)
dashSoundAndLED(buzzer, blueLED)
dashSoundAndLED(buzzer, blueLED)
sleep(0.18)
dashSoundAndLED(buzzer, blueLED)
dashSoundAndLED(buzzer, blueLED)
dashSoundAndLED(buzzer, blueLED)
sleep(0.18)
ditSoundAndLED(buzzer, blueLED)
ditSoundAndLED(buzzer, blueLED)
ditSoundAndLED(buzzer, blueLED)
sleep(0.18)
ditSoundAndLED(buzzer, blueLED)
#function to check how long buzzer held down for
def exitMessage(start_time, end_time):
from time import ticks_diff # getting libraries into the function
elapsedTimePress = ticks_diff(end_time, start_time) # setting up the measure for time between press and release.
toolong = 500 #setting the measure of what time a pressed button takes to exit the message
if start_time is None or end_time is None: #if start_time is not started. but it wil be in the while loop in main program. and end time also will have value.
return # if user doesnt press the endtime will start but no startime there this will exit function with no action.
elif elapsedTimePress < toolong: # if press not long enough ignore and carry on
stop = False
return stop
elif elapsedTimePress >= toolong: # if press is long enough then do these things
print("pressed for too long. Exiting message") # this held down ends the message
#return a value eg the boolean STOP
stop = True
return stop
else:
print("pressed too short")
#function for opening the thing - servo
def servoOperation(servo, position):
servo.duty_u16(position)
sleep(0.025)
#functions for the stepper motor
def step(stepPin):
stepPin.value(not stepPin.value())
#toggles the value of step_pin, effectively sending a pulse to the stepper motor to make a step. This function will be used as a callback for the timer.
#https://how2electronics.com/control-stepper-motor-with-a4988-raspberry-pi-pico/
def rotate_motor(delay, timer):
timer.init(freq=delay)
#his function initializes the timer with a frequency calculated from the input delay, and sets it to the PERIODIC mode, meaning it will trigger at fixed intervals. The step function is passed as a callback, so it will be executed each time the timer triggers.
#https://how2electronics.com/control-stepper-motor-with-a4988-raspberry-pi-pico/
def stepperMotor(dirPin, steps_per_revolution, timer, stepPin):
import machine
import time
while True:
# Set motor direction clockwise
dirPin.value(1)
# Spin motor slowly
rotate_motor(2000, timer)
time.sleep_ms(steps_per_revolution)
timer.deinit() # stop the timer
time.sleep(1)
# Set motor direction counterclockwise
dirPin.value(0)
# Spin motor quickly
rotate_motor(1000, timer)
time.sleep_ms(steps_per_revolution)
timer.deinit() # stop the timer
time.sleep(1)
#the main loop of the script. It continuously rotates the motor in one direction at a slower speed, then in the other direction at a faster speed. It does this by first setting the direction pin, then starting the motor rotation with the rotate_motor function. It then waits for a time equal to the number of milliseconds it takes for the motor to complete a full revolution, stops the timer, waits for another second, and then repeats the process in the opposite directio
#https://how2electronics.com/control-stepper-motor-with-a4988-raspberry-pi-pico/
#program
print("programm running")
## you need tro figure out how to set the lingth of a press with out time functions see whatis availabkle and fidhure oit ot.
#-----------------------------------------------------------------------------------------------
# stop = False
# last_release_time = None
# #activity 1 - enter 42 as morse code
# while True:
# while True:
# #this takes in the user answer and build the userinput.
# if morseButton.value() == 0:
# print("Button state:", morseButton.value())
# blueLED.value(1)
# buzzer.duty_u16(int(65536*0.2)) ##activate buzzer
# buzzer.freq(frequency)
# sleep(0.01)
# start_time = ticks_ms()
# space = None
# if last_release_time != None: #co pilot pasted in - i need to some how measure the time between the release of the button (endtime) and the next button press (starttime of the next loop) 23/07/25
# space = ticks_diff(start_time, last_release_time)
# while morseButton.value() == 0:
# pass
# print("Button state:", morseButton.value())
# blueLED.value(0)
# buzzer.duty_u16(int(65536*0)) ## deactivates the buzzer
# sleep(0.01)
# end_time = ticks_ms()
# stop = writeDitOrDash(start_time, end_time, space)
# last_release_time = end_time
# print(userinput)
# elif stop == True:
# start_time = None #reset the start time and end time to none so that the next button press can be gotten.
# end_time = None
# break
# else:
# pass
# if ''.join(userinput).strip() == answer1: #42 "....- ..---" co pilot join strip etc. my userinput list is this pressed too long. end of word ['.', '.', '.', '.', '-', ' ', '.', '.', '-', '-', '-'] and its being compared to a string called answer1 = "....- ..---" when i enter the right symbols its incorrecxt. is that because the sting doesnt have "" around every character? 23/07/25
# print()
# print("Correct")
# print()
# print(answer1)
# print("press the morseButton to continue!")
# while morseButton.value() == 1:
# greenLED(1)
# sleep(0.1)
# greenLED(0)
# sleep(0.1)
# break
# else:
# print()
# print("Incorrect. Enter a new code below")
# print()
# print(answer1)
# print()
# print("press the morseButton to continue!")
# while morseButton.value() == 1:
# redLED(1)
# sleep(0.1)
# redLED(0)
# sleep(0.1)
# #reseting for next attempt
# userinput = []
# stop = False
# last_release_time = None
# sleep(0.05)
#sleep(0.05)
#-------------------------------------------------------------------------------------------------------------
#resetting for next set of activities
userinput = []
stop = False
last_release_time = None
#activity 2 - listen to message
print("To play the message, press the rotator button(RED).")
while True:
if rotatorButton.value() == 0:
print("Button state:", rotatorButton.value())
blueLED.value(1)
buzzer.duty_u16(int(65536*0.2)) ##activate buzzer
buzzer.freq(frequency)
sleep(0.1)
print("Button state:", rotatorButton.value())
blueLED.value(0)
buzzer.duty_u16(int(65536*0)) ## deactivates the buzzer
sleep(0.01)
print("Sending message")
sleep(1.5)
message2(buzzer, blueLED)
print("To hear again press once. Too stop press and hold for 5 seconds")
#sound end of message alarm
while rotatorButton.value() == 1:
pass
sleep(0.05)
start_time = ticks_ms()
#wait for release
while rotatorButton.value() == 0:
pass
sleep(0.05)
end_time = ticks_ms()
stop = exitMessage(start_time, end_time)
elif stop == True:
start_time = None #reset the start time and end time to none so that the next button press can be gotten.
end_time = None
print("Next activity. Enter the an answer using the MORSE button (YELLOW)")
break ### need a way to exit - hold button again?? need to insert the timing code again.
else:
pass
#need an exit function - need to figure out how to release the button
sleep(0.05)
#----------------------------------------------------------------------------------------------------------------
#activity 3 - input morse code for rotator
while True:
while True:
#this takes in the user answer and build the userinput.
if morseButton.value() == 0:
print("Button state:", morseButton.value())
blueLED.value(1)
buzzer.duty_u16(int(65536*0.2)) ##activate buzzer
buzzer.freq(frequency)
sleep(0.01)
start_time = ticks_ms()
space = None
if last_release_time != None: #co pilot pasted in - i need to some how measure the time between the release of the button (endtime) and the next button press (starttime of the next loop) 23/07/25
space = ticks_diff(start_time, last_release_time)
while morseButton.value() == 0:
pass
print("Button state:", morseButton.value())
blueLED.value(0)
buzzer.duty_u16(int(65536*0)) ## deactivates the buzzer
sleep(0.01)
end_time = ticks_ms()
stop = writeDitOrDash(start_time, end_time, space)
last_release_time = end_time
print(userinput)
elif stop == True and userinput:
start_time = None #reset the start time and end time to none so that the next button press can be gotten.
end_time = None
break
else:
pass
#testing with right answer
userinput = ['.','-','-','.',' ','.','-','.',' ','-','-','-',' ','-','-','.',' ','.','-','.',' ','.',' ','.','.','.',' ','.','.','.']
#getting rid of spaces and ' and ,
user_answer = ''.join(userinput).strip()
print("User entered:", user_answer)
if not user_answer: # co pilot idea 23/07/25 #if the userinput is empty - maybe becuase it cant be filled before this starts.
continue # skip the rest of the current loop iteration and go straight back to the top.
elif user_answer == answerA: #4Progress - .--. .-. --- --. .-. . ... ... co pilot join strip etc. my userinput list is this pressed too long. end of word ['.', '.', '.', '.', '-', ' ', '.', '.', '-', '-', '-'] and its being compared to a string called answer1 = "....- ..---" when i enter the right symbols its incorrecxt. is that because the sting doesnt have "" around every character? 23/07/25
#move servo1 to the poistion A
#practice
#stepperMotor(dirPin, steps_per_revolution, timer, stepPin)
print()
print("Correct")
print()
print(answer1)
#move servo2 to reveal the thing
#insert servo 1 function
for i in range(4850, 8000, 50): # something wrong with simulation not starting in same position.
servoOperation(servo1,i)
print("servo 1 complete")
print("press the rotor button to continue!")
while rotatorButton.value() == 1:
greenLED(1)
sleep(0.1)
greenLED(0)
sleep(0.1)
break
elif user_answer == answerB: #Doom - -.. --- --- --
#move servo1 to the poistion B
print()
print("Incorrect. Enter a new code")
print()
#move servo1 back to default position
print("press the rotator button to continue!")
while rotatorButton.value() == 1:
redLED(1)
sleep(0.1)
redLED(0)
sleep(0.1)
elif user_answer == answerC: #Restart - .-. . ... - .- .-. -
#move servo1 to the poistion C
print()
print("Incorrect. Enter a new code")
print()
#move servo1 back to default position
print("press the rotator button to continue!")
while rotatorButton.value() == 1:
redLED(1)
sleep(0.1)
redLED(0)
sleep(0.1)
elif user_answer == answerD: #Adapt - .- -.. .- .--. -
#move servo1 to the poistion D
print()
print("Incorrect. Enter a new code")
print()
#move servo1 back to default position
print("press the rotator button to continue!")
while rotatorButton.value() == 1:
redLED(1)
sleep(0.1)
redLED(0)
sleep(0.1)
else:
print("Incorrect. You failed to enter one of the codes.")
print("Press the rotator Button(RED) to try again")
while rotatorButton.value() == 1:
redLED(1)
sleep(0.1)
redLED(0)
sleep(0.1)
print("Now use the morse button to enter a new code")
#resetting for next attempt
stop = False
last_release_time = None
userinput = []
#add int he code for the rotary behaviour for each answer.
sleep(0.05)
sleep(0.05)