Beskrivelse
I dette step gennemgår vi, hvordan du laver styring af din tegnemaskine ved at bruge den enkoderskive og linjesensor der følger med. Vi starter dog med noget grundlæggende kode til at få tegnemaskinen til at køre, så den hæver og sænker pennen og starter og stopper maskinen, når man trykker på en knap.
Step 1
Sæt en knap fra sættet mellem pin 1 og 3 på picoen som vist på billedet herunder
Step 3
Start med at skrive følgende program:
Start med at skrive følgende program
import PicoRobotics
import utime
import machine
board = PicoRobotics.KitronikPicoRobotics()
button = machine.Pin(0, machine.Pin.IN, machine.Pin.PULL_UP) # Knap til at tænde og slukke med
board.motorOff(1) # Start med at sætte motor 1 til ikke at køre
board.servoWrite(1,45) # Hæv penløfteren, så maskinen ikke tegner (servoport 1, vinkel 45 grader)
utime.sleep(1) # Sov i et sekund
started = False # En boolean, der fortæller om maskinen er startet eller ej
while True:
if button.value() == 0: # Hvis knappen trykkes ned (den bliver 0, fordi dens andet ben er sat til ground)
print("Du trykkede på knappen!") # Skriv ud at knappen er trykket ned
utime.sleep_ms(200) # Vent lidt tid, for at den ikke tænder og slukker flere gange
if not started: # Hvis vi ikke er startet endnu
started = True # Så lad os starte
board.servoWrite(1,70) # Sænk pennen, så vi kan tegne
utime.sleep_ms(200) # Vi venter et lidt tid, så vi er sikker på pennen er sænket inden vi starte med at dreje tegnepladen
board.motorOn(1,"r",100) # Start motoren
else: # Ellers, hvis vi er startet, når knappen trykkes ned
started = False # Så lad os stoppe
board.motorOff(1) # Stop motoren
utime.sleep_ms(400) # Vi venter lige lidt tid inden vi hæver pennen, for at sikre os at tegnepladen er stoppet med at dreje rundt.
board.servoWrite(1,45) # Hæv pennen, så vi ikke tegner mere
utime.sleep_ms(10) # Kort Loop-pause
Step 4
Programmet har en masse #kommentarer, så vi vil ikke gøre så meget ud af at beskrive det her. Sørg for at prøve programmet med tegnemaskinen, så du ved det virker. Når du skruer pennen fast i penholderen, så skal det passe med at den er ca. højden på en afstandsskive over tegne pladen, når den står i 45 graders positionen som i programmet, for så kommer den helt ned og er i kontakt med tegnepladen, når vi skifter til 75 grader. Så start programmet først og sæt pennen i og skru den fast som vist herunder.
Så kan du fjerne afstandsskiven og starte med at tegne ved at rykke på knappen 🙂.
Step 5
Næste skridt er at få tegnemaskinen til at tælle hvor mange gange tegnepladen drejer rundt mens vi tegner.
Start med at sætte linjesensoren og enkoderen fast på motoren, hvis du ikke allerede har gjort det:
Note: Det er vigtigt at enkoderhjulet (det sorte og hvide) trykkes helt fast og så langt ind på motorakslen som det kan komme. Det kan være der skal en voksen til at hjælpe med dette og lige checke.
Formålet med enkoder og linjesensor
Grunden til vi kan bruge enkoderhjulet sammen med linjesensoren, er at der er forskel på hvor meget lys der reflekteres fra hvid og sort, og derfor kan vi også tælle hver gang der kommer et “hul” i enkoderskiven forbi linjesensoren. Skiven ser sådan ud som vist på billedet til højre.
Og den har 12 huller hele vejen rundt på skiven – hvilket vil sige at vi har en opløsning på ca. 360 grader / 12 = 30 grader på vores motorstyring.
Step 6
Programmet for at læse sensoren er bygget oven på programmet fra før, og ser sådan ud
import PicoRobotics
import utime
import machine
from machine import Timer
global ticks # En global variabel, der holder antallet af huller der er læst på enkoderskiven
global currentstate # En global variabel, der fortæller om det sidste der blev læst var hvidt (1) eller sort (0)
ticks = 0 # Vi starter med at sætte vores tæller til 0
currentstate = 0 # Vi starter med at sætte tilstanden til sort (0)
rounds = 0
linesensor = machine.ADC(26)
button = machine.Pin(0, machine.Pin.IN, machine.Pin.PULL_UP) # Knap til at tænde og slukke med
board = PicoRobotics.KitronikPicoRobotics()
def tick(timer): # Denne funktion bliver kaldt af interruptet og kørt 1000 gange i sekundet
global ticks
global currentstate
line = linesensor.read_u16() # Vi læser linjesensoren
#print(line)
if (line > 31000) and (currentstate == 0): # Hvis værdien er hvid og det sidste vi har set er sort (currentstate)
currentstate = 1 # Så skifter vi tilstand til hvid
ticks += 1 # og tæller vores ticks-variabel 1 op
elif (line < 27000) and (currentstate == 1): # Hvis værdien er sort og det sidste vi har set er hvid (currentstate)
currentstate = 0 # Så skifter vi tilstand til sort
Timer().init(freq=1000, mode=Timer.PERIODIC, callback=tick) # Vi sætter et timerinterrupt op, der læser vores linjesensor 1000 gange i sekundet
board.motorOff(1) # Start med at sætte motor 1 til ikke at køre
board.servoWrite(1,45) # Hæv penløfteren, så maskinen ikke tegner (servoport 1, vinkel 45 grader)
utime.sleep(1) # Sov i et sekund
started = False # En boolean, der fortæller om maskinen er startet eller ej
while True:
if started:
rounds = ticks/57 #Tegnepladen har 152 tænder og motortandhjulet 32, så antal ticks for en tegneplade omgang bliver 152/32 * 12 = 57
print(rounds)
if button.value() == 0: # Hvis knappen trykkes ned (den bliver 0, fordi dens andet ben er sat til ground)
print("Du trykkede på knappen!") # Skriv ud at knappen er trykket ned
utime.sleep_ms(200) # Vent lidt tid, for at den ikke tænder og slukker flere gange
if not started: # Hvis vi ikke er startet endnu
started = True # Så lad os starte
board.servoWrite(1,70) # Sænk pennen, så vi kan tegne
utime.sleep_ms(200) # Vi venter et lidt tid, så vi er sikker på pennen er sænket inden vi starte med at dreje tegnepladen
board.motorOn(1,"r",100) # Start motoren
else: # Ellers, hvis vi er startet, når knappen trykkes ned
started = False # Så lad os stoppe
board.motorOff(1) # Stop motoren
utime.sleep_ms(400) # Vi venter lige lidt tid inden vi hæver pennen, for at sikre os at tegnepladen er stoppet med at dreje rundt.
board.servoWrite(1,45) # Hæv pennen, så vi ikke tegner mere
utime.sleep_ms(50) # Kort Loop-pause
Beskrivelse af ovenstående kode
Vi bruger noget der hedder et timer interrupt til at sikre os at vores enkoderhjul bliver aflæst ofte nok til at vi kan detektere alle 12 huller i det. Til det bruger vi en interruptrutine, der kører 1000 gange i sekundet – altså ved 1000Hz.
For at tælle hvor mange omgange tegnepladen har roteret bruger vi antal huller enkoderen tæller – altså 12 per omgang sammen med forholdet mellem tandhjulene på motoren og tegnepladen
Tegnepladen har 152 tænder og motortandhjulet har 32 tænder. Det giver en gearingsforhold på 152/32 = 4,75, og da vi ved at motortandhjulet sidder på samme aksel som enkoderen får vi 12 ticks for hver gang motortandhjulet drejer en omgang. Hvis vi ganger de 12 ticks per omgang med gearingsforholdet mellem tegnepladen og motortandhjulet på de 4,75 så får vi: 4,75*12 = 57. Dvs vi skal læse 57 huller i enkoderen for at tegnepladen har drejet en hel omgang.
For at sikre at hullerne tælles rigtigt i enkoderen har vi i programmet fastlagt nogle værdier for hvornår en linjesensorværdi tæller som hvid og hvornår den tæller som sort.
Det er den her del af programmet fra interruptrutinen:
line = linesensor.read_u16() # Vi læser linjesensoren
#print(line)
if (line > 31000) and (currentstate == 0): # Hvis værdien er hvid og det sidste vi har set er sort (currentstate)
currentstate = 1 # Så skifter vi tilstand til hvid
ticks += 1 # og tæller vores ticks-variabel 1 op
elif (line < 27000) and (currentstate == 1): # Hvis værdien er sort og det sidste vi har set er hvid (currentstate)
currentstate = 0 # Så skifter vi tilstand til sort
Da der kan være lidt forskel på linjesensorerne, og da det lys der er i omgivelserne hvor tegnemaskinen står også kan spille ind – især sollys, så er det en god idé at checke om programmet også virker for din maskine, og om tegnepladen rent faktisk er kørt en hel omgang, når der står 1.0 på skærmen. Hvis det slet ikke passer – hvis maskinen enten tæller for hurtigt, langsomt eller måske slet ikke, så få en voksen til at hjælpe dig med at skrive de værdier ud der bliver læst ind i variablen “line” i den øverste linje i ovenstående (og linje 20 i programmet), når du har dem giver det dig måske en ide om, hvad værdierne for hvid – der lige nu er 31000 og sort – der lige nu er 27000 skal ændres til?
Opgave: Når du er sikker på enkoderen tæller rigtigt, så prøv at tegne nogle forskellige mønstre, hvor du via programmet tæller, hvor mange omgange tegnepladen skal dreje for at mønsteret er tegnet færdigt.
Tænkeopgave: Kan du finde ud af, hvad det er der gør at det lige præcis er det antal omgange der skal til?