Simple Komponenter
For at få en god fornemmelse for programafvikling og sammenhængen med hardwaren omkring Arduinoen, så er det en god idé at starte med at koble simple komponenter op på Arduinoen.
Lysdioder
For at lave noget visuelt (tænde en lampe) så er den simpleste måde at gøre det på, er ved at koble en lysdiode på.
Man kan koble lysdioden direkte på udgangen og til GND, men det er ikke en god ide, da strømmen bliver for stor, så derfor sættes en modstand i serieforbindelse med lysdioden.
Størrelsen af modstanden bestemmer strømmen igennem lysdioden, og dermed hvor meget den lyser, men til langt de fleste ting, så er en modstand på 330Ω helt fin. Den vil typisk have farvekoden orange, orange, brun, guld som det kan ses på modstanden i figur 1.
Opstillingen kan skitseres på forskellige måder (se figur 1). Husk at vende lysdioden korrekt: Det lange ben er anode (+), og forbindes gennem modstanden til en af portbenene på Arduinoboardet, mens det korte ben er kathode (-), og forbindes til GND på Arduinoboardet.
Figur 1 Simpel måde at sætte en lysdiode på en udgang. Husk, at det lange ben på lysdioden er anode (+).
Som man kan se i figur 1, så kan det virke med at sætte lysdioden på i en fuglerede-opstilling. Det virker til en helt simpel test, men det har den ulempe, at man hurtigt kommer til at mangle GND-forbindelser, og at man er nødt til at lodde komponenterne sammen, hvis det skal fungere stabilt.
Hvis man er skrap til at lodde, så kan man koble mere sammen i en fuglerede og løse det på den måde, som det er vist i figur 2.
Figur 2 Eksempel på at koble flere udgange på samme GND i en fuglerede.
Men igen, så er dette ikke den bedste løsning, da ting let kan kortslutte og de løse ledninger kan let afbryde.
Fumlebræt
En noget simplere teknik er at opbygge tingene på et fumlebræt (engelsk kaldet for Bread board), hvor man kan samle tingene.
Fumlebrættet stiller en række forbindelser til rådighed, som man kan udnytte ved at sætte komponenter og ledninger i fumlebrættets huller. De forbindelse der er i fumlebrættet er illustreret i figur 3.
Figur 3. Et fumlebræt til venstre og til høje angivet hvordan hullerne har forbindelser.
Ideen med forbindelserne som vist i figur 3 er, at man kan anvende den blå række til GND, den røde række til +5V eller en anden forsyning, mens de sorte er til komponenter. Den grundlæggende idé er, at man kan placere en IC over den midterste rende, og på den måde kan få forbindelse til alle ben på begge sider af IC’en. Der findes forskellige størrelser og udformninger af et fumlebræt, men den grundlæggende tankegang er den samme.
En måde man kan lave samme opstilling som i figur 2 er ved at opbygge det på et fumlebræt som det er illustreret i figur 4
Figur 4. Opstilling med 3 udgange koblet op på et fumlebræt.
Fordelen ved at koble tingene op på et fumlebræt som vist i figur 4 er, at det er simpelt og fleksibelt; Specielt at man kan lave forbindelse til GND og fordele de forbindelser ud til hele opstillingen.
Typiske Fejl
Uanset hvordan man kobler lysdioder på arduinoen, så er der altid en række fejlmuligheder som kan drille i testen af programmet.
Lysdioden skal vende rigtigt.
Det lange ben er den positive ende, og den negative ende er markeret som en affaset kant på LED-huset.
Der skal være forbindelse hele vejen.
Man skal kunne følge signalet fra udgangen på Arduinoen gennem modstanden, gennem lysdioden og til GND.
Når man flytter på et fumlebræt kan ledningerne hoppe op.
Der skal være forbindelse til GND.
Den fælles side af lysdioderne skal forbindes til GND på Arduinoen.
Der må ikke være kortslutninger.
En klassisk fejl er at placere lysdioden så begge ben sidder i samme bane på fumlebrættet, det kortslutter lysdioden.
Fuglereder kan også let kortslutte når man flytter med dem.
Udgangen er ikke sat til at være output i softwaren.
Man vil på meget følsomme lysdioder opleve at lysdioden lyser svagt, det skyldes at der er en elektrisk styret modstand inde i Arduinoen.
Man skal indsætte pinMode(pinNummer, OUTPUT);
i softwaren (se dokumentet Programafvikling i Arduino)
Diagram
En anden måde at udtrykke kredsløbet på er ved at tegne det som et diagram.
Figur 5. Diagram over Arduinoen med 3 lysdioder tilkoblet.
Når man skal dokumentere hardware, så er diagrammer den mest strukturerede måde at dokumentere på, som det er illustreret i figur 5.
Anvendelse af Shield
En alternativ løsning på at koble lysdioder på udgangene er ved at anvende et Shield[1] der sættes på Arduinoen, som dette eksempel anvendt i Programmeringsundervisningen. Et shield er en printplade, hvorpå alle komponenter der skal anvendes er monteret. Dette ses på figur 6.
Fordelen ved at anvende et Shield er, at når det først er sat på Arduinoen, så vil det fungere i langt de fleste tilfælde, og der sjældent optræder fejl i shieldet.
Ulempen er at det er meget lidt fleksibelt i anvendelsen; Man skal sikre at shieldet har de muligheder man ønsker at anvende i undervisningen. På dette shield er der koblet 6 lysdioder op, og de er koblet til udgangene 3, 4, 5, 6, 7 og 9. De har ingen mulighed for at flyttes til andre udgange.
Figur 6. Et eksempel på et Shield der anvendes i programmering.
På Shieldet i figur 6 sidder der mange andre komponenter end de 6 lysdioder, så man kan koble mange andre ting på. Der sidder også to kontakter på to indgange, ud fra den teknik der beskrives i næste afsnit.
Kontakter
En simpel kontakt er lavet til at kunne påvirke et input på Arduinoen, hvor man kan læse høj (+ 5V) når der er trykket på kontakten og man kan læse lav (0V) når der ikke er.
Figur 7. Arduino med en vippekontakt til input pin 5.
Som man kan se det i figur 7 så kan man påvirke et input med en vippekontakt, så man kan sætte en input pin høj eller lav.
Kontakter på fumlebræt
En enklere måde at gøre det på, hvis man arbejder med fumlebræt er at bruge trykknapper, hvor man sender højt signal ind når der er trykket på knappen og lavt når der ikke er.
Figur 8. En enkelt trykknap koblet til input pin 5.
Som man kan se i figur 8, så skal der både +5V og GND ned på fumlebrættet og der skal anvendes en modstand til at holde signalet lavt (pull-down modstand). Årsagen til dette er at inputtet vil svæve (kan være både højt og lavt) når der ikke er trykket på knappen. Som pull-down modstand anvendes ofte 10kΩ (brun - sort - orange).
Typiske fejl
Den mest typiske fejl med en indgang er, at man mangler en pull-down-modstand, så indgangen giver tilfældigt input når der ikke er trykket på knappen.
Der kan selvfølgelig også være afbrydelser, eller at man ikke har både GND og +5V med ovre på fumlebrættet.
Alle ben på Arduinoen kan læses som digitalt input, og som standard står de som input, så dette er sjældent en fejl.
En typisk programmeringsfejl er, hvis man ønsker at tælle antallet af gange der trykkes på knappen; man skal være opmærksom på, hvor ofte koden hvor portbenet læses, bliver kørt:
- Har man meget delay mellem portbenet læses (500 ms og derover), så vil man typisk se at man “mister” tastetryk.
- Har man middellangt delay (omkring 100 ms), så vil man se af den nogen gange tæller flere gange på et tastetryk.
- Har man meget lidt delay (under 10ms) så vil man se at den tæller helt vildt hver gang man trykker.
Man kan lave en “fusket” løsning, hvor man tilpasser delayet, så det går godt i de fleste tilfælde, men løsningen ligger i at læse forkanter. Dette bliver gennemgået i afsnittet Tælling af tryk på en kontakt.
Diagram
En anden måde at udtrykke kredsløbet på, er ved at tegne det som et diagram.
Figur 9. Diagram over Arduinoen med en vippekontakt tilsluttet input pin 5.
Når man skal dokumentere hardware, så er diagrammer den mest strukturerede måde at dokumentere på, som det er illustreret i figur 9. Dette er blot den ene måde at påvirke et input på digitalt. Normalt er det lettere at bruge trykknapper som vist i figur 10.
Figur 10. Diagram over Arduinoen med en trykknap tilsluttet input pin 5.
I figur 10 er der diagrammet som dokumenterer tilslutningen af en enkelt trykknap til Arduinoen. Det er vigtigt at den ene side af kontakten er forbundet til +5V og at den anden side, som går ind til inputtet har en modstand ned til GND. Det kan være svært at opstille beregninger for denne modstand, men typiske værdier er i området 10kΩ til 100kΩ.
Anvendelse af Shield
Som nævnt under lysdioderne, så kan et Shield være med til at begrænse fejlmulighederne, og på shieldet [1] i figur 6, sidder der to trykknapper koblet på input pin 8 og 9. Som nævnt så virker det også meget begrænsende at anvende et Shield.
De resterende trykknapper der sidder på Shieldet er sat sammen i et tastatur, som anvender en analog indgang [2] til aflæsning af tastaturet. Dette kræver anvendelse af biblioteker som det omtales i dokumentet Moduler og Biblioteker.
Tælling af tryk på en kontakt 
Problemet med at tælle på en kontakt lyder umiddelbart simpelt, men kræver trods alt noget overvejelse.
Den første overvejelse er, at der ikke må være så lange ventetider i loopet, at man misser trykket på en kontakt. Det kræver at man skriver sin software uden delay. Ideen bag dette er beskrevet nærmere i dokumentet Tid og Samtidighed i Software, hvor tricket er, at man tjekker portbenene lige så hurtigt man kan, og så husker på hvad der er sket sidst.
Til tælling af en kontakts input er det princippet i at finde forkanten i koden. Se figur 11 for definition af en forkant.
int cnt = 0; // Den variabel man ønsker at tælle op
int trykknap = 5; // Inputbenet man ønsker at tælle på
boolean lastButton = false; // Husker om der var trykket i sidste loop
void setup() {
Serial.begin(9600);
pinMode(trykknap, INPUT);
}
void loop() {
if (digitalRead(trykknap)) { // Læs status på trykknappen
if (! lastButton) { // Hvis der ikke var trykket på knappen sidst
cnt++;
Serial.println(cnt); // Test-udskrift til Serial Monitor
}
lastButton = true; // Husk status af knappen i en boolean variabel
} else {
lastButton = false;
}
}
Koden udskriver antallet af tryk på knappen i den serielle monitor, se Serial Monitor for nærmere beskrivelse.
Som det kan ses i den viste kode, så er der slet ingen delays, altså looper den så hurtigt processoren kan finde ud af det (omkring 100.000 gange i sekundet), men vil stadig kun finde forkanten af signalet.
Figur 11. Definitionen af henholdsvis forkant og bagkant på et digitalt signal.
Hvis man stadig får fejltællinger, så er problemet sikkert, at kontakten har prel, hvilket er det fænomen at idet kontakten går høj, så har den en kort periode hvor kontakten tænder og slukker, som vist i figur 12.
Figur 12. Illustration af prel-fænomenet både på forkant og bagkant.
Håndtering af Prel
Hvis man kigger på hvordan en kontakt opfører sig i det tidspunkt hvor den slutter forbindelse, og tilsvarende når den afbrydes, så kan der opstå det der hedder prel, som er at kontakten sluttes og afbrydes igen mange gang inden den endelig er helt sluttet. Det kan specielt opstå når kontakter bliver slidte.
Specielt hvis man looper hurtigt rundt i loopet (1 ms eller derunder), så vil man kunne opleve at et tryk måske kan resultere i 2-3 tællinger, hvilket jo ikke er heldigt.
Hvis man kan tillade at der kommer lidt ekstra delay ind i programmet, lige når man trykker, så kan det løses som følger:
if trykknap then
if ! last_knap then
delay_1ms(10)
if trykknap then
taeller = taeller + 1
end if
end if
last_knap = true
else
last_knap = false
end if
Til Arduino ser koden ud som følger:
if (digitalRead(trykknap)) { // Læs status på trykknappen
if (! lastButton) { // Hvis der ikke var trykket på knappen sidst
delay(10);
cnt++;
Serial.println(cnt);
}
lastButton = true; // Husk status af knappen i en boolean variabel
} else {
lastButton = false;
}
Koden her kan dog have en tendens til også at tælle på bagkanten.
Hvis programmet er meget afhængigt af at man kommer hurtigt rundt, så kan man lave en lidt anderledes konstruktion:
if trykknap then
if tryk_count < 25 then
tryk_count = tryk_count + 1
else
taeller = taeller + 1
end if
else
tryk_count = 0
end if
Med denne konstruktion vil man holde tryk_count på 0 så længe der ikke er trykket på knappen, og så længe man ikke kommer forbi mere end 25 gange i en af de små perioder inden signalet er stabilt, så vil der ikke blive talt op i taeller, man må så heller ikke have mere end 25 gange i de små perioder ved bagkanten.
Til Arduino ser koden ud som følger:
if (digitalRead(trykknap)) { // Læs status på trykknappen
if (! lastButton) { // Hvis der ikke var trykket på knappen sidst
edge = millis(); // Registrer tidspunktet for kanten
} else {
if ((millis() - edge) > debounceTime) { // Hvis knappen har været trykket længe nok
if (! counted) { // og der ikke har været talt op før
cnt++;
Serial.println(cnt);
counted = true;
}
}
}
lastButton = true; // Husk status af knappen i en boolean variabel
} else {
lastButton = false;
counted = false;
}
Arduino C-kode
I arduino vil koden kunne løses på følgende måde[3]:
void loop() {
// read the state of the switch into a local variable:
int reading = digitalRead(buttonPin);
// check to see if you just pressed the button
// (i.e. the input went from LOW to HIGH), and you've waited
// long enough since the last press to ignore any noise:
// If the switch changed, due to noise or pressing:
if (reading != lastButtonState) {
// reset the debouncing timer
lastDebounceTime = millis();
}
if ((millis() - lastDebounceTime) > debounceDelay) {
// whatever the reading is at, it's been there for longer
// than the debounce delay, so take it as the actual current state:
// if the button state has changed:
if (reading != buttonState) {
buttonState = reading;
// only toggle the LED if the new button state is HIGH
if (buttonState == HIGH) {
ledState = !ledState;
}
}
}
// set the LED:
digitalWrite(ledPin, ledState);
// save the reading. Next time through the loop,
// it'll be the lastButtonState:
lastButtonState = reading;
}
Indbygget pull-up modstand
Hvis man ikke ønsker at bruge pull-down modstande til at sikre indgangenes niveau med, når der ikke er trykket på en kontakt, så har Arduinoen en indbygget pull-up modstand man kan aktivere [4]. Som det er angivet i Arduinos eksempel i tutorialen [5], så skal man sætte indgangen op til at være pull-up på følgende måde:
pinMode(2, INPUT_PULLUP);
pinMode(13, OUTPUT);
Dette gør at der elektrisk inde i Arduinoen placeres en modstand fra benet og op til +5V på ca 20kΩ.
Det har så den ulempe, at man skal trække til GND med sin kontakt, og i sit program skal man tænke omvendt, fordi inputtet er højt når der ikke er trykket på kontakten, og lavt når der er trykket kontakten; Det kræver at man lige vender sin logik, så hvis man vil skrive et program hvor en udgang tænder på kontakten, så ser det ud som følger:
if (sensorVal == HIGH) {
digitalWrite(13, LOW);
} else {
digitalWrite(13, HIGH);
}
Opkoblingen af hardwaren ser så ud som vist i figur 13
Figur 13. Kobling af trykknap til input pin 2 med indbygget pull-up modstand.
Konsekvensen er at det er nemmere i hardwaren, men man skal tænke sig mere om i softwaren.
Referencer
- ↑ 1,0 1,1 Programmerings-Shield 2017
- ↑ Arduino Analog Keyboard Okt 6, 2017
- ↑ http://arduino.cc/en/Tutorial/Debounce Debounce
- ↑ Arduino pinMode 2017
- ↑ Arduino - DigitalInputPullup 2015