I denna lektion skall vi lära oss lite om ingångar. Till detta behöver vi en omkopplare (knapp) som vi skall koppla in till I/O pinne 2. Digitala ingångar från knappar och vred etc. kopplar vi gärna mot 0V (GND), så när de inte är aktiva ger de en logisk etta (5V) till vår ingång och när vi trycker ned den så blir det en logisk nolla (0V) på ingången. För att signalen skall vara stabil när vi inte trycker på knappen ansluter vi ett s.k. Pullup motstånd som ser till att signalen håller sig till 5V och inte fladdrar/svävar. Hade man inte haft detta motstånd kan ingången anta vilket läge som helst (hög eller låg) då den fungerar som en antenn. Ett pullup motstånd skall ha ett så högt värde som möjligt då det räcker att binda den till 5V med liten ström, så vi använder oss av 10Kohm. När sedan knappen trycks ner drar strömmen igenom knappen ner till 0V och ingången får samma potential, dvs. 0V. I dagens microcontrollers kan man slå på en intern pullup via mjukvaran, så man slipper extern pullup. Men vi vill visa detta först med att använda extern pullup. Bilden nedan visar vår inkoppling.
Lysdioden är den samma som vid förra lektionen och ansluten på samma I/O, men den som är lite uppmärksam ser att vi bytt plats på motståndet/resistorn och lysdioden. Vi har gjort detta för att visa att det spelar ingen roll i vilken ordning man sätter detta förkopplingsmotstånd, resultatet blir detsamma men mest har vi gjort detta för att spara kopplingstrådar, vi kan ansluta 330ohms motståndet direkt till 0V. Knappen (finns 5st i vårt kit) sätter vi i mitten på t.ex. rad 14, så att benen ansluts till varsin bana om mitten, högra sidan kopplar vi till 0V och högra sidan kopplar vi med ett 10Kohms till +5V (pullup). Sen kopplar vi en tråd från vänstra benet på knappen in till I/O pinne 2 på utvecklingskortet.
Programmet som vi skall köra syns nedan och kan laddas hem här (förut hade programmen tillägget *.pde men sedan version 1.0 har de ändrat det till *.ino. Programmet visas i Arduino® IDE nedan, ladda hem programmet och lägg det förslagsvis under Dokument och en underkatalog som heter Arduino eller direkt under “C:\Arduino\”. Öppna programmet (Sketch:en) från “File->Open” och leta upp “BtnLed.ino” där du sparat programmet när du laddade hem det. Lite nya rader har tillkommit och andra tagits bort från förra exemplet. Förklaring till koden finns nedan under bilden.
Som början på det föregående exemplet finns kommentarer.
/* Button & LED Test Turns on an LED on Pin 13 when button on Pin 2 is pressed. This example code is in the public domain. */
funktion setup() körs precis som innan en gång när programmet (sketch:en) startas, nytt här är två nya kommentarer samt att vi valt att använda I/O pinne 2 som ingång.
void setup() { // initialize the digital pin as an output. // Pin 13 has an LED connected on most Arduino boards. pinMode(13, OUTPUT); // initialize the digital pin as an input. // Pin 2 is connected to a button tied to GND with pullup 10K to VCC. pinMode(2, INPUT); }
När setup() är klart så körs denna loop hela tiden, här ser vi en ny funktion digitalRead() som tar en parameter och det är den I/O pinne som vi vill läsa status på. Funktionen returnerar det aktuella värdet på den ingången (då det är en digital ingång kan värdet anta LOW eller HIGH) och sedan jämför (==) man detta med LOW. I C och C++ har man ett = för tilldelning och två == för att jämföra, vanligt fel att missa detta i en jämförelse. För att testa jämförelsen med den aktuella ingången och om det är LOW (0V, vilket betyder knapp nedtryckt) använder man if-satsen. Det man vill testa omsluts av parenteser och det man vill utföra om uttrycket är sant omsluts av {}. Skulle det inte vara sant (dvs. HIGH/5V, vilket betyder att knappen inte är nedtryckt) då utförs det som finns innanför {} efter else. Det vi gör är att sätta på LED om knappen är nedtryckt och stänga av LED om knappen ej är påverkad.
void loop() { if (digitalRead(2) == LOW) { digitalWrite(13, HIGH); // set the LED on } else { digitalWrite(13, LOW); // set the LED off } }
Skall man bara utföra en sak efter if-else satserna kan man utesluta {} om det man vill utföra, men så fort du skall ha två kommandon/funktioner måste dessa vara där, annars utförs bara den första och sedan blir det fel. Så koden i vårt fall kan även se ut så här.
void loop() { if (digitalRead(2) == LOW) digitalWrite(13, HIGH); // set the LED on else digitalWrite(13, LOW); // set the LED off }
Men vi föredrar att markera med {} så blir det inte något fel om man senare skulle lägga till något i satsen, samt det blir mer lättläst.
En sak som ni kan testa är att se innebörden av att man måste ha ett pullup motstånd, prova med att lyfta upp den gröna tråden som vi anslutet vid knappen, nu har vi i princip en antenn ansluten till ingång 2 och man kan se att lysdioden inte lyser lika skarpt och stadigt som när ledaren var ansluten, det är för att den oscillerar och troligtvis runt 50Hz då den plockar upp nätspänningen i rummet och dess frekvens eller annan frekvens som finns i rummet. Man kan faktiskt få den att blinka till om man rör ledaren med fingret. Man kan även använda intern pullup i en Atmel AVR (i vårt fall en ATMega328P). När man definierar en I/O pinne som ingång är pullup som standard avstängd, men för att slå på den, så skriver vi en logisk etta till ingången, detta gör man efter pinMode() med samma funktion som för att ändra läget på en utgång, dvs. digitalWrite(). Nedan ser du hur detta ser ut, testa gärna och kompilera om programmet och ta bort 10K motståndet.
// initialize the digital pin as an input. // Pin 2 is connected to a button tied to GND with pullup 10K to VCC. pinMode(2, INPUT); digitalWrite(2, HIGH);
Nu har vi lärt oss lite om digitala in och utgångar samt vad pullup är, nu skall vi vidareutveckla detta och även använda oss av variabler.