digitalRead-Abtastrate für Arduino Uno

Ich versuche, ein Zeichen über die serielle Schnittstelle zu senden, wenn ich eine externe Taste drücke, die Taste ist an den digitalen IO-Pin 3 angeschlossen, ich habe den Code aus dem SerialCallResponse-Beispiel verwendet und das "Sensor"-Zeug ersetzt, das es in der Hauptsache gemacht hat Schleife mit folgendem:

void loop()
{
 // if we get a valid byte, read button in:
  if (Serial.available() > 0) {
   // read the state of the pushbutton value:
   buttonState = digitalRead(3);  
   if (buttonState == HIGH) {     
     // print B on serial port:    
      Serial.print('B', BYTE);   // send a T
    } 
  }
}

Ich bekomme jedoch mehrere Bs gesendet, also habe ich versucht, eine While-Schleife in den Abschnitt if buttonState==HIGH zu setzen, um zu warten, bis buttonState==LOW, aber wenn ich die Taste drücke und dann loslasse und dann erneut drücke, reagiert sie nicht so schnell, wie ich erwartet hatte, schien eine Antwort von einer Sekunde bis anderthalb Sekunden zu sein (wenn auch nicht genau getimt).

Gibt es eine bestimmte Zeit, die zwischen dem Wechsel des digitalRead auf einen anderen Wert liegen muss? Gibt es eine Art internes „Entprellen“ eines Signals am Digital IO?

Dies ist mein erstes Arduino und ich habe es vor zwei Tagen bekommen, es ist schon viel weiter in meinem Projekt, als ich mit meinem Pic aufgrund des vollen Entwicklungsboards zum Glück kommen konnte.

BEARBEITEN: Also habe ich früher in Adafruits-Tutorials gestöbert und versucht herauszufinden, ob sie irgendetwas über das erwähnt, was ich sehe. Ich habe diesen Code als zusätzlichen Test ausprobiert:

int switchPin = 3;              // Switch connected to digital pin 2

void setup()                    // run once, when the sketch starts
{
  Serial.begin(115200);           // set up Serial library at 9600 bps
  pinMode(switchPin, INPUT);    // sets the digital pin as input to read     switch
}


void loop()                     // run over and over again
{
  Serial.print("Read switch input: ");
  Serial.println(digitalRead(switchPin));    // Read the pin and display the value
  delay(300);
}

Ich drücke den Taster, nachdem ich ihn losgelassen habe, kamen noch etwa 15 1er rüber, was mir sagt, dass selbst wenn ich digitalRead aufrufe, es wirklich nur das Lesen eines Puffers (oder so ähnlich) ist, der den digitalen IO-Port mit einer bestimmten Rate abtastet dies erwartet, irgendwelche Ideen, wo ich herausfinden kann, wo diese Nummer ist? Woher kam es (wieso diese Nummer)?

Wäre die Verwendung eines Interrupts sinnvoller? Auf diese Weise würden Sie nur dann „benachrichtigt“, wenn ein neues Ereignis eintritt.

EDIT #2: Also entschied ich mich, Interrupts auszuprobieren, ich änderte meinen Code wie folgt:

int switchPin = 3;              // Switch connected to digital pin 2

void setup()                    // run once, when the sketch starts
{
  Serial.begin(115200);           // set up Serial library at 9600 bps
  pinMode(switchPin, INPUT);    // sets the digital pin as input to read switch
  attachInterrupt(1,handle_button,FALLING);
}

void loop()                     // run over and over again
{
}

void handle_button()
{
  Serial.print("Read switch input: ");
  Serial.println(digitalRead(switchPin));    // Read the pin and display the value
}

Diese Änderung zeigt jetzt nur noch etwas auf der seriellen Schnittstelle an, wenn ein Interrupt ausgelöst wird. Ich habe die Taste gedrückt und "Lese Schaltereingang: 1" erhalten, aber wenn ich die Taste jederzeit drücke, bevor 30 Sekunden vergangen sind (ungefähr bis 30 gezählt), scheint es den Interrupt nicht auszulösen. Ich warte auf eine Zählung von 30 und erhalte die Meldung "Schaltereingang lesen: 1". Auch dies sagt mir weiterhin, dass das digitale IO nicht sehr schnell abgefragt wird, ich finde das überraschend, ich habe in der Vergangenheit mit Pics herumgespielt und dieses Problem nicht bemerkt, und dies ist mein erstes "richtiges" Programm Mit dem Arduino frage ich mich, ob ich vielleicht etwas einrichten muss?

Das Problem ist und bleibt, dass ich mich frage, mit welcher Rate das Arduino Uno (und genauer gesagt das Atmel Atmega 328P) die digitalen IO-Ports abfragt.

BEARBEITEN #3 Um genauer zu sein, es sind ungefähr 12 Sekunden (verwendete einen Online-Timer und behielt ihn im Auge). Wenn ich innerhalb von 11 Sekunden ein zweites Mal drücke, wird es nicht ausgelöst und ich muss nach dem zweiten Drücken noch weitere 12 Sekunden warten.

Was ist der Zweck, es in ein if serial.available () zu packen?
Ich habe das Beispielprogramm verwendet, im Grunde muss das externe Gerät einmal reagieren, um die Existenz zu bestätigen, dann überträgt die MCU die Daten, wenn ein Tastendruck auftritt, es ist nicht kritisch für das Projekt und wird wahrscheinlich irgendwann entfernt, ist es möglich, dass gelesen wird verlangsamt die Dinge .... jetzt muss ich es vielleicht versuchen ....
Ich würde es vorerst verschrotten - eine Sache, die nur im Weg steht. Halten Sie das Programm zu Beginn so einfach wie möglich.
@onaclov2000 - wie genau ist dein Button verbunden? Hast du einen Pullup- oder Pulldown-Widerstand angeschlossen?
Kein Widerstand, aber ich habe einen eingebaut, jetzt funktioniert es wie erwartet.

Antworten (2)

Sie haben jetzt zwei Probleme, die voneinander getrennt sind.

1) Tastenprellen

2) Falsche Tastenverdrahtung

Zuerst müssen Sie eine Verzögerung in Ihre Unterbrechungsfunktion einführen, damit sie nicht jeden Anstieg und Abfall des Aufpralls als separaten Tastendruck registriert. Verwenden Sie "delayMicroseconds()", da Sie anscheinend kein reguläres "delay()" innerhalb von Interrupts verwenden können. Ich würde eine Verzögerung von 20.000 Mikrosekunden vorschlagen.

Zweitens müssen Sie einen Pulldown-Widerstand auf den digitalen Pin legen, den Sie abtasten.

Das Problem, das Sie haben, ist, dass sich der Pin im Eingangsmodus befindet und daher hochohmig (sehr hochohmig) ist und daher "schweben" muss. Wenn Sie eine Spannung daran anlegen, lädt er sich wie ein Kondensator auf und da der Pin selbst einen sehr hohen Widerstand gegen Masse hat, dauert es eine Weile, bis sich die Ladung bis zu dem Punkt aufgelöst hat, an dem der Arduino wieder ein LOW registriert. Ein 10k-Widerstand vom Pin zur Masse zwingt den "Kondensator", sich schnell zu entladen, nachdem der Strom von der Taste aufgehört hat zu fließen.

Schließlich ist der Arduino ziemlich schnell bei seinen Lese- / Schreibvorgängen (ich bin Maschinenbauingenieur, ALLE Elektronik passiert "schnell" im Vergleich zu mechanischen Systemen, also ist es relativ, denke ich). Hier ist ein Link zu einigen Testergebnissen.

TL;DR-Version:

What these values tell me, is that we can do about:

10 analog 10-bit readings per millisecond with analogRead()
128 pwm settings per millisecond with analogWrite()
220 pin reads per millisecond with digitalRead()
224 pin writes per millisecond with digitalWrite()
1056 pin reads per millisecond with direct port reads
1059 pin writes per millisecond with direct port writes
Das würde es tun, wieder vereitelt durch Pull-Up / Down-Widerstände. Ich hatte wahrscheinlich vor 2 Jahren ein ähnliches Problem (das letzte Mal, als ich offensichtlich mit einem Knopf herumgespielt habe), kann nicht glauben, dass ich es nicht erkannt habe.
Kein Problem, eigentlich hatte ich dieses Problem erst letzte Woche selbst...

Der Grund, warum Sie mehrere Bs erhalten, liegt darin, dass die Funktion "Schleife" in einer Endlosschleife aufgerufen wird.

while (true) {
    loop();
}

Vielleicht hilft es, Ihre Funktion so zu betrachten:

while (true) {
    if (Serial.available() > 0) {
        buttonState = digitalRead(3);  
        if (buttonState == HIGH) {     
            Serial.print('B', BYTE);   // send a T
        } 
    }
}

Sobald die serielle Eingabe verfügbar ist, lesen Sie den Zustand der Taste und senden ein 'B', falls die Taste gedrückt wird. Die serielle Eingabe wird nie verbraucht, weil Serial.read() nie aufgerufen wird, also passiert beim nächsten Durchgang durch Ihre Schleifenfunktion dasselbe.

Wenn Sie nur ein 'B' senden möchten, wenn die Taste gedrückt wird, könnte dies Folgendes tun:

int buttonState = LOW;
int button0, button1;

void setup()
{
    Serial.begin(9600);
    pinMode(3, INPUT);
}

void loop()
{
    button0 = digitalRead(3);
    delay(10);
    button1 = digitalRead(3); // de-bounce

    if (button0 == button1) {
        if (button0 != buttonState) {
            buttonState = button0;
            if (buttonState == HIGH) {     
            Serial.println("B");
            } 
        }
    }
}

Unten ist ein Link zu einem ziemlich gründlichen Tutorial für den Umgang mit Schaltflächen. Es erklärt auch die Verzögerung von 10 ms, um die Taste einschwingen zu lassen.

http://www.ladyada.net/learn/arduino/lesson5.html

Ich verstehe, dass es wegen der While-Schleife mehrere Bs sendet. Was ich nicht verstehe, ist, warum es nicht mehr oder weniger schnell von High zu Low wechselt ... wenn das Sinn macht.