Forskel mellem versioner af "Testprogram Prog Shield"

Fra Holstebro HTX Wiki
Skift til: navigering, søgning
(Brugervejledning)
(Brugervejledning)
 
(12 mellemliggende versioner af den samme bruger vises ikke)
Linje 129: Linje 129:
 
Der er ikke en bestemt test af displayet, men i stedet bliver displayet anvendt i alle states, så på den måde testes det indirekte.
 
Der er ikke en bestemt test af displayet, men i stedet bliver displayet anvendt i alle states, så på den måde testes det indirekte.
  
Der anvendes standard biblioteket til displayet og de tilpassede benforbindelser, som er lavet på programmeringsshieldet.
+
Der anvendes standard biblioteket til displayet<ref>[https://www.arduino.cc/en/Reference/LiquidCrystal Liquid Crystal Display]</ref> og de tilpassede benforbindelser, som er lavet på programmeringsshieldet.
  
 
Der er enkelte variabler der er lokale, som forklares ved den relevante kode.
 
Der er enkelte variabler der er lokale, som forklares ved den relevante kode.
Linje 447: Linje 447:
  
 
===Analoge indgange===
 
===Analoge indgange===
Der er ingen lokale variable til test af de analoge indgange, med de globale variable analogValue og subState anvendes i styringen, men skal også kunne anvendes i visningen
+
Der er ingen lokale variable til test af de analoge indgange<ref>[https://www.arduino.cc/reference/en/language/functions/analog-io/analogread/ analogRead]</ref>, med de globale variable analogValue og subState anvendes i styringen, men skal også kunne anvendes i visningen
  
 
I initialiseringen sikres at de 3 analoge indgange er input:
 
I initialiseringen sikres at de 3 analoge indgange er input:
Linje 567: Linje 567:
  
 
===Servomotorer===
 
===Servomotorer===
Testen af servoerne er også baseret på standardbiblioteket fra Arduino
+
Testen af servoerne er også baseret på standardbiblioteket fra Arduino<ref>[https://www.arduino.cc/reference/en/libraries/servo/ Servo bibliotek]</ref>.
  
 
Dette bibliotek includes, og der oprettes to objekter til hver sin servomotor.
 
Dette bibliotek includes, og der oprettes to objekter til hver sin servomotor.
Linje 634: Linje 634:
  
 
==Brugervejledning==
 
==Brugervejledning==
 +
Denne brugervejledning beskriver forløbet i at teste [[Programmerings-Shield]]et.
 +
===Trin 1===
 +
Monter programmerings-shieldet på en Arduino ONU ved at sætte de 28 pins ned i Arduinoen - gør det inden der sættes strøm på Arduinoen. Monter et 16x2 karakters LCD Display i det 16 polede stik der passer til det. Tilslut Arduinoen til en USB-port i PC'en og se at der kommer spænding på Arduino og Programmerings-shield,
 +
 +
===Trin 2===
 
For at kunne teste programmerings-shieldet skal softwaren kan hentes fra [[media:test-arduino.zip|denne ZIP-fil]], som indeholder hele den beskrevne software samt det analoge keypad-bibliotek der anvendes af softwaren.
 
For at kunne teste programmerings-shieldet skal softwaren kan hentes fra [[media:test-arduino.zip|denne ZIP-fil]], som indeholder hele den beskrevne software samt det analoge keypad-bibliotek der anvendes af softwaren.
 +
 +
Kontroller at den rigtige COM-port er tilsluttet i Arduino IDE'et (Softwaren til at programmere Arduino med).
  
 
Først installeres analog keyboard biblioteket, og herefter oversættes Test-Arduino.ino og uploades på en Arduino UNO, der har et programmeringsshield tilsluttet.
 
Først installeres analog keyboard biblioteket, og herefter oversættes Test-Arduino.ino og uploades på en Arduino UNO, der har et programmeringsshield tilsluttet.
  
 +
===Trin 3===
 
{|
 
{|
 
|-
 
|-
|valign="top"|Den første test er af analog keypad,<br /> der har 12 taster med det viste layout.  
+
|valign="top"|Den første test er af analog keypad,<br /> der har 12 taster med det viste layout. <br />
 +
Displayet viser hvilke taster der skal tastes.<br />
 +
Testen afsluttes, når den er korrekt gennemført.
 
|[[fil:analog-keyboard-detail.png|thumb|left|150px|Keyboard Layout]]
 
|[[fil:analog-keyboard-detail.png|thumb|left|150px|Keyboard Layout]]
 +
|}
 +
 +
===Trin 4===
 +
{|
 
|-
 
|-
|valign="top"|Den næste test er de 6 LED'er der er tilsluttet ben 3-7 og 9. <br />LED'erne er placeret som vist.  
+
|valign="top"|Den næste test er de 6 LED'er der er tilsluttet ben 3-7 og 9. <br />LED'erne er placeret som vist. <br />
 +
Observer at alle 6 LED'er kan lyse og at der kun tænder en af gangen.<br />
 +
Testen afsluttes ved tat trykke s14.
 
|[[fil:layout-LED.png|thumb|left|250px|Layout af LED'er]]
 
|[[fil:layout-LED.png|thumb|left|250px|Layout af LED'er]]
 +
|}
 +
 +
===Trin 5===
 +
{|
 
|-
 
|-
 
|valign="top"|De analoge input testes ved at give dem de ønskede værdier<br />
 
|valign="top"|De analoge input testes ved at give dem de ønskede værdier<br />
 
A0 varieres ved at dreje på trimmeren ved R0.<br />
 
A0 varieres ved at dreje på trimmeren ved R0.<br />
 
A1 er LDR'en, som skal dækkes til for at give en lav værdi<br />
 
A1 er LDR'en, som skal dækkes til for at give en lav værdi<br />
Har man problemer med at få lys nok, så kan en mobil anbefales<br />
+
Har man problemer med at få lys nok, så kan en mobil anbefales til den høje værdi.<br />
A2 er det analoge keypad igen, hvor der kan tastes 6 og B
+
A2 er det analoge keypad igen, hvor der kan tastes 6 og B<br />
|[[fil:layout-analoge-input.png|thumb|left|250px|Layout af de 3 analoge Input A0, A1 og A2]]
+
Testen afsluttes, når den er korrekt gennemført.
 +
|[[fil:layout-analoge-input.png|thumb|left|250px|Layout af de 3 analoge Input A0-A2]]
 +
|}
 +
 
 +
===Trin 6===
 +
{|
 
|-
 
|-
|valign="top"|
+
|valign="top"|De to kontakter s13 og s14 skal der trykkes på, så de viser ON<br />
|[[fil:.png|thumb|left|200px|Layout af ]]
+
Kontakterne skal samlet være trykket ned i 3 sekunder.<br />
 +
Testen afsluttes, når den er korrekt gennemført.
 +
|[[fil:layout-kontakt.png|thumb|left|250px|Layout af de to kontakter]]
 +
|}
 +
 
 +
===Trin 7===
 +
{|
 
|-
 
|-
|valign="top"|
+
|valign="top"|Stepmotoren sættes på det 5 polede stik, og tilsluttes først når man komme til testen.<br />
|[[fil:.png|thumb|left|200px|Layout af ]]
+
Stikket til testmotoren skal vende rigtigt, det kan man orientere efter de to tapper på stikket.<br />
 +
Når man har testet pilles den af igen. Årsagen er at den bruger ret meget strøm.<br />
 +
Testen afsluttes ved at trykke s13.
 +
|[[fil:layout-Step-Motor.png|thumb|left|250px|Layout af stik til stepmotor]]
 +
|}
 +
 
 +
===Trin 8===
 +
{|
 
|-
 
|-
|valign="top"|
+
|valign="top"|Når Servo 1 skal testes tilsluttes en lille servomotor til Servo1 stikket,<br />
|[[fil:.png|thumb|left|200px|Layout af ]]
+
Vær opmærksom på at stikket skal vendes, så ledningsfarverne passer.<br />
 +
Herefter skiftes til Servo2 stikket og der trykkes 5 på analog keypad for at skifte.<br />
 +
Testen afsluttes ved tat trykke s14.
 +
|[[fil:layout-servo2.png|thumb|left|250px|Layout af servo-stik]]
 
|}
 
|}
 +
 +
Når testen er afsluttes kan man starte den forfra igen, men den følger samme sekvens.
  
 
==Referencer==
 
==Referencer==

Nuværende version fra 9. okt 2021, 09:13

Setup til testprogrammet for Prog-shieldet

Denne side dokumenterer et testprogram, der er lavet til at gennemteste dele af programmerings-shildet.

Ideen med et sådant testprogram, er at man kan teste om shieldet er loddet korrekt sammen, og om de komponenter der sidder på det fungerer som de skal - det giver også en mulighed for at teste enkelte komponenter som tilsluttes shieldet til test.

De dele programmet tester er følgende:

Softwaren kan hentes i denne ZIP-fil, som indeholder hele den beskrevne software samt det analoge keypad-bibliotek der anvendes af softwaren.

Strukturen i testprogrammet

Flowet i programmet kan illustreres som følger:
Flowchart over testprogrammet
Flowchart over testprogrammet

For at dele softwaren op, så er den struktureret i en tab til hvert hardware-del, hvor de fleste har hvert sit test-forløb, mens andre mere eller mindre servicerer de andre dele.

Ud fra den struktur, så er den normale setup() skilt ad i en række funktion, og tilsvarende har alle dele en loop-del, som servicerer den aktuelle del af hardwaren.

Undtagelser i den generelle struktur

Ud fra den måde programmerings-shildet er lavet på, så er der forskellig hardware, som genbruger nogle af de samme ben.

Det giver problemer for input-delen, fordi et af benene - pin 9 bliver brugt både til s13 som input, og LED6 som output. Derfor kan man ikke initialisere benet som input, inden man har kørt gennem testen for output, og når man anvender testen igen, så skal man gen-initialisere ben 9 til output.

Tilsvarede kan servoen heller ikke initialiseres inden man har kørt stepper-testen, da både stepper-motor og servo-motor ligger på ben 10 og 11.

For at samle disse undtagelser, så er der lavet en funktion, som skifter til næste state, og som forholder sig til disse undtagelser. Nogle steder er det nok at nulstille nogle variabler, for at testen kan forløbe korrekt.

Umiddelbart har alle dele sin egen test, bortset fra displayet, som bliver testet ved at den laver visningen for de andre dele. Der er dog også nogle af delene som bliver testet med hjælp fra de andre, specielt fra keypadden og tasterne.

Håndtering af testen i states

Programmet er lavet, så det hele tiden looper gennem alle delene i programmet, så tingene kan foregå med noget der minder om samtidighed for brugeren.

Selve testen er dog opbygget som en sekvens, der overordnet styres af en state-variabel, hvor fremskridtet i testen kan illustreres med følgende state-machine:
Statediagram der styrer forløbet i testen
Statediagram der styrer forløbet i testen

Hvert state styres primært af en programdel, men i en del tilfælde også understøttet af andre programdele til at godkende et trin (et state) i testen.

Globale data

I programmet er der en række variabler, der anvendes på tværs af alle programdele.

Variablerne er erklæret i hovedprogrammet, så alle programdelene kan tilgå dem.

byte state = 0;       // State-variabel, der styrer hvilken test der er i gang
byte subState = 0;    // Underliggende states i analog-testen
int analogValue = 0;  // Den analoge værdi der skal vises i displayet
char nextKey = '1';   // Den næste tast-værdi der forventes i key-test
byte keyIndex = 0;    // Index til hvor langt key-testen er kommet
byte outNr = 0;       // Det aktuelle output der tændes/slukkes
bool s14pressed = false;  // Aflæsning om der er trykket på s14
bool s13pressed = false;  // Aflæsning om der er trykket på s13
bool clearDisplay = false;// Signal til at hele displayet skal renses
byte servoNr = 1;         // Angivelse af hvilken servomotor der testes

Modulerne

Det grundlæggende program i Test-Arduino indeholder setup() og loop() som er standard i Arduino. Der ud over er der en funktion, der anvendes til at skifte mellem de forskellige states i programmet.

Setup kalder de funktioner i dele af programmet, som kan initialiseres, uden at det giver konflikt mellem de forskellige dele.

void setup() {
  Serial.begin(9600);
  setKeypad();
  setDisplay();
  setOutput();
  setAnalog();
  setStep();
}

Loop bliver ved med at kalde alle funktioner der skal servicere de forskellige dele - det er så funktionerne selv der bestemmer, om der skal ske noget.

void loop() {
  loopKeypad();
  loopDisplay();
  loopOutput();
  loopInput();
  loopAnalog();
  loopStep();
  loopServo();
  delay(2);  // Sikrer tid, så analog knapper ikke aflæses for hurtigt
}

Den sidste funktion nextState() er tilføjet for at kunne håndtere stateskiftet ensartet, og alligevel give plads til specielle initialiseringer af moduler og nulstilling af variabler, hvis de skal bruges igen.

// Funktion der udfører det der skal ske ved skift fra et state til et andet
void nextState() {
  switch(state) {
    case 0:  // Skift fra KeyPad
      outNr = 0;
      setOutput();
      break;
    case 1:  // Skift fra Output
      subState = 0;
      break;
    case 2:  // Skift fra Analog in
      setInput();
      break;
    case 3:  // Skift fra Key Input
      keyIndex = 0;
      nextKey = '1';
      setStep();
      break;
    case 4:  // Skift fra Stepper
      setServo();
      break;
    case 5:  // Skift fra Servo
      break;
    case 6:  // Skift fra Afsluttet til genstart
      break;
    default:
      state = 0;
  }
  // Det der sker ved alle skift
  s13pressed = false;
  s14pressed = false;
  state++;
  clearDisplay = true;
}

Display del

Der er ikke en bestemt test af displayet, men i stedet bliver displayet anvendt i alle states, så på den måde testes det indirekte.

Der anvendes standard biblioteket til displayet[1] og de tilpassede benforbindelser, som er lavet på programmeringsshieldet.

Der er enkelte variabler der er lokale, som forklares ved den relevante kode.

#include <LiquidCrystal.h>

LiquidCrystal lcd(13, 12, 7, 6, 5, 4);

unsigned long displayTime = 0;
int displayInterval = 300;
byte inputCount = 0;

Initialiseringen af displayet er standard, den tilpasser blot størrelsen til 16 karakterer x 2 linjer.

void setDisplay() {
  lcd.begin(16, 2);
}

Som det første i loopDisplay håndterer displayTime og displayInterval der der går 300 ms mellem hver opdatering af displayet - det passer med hvad den menneskelige opfattelsesevne normalt ligger på.

Ved hvert state-skifte sættes clearDisplay til true, så man kan starte på et rent display.

void loopDisplay() {
  if ((millis() - displayTime) > displayInterval) {
    displayTime += displayInterval;
    if (clearDisplay) {
      lcd.clear();
      clearDisplay = false;
    }

Herefter starter visningen, som er baseret på hvilket state testen er i.

Det første state tester analog keypad, og der skrives hvilken key der forventes trykket på - håndteringen af variablerne sker i keypad delen af koden. Her håndteres bare visningen.

    switch (state) {
      case 0:
        lcd.setCursor(0, 0);
        lcd.print("Analog Keypad");
        lcd.setCursor(0, 1);
        lcd.print("Tast ");
        lcd.print(nextKey);
        break;

Visningen i state 0 giver følgende resultat:
Visningen i displayet ved state 0 - test af analog keypad
Visningen i displayet ved state 0 - test af analog keypad

I state 1 er display-håndteringen lidt speciel. Årsagen til dette er at udgangene 4-7 bliver brugt til at vise tingene i displayet, så derfor kan vi ikke skrive i displayet mens der testes udgange.

Måden det håndteres på er ved at sætte variablen outNr til 0 når programmet startes. Første gang man kommer ind i display-funktionen med state = 1, så skrives teksten til displayet, og outNr sættes til 3, som er den første udgang til LED'erne - det er så output-delen af softwaren, der håndterer den egentlig test af udgangene.

For at der ikke skal så en rest af displayets brug af udgangene, så sættes hele PORTD (udgang 0-7) til værdien 2, så TX-benet på den serielle ikke forstyrres. udgang 9 (LED 6) sættes også lav.

      case 1:
        if (outNr == 0) {
          outNr = 3;
          lcd.print("LED 1-6");
          lcd.setCursor(0, 1);
          lcd.print("Press S14");
          PORTD = 2;  // Sæt alle ben undtaget TX-benet lavt
          digitalWrite(9, LOW);
        }
        break;

Visningen i state 1 giver følgende resultat:
Visningen i displayet ved state 1 - test af udgange til LED'er
Visningen i displayet ved state 1 - test af udgange til LED'er

I state 2 testes 3 forskellige analoge indgange.

  • Potentiometeret (drejemodstand) ind på A0 testes ved at den skal under 3, og derefter over 1010.
  • LDR'en (den lysfølsomme modstand) ind på A1 testes ved at den skal under 50, og derefter over 400.
  • Det analoge keyboard testes igen. Det går ind på A2, og det testes ved at det først skal over 500 - det er tast 6 - B, og derefter over 1010, som er tast B.

Det er 6 tests der laves, men kun de 3 første er vist i koden herunder.

      case 2:
        lcd.setCursor(0, 0);
        lcd.print("Analog ");
        lcd.print(analogValue);
        lcd.print("   ");
        lcd.setCursor(0, 1);
        switch(subState) {
          case 0:
            lcd.print("R0 below 3");
            break;
          case 1:
            lcd.print("R0 over 1010");
            break;
          case 2:
            lcd.print("LDR below 50");
            break;

Visningen i state 2 giver følgende resultat:
Visningen i displayet ved state 2 - test af analoge indgange
Visningen i displayet ved state 2 - test af analoge indgange

I state 3 indgår display-funktionen aktivt i aftestningen.

Det er input-delen af softwaren, der registrerer i variablerne s14pressed og s13pressed om der er trykket på en kontakt.

Display-delen sørger så for at sætte dem ikke aktive igen ved hver visning, som sker med 300 ms interval.

Variablen inputCount sørger så for at testen stopper igen efter at der har været 10 visninger, svarende til at der har været trykket på kontakterne i samlet 3 sekunder.

For at sikre at den næste test ikke afbrydes, ved at s13 er aktiv når denne test slutter, så afsluttes testen ikke inden s13 er sluppet

      case 3:
        lcd.setCursor(0, 0);
        lcd.print("s14 ");
        if (s14pressed) {
          lcd.print("ON  ");
          inputCount++;
        } else {
          lcd.print("OFF ");
        }
        lcd.print("s13 ");
        if (s13pressed) {
          lcd.print("ON  ");
          inputCount++;
        } else {
          lcd.print("OFF ");
        }
        if (inputCount > 10) {
          while(digitalRead(9)) ;  // Vent på at s13 ikke er aktiv længere
          nextState();
        }
        s14pressed = false;
        s13pressed = false;
        break;

Visningen i state 3 giver følgende resultat:
Visningen i displayet ved state 3 - test af trykknap input
Visningen i displayet ved state 1 - test af trykknap input

I state 4 sættes stepmotoren til at bevæge sig frem og tilbage. Der sker ikke andet i displayet end at der indikeres hvad der gerne skulle ske, og hvad man så skal gøre.

      case 4:
        lcd.setCursor(0, 0);
        lcd.print("Stepper moving");
        lcd.setCursor(0, 1);
        lcd.print("press s13 for OK");
        break;

Visningen i state 4 giver følgende resultat:
Visningen i displayet ved state 4 - test af stepper motor
Visningen i displayet ved state 4 - test af stepper motor

I state 5 testes 2 servoer, og det er lavet, så de kan testes hver for sig.

Displayet viser hvilken servo der testes, og angiver at man kan trykke s14 for at godkende testen, eller man kan trykke 5 på det analoge keypad for at skifte servoNr - teksten i displayet er her blevet meget komprimeret på grund af den begrænsede plads - det betyder at man skal kende programmets funktion for at forstå visningen.

      case 5:
        lcd.setCursor(0, 0);
        lcd.print("Servo ");
        lcd.print(servoNr);
        lcd.print(" moving");
        lcd.setCursor(0, 1);
        lcd.print("s14 OK key 5 sNr");
        break;

Visningen i state 5 giver følgende resultat:
Visningen i displayet ved state 5 - test af servo motorer
Visningen i displayet ved state 5 - test af servo motorer

Når testen er færdig ender state med at være 6 - dette er håndteret ved at placere visningen i default, så det bliver lettere at udvide koden.

Der er lavet så man kan starte testsekvensen forfra ved at trykke s13 - det er lavet her i display-koden, da der ikke er en speciel programdel til afslutningen.

      default:
        lcd.setCursor(0, 0);
        lcd.print("Test OK");
        lcd.setCursor(0, 1);
        lcd.print("press s13");
        if (s13pressed) {
          nextState();
          state = 0;
        }
        break;
    }

Visningen i state 6 giver følgende resultat:
Visningen i displayet ved state 6 - test af analog keypad
Visningen i displayet ved state 6 - test af analog keypad

Analog KeyPad

Teknikken i det analoge keypad er beskrevet på Arduino Analog Keyboard, og for at man kan få keyboardet til at fungere, så skal man have installeret et bibliotek, der kan findes på den side.

Softwaren ligger i den del der hedder KeyPad, og i starten er der kontakten til biblioteket, og de definitioner der skal til for at få keyboardet til et fungere:

#include <Analog_Keypad.h>

const byte NUM_KEYS = 12;
const byte KEYB_PIN = A2;
char hexaKeys[NUM_KEYS] =
{'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B'};

//initialize an instance of class Analog_Keypad
Analog_Keypad myKeypad = Analog_Keypad(hexaKeys, KEYB_PIN, NUM_KEYS);

I den aktuelle software ønskes en bestemt key-sekvens, hvor der skal tastes 5 taster. Sekvensen er lavet 6 lang, da man henvender sig til den næste key, så det sidste element er en dummy-key, som bare sørger for at man ikkke læser uden for arrayet.

Styringen af funktionen og visningen hænger sammen med de to globale variabler nextKey og keyIndex.

I setuppet til denne software-del bliver biblioteket initialiseret.

char keySequence[6] = {'1', '4', '7', '0', 'B', 'A'};

void setKeypad() {
  myKeypad.begin();
}

Selve loop-delen af koden håndterer indtastninger på keypadden uanset hvilket state softwaren befinder sig i. Håndteringen er i høj grad baseret på bibliotekets funktion, der gør at der kun kommer en key-værdi i starten af hvert taste-tryk (værdien skal være den samme i 5 kald inden den sendes), ellers sendes blot NOKEY.

Uanset statet kan man skifte servoNr - det giver godt nok kun mening i state 5, men det skader heller ikke, da det er skevet, så den kun kan skifter mellem 1 og 2.

Selve test-delen, hvor den skal igennem taste-sekvensen sker så kun i state 0.

Hvis den registrerede tast er den samme som den ønskede (i nextKey), så hentes den næste tast fra sekvensen, ellers startes sekvensen forfra. Sekvensen er udformet, så man får testet grænserne af tastaturet og noget omkring midten.

Hvis man kommer igennem de 5 første i sekvensen, så fortsætter programmet til det næste state.

void loopKeypad() {
  char key = myKeypad.getKey(); // Poll for a key value
  if (key != NO_KEY) {  // Are a valid key pressed?
    if (key == '5') servoNr = (servoNr % 2) + 1;
    if (state == 0) {
      if (key == nextKey) {
        keyIndex++;
        nextKey = keySequence[keyIndex];
      } else {
        keyIndex = 0;
        nextKey = keySequence[keyIndex];
      }
      if (keyIndex == 5) {
        nextState();
      }
    }
  }
}

Output til LED'er

For at teste de 6 LED'er skal de hver især kunne både tænde og slukke individuelt, så der laves en sekvens, hvor de er tændt i 200 ms og slukket i 200 ms, hvorefter den næste LED gør det samme.

For at styre tiden og om den aktuelle LED er tændt eller slukket erklæres 3 interne variabler:

unsigned long outputTime = 0;
int outputInterval = 200;
boolean outputLevel = LOW;

Det er den globale variabel outNr der styrer hvilken udgang der skal tænde/slukke en LED.

I initialiseringen sættes alle de aktuelle udgange op til output.

void setOutput() {
  pinMode(3, OUTPUT);
  pinMode(4, OUTPUT);
  pinMode(5, OUTPUT);
  pinMode(6, OUTPUT);
  pinMode(7, OUTPUT);
  pinMode(9, OUTPUT);
}

Selve loopet aktiverer kun kode hvert 200. ms, styret af outputTime og outputInterval.

Hvis det ikke er state 1, så returneres.

Hvis outNr stadig står på 0, så returneres også - det kan ske, hvis ikke displaydelen har fået skrevet til displayet og sat udgangen til nr 3.

void loopOutput() {
  if ((millis() - outputTime) > outputInterval) {
    outputTime += outputInterval;
    if (state != 1) return;
    if (outNr == 0) return;
    Serial.println(outputTime);
    Serial.println(outNr);

Herefter tændes eller slukkes udgangen, så den samlede periodetid på en LED bliver 400 ms.

Der skiftes til den næste LED, hvor udgang nr 8 springes over, og når nr 9 er serviceret, så startes forfra med nr 3, så der hele tiden loopes.

Testen af LED'erne afsluttes ved at der trykkes s14.

    if (outputLevel) {
      digitalWrite(outNr, LOW);
      outputLevel = LOW;
      outNr++;
      if (s14pressed) {
        nextState();
        s14pressed = false;
      }
      if (outNr == 8) {
        outNr++;
      } else if (outNr == 10) {
        outNr = 3;
      }
    } else {
      digitalWrite(outNr, HIGH);
      outputLevel = HIGH;
    }

Analoge indgange

Der er ingen lokale variable til test af de analoge indgange[2], med de globale variable analogValue og subState anvendes i styringen, men skal også kunne anvendes i visningen

I initialiseringen sikres at de 3 analoge indgange er input:

void setAnalog() {
  pinMode(A0, INPUT);
  pinMode(A1, INPUT);
  pinMode(A2, INPUT);
}

Når der loopes, så sikres det at de analoge værdier kun testes i state 2.

Der er opsat 6 betingelser på testen, 2 på hver af de 3 indgange. Dette styres i en else-if struktur bestemt af subState.

I hver subState er der en lidt kompliceret test, som læser den relevante analoge indgang, lægger værdien i analogValue, og derefter tester på betingelsen for om der skal skiftes til næste subState.

Når subState kommer op på 6 så skiftes der til næste hoved-state.

void loopAnalog() {
  if (state != 2) return;
  if (subState == 0) {
    if ((analogValue = analogRead(A0)) < 3) subState++;
  } else if (subState == 1) {
    if ((analogValue = analogRead(A0)) > 1010) subState++;
  } else if (subState == 2) {
    if ((analogValue = analogRead(A1)) < 50) subState++;
  } else if (subState == 3) {
    if ((analogValue = analogRead(A1)) > 400) subState++;
  } else if (subState == 4) {
    if ((analogValue = analogRead(A2)) > 500) subState++;
  } else if (subState == 5)) {
    if ((analogValue = analogRead(A2)) > 1010) subState++;
  } else if (subState == 6) {
    nextState();
  }
}

Input fra kontakter

Programdelen med input fra kontakterne har ingen interne variable, men skriver direkte i de globale variable s14pressed og s13pressed.

Initialiseringen må ikke kaldes efter outputtet er afviklet, da pin 9 her bliver sat til input, så LED 6 ikke fungerer rigtigt i output-delen.

Derfor kaldes setInput() fra nextState() funktionen når output-delen er overstået - ligeledes skal setOutput() kaldes igen fra nextState(), inden output-delen afvikles igen.

void setInput() {
  pinMode(8, INPUT);
  pinMode(9, INPUT);
}

I loop-delen af input aflæses de to input der knytter sig til kontakterne, uanset hvilket state vi befinder os i.

Det betyder at de to kontakter kan anvendes i alle moduler, og at de altid reagerer i de to globale variable. De to globale variable nulstilles derfor også ved hvert skift af state.

void loopInput() {
  if (digitalRead(8)) {
    s14pressed = true;
  }
  if (digitalRead(9)) {
    s13pressed = true;
  }
}

Stepmotor

Testen af stepmotoren er baseret på det standard bibliotek der kommer med Arduino[3]].

Til den gearede stepmotor skal der angives at den har 2038 step pr. omgang, og på programmerings-shieldet er det udgang 10 og 11 der anvendes til stepmotoren.

Det er de samme ben som anvendes til servomotoren, så man skal i testen ikke have begge dele sluttet til mens man tester, da de vil have indflydelse på hinanden, og fordi Arduinoen ikke kan lever nok strøm til begge dele.

#include <Stepper.h>

const int stepsPerRevolution = 2038;  // change this to fit the number of steps per revolution

Stepper myStepper(stepsPerRevolution, 10, 11);

Der anvendes en intern variabel steps, ser angiver hvor mange blokke af step der er taget, den anvendes i loop-delen.

Stepmotoren har også brug for en angivelse af hvor lang tid det enkelte step må tage. Det angives ved at sætte en RPM i setSpeed, som kaldes i initialiseringen. Det betyder at der tages 6 rotationer pr. minut, hvilket med 2038 step pr omgang betyder at der tages ca. 203,8 step pr. sekund.

int steps = 0;

void setStep() {
  myStepper.setSpeed(6);
}

I selve loop-delen returneres der, hvis state ikke er 4, så der kun gøres noget når det state er aktivt.

Den interne variabel steps bliver talt fra 0 til 100, og starter igen forfra på 0.

I de første 50 step sættes motoren til at køre 21 step hver gang steps tælles 1 frem, hvilket betyder at motoren kører 1050 step, eller ca. en halv omgang i den ene retning.

I de step der ligger mellem 50 og 100 sættes motoren til at køre -21 step, altså 21 step den modsatte vej, så den ender der hvor den startede.

Dette fortsætter indtil der trykkes på knappen s13.

void loopStep() {
  if (state != 4) return;
  steps++;
  if (steps < 50) {
    myStepper.step(21);
  } else if (steps < 100) {
    myStepper.step(-21);
  } else {
    steps = 0;
  }
  if (s13pressed) {
    nextState();
  }
}

Servomotorer

Testen af servoerne er også baseret på standardbiblioteket fra Arduino[4].

Dette bibliotek includes, og der oprettes to objekter til hver sin servomotor.

#include <Servo.h>

Servo myServo1;
Servo myServo2;

Der erklæres en række interne variable, som dels skal holde styr på motoren og hvordan den kører, og dels skal der holdes styr på tiden.

int pos = 0;
boolean goingUp = false;
unsigned long servoTime = 0;
int servoInterval = 10;

I initialiseringen sker der det at de to objekter attaches til hhv. ben 10 og ben 11. Timeingen for servoen forberede også, da der skal ske et skift i vinklen for hvert 10. ms.

void setServo() {
  myServo1.attach(10);  // attaches the servo on pin 10
  myServo2.attach(11);  // attaches the servo on pin 11
  servoTime = millis();
}

I loopdelen af servoen sikres først at der kun sker noget, når det er state 5.

Herefter håndteres afslutningen af statet. Der er man nødt til at koble de to servoer af igen. Årsagen til dette er at det signal der sendes til servoen er lavet nede i hardwaren af processoren, så signalet vil køre videre også selvom der ikke skives noget til servoen - dette vil få en dårlig indflydelse på stepmotorens kørsel.

Hvis der skal fortsættes med servoen, så laves det sådan, at koden kun fortsætter hvert 10. ms.

void loopServo() {
  if (state != 5) return;
  if (s14pressed) {
    myServo1.detach();
    myServo2.detach();
    nextState();
  }
  if ((millis() - servoTime) < servoInterval) return;
  servoTime += servoInterval;

Afhængigt af hvilken servo der er aktiv, så skrives positionen til den aktuelle servo - servoNr ligger som en global variabel, da den skal vises i displayet.

Herefter tælles positionen op mod 180, et skridt fro hvert 10. ms, hvorefter den sættes til at ned mod 0. Dette håndteres af de to interne variable goingUp og pos.

  if (servoNr == 1) {
    myServo1.write(pos);
  } else {
    myServo2.write(pos);
  }
  if (goingUp) {
    pos++;
    if (pos > 179) {
      goingUp = false;
    }
  } else {
    pos--;
    if (pos < 1) {
      goingUp = true;
    }
  }

Brugervejledning

Denne brugervejledning beskriver forløbet i at teste Programmerings-Shieldet.

Trin 1

Monter programmerings-shieldet på en Arduino ONU ved at sætte de 28 pins ned i Arduinoen - gør det inden der sættes strøm på Arduinoen. Monter et 16x2 karakters LCD Display i det 16 polede stik der passer til det. Tilslut Arduinoen til en USB-port i PC'en og se at der kommer spænding på Arduino og Programmerings-shield,

Trin 2

For at kunne teste programmerings-shieldet skal softwaren kan hentes fra denne ZIP-fil, som indeholder hele den beskrevne software samt det analoge keypad-bibliotek der anvendes af softwaren.

Kontroller at den rigtige COM-port er tilsluttet i Arduino IDE'et (Softwaren til at programmere Arduino med).

Først installeres analog keyboard biblioteket, og herefter oversættes Test-Arduino.ino og uploades på en Arduino UNO, der har et programmeringsshield tilsluttet.

Trin 3

Den første test er af analog keypad,
der har 12 taster med det viste layout.

Displayet viser hvilke taster der skal tastes.
Testen afsluttes, når den er korrekt gennemført.

Keyboard Layout

Trin 4

Den næste test er de 6 LED'er der er tilsluttet ben 3-7 og 9.
LED'erne er placeret som vist.

Observer at alle 6 LED'er kan lyse og at der kun tænder en af gangen.
Testen afsluttes ved tat trykke s14.

Layout af LED'er

Trin 5

De analoge input testes ved at give dem de ønskede værdier

A0 varieres ved at dreje på trimmeren ved R0.
A1 er LDR'en, som skal dækkes til for at give en lav værdi
Har man problemer med at få lys nok, så kan en mobil anbefales til den høje værdi.
A2 er det analoge keypad igen, hvor der kan tastes 6 og B
Testen afsluttes, når den er korrekt gennemført.

Layout af de 3 analoge Input A0-A2

Trin 6

De to kontakter s13 og s14 skal der trykkes på, så de viser ON

Kontakterne skal samlet være trykket ned i 3 sekunder.
Testen afsluttes, når den er korrekt gennemført.

Layout af de to kontakter

Trin 7

Stepmotoren sættes på det 5 polede stik, og tilsluttes først når man komme til testen.

Stikket til testmotoren skal vende rigtigt, det kan man orientere efter de to tapper på stikket.
Når man har testet pilles den af igen. Årsagen er at den bruger ret meget strøm.
Testen afsluttes ved at trykke s13.

Layout af stik til stepmotor

Trin 8

Når Servo 1 skal testes tilsluttes en lille servomotor til Servo1 stikket,

Vær opmærksom på at stikket skal vendes, så ledningsfarverne passer.
Herefter skiftes til Servo2 stikket og der trykkes 5 på analog keypad for at skifte.
Testen afsluttes ved tat trykke s14.

Layout af servo-stik

Når testen er afsluttes kan man starte den forfra igen, men den følger samme sekvens.

Referencer