Robottiohjelmointi – Lego Spike Prime




1. Perustehtävät
Liike
Tehtävä 1. Liikkuminen eteen- ja taaksepäin
Kirjoita koodi, jonka avulla robotti liikkuu ensin suoraan eteenpäin ja sitten taaksepäin, eli palaa alkupisteeseen.
Esimerkkikoodi:
from hub import port
import runloop
import motor_pair
async def main():
#alustetaan moottoripari
motor_pair.pair(motor_pair.PAIR_1, port.C, port.D)
#Ajetaan suoraan 10s asetetulla nopeudella.
await motor_pair.move_for_time(motor_pair.PAIR_1, 5000, 0, velocity=500)
#Ajetaan suoraan10s asetetulla nopeudella.
await motor_pair.move_for_time(motor_pair.PAIR_1, 5000, 0, velocity=-500)
runloop.run(main())
Ratkaisun voi toteuttaa myös palikoita käyttäen seuraavasti:

Tehtävä 2. Kääntyminen
Kirjoita koodi, joka kääntää robotin paikallaan ensin oikealle ja sitten vasemmalle.
Esimerkkikoodi:
from hub import port
import runloop
import motor_pair
async def main():
# alustetaan moottoripari
motor_pair.pair(motor_pair.PAIR_1, port.C, port.D)
#käänny oikealle
await motor_pair.move_tank_for_degrees(motor_pair.PAIR_1, 180, 1000, 0)
#käänny vasemmalle
await motor_pair.move_tank_for_degrees(motor_pair.PAIR_1, 180, 0, 1000)
runloop.run(main())
Ratkaisun voi toteuttaa myös palikoita käyttäen seuraavasti:

Tehtävä 3. Liikkuminen + kääntyminen
Aja robotilla aluksi suoraan taaksepäin ja sitten käänny oikealle. Aja lopuksi vielä eteenpäin.
Esimerkkikoodi:
from hub import port
import runloop
import motor_pair
async def main():
# alustetaan moottoripari
motor_pair.pair(motor_pair.PAIR_1, port.C, port.D)
#suoraan taaksepäin
await motor_pair.move_for_time(motor_pair.PAIR_1, 5000, 0, velocity=-500)
#kääntyminen oikealle
await motor_pair.move_tank_for_degrees(motor_pair.PAIR_1, 180, 0, 1000)
#suoraan eteenpäin
await motor_pair.move_for_time(motor_pair.PAIR_1, 5000, 0, velocity=500)
runloop.run(main())
Ratkaisun voi toteuttaa myös palikoita käyttäen seuraavasti:

Anturit
Tehtävä 4. Valomatriisi
a) Teksti valomatriisiin. Tulosta robotin valomatriisiin teksti.
Esimerkkikoodi:
from hub import light_matrix
#näyttää Terve!-tekstin robotin valomatriisilla
light_matrix.write("Terve!")
Ratkaisun voi toteuttaa myös palikoita käyttäen seuraavasti:

b) Kuva valomatriisiin. Tulosta robotin valomatriisiin kuva ja vaihda robotin käynnistyspainikkeen väri haluamaksesi.
Esimerkkikoodi:
from hub import light, light_matrix
import color
#Näyttää kirahvin kuvan robotin valomatriisilla
light_matrix.show_image(light_matrix.IMAGE_GIRAFFE)
#Värjää käynnistyspainikkeen violetiksi
light.color(light.POWER, color.PURPLE)
Ratkaisun voi toteuttaa myös palikoita käyttäen seuraavasti:

Tehtävä 5. Väri- ja valosensori
Tulosta tietokoneen näytölle, että asettamasi väri on havaittu.
Esimerkkikoodi:
import color_sensor
from hub import port
import color
if color_sensor.color(port.B) == color.YELLOW:
print("Keltainen havaittu")
Tehtävä 6. Gyroanturi
a) Käännä robottia komennolla n. 90 astetta käyttäen liikeanturia (motion_sensor-moduuli). Käännä sitten robotti takaisin alkuasentoon.
Arvot voivat vaihdella, sillä robotit ovat yksilöllisiä.
Käytetään yksittäisiä moottoreita, myös tankkikäännös kenties mahdollinen.
Esimerkkikoodi:
from hub import port, motion_sensor as ms
import runloop, motor
moottori1 = port.C
moottori2 = port.D
async def main():
ms.reset_yaw(0)
motor.run(moottori1, 300)
motor.run(moottori2, 300)
while ms.tilt_angles()[0] < 850:
await runloop.sleep_ms(5)
motor.stop(moottori1)
motor.stop(moottori2)
await runloop.sleep_ms(600)
motor.run(moottori1, -300)
motor.run(moottori2, -300)
ms.reset_yaw(0)
while ms.tilt_angles()[0] > -850:
await runloop.sleep_ms(5)
motor.stop(moottori1)
motor.stop(moottori2)
runloop.run(main())
b) Robotti on tässä tehtävässä oikein päin, kun valomatriisi on kohti kattoa. Kirjoita koodi, joka havaitsee robotin kolmiulotteisen asennon ja näyttää valomatriisilla oikeanlaisen kuvion. Jos robotti on oikein päin, matriisilla näytetään hymiö. Jos se on väärinpäin, näytetään surunaama. Muuten näytetään se suunta, johon robottia olisi käännettävä, jotta se olisi oikein päin.
Esimerkkikoodi:
from hub import light_matrix, motion_sensor
import orientation, runloop
async def main():
while True:
side = motion_sensor.up_face()
# Oikein päin
if side == motion_sensor.TOP:
light_matrix.show_image(light_matrix.IMAGE_HAPPY)
# Ylösalaisin
elif side == motion_sensor.BOTTOM:
light_matrix.show_image(light_matrix.IMAGE_SAD)
# Kaiutin ylöspäin → käännä taakse
elif side == motion_sensor.FRONT:
light_matrix.set_orientation(orientation.DOWN)
light_matrix.show_image(light_matrix.IMAGE_ARROW_N)
# USB-portti ylöspäin → käännä eteen
elif side == motion_sensor.BACK:
light_matrix.set_orientation(orientation.UP)
light_matrix.show_image(light_matrix.IMAGE_ARROW_N)
# Vasen sivu ylöspäin → käännä oikealle
elif side == motion_sensor.LEFT:
light_matrix.set_orientation(orientation.LEFT)
light_matrix.show_image(light_matrix.IMAGE_ARROW_N)
# Oikea sivu ylöspäin → käännä vasemmalle
elif side == motion_sensor.RIGHT:
light_matrix.set_orientation(orientation.RIGHT)
light_matrix.show_image(light_matrix.IMAGE_ARROW_N)
await runloop.sleep_ms(100)
runloop.run(main())
Tehtävä 7. Etäisyysanturi
Aja robotilla eteenpäin, kunnes robotti näkee seinän. Seinän havaittuaan robotti peruuttaa vähän matkaa (esim. sekunnin) ja näyttää etäisyysanturilla mitatun etäisyyden näytöllä.
Esimerkkikoodi:
from hub import light_matrix, port
import runloop, distance_sensor as ds, motor, time
moottori1 = port.C
moottori2 = port.D
async def main():
while True:
etäisyys = ds.distance(port.A)
motor.run(moottori1, -600)
motor.run(moottori2, 600)
if etäisyys > 200 or etäisyys == -1 or etäisyys is None:
time.sleep_ms(100)
else:
motor.run(moottori1, 600)
motor.run(moottori2, -600)
time.sleep_ms(1000)
motor.stop(moottori1)
motor.stop(moottori2)
break
await light_matrix.write(str(etäisyys))
runloop.run(main())
Tehtävä 8. Voima-anturi
Toteuta voimapeli, johon voi osallistua 1–5 pelaajaa. Jokainen pelaaja painaa vuorollaan voima-anturia täysillä. Tämä tehdään kolme kertaa ja korkein tulos jää voimaan. Korkeimman tuloksen saanut pelaaja voittaa.
Esimerkkikoodi:
from hub import button, port
import force_sensor
import time
players = 1
min_players = 1
max_players = 5
print("Valitse kilpailijoiden määrä")
print("Oikea = lisää, vasen = aloittaa pelin")
print("Kilpailijoita:", players)
while True:
if button.pressed(button.RIGHT):
if players < max_players:
players += 1
print("Kilpailijoita:", players)
time.sleep(0.3)
if button.pressed(button.LEFT):
print("\nKISA ALKAA!")
time.sleep(0.5)
break
time.sleep(0.05)
all_results = []
for player in range(1, players + 1):
print("\nKILPAILIJA", player)
results = []
for press in range(1, 4):
max_force = 0
print("Painallus", press, ": paina anturia")
# Odota painalluksen alkua
while force_sensor.force(port.E) == 0:
time.sleep(0.01)
# Mittaa painalluksen ajan
while force_sensor.force(port.E) > 0:
f = force_sensor.force(port.E)
if f > max_force:
max_force = f
time.sleep(0.01)
results.append(max_force)
print("→ Tulos:", max_force, "%\n")
time.sleep(0.5)
best = max(results)
all_results.append(best)
print("Kilpailijan", player, "paras tulos:", best, "%")
# VOITTAJA
print("\nLOPPUTULOKSET")
for i, score in enumerate(all_results):
print("Kilpailija", i + 1, ":", score, "%")
winner_force = max(all_results)
winner_index = all_results.index(winner_force) + 1
print("\nVOITTAJA")
print("Kilpailija", winner_index, "voitti voimalla", winner_force, "%")
Tehtävä 9. Ääni
Laita robotti soittamaan Ukko Nooa -laulun alku. Pyydä kappaleen alun sävelten taajuudet hertseinä esimerkiksi tekoälyltä, älä kuitenkaan kopioi koko koodia.
Esimerkkikoodi:
from hub import sound
import time
sound.beep(440, 300, 100)
time.sleep_ms(300)
sound.beep(440, 300, 100)
time.sleep_ms(300)
sound.beep(440, 300, 100)
time.sleep_ms(300)
sound.beep(555, 300, 100)
time.sleep_ms(300)
sound.beep(494, 300, 100)
time.sleep_ms(300)
sound.beep(494, 300, 100)
time.sleep_ms(300)
sound.beep(494, 300, 100)
time.sleep_ms(300)
sound.beep(587, 300, 100)
time.sleep_ms(300)
sound.beep(555, 300, 100)
time.sleep_ms(300)
sound.beep(555, 300, 100)
time.sleep_ms(300)
sound.beep(494, 300, 100)
time.sleep_ms(300)
sound.beep(494, 300, 100)
time.sleep_ms(300)
sound.beep(440, 300, 100)
time.sleep_ms(600)
Ratkaistavissa myös palikoilla:

Tehtävä 10. Painikkeet
Toteuta koodi, jossa oikeaa painiketta painamalla robotti kääntyy oikealle ja vasenta painiketta painamalla vasemmalle.
Esimerkkikoodi:
from hub import button, port
import motor_pair
import runloop
async def main():
motor_pair.pair(motor_pair.PAIR_1, port.C, port.D)
while True:
if button.pressed(button.LEFT):
motor_pair.move_tank_for_degrees(motor_pair.PAIR_1, 180, 1000, 0)
elif button.pressed(button.RIGHT):
motor_pair.move_tank_for_degrees(motor_pair.PAIR_1, 180, 0, 1000)
await runloop.sleep_ms(10)
runloop.run(main())

Ohjelmoinnin perusominaisuudet
Tehtävä 11. Silmukat
Ohjelmoi robotti ajamaan ympäri siten, että se päätyy suurin piirtein samaan aloitusasemaan ja -asentoon. Käännöksiä voi olla vapaavalintainen määrä. Robotti voi ajaa esim. neliön mallisesti, kuten esimerkissä. Esimerkki on tehty käyttäen robotin asentoanturia.
Esimerkkikoodi:
from hub import light_matrix, port, motion_sensor as ms
import runloop, motor
moottori1 = port.C
moottori2 = port.D
async def main():
for i in range(8):
print(i)
ms.reset_yaw(0)
motor.run(moottori1, 300)
motor.run(moottori2, 300)
while ms.tilt_angles()[0] < 700:
await runloop.sleep_ms(5)
motor.stop(moottori1)
motor.stop(moottori2)
print(i)
motor.run(moottori1, -500)
motor.run(moottori2, 500)
await runloop.sleep_ms(500)
motor.stop(moottori1)
motor.stop(moottori2)
await light_matrix.write("Ympäri")
runloop.run(main())
Tehtävä 12. Ehdot
Toteuta koodi, jonka avulla havaitaan, minkä värinen objekti on näytetty värianturille. Valomatriisille tulostetaan teksti ja käynnistyspainikkeen väri vaihtuu näytetyn objektin värin mukaisesti. Jos värianturille näytetään esim. punainen palikka, valomatriisille tulee tulostaa PUNAINEN ja käynnistyspainikkeen väri muuttuu punaiseksi.
Koodissa tulee huomioida kaikki värianturin tunnistamat värit.
Esimerkkikoodi:
from hub import port, light_matrix, light
import color_sensor
import color
while True:
if color_sensor.color(port.F) == color.RED:
light_matrix.write("PUNAINEN")
light.color(light.POWER, color.RED)
elif color_sensor.color(port.F) == color.GREEN:
light_matrix.write("VIHREÄ")
light.color(light.POWER, color.GREEN)
elif color_sensor.color(port.F) == color.BLUE:
light_matrix.write("SININEN")
light.color(light.POWER, color.BLUE)
elif color_sensor.color(port.F) == color.MAGENTA:
light_matrix.write("MAGENTA")
light.color(light.POWER, color.MAGENTA)
elif color_sensor.color(port.F) == color.YELLOW:
light_matrix.write("KELTAINEN")
light.color(light.POWER, color.YELLOW)
elif color_sensor.color(port.F) == color.ORANGE:
light_matrix.write("ORANSSI")
light.color(light.POWER, color.ORANGE)
elif color_sensor.color(port.F) == color.AZURE:
light_matrix.write("TAIVAANSININEN")
light.color(light.POWER, color.AZURE)
elif color_sensor.color(port.F) == color.BLACK:
light_matrix.write("MUSTA")
light.color(light.POWER, color.BLACK)
elif color_sensor.color(port.F) == color.WHITE:
light_matrix.write("VALKOINEN")
light.color(light.POWER, color.WHITE)
else:
pass
Tehtävä 13. Muuttujat
Näytä luvut 1–10 robotin valomatriisilla sekunnin välein.
Esimerkkikoodi:
from hub import light_matrix as lm
import runloop
async def main():
for i in range(1,11):
await runloop.sleep_ms(1000)
lm.write(str(i))
runloop.run(main())
Tehtävä 14. Yhdistelmä
Yhdistetäänpä hieman edellisissä tehtävissä mainittuja asioita. Luo ohjelma, jossa asetetaan erisuuruiset arvot kahdelle muuttujalle. Lisäksi ohjelmassa tulee olla silmukka, jossa vähennetään suuremman muuttujan arvosta, kunnes sen arvo on toisen muuttujan arvoa pienempi. Robotin tulee liikkua sekä näyttää valomatriisilla jokin kuvio silmukan suorituksen ajan. Kun silmukan suoritus päättyy, robotin tulee pysähtyä ja valomatriisilla näytettävän kuvion vaihtua.
Esimerkkikoodi:
from hub import light_matrix, port
import runloop, motor_pair
motor_pair.pair(motor_pair.PAIR_1, port.C, port.D)
async def main():
var1 = 1
var2 = 4
while var1 < var2:
var2 -= 1
await light_matrix.write("M")
motor_pair.move(motor_pair.PAIR_1, 0, velocity=500)
await runloop.sleep_ms(1000)
motor_pair.stop(motor_pair.PAIR_1)
await light_matrix.write("S")
runloop.run(main())
Tehtävä 15. Funktiot
Ohjelmoi robotti ajamaan siksakkia annetuin parametrein (pituus, kääntymiskulma). Pituuden tai kulman yksikköä ei tarvitse olla määriteltynä. Mahdollista myös pidemmän siksakin ajaminen hyödyntämällä funktiokutsuja, jotta siksakin ajaminen voidaan tarvittaessa toistaa.
Esimerkkikoodi:
from hub import port, motion_sensor as ms
import runloop, motor
moottori1 = port.C
moottori2 = port.D
async def suorita_siksakki(matka, käännös):
motor.run(moottori1, -500)
motor.run(moottori2, 500)
await runloop.sleep_ms(matka)
ms.reset_yaw(0)
motor.run(moottori1, 300)
motor.run(moottori2, 300)
while ms.tilt_angles()[0] < käännös:
await runloop.sleep_ms(5)
motor.stop(moottori1)
motor.stop(moottori2)
motor.run(moottori1, -500)
motor.run(moottori2, 500)
await runloop.sleep_ms(matka)
ms.reset_yaw(0)
motor.run(moottori1, -300)
motor.run(moottori2, -300)
while ms.tilt_angles()[0] > -käännös:
await runloop.sleep_ms(5)
motor.stop(moottori1)
motor.stop(moottori2)
async def main():
for i in range(3):
await suorita_siksakki(500, 700)
runloop.run(main())
Tehtävä 16. Ajastus
Kirjoita ohjelma, joka toteuttaa seuraavat toiminnot järjestyksessä:
– Ohjelma alkaa viisi sekuntia käynnistyksen jälkeen.
– Robotti liikkuu suoraan eteenpäin viiden sekunnin ajan.
– Sitten robotti odottaa jälleen viisi sekuntia.
– Robotti tekee seuraavaksi viisi sekuntia kestävän tankkikäännöksen.
– Robotti odottaa viiden sekunnin ajan, minkä jälkeen se tekee viisi sekuntia kestävän äänen.
Esimerkkikoodi:
from hub import port, sound
import motor_pair
import runloop
import time
async def main():
motor_pair.pair(motor_pair.PAIR_1, port.C, port.D)
time.sleep_ms(5000)
motor_pair.move_tank_for_time(motor_pair.PAIR_1, 5000, 5000, 5000)
time.sleep_ms(5000)
motor_pair.move_tank_for_time(motor_pair.PAIR_1, 5000, -5000, 5000)
time.sleep_ms(5000)
sound.beep(500, 5000, 100)
runloop.run(main())
Voi luoda vastaavan myös ohjelmointipalikoita käyttäen.

2. Lopputyö
Valitse kaksi projektitehtävää tai projektitehtävä 6.
Mallivideon, malliratkaisujen sekä pitkien tekstipätkien kopioiminen LEGO SPIKE:n tietokannasta tekoälylle on kiellettyä ja rikkoo tekijänoikeuslakeja. Muutoin tekoälyn hyödyntäminen on sallittua. Toteuta koodi, jossa robotti noudattaa seuraavia kriteerejä.
Jos etäisyysanturi ei havaitse mitään, se palauttaa arvon -1. Projektitehtäviin on sallittua lisätä omia parannuksia, kuten arvojen tulostamista komentokehotteeseen sekä aloitus- ja lopetusehtoja, kunhan kaikki vaaditut asiat toteutuvat. Koodiin on suositeltavaa lisätä omia selittäviä kommentteja #-merkillä. Pidä robotin nopeudet aluksi matalina ja nosta niitä vasta siinä vaiheessa, kun koodi toimii luotettavasti. Jos akku on vähissä, robotti toimii huonommin. Liian alhainen nopeus voi kuitenkin tehdä robotista tarpeettoman hitaan ja aiheuttaa toiminnallisia ongelmia.
Projektitehtävien tulee toimia vaadittavien ominaisuuksien mukaisesti. Robotin ei tarvitse toimia täysin virheettömästi, kunhan sen toiminta on pääosin samankaltainen kuin mallivideolla. Lopullisen koodin tulee ymmärtää riveittäin ja osata selittää, mitä kukin koodirivi tekee.
Projektitehtävä 1.
Robotti liikkuu automaattisesti suoraan eteenpäin tasaisella perusnopeudella. Valkoisella paperilla robotin nopeus kasvaa ja se kiihdyttää. Nopeuden kasvulle on asetettu aikaehto, jonka jälkeen robotti palaa normaaliin ajonopeuteen, vaikka se olisi edelleen valkoisella paperilla. Tämä ominaisuus ei näy mallivideolla. Robotti pysähtyy havaitessaan edessään esteen ja kääntyy sen jälkeen 180 astetta. Ajon aikana näytetään itse toteutettu valomatriisikuvio vapaavalintaisessa kohdassa. Valmiita valomatriiseja ei saa tuoda kirjastoista.
Projektitehtävä 2.
Robotti liikkuu ainoastaan silloin, kun voima-anturia painetaan. Robotin nopeus määräytyy painamisen voimakkuuden ja väriin sidotun nopeuskertoimen tulona. Värianturin tulee tunnistaa kolme eri väriä. Käytössä on kolme nopeuskerrointa: hidas, keskinopea ja nopea. Suurimman ja pienimmän kertoimen välisen eron tulee olla selkeästi havaittavissa robotin liikkeessä. Havaittu väri esitetään palkkikaaviossa. Valitun värin tulee olla sidottu palkkikaavion väriin silloin, kun kyseinen väri on palkkikaaviossa käytettävissä. Väri valitaan ohjelman alussa. Värin valinnan jälkeen ei tarvitse tarjota mahdollisuutta muuttaa väriä myöhemmin.
Projektitehtävä 3.
Piirrä A4‑paperille mustalla tussilla rata. Puuvärejä tai lyijykynää ei saa käyttää, sillä niistä irtoava materiaali voi tarttua robotin renkaisiin ja jättää paperiin jälkiä, joita robotti voi virheellisesti seurata. Radassa tulee olla loiva kaari, 90 asteen kulma sekä S‑mutka, jossa on selkeästi kaartuvat osuudet. Robotti seuraa mustaa viivaa. Se voi hetkellisesti etsiä viivaa, mutta ei saa selkeästi poiketa radalta ja sattumalta palata takaisin mustalle viivalle. Lähtöviivan päältä aloittaminen on sallittua. Värianturin näkemät arvot tulostetaan viivakaaviona. Robotin pitää läpäistä rata molempiin suuntiin. Eli lähtöpiste vaihdetaan ensimmäisen ajon jälkeen.
Projektitehtävä 4.
Ajo käynnistyy painamalla vasenta painiketta. Robotti havaitsee esteen ja kiertää sen. Tämän jälkeen robotti jatkaa etenemistä samaan suuntaan kuin ennen estettä. Kun robotti käännetään ylösalaisin, valomatriisiin ilmestyy surunaama. Toteutuksen tarvitsee toimia vain tietyn ennalta määritellyn esteen kanssa, eikä sen tarvitse olla yleiskelpoinen muihin esteisiin.
Projektitehtävä 5.
Kun este esimerkiksi käsi on lähellä, robotti peruuttaa. Kun käsi on tietyillä, hieman kauempana olevilla etäisyyksillä, robotti liikkuu eteenpäin. Jos kättä ei havaita lainkaan, robotti pysyy paikoillaan. Seinään peruuttaessa robotti pysähtyy, kun voima-anturin painike painautuu alaspäin seinään törmäyksen seurauksena. Robottiin tulee valomatriisiin rasti, kun osuu seinään. Robotti liikkuu tämän jälkeen hieman eteenpäin, minkä jälkeen se ei reagoi hetkeen mihinkään komentoihin. Liikkeen arvot tulee lisäksi esittää viivakaaviossa siten, että paikoillaan olemista vastaa arvo 0, peruutusta arvo -1 ja eteenpäin liikkumista arvo 1.
Projektitehtävä 6.
Toteutus sekä ohjelmoinnin että robotin rakenteen osalta on vapaavalintainen. Työn tulee sisältää kaikki LEGO Spike -ympäristön “Aloita”-osion Prime-oppitunneissa käytetyt robottiosat. Kolmen moottorin käyttö lasketaan kahdeksi osaksi ja yhden moottoriparin käyttö yhdeksi osaksi. Yhden osan voi korvata pylväs- tai viivakuvaajan käytöllä ja toisen osan rakentamalla ympäristöä. Ympäristö voi olla viivarata, labyrintti, värialueet sekä erilaiset rakennetut kokonaisuudet, kuten useista palikoista muodostetut rakenteet. Rakenteella tulee olla selkeä toiminnallinen tarkoitus, kuten korkeus tai väri, eikä se saa olla pelkästään esteettinen.
Kaikkien käytettävien osien tulee toimia tietyillä ehdoilla. Esimerkiksitilanteessa valomatriisi on päällä kymmenen sekunnin ajan. Lisäksi joidenkin robottiosien tulee olla riippuvaisia toisistaan, kuten moottorien pysähtyminen voima-anturin painalluksesta. Koodissa tulee olla main-funktion lisäksi vähintään kolme funktiota. Robotin tulee liikkua vähintään kahteen suuntaan sekä reagoida ympäristöön jollakin tavalla.
