Skip to content

Commit

Permalink
Merge pull request #19 from IDATT1004-Team13-H2025/oving_3
Browse files Browse the repository at this point in the history
Oving 3
  • Loading branch information
martaron authored Sep 30, 2025
2 parents 38a783d + 79b3d29 commit 66740c9
Show file tree
Hide file tree
Showing 4 changed files with 224 additions and 2 deletions.
1 change: 1 addition & 0 deletions oving_2/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@

leftMotor = Motor(port=Port.A)
rightMotor = Motor(port=Port.C)

robotDriveBase = DriveBase(leftMotor, rightMotor, wheel_diameter=56, axle_track=160)

startBtn = TouchSensor(port=Port.S1)
Expand Down
105 changes: 103 additions & 2 deletions oving_3/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,11 @@
from pybricks.robotics import DriveBase
from pybricks.media.ev3dev import SoundFile, ImageFile

from rtttl_player import RTTTLPlayer
from random import randint
import time



# This program requires LEGO EV3 MicroPython v2.0 or higher.
# Click "Open user guide" on the EV3 extension tab for more information.
Expand All @@ -15,6 +20,102 @@
# Create your objects here.
ev3 = EV3Brick()

# Eksempelmelodi (Nokia)
#take_on_me = "Take On Me:o=5,d=8,b=160,b=160:f#,f#,f#,d,p,b4,p,e,p,e,p,e,g#,g#,a,b,a,a,a,e,p,d,p,f#,p,f#,p,f#,e,e,f#,e,f#,f#,f#,d,p,b4,p,e,p,e,p,e,g#,g#,a,b,a,a,a,e,p,d,p,f#,p,f#,p,f#,e,e5"
#postman_pat ="Postman Pat:o=5,d=16,b=100,b=100:f#,p,a,p,8b,8p,f#,p,a,p,8b,8p,f#,p,a,p,b,p,d6,d6,c#6,c#6,a,p,4b.,8p,32f#,g,p,a,p,b,p,g,p,8f#.,8e,8p,32f#,g,p,a,p,32b.,32b.,g,p,8f#.,8e,8p,32f#,g,p,a,p,b,p,g,p,f#,p,e,p,d,p,c#,p,2d"
#simpsons = "Simpsons:o=5,d=8,b=160,b=160:c6.,4e6,4f#6,a6,4g6.,4e6,4c6,a,f#,f#,f#,2g,p,p,f#,f#,f#,g,4a#.,c6,c6,c6,4c6"
#mission_impossible = "Mission Impossible:o=5,d=16,b=100,b=100:32d,32d#,32d,32d#,32d,32d#,32d,32d#,32d,32d,32d#,32e,32f,32f#,32g,g,8p,g,8p,a#,p,c6,p,g,8p,g,8p,f,p,f#,p,g,8p,g,8p,a#,p,c6,p,g,8p,g,8p,f,p,f#,p,a#,g,2d,32p,a#,g,2c#,32p,a#,g,2c,p,a#4,c"

songs = [
"Take On Me:o=5,d=8,b=160,b=160:f#,f#,f#,d,p,b4,p,e,p,e,p,e,g#,g#,a,b,a,a,a,e,p,d,p,f#,p,f#,p,f#,e,e,f#,e,f#,f#,f#,d,p,b4,p,e,p,e,p,e,g#,g#,a,b,a,a,a,e,p,d,p,f#,p,f#,p,f#,e,e5",
"Postman Pat:o=5,d=16,b=100,b=100:f#,p,a,p,8b,8p,f#,p,a,p,8b,8p,f#,p,a,p,b,p,d6,d6,c#6,c#6,a,p,4b.,8p,32f#,g,p,a,p,b,p,g,p,8f#.,8e,8p,32f#,g,p,a,p,32b.,32b.,g,p,8f#.,8e,8p,32f#,g,p,a,p,b,p,g,p,f#,p,e,p,d,p,c#,p,2d",
"Simpsons:o=5,d=8,b=160,b=160:c6.,4e6,4f#6,a6,4g6.,4e6,4c6,a,f#,f#,f#,2g,p,p,f#,f#,f#,g,4a#.,c6,c6,c6,4c6",
"Mission Impossible:o=5,d=16,b=100,b=100:32d,32d#,32d,32d#,32d,32d#,32d,32d#,32d,32d,32d#,32e,32f,32f#,32g,g,8p,g,8p,a#,p,c6,p,g,8p,g,8p,f,p,f#,p,g,8p,g,8p,a#,p,c6,p,g,8p,g,8p,f,p,f#,p,a#,g,2d,32p,a#,g,2c#,32p,a#,g,2c,p,a#4,c"
]

# Lag spiller og kjør
#player = RTTTLPlayer(ev3, songs[3])
#ev3.screen.print("Spiller", player.name, "...")
#player.play()

def doRandomTrick(actions):
trick = actions[randint(0, len(actions) - 1)]
trick()

def spin():
directions = [-1, 1]
directionIndex = randint(0, 1)
robotDriveBase.stop()
speaker.say("Look at my trick")
robotDriveBase.turn(360 * directions[directionIndex])

def playMusic():
robotDriveBase.stop()
player = RTTTLPlayer(ev3, songs[3])
ev3.screen.print("Spiller", player.name, "...")
player.play()

actions = [spin, playMusic]

leftMotor = Motor(port=Port.A)
rightMotor = Motor(port=Port.C)
robotDriveBase = DriveBase(leftMotor, rightMotor, wheel_diameter=56, axle_track=160)

startBtn = TouchSensor(port=Port.S1)
usSensor = UltrasonicSensor(port=Port.S3)

leftColorSensor = ColorSensor(port=Port.S2)
rightColorSensor = ColorSensor(port=Port.S4)

speaker = ev3.speaker

leftSensorThreshold = 9
rigthSensorThreshold = 10
speed = 115

currentTime = time.time()
lastCorrection = currentTime
lastDirection = 1
lastTrick = currentTime
rotationSpeed = 40

while True:
currentTime = time.time()

ev3.screen.print(leftColorSensor.reflection(), rightColorSensor.reflection())

if usSensor.distance() <= 50:
break
"""
if currentTime - lastCorrection > 2:
while leftColorSensor.reflection() > leftSensorThreshold or rightColorSensor.reflection() < rigthSensorThreshold:
i = (time.time() - lastCorrection) * 3
robotDriveBase.drive(-speed, i * lastDirection)
lastCorrection = time.time()
continue
"""
if currentTime - lastTrick > 10:
doRandomTrick(actions)
lastTrick = time.time()

if leftColorSensor.reflection() < leftSensorThreshold:
robotDriveBase.drive(-speed, rotationSpeed)
lastCorrection == time.time()
lastDirection = 1
continue

if rightColorSensor.reflection() < rigthSensorThreshold:
robotDriveBase.drive(-speed, -rotationSpeed)
lastCorrection = currentTime
lastDirection = -1
continue



robotDriveBase.drive(-speed, 0)


# Write your program here.
ev3.speaker.beep()
robotDriveBase.stop()
ev3.speaker.play_file(SoundFile.FANFARE)
60 changes: 60 additions & 0 deletions oving_3/rtttl_player.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
import re


class RTTTLPlayer:
NOTE_FREQS = {
'c': 16.35, 'c#': 17.32, 'd': 18.35, 'd#': 19.45,
'e': 20.60, 'f': 21.83, 'f#': 23.12, 'g': 24.50,
'g#': 25.96, 'a': 27.50, 'a#': 29.14, 'b': 30.87
}

def __init__(self, ev3, rtttl: str):
"""
:param ev3: EV3Brick instance from pybricks.hubs
:param rtttl: RTTTL string (name:d=4,o=5,b=100:notes)
"""
self.ev3 = ev3
self.name, self.defaults, self.notes = self.parse_rtttl(rtttl)

def parse_rtttl(self, rtttl: str):
name, settings, notes = rtttl.split(':')
defaults = {}
for s in settings.split(','):
k, v = s.split('=')
defaults[k] = int(v)
notes = notes.split(',')
return name, defaults, notes

def note_to_freq(self, note: str, octave: int):
"""
Convert note name + octave to frequency in Hz.
"""
base = self.NOTE_FREQS[note]
return round(base * (2 ** octave), 2)

def play(self, tempo_scale: float = 1.0):
"""
Play the parsed RTTTL melody.
:param tempo_scale: Scale factor for speed (1.0 = normal, 2.0 = twice as fast, 0.5 = half speed)
"""
bpm = self.defaults.get('b', 63)
whole_note = (60 / bpm) * 4 * 1000 # ms

for raw in self.notes:
match = re.match(r'(\d+)?([a-gp][#]?)(\d)?(\.*)?', raw.strip(), re.I)
if not match:
continue

dur, note, octave, dot = match.groups()
dur = int(dur) if dur else self.defaults.get('d', 4)
octave = int(octave) if octave else self.defaults.get('o', 6)

duration = (whole_note / dur) * tempo_scale
if dot:
duration *= 1.5

if note.lower() == 'p': # pause
self.ev3.speaker.beep(0, int(duration))
else:
freq = self.note_to_freq(note.lower(), octave)
self.ev3.speaker.beep(int(freq), int(duration))
60 changes: 60 additions & 0 deletions oving_4/rttl_player.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
import re


class RTTTLPlayer:
NOTE_FREQS = {
'c': 16.35, 'c#': 17.32, 'd': 18.35, 'd#': 19.45,
'e': 20.60, 'f': 21.83, 'f#': 23.12, 'g': 24.50,
'g#': 25.96, 'a': 27.50, 'a#': 29.14, 'b': 30.87
}

def __init__(self, ev3, rtttl: str):
"""
:param ev3: EV3Brick instance from pybricks.hubs
:param rtttl: RTTTL string (name:d=4,o=5,b=100:notes)
"""
self.ev3 = ev3
self.name, self.defaults, self.notes = self.parse_rtttl(rtttl)

def parse_rtttl(self, rtttl: str):
name, settings, notes = rtttl.split(':')
defaults = {}
for s in settings.split(','):
k, v = s.split('=')
defaults[k] = int(v)
notes = notes.split(',')
return name, defaults, notes

def note_to_freq(self, note: str, octave: int):
"""
Convert note name + octave to frequency in Hz.
"""
base = self.NOTE_FREQS[note]
return round(base * (2 ** octave), 2)

def play(self, tempo_scale: float = 1.0):
"""
Play the parsed RTTTL melody.
:param tempo_scale: Scale factor for speed (1.0 = normal, 2.0 = twice as fast, 0.5 = half speed)
"""
bpm = self.defaults.get('b', 63)
whole_note = (60 / bpm) * 4 * 1000 # ms

for raw in self.notes:
match = re.match(r'(\d+)?([a-gp][#]?)(\d)?(\.*)?', raw.strip(), re.I)
if not match:
continue

dur, note, octave, dot = match.groups()
dur = int(dur) if dur else self.defaults.get('d', 4)
octave = int(octave) if octave else self.defaults.get('o', 6)

duration = (whole_note / dur) * tempo_scale
if dot:
duration *= 1.5

if note.lower() == 'p': # pause
self.ev3.speaker.beep(0, int(duration))
else:
freq = self.note_to_freq(note.lower(), octave)
self.ev3.speaker.beep(int(freq), int(duration))

0 comments on commit 66740c9

Please sign in to comment.