Område 2 · lektion 6
Mikrokontrollern och Arduino IDE
Nu kommer kortet fram. Område 1 handlade om kretsen som gör samma sak varje gång den får spänning. Härifrån och framåt sitter det något emellan som kan bestämma sig – och det du skriver är det som bestämmer.
Mål
- Du kan peka ut 5 V, GND, de digitala pinnarna och USB-uttaget på ett Uno-kort och säga vad var och en gör.
- Du kan välja kort och port i Arduino IDE och ladda upp en sketch.
- Du kan förklara vad
setup()ochloop()gör, och i vilken ordning de körs. - Du kan tända och släcka en lysdiod med
digitalWrite()på en pinne du valt själv, med rätt förresistor.
Genomgång
Vad en styrenhet är
En styrenhet sitter mitt i en kedja. Något går in, något händer inuti, något går ut. Bygge 0 hade bara den vänstra och den högra delen ihopkopplade med koppartråd: kretsen kunde inte välja något.
- Givaren är det som mäter eller känner av något. I bygge 1 är det en knapp, i område 4 blir det en sensor med ett mätvärde.
- Styrenheten är kortet. Den läser insignalen, kör ditt program och bestämmer vad utsignalen ska bli.
- Ställdonet är det som rör sig. I bygge 1 ett servo som drar en spak.
- Det är den här kedjan – givare, via styrenhet, till ställdon – som ämnesplanen kallar uppbyggnaden av ett mekatroniskt system. Kan du rita den för ditt eget bygge kan du också beskriva det.
Kortet, och vad de fyra pinngrupperna heter
Kortet i ditt kit är en Arduino Uno R3. Chippet på det heter ATmega328P och är själva mikrokontrollern; resten av kortet finns för att göra chippet användbart – USB-anslutning, spänningsregulator, stiftlister att sticka sladdar i.
- D0–D13 är de fjorton digitala pinnarna. Varje pinne kan
vara antingen ingång eller utgång, och känner bara till två lägen:
HIGH(5 V) ochLOW(0 V). - A0–A5 är de sex analoga ingångarna. De kan läsa en spänning någonstans mellan 0 och 5 V i stället för bara två lägen. Vi använder dem först i område 4.
- 5 V och 3,3 V lämnar spänning till kretsen du bygger. GND är nollan – returvägen som allting mäts mot.
- D0 och D1 används av USB-anslutningen för seriell kommunikation. Sitter något på dem går uppladdningen ofta fel. Börja på D2 och uppåt.
Talen du behöver komma ihåg:
| Storhet | Uno R3 / ATmega328P |
|---|---|
| Logiknivå | 5 V. HIGH är 5 V, LOW är 0 V |
| Digitala pinnar | 14 stycken, D0–D13 |
| Analoga ingångar | 6 stycken, A0–A5 |
| Klockfrekvens | 16 MHz |
| Programminne (flash) | 32 KB, varav 0,5 KB tas av bootloadern |
| Arbetsminne (SRAM) | 2 KB |
| Ström per pinne | 20 mA rekommenderat, 40 mA absolut tak |
| Ström genom alla I/O-pinnar tillsammans | 200 mA. Chippets absoluta tak |
| Ström ut ur 5 V-stiftet | Sätts av matningen, inte av chippet. Över USB: 500 mA att dela på |
De två sista raderna handlar om olika saker, och de blandas lätt ihop. De 200 mA är vad chippet självt tål genom sina pinnar tillsammans – en gräns i kislet, som du slår i genom att hänga för många lysdioder på för många pinnar. 5 V-stiftet är däremot ingen pinne på chippet utan en genomkoppling till kortets matning: matas kortet över USB delar kortet och allt du kopplat in på portens 500 mA. Servot i lektion 9 slår i den andra gränsen, aldrig i den första.
Två av talen är värda att räkna på direkt. 16 MHz betyder 16 000 000 klockcykler per sekund, alltså
1 / 16 000 000 s = 0,0000000625 s = 62,5 ns per cykel
Det är därför en loop() som bara läser en pinne hinner varvas
många tusen gånger i sekunden. 2 KB SRAM är 2048 byte, och
där ska allt som ändrar sig medan programmet kör rymmas. En lista med 100
heltal tar 100 · 2 = 200 byte, alltså 200 / 2048 ≈ 9,8 procent av hela
arbetsminnet. Datorn du skriver på har ungefär en miljon gånger mer.
Kortet är litet med flit: det ska kosta lite, dra lite ström och göra en
sak pålitligt.
Programmet körs på kortet, inte på datorn
Det här är den vana från Programmering 1 som spricker först. I Python skriver du en rad och den körs. Här händer i stället det här:
- Du skriver en sketch – ett Arduino-program – i Arduino IDE på datorn.
- Du trycker Ladda upp. IDE:n kompilerar hela sketchen till maskinkod. Finns ett enda fel någonstans stannar det här, och ingenting laddas upp.
- Maskinkoden överförs via USB-sladden till kortets flashminne.
- Kortet startar om och börjar köra. Nu är datorn inte längre inblandad. Drar du ur USB-sladden och sätter i den igen kör programmet från början, utan att du laddat upp något nytt.
Följden är att du inte kan skriva en halv rad och se vad som händer. Det finns ingen REPL. Det finns heller ingen skärm att skriva ut på – det närmaste är seriemonitorn, och den tas upp i nästa guide.
Arduino IDE: de fyra sakerna du behöver hitta
- Verktyg → Kort ska stå på Arduino Uno.
- Verktyg → Port ska stå på den port kortet dök upp på när du satte i sladden. Är listan tom är det sladden eller drivrutinen det är fel på, inte koden. Vissa USB-sladdar är rena laddsladdar och saknar datatrådar.
- Verifiera (bocken) kompilerar utan att ladda upp. Använd den ofta – det är billigare att hitta felet där.
- Ladda upp (pilen) kompilerar och överför. Medan överföringen pågår blinkar två små lysdioder märkta RX och TX på kortet.
setup() och loop()
En sketch måste innehålla exakt två funktioner, och de har bestämda namn.
void setup() {
// Körs en gång, direkt efter att kortet startat.
}
void loop() {
// Körs sedan om och om igen, för alltid.
}
setup() är där du ställer in saker som ska gälla hela tiden:
vilka pinnar som är ingångar och vilka som är utgångar. loop()
är själva programmet. När loop() nått sista raden börjar den
om från den första, utan paus. Det är inte du som skriver den slingan –
den finns redan i Arduino-miljön och anropar din loop().
void framför namnet betyder att funktionen inte lämnar
tillbaka något värde. Mer om varför det måste stå där i nästa guide.
Den första utsignalen: digitalWrite
Uno-kortet har en inbyggd lysdiod kopplad till pinne 13. Den har det
färdiga namnet LED_BUILTIN, och den är perfekt att börja med
eftersom den inte kräver en enda sladd.
void setup() {
pinMode(LED_BUILTIN, OUTPUT);
}
void loop() {
digitalWrite(LED_BUILTIN, HIGH);
delay(500);
digitalWrite(LED_BUILTIN, LOW);
delay(500);
}
Tre nya ord:
pinMode(pinne, OUTPUT)bestämmer att pinnen ska driva ut spänning i stället för att lyssna. Den raden måste stå isetup(). Utan den händer ingenting, och koden kompilerar ändå utan minsta klagomål.digitalWrite(pinne, HIGH)lägger 5 V på pinnen.LOWlägger 0 V.delay(500)väntar 500 millisekunder, alltså en halv sekund. Under tiden gör kortet ingenting annat alls – det är en begränsning vi lever med i område 2 och gör oss av med i område 3.
Blinkningen ovan tar 500 + 500 = 1000 ms per varv, alltså ett varv i sekunden.
En egen lysdiod på en egen pinne
Byt LED_BUILTIN mot ett tal och du styr vilken pinne som
helst. Men en lysdiod på en egen pinne behöver samma förresistor som i
område 1, av exakt samma skäl:
U = 5,0 V − 2,0 V = 3,0 V
R = U / I = 3,0 V / 0,020 A = 150 Ω
De 20 mA som är rekommenderat tak per pinne är alltså precis den ström en vanlig lysdiod vill ha. Det är ingen tillfällighet – men det betyder också att pinnen inte har något över. Ska något dra mer än så måste strömmen komma någon annanstans ifrån, vilket är hela poängen med servot i lektion 9 och med drivkretsen i område 5.
const int LAMPA_PIN = 8;
void setup() {
pinMode(LAMPA_PIN, OUTPUT);
}
void loop() {
digitalWrite(LAMPA_PIN, HIGH);
delay(500);
digitalWrite(LAMPA_PIN, LOW);
delay(500);
}
Rita innan du kopplar Kopplingsschemat från område 1 gäller fortfarande. Kortet ritas som en ruta med de pinnar du faktiskt använder utsatta – inte alla fjorton. En lysdiod på D8 blir: D8 → motstånd → lysdiodens anod, lysdiodens katod → GND. Två komponenter och två sladdar, och ändå värt att rita, eftersom det är ritningen du felsöker mot när den inte lyser.
I industrin och i vardagen
I industrin: en produktionslina styrs sällan av ett Uno-kort utan av en PLC – en programmerbar styrenhet byggd för verkstadsmiljö. Idén är densamma: ingångar läses, ett program kör, utgångar sätts. Skillnaden syns i talen. Uno-kortets pinnar arbetar med 5 V och 20 mA per pinne, medan en PLC:s in- och utgångar typiskt arbetar med 24 V och kan koppla en halv ampere direkt ut på en kontaktor eller en ventil. Det är ungefär fem gånger spänningen och tjugofem gånger strömmen, plus ett hölje som tål damm, olja och vibration. En PLC är dessutom byggd för att köra i åratal utan omstart, medan ett Uno-kort är byggt för att kosta lite.
I vardagen: centrallåset i en bil är samma kedja som figuren ovan, en gång per dörr. Du trycker på knappen i förardörren – det är givaren. En styrenhet läser trycket och avgör om bilen står stilla och om nyckeln finns i närheten. Sedan får en liten motor i varje dörr order om att dra låskolven – ställdonet. Att det inte är fyra sladdar direkt från knappen till fyra motorer märker du på att bilen vägrar låsa när en dörr står på glänt: mellan knappen och motorn sitter något som kan säga nej. Det är precis det en styrenhet är till för.
Prova själv
- Sätt i kortet, välj kort och port, och ladda upp blinkexemplet med
LED_BUILTIN. Kontrollera att lysdioden på kortet blinkar en gång i sekunden. - Ändra de två
delay(500)tilldelay(100)och ladda upp igen. Räkna ut i förväg hur många blinkningar per sekund du ska få, och kontrollera sedan mot verkligheten. - Dra ur USB-sladden. Sätt i den igen utan att ladda upp. Vad händer, och varför?
- Räkna ut förresistorn till en röd lysdiod från 5 V vid 20 mA, bygg kretsen på kopplingsdäcket från pinne D8, och flytta över blinkningen dit. Rita schemat innan du kopplar.
Kontrollfrågor
Varför räcker det inte att skriva digitalWrite(8, HIGH);
om man glömt pinMode()?
Utan pinMode(8, OUTPUT) står pinnen kvar som ingång. En
ingång lyssnar, den driver ingenting, och digitalWrite på
en ingång slår i stället på det interna pull-up-motståndet. Resultatet
blir i bästa fall en mycket svagt lysande lysdiod, i praktiken oftast
ingenting alls. Koden kompilerar utan fel, vilket är det som gör felet
svårt: det finns inget felmeddelande att läsa.
Vad är skillnaden mellan Verifiera och Ladda upp?
Verifiera kompilerar sketchen och stannar där. Ladda upp kompilerar och överför resultatet till kortet. Verifiera går alltså att göra utan att kortet ens är inkopplat, och är det snabbaste sättet att kontrollera att koden är syntaktiskt hel.
Din blinkning har delay(250) både för tänt och för
släckt. Hur många hela blinkningar blir det på tio sekunder?
Ett varv tar 250 + 250 = 500 ms. På 10 sekunder, alltså 10 000 ms, blir det 10 000 / 500 = 20 varv. Tjugo blinkningar.
Du vill driva en liten summer som drar 60 mA direkt från en pinne. Går det?
Nej. Absolut tak per pinne är 40 mA och rekommenderat är 20 mA, så 60 mA ligger en och en halv gång över det absoluta taket. Pinnen kan skadas, och skadan är permanent. Något som drar mer än 20 mA behöver ta strömmen någon annanstans ifrån och bara styras av pinnen – det är vad drivkretsen i område 5 handlar om.
Varför ska du undvika pinne 0 och 1 till dina egna komponenter?
De används av kortets seriella kommunikation över USB, alltså av samma kanal som uppladdningen och seriemonitorn går genom. Sitter en komponent på dem kan uppladdningen misslyckas eller utskrifterna bli obegripliga. Det finns tolv andra digitala pinnar – använd dem.
Kortet har 2 KB SRAM. Hur många heltal av typen int
ryms i minnet om ingenting annat funnes där?
2 KB är 2048 byte och en int tar 2 byte på det här
kortet, alltså 2048 / 2 = 1024 heltal. I praktiken betydligt färre,
eftersom biblioteken och Arduino-miljön också behöver plats. Att en
int är just 2 byte här är nästa guides ämne.
Vanliga fel
- Port saknas i listan. Kortet syns inte. Testa en annan USB-sladd först – laddsladdar utan datatrådar ser identiska ut och är den vanligaste orsaken. Sedan en annan USB-port, sedan drivrutinen. Koden är oskyldig här.
- Fel kort valt. Står Verktyg → Kort på något annat än Arduino Uno kompilerar sketchen ofta ändå, och uppladdningen avbryts med ett kryptiskt fel om synkronisering. Kontrollera kortvalet innan du börjar leta i koden.
pinMode()glömd isetup(). Klassikern. Inget felmeddelande, ingen lysdiod, ingenting att gå på. Vänj dig vid att läsasetup()först när något inte fungerar.- Lysdioden sitter direkt på pinnen utan motstånd. Den lyser, ofta starkt, ett tag. Sedan är antingen lysdioden eller pinnen förbrukad, och en trasig pinne syns inte utanpå. Räkna motståndet.
- Lysdioden vänd åt fel håll. Den lyser inte, och det ser ut som ett kodfel. Långa benet mot pinnen, plattade kanten mot GND.
- Ingen gemensam GND. Så fort något får ström från annat håll än kortet måste de två kretsarnas GND kopplas ihop. Utan det finns ingen gemensam nolla att mäta signalen mot, och signalen betyder ingenting. Det här felet återkommer i varenda bygge resten av kursen.
- Uppladdningen fungerar men ingenting händer.
Kontrollera att koden ligger i
loop()och inte isetup(). Något som skulle upprepas men står isetup()gör exakt en sak, en gång, för fort för att synas. - Sladdar flyttade medan kortet var strömsatt. Koppla alltid ur USB-sladden innan du bygger om. En felsatt sladd mellan 5 V och GND är en kortslutning, och den märks som att kortet slocknar.
Vidare
Kapitlet Från Python till C++ i språkreferensen hör till den här guiden – särskilt den första raden i tabellen, om att ingenting kör förrän allt kompilerat.
Nästa guide är C++ efter Python,
där du får veta varför void och int måste stå
utskrivna, och hur du får se vad som händer inuti kortet.