Simple Komponenter

Fra HTX Arduino
Spring til navigation Spring til søgning
Video med forklaring til kapitlet

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.

Simpel måde at sætte en lysdiode på en udgang   Simpel måde at sætte en lysdiode på en udgang
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.

Simpel måde at sætte en lysdiode på en udgang   Simpel måde at sætte en lysdiode på en udgang
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.

Et fumlebræt til venstre og til høje angivet hvordan hullerne har forbindelser
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


Opstilling med 3 udgange koblet op på et fumlebræt
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.


Diagram over Arduinoen med 3 lysdioder tilkoblet
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.


Et eksempel på et Shield der anvendes i programmering
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.


Arduino med en vippekontakt til input pin 5
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.


En enkelt trykknap koblet til input pin 5
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.


Diagram over Arduinoen med en vippekontakt tilsluttet input pin 5
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.


Diagram over Arduinoen med en trykknap tilsluttet input pin 5
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 Svaert.png

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.


Definitionen af henholdsvis forkant og bagkant på et digitalt signal
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.


Illustration af prel-fænomenet både på forkant og bagkant
Figur 12. Illustration af prel-fænomenet både på forkant og bagkant.

Håndtering af PrelSvaert.png

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.

Trykknap med prel

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


Kobling af trykknap til input pin 2 med indbygget pull-up modstand
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

Kom i gang med Arduino
Grundlæggende forståelse for Arduino Arduino Hardware - Arduino Prototype Print - Blink Eksempel - Overblik - Serial Monitor - Simple Komponenter - Software og Udviklingsmiljø
Programmering af Arduino Anvendelse af Eksempler - Klasser og Objekter - Programafvikling i Arduino - Test af Programmer
Dokumentationsformer Dokumentation med Kode og Flowchart - Dokumentation med State-machines - Flowchart - Pseudokode - Program-kommentarer - Systemdokumentation - Syntaksfarvning - Blokdiagram - Pulsplaner - UML
Opkoblinger til Arduino Moduler og Biblioteker - Driver - Opkobling af Hardware - Simple Komponenter - Tips til anvendelse af ben på Arduino UNO
Kompliceret Programmering Arduino kombineret med Processing - Kommunikation fra Arduino til Processing - Kommunikation fra Processing til Arduino - CopyThread Multitasking - Dokumentation med State-machines - Tid og Samtidighed i Software - Arduino Memory
Kompliceret Hardware I2C - Andre Processorboards - Internet of Things (IoT)
Oprindelige Dokumenter PDF-Version - Forfattere
Software Udviklingsteknikker Agile metoder - Brugertest - SCRUM

Fasemodellen - Kravspecifikation - Databasedesign - Struktur eller Arkitektur - Softwaretest

Projekter Afstand programforslag - Lysmåling - Projektforslag - Prototyper
Undervisningsforløb 4t Valgfag til Folkeskolen - Læsevejledning 4t Valgfag - Materialer til 4t Valgfag - Undervisningsnoter 4t Valgfag - Undervisningsplan 4t Valgfag - Slides til Undervisning

Kort Valgfag til Folkeskolen - Læsevejledning Kort Valgfag - Materialer til Kort Valgfag - Undervisningsnoter Kort Valgfag - Undervisningsplan Kort Valgfag