Teknik 1 · område 2 · pass 7
Linjeföljaren
Fem tal säger var linjen är. Biblioteket gör om dem till ett enda – en position – och på den kan roboten styra. Först måste den veta vad som är vitt och vad som är svart: det är kalibreringen. Sidan förutsätter att biblioteken ligger på Pico:n.
1. Kalibrera
Vitt golv ger 60 i ett rum och 200 i ett annat. Sensorerna är inte heller exakt lika. Därför kalibrerar du: låt varje sensor se både vitt och svart, så vet biblioteket vad som är vad.
from TRSensor import TRSensor
from time import sleep
sensor = TRSensor()
for i in range(100):
sensor.calibrate()
while True:
position, varden = sensor.readLine()
print(position)
sleep(0.2)
De 100 varven tar tre–fyra sekunder. Under tiden håller du roboten i handen och vaggar den fram och tillbaka i sidled över tejpen, så att alla fem sensorerna hinner se både vitt och svart. Kalibreringen görs om varje gång programmet startar – vagga direkt när du kört.
2. En position
readLine() svarar med två saker på samma gång –
returvärdet från förra veckan, fast två i stället för ett:
| Namn | Vad det är |
|---|---|
position | Ett tal 0–4000. 0 = linjen under vänster kant. 2000 = linjen i mitten. 4000 = under höger kant. Ser ingen sensor linjen får du 0 eller 4000, beroende på vilken sida den senast var på |
varden | Listan igen, men kalibrerad: 0 = det ljusaste sensorn såg, 1000 = det mörkaste. Summan av alla fem säger hur mycket svart roboten ser totalt – alla över tejp ger nära 5000 |
Flytta roboten i sidled över linjen och se position glida. Visa den
stort på skärmen: lcd.text("pos " + str(position), 10, 10, lcd.VIT).
3. kor(v, h) – två farter
För att svänga mjukt behöver hjulen olika fart. En funktion som tar två – den var
utmaning förra veckan, nu behöver alla den. Pinnarna från kor.py ovanför.
def kor(v, h):
v_fram.value(1)
v_bak.value(0)
h_fram.value(1)
h_bak.value(0)
fart_v.duty_u16(int(v * 65535 / 100))
fart_h.duty_u16(int(h * 65535 / 100))
kor(20, 45): vänster hjul långsamt, höger fort – roboten svänger
vänster. kor(40, 40): rakt.
4. Följa linjen: bang-bang
Tre lägen, inget däremellan. Antingen eller – det heter bang-bang.
while True:
position, varden = sensor.readLine()
if position < 1500:
kor(20, 45)
elif position > 2500:
kor(45, 20)
else:
kor(40, 40)
Linjen till vänster (under 1500) → sväng vänster. Till höger (över 2500) → sväng höger. Mitten → rakt. Ställ roboten på ovalen, vagga för kalibreringen, släpp. Den följer – och vaggar. Justera farterna tills den klarar ett varv.
Då är sensorkortet vänt, så att 0 är höger kant. Byt < och
> – eller byt farterna i de två svängarna. Testa först med
print(position): linjen till vänster ska ge under 2000.
5. Följa linjen bättre: P-reglering
Bang-bang svänger lika hårt oavsett om linjen är lite eller mycket åt sidan. Bättre: ju längre ut linjen är, desto mer sväng. Det heter proportionell reglering, P-reglering, och det är en rad:
fart = 45
k = 0.015
while True:
position, varden = sensor.readLine()
fel = position - 2000
v = fart + fel * k
h = fart - fel * k
kor(max(0, min(100, v)), max(0, min(100, h)))
| Raden | Vad den gör |
|---|---|
fel = position - 2000 | Hur långt från mitten linjen är: −2000 … 2000. Noll = mitt på |
v = fart + fel * k | Linjen till höger (fel positivt) → vänster hjul fortare → roboten svänger höger. Lagom mycket |
k | Hur hårt roboten reagerar. För litet: tappar kurvan. För stort: vaggar. Hitta ert k – börja på 0.015 |
max(0, min(100, v)) | Håller farten inom 0–100. Utan det kan v bli 75 eller −5, och duty_u16 vill inte ha det |
Det är hela reglertekniken i en rad. Att ni provade bang-bang först och bytte till P – och varför – är precis den sortens resonemang dokumentationen frågar efter.
6. main.py
Kalibreringen först, sedan tre sekunder, sedan loopen. Ladda upp, dra ur kabeln, ställ på ovalen, slå på, vagga direkt, släpp.
# pinnar, kor() och stopp() ovanför ...
sensor = TRSensor()
lcd = ST7789()
for i in range(100):
sensor.calibrate()
sleep(3)
while True:
position, varden = sensor.readLine()
lcd.fill(lcd.SVART)
lcd.text("pos " + str(position), 10, 10, lcd.VIT)
lcd.show()
if position < 1500:
kor(20, 45)
elif position > 2500:
kor(45, 20)
else:
kor(40, 40)
Skärmen visar positionen medan den kör. Det är så du ser vad roboten ser när den tappar linjen.
Klart när — det här ska alla ha
Om du hinner — utmaning
Kryssen sparas i din webbläsare.
7. Felsökning
7 rader
| Symptom | Trolig orsak | Åtgärd |
|---|---|---|
position är alltid 0 eller 4000 | Ingen kalibrering, eller kalibrerad utan att någon sensor såg tejpen | Kör om programmet och vagga över linjen under de 100 varven |
| Roboten svänger åt fel håll | Sensorkortet vänt, eller </> förväxlade | Testa med print: linjen till vänster ska ge under 2000. Annars byt tecknen |
| Tappar linjen i kurvan | För hög fart, eller för liten skillnad mellan hjulen | Mittfart 30. Svängarna 15/45 |
| Vaggar våldsamt | Bang-bang gör det. Eller för stort k | Mindre skillnad mellan farterna, eller P-reglering med mindre k |
| Kör rakt fram och struntar i linjen | Kalibreringen gjordes i luften – allt ser likadant ut | Roboten ska stå på banan under kalibreringen |
Ingenting händer efter calibrate-loopen | Den tar 3–4 sekunder | Vänta. Skriv något på skärmen efter loopen så att du ser när den är klar |
ValueError på duty_u16 | Farten är utanför 0–100 | max(0, min(100, …)) runt v och h |
Ord på den här sidan
| Ord | Betyder |
|---|---|
| kalibrering | Låta sensorn se vitt och svart så att den vet vad som är vad. Görs varje start |
| position | Ett tal 0–4000 som säger var linjen är under roboten. 2000 = mitten |
| bang-bang | Styrning med bara några fasta lägen. Sväng eller sväng inte |
| P-reglering | Styrning där reaktionen är proportionell mot felet. Lite fel – lite sväng |
| fel | Skillnaden mellan där man är och där man vill vara |
| k | Förstärkningen – hur hårt man reagerar på felet |
Ordträning