Trykknap
Det er sjældent svært at håndtere en trykknap, hvis det man ønsker er, at når den er trykket nede, så skal der ske et eller andet.
Elektrisk tilslutning
Man skal være opmærksom på at man ikke bare kan slutte den ene side af kontakten til høj, og den anden til et input - det vil få indgangen til at svæve når der ikke er trykket på knappen. Man kan læse mere om dette under pull-down.
Det kan lade sig gøre at slutte kontakten til uden andre komponenter, men der skal man sætte kontakten til stel, så man læser den som aktivt lav, og samtidigt skal man så aktivere den interne pull-up som følger:
byte kontaktPin = 8;
void setup() {
pinMode(kontaktPin, INPUT_PULLUP);
}
Niveau
Hvis det f.x. er at en udgang skal være høj når knappen er trykket ned, og lav når den ikke er det, så er det en simpel konstruktion:
if trykknap then
udgang = high
else
udgang = low
end if
Arduino C-kode
I arduino vil koden kunne løses på følgende måde[1]:
digitalWrite(ledPin, digitalRead(buttonPin));
Dette er en meget komprimeret måde at gøre det på, og det kunne også gøres som følger:
if (digitalRead(buttonPin)) {
digitalWrite(ledPin, HIGH);
} else {
digitalWrite(ledPin, LOW);
}
Forkant
Det er bare sjældent at det er så simpelt. Hvis man har etableret sit eget styresystem, så man har gang i flere ting på en gang, så vil man typisk komme rundt i loopet mange gange i sekundet.
Hvis man f.x. ville tælle en frem hver gang der bliver trykket på en knap, så stiller det sig noget anderledes.
Elektrisk kan trykknappen kobles op med en kontakt og en Pull-down modstand.
Man kan godt prøve at indstille på den tid som man looper med, og i de fleste tilfælde kan man godt få det indstillet så man selv kan taste fornuftigt ind, men der vil altid ske det at man nogle gange fanger 2 gange på den samme indtastning og andre gange fanger man slet ikke indtastningen.
Løsningen er at i softwaren fanger en forkant, ved at man husker på hvad status var af knappen sidst man kom rundt i loopet, og så forholde sig til det. Det kan løses som følger:
if trykknap then
if ! last_knap then
taeller = taeller + 1
end if
last_knap = true
else
last_knap = false
end if
Denne måde at løse tingene på vil virke fint, specielt hvis man har et delay i loopet på ca. 10 ms.
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
cnt++;
Serial.println(cnt);
}
lastButton = true; // Husk status af knappen i en boolean variabel
} else {
lastButton = false;
}
Bagkant
Man kan også løse det ved at det er på bagkanten af signalet man tæller op. Det løses som følgende:
if ! trykknap then
if last_knap then
taeller = taeller + 1
end if
last_knap = false
else
last_knap = true
end if
Dette kunne også være fordi trykknappen er realiseret ved hjælp af en Pull-up modstand i stedet for en Pull-down.
Til Arduino ser koden ud som følger:
if (! digitalRead(trykknap)) { // Læs status på trykknappen
if (lastButton) { // Hvis der var trykket på knappen sidst
cnt++;
Serial.println(cnt);
}
lastButton = false; // Husk status af knappen i en boolean variabel
} else {
lastButton = true;
}
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[2]:
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;
}
Referencer
- ↑ http://arduino.cc/en/Reference/DigitalWrite DigitalWrite
- ↑ http://arduino.cc/en/Tutorial/Debounce Debounce