Trykknap

Fra HTX Arduino
(Omdirigeret fra Forkant)
Spring til navigation Spring til søgning

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.

Pulsdiagram for en trykknap

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.

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[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

Programmering
Programmeringsbegreber Initialisering - Sekvens - Algoritme - Hexadecimal - Det Binære Talsystem - HEX-fil - ASCII - Interrupt - Events - Styresystem - Autocomplete - Selvstudie Programmering - Hour Of Code - Stepwise Improvement - Syntaks - Prog-links - Microcontroller - ChatGPT
Grundlæggende C C float - C double - C-løkker - Datatyper - Konstanter - Regnearter - Funktioner - Return - Returværdi - Rekursion - Semikolon
Variabel Typer boolean - byte - int - unsigned int - word - long - unsigned long - short - float - double - char - unsigned char - string - char array - String - object - Array - 2-dimensionelt Array - void
Program-klassikere Polling - State-machine - Trykknap - Forkant - Bagkant - Prel
Arduino Arduino til Programmering - C til Arduino - Programmering Shield - Arduino PC-software - Arduino Udviklingsmiljø - Arduino Pin Library - Funktion - Arduino Seriel - Arduino String - Arduino String Split - Arduino StateChangeDetection - setup() - loop() - Compilerdirektiver - Asynkron kommunikation - millis() - micros() - Scratch for Arduino - Send fra Arduino til Excel - [[]] - [[]]
Processing Grafik i Processing‎ - Keyboard i Processing - Mus i Processing‎ - Tid i Processing‎ - Draw() - Setup() - Tal Input til Processing - Syntaksfarvning - Kommunikation fra Arduino til Processing - Kommunikation fra Processing til Arduino
javaScript Javascript input‎ - Javascript output‎ - Javascript strukturer‎ - Javascript syntaks‎ - Tid i javaScript - Objekt‎ - AJAX
Serverprogrammering PHP - MySQL - Task Scheduler - WeMOS
PIC JAL - [[]]
Scratch for Arduino S4A Installation - S4A programmering - S4A undervisningsforløb - S4A begrænsninger
Program Dokumentation Algoritme - Flowchart - Pseudokode - Datastruktur - Dataabstraktion - Pulsplaner - Program-kommentar - Teori - Test - UML


Keyes-moduler på Holstebro HTX
Simple Digitale Input Switch modul - Reedrør - Hall sensor - Optisk Skift - Photo Gate - Vibration sensor - Vibration switch - Tilt sensor - Kviksølv kontakt - Linje følger
Digitalt kodede Input IR Modtager - Humidity -Digital Temperatur
5 benede Input Rotary Encoder -XY Joystick
Digitale 4 benede Input Magic Cup Light - LED 3-farve - RGB - RF-link - Afstand
Justerbare analoge/digitale Input Reed Magnetsensor - Temperatur Niveau - Metal detektor - Flamme - Hall Kontakt - Almindelig Mikrofon - Følsom Mikrofon
Simple digitale Output LED 2-farve - Aktiv Buzzer - Blink LED - IR LED - Laser - Relæ modul - Passiv Buzzer
Analoge input Analog Temperatur - LDR - Finger Pulsmåler - Lineær Magnetfelt