Wie man sechs Tasten auf einem analogen Pin mit Arduino entprellt

Ich verwende den analogen Pin 5 auf Arduino, um das Drücken von 6 Drucktasten zu erkennen. Auf dem Bild oben rechts ist die Nummer 1 und dann von rechts nach links gehen sie als 2, 3, 4, 5, 6. Das Programm sollte 0 drucken, wenn keine der Tasten gedrückt wird, und wenn eine von ihnen gedrückt wird, sollte es Drucken Sie seine Position, wie ich zuvor erwähnt habe. Derzeit besteht das Problem darin, dass, wenn ich die zweite Taste drücke, manchmal (statt nur einmal) manchmal ein paar Mal 2 gedruckt wird. Ich denke, es liegt an dem "Rauschen", wenn die Taste gedrückt wird, und dass es entprellt werden sollte, aber ich weiß nicht, wie man den analogen Pin entprellt.

Mein Code:

int old_button = 0;
int button;
int pressed_button;
int z;

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

void loop () {
  z = analogRead(5);
  if (z > 1021) button = 0;                                           
  else if (z > 511 && z < 514) button = 1;                     
  else if (z > 680 && z < 684) button = 2;                
  else if (z > 766 && z < 770) button = 3;                
  else if (z > 817 && z < 822) button = 4;             
  else if (z > 851 && z < 856) button = 5; 
  else if (z > 875 && z < 880) button = 6;
  else button = 0;                                                      

  if (old_button == button) {                                           
    old_button = button;                                              
    pressed_button = 0;                                               
  }  

  else {                                                                
    old_button = button;                                             
    pressed_button = button;                                        
  }
  Serial.println(pressed_button);
}

Schaltung (2200 Ohm Widerstände):

Geben Sie hier die Bildbeschreibung ein

Ein elektrischer Schaltplan wäre in diesem speziellen Fall besser als ein Fritzing-Diagramm. Verwenden Sie den integrierten Schaltplan-Editor.
@Mate Nur zur Info. Es gibt jetzt einen spezialisierten Arduino-Stack: arduino.stackexchange.com
Kann diese Lösung mit dem DEEP SLEEP-Modus (unter Verwendung von durchschnittlich 0,2 uA mit einem ATmega oder ATtiny auf dem Steckbrett) und Pin Change Interrupt (PCINT) arbeiten?

Antworten (4)

Wenn Sie einen signifikanten Unterschied im ADC-Messwert feststellen, warten Sie 20 Millisekunden und mitteln Sie dann einige Messwerte und treffen Sie dann eine Entscheidung. Wenn einer der Messwerte immer noch schlecht quantifizierbar aussieht, warten Sie eine weitere kurze Zeit.

+1 für die Antwort. Hey Andy, ist es klug, einen 104-Kondensator von der Tastenleitung zu erden (zum Debancing)?
@roh nicht klug, wenn dies bedeutet, dass ein Schalter über eine aufgeladene 100-nF-Kappe angeschlossen wird, da der Stromimpuls die MCU zurücksetzen könnte. Am besten 100 Ohm in Reihe mit dem Schalter schalten.
@Andyaka: Könntest du mir bitte einen Pseudocode für deine Antwort schreiben?
@Mate Ich bin ein verbaler Typ (na ja, die meiste Zeit und manchmal nicht entzifferbar!) Und ich habe seit Jahrtausenden keinen Pseudocode geschrieben. Es sollte nicht schwierig sein, sich vorzustellen, was ich sage - ich mag Schaltungen, aber ich habe Sie nicht gebeten, dieses schreckliche Fritzing-Ding in ein LOL zu ändern
@Andyaka Der Stromimpuls von 100 nF könnte die MCU zurücksetzen?! Was ist das für eine wertlose Mist-MCU?! Werfen Sie es sofort weg, holen Sie sich ein echtes ...
@Lundin Sei nicht zu hastig. Wenn das Leiterplattenlayout nicht gut ist, kann der Strom (10 Ampere in wenigen Nanosekunden) leicht einen Reset verursachen.
Hmm. Ich glaube, er hat gefragt, ob er eine Entkopplungskappe hinzufügen könnte, und Sie haben geantwortet, dass Sie eine Kappe in Reihe geschaltet haben? Auf jeden Fall möchten Sie diesen Vorwiderstand wahrscheinlich sowieso dort haben, um ESD-Immunität zu erhalten, Mist-MCU oder nicht. Knöpfe werden wahrscheinlich mit aufgeladenen Menschen in Kontakt treten.

Ja, es ist ein Entprellgeräusch. Sie müssen etwas warten (z. B. 50 ms) und den analogen Eingang erneut lesen. Wenn das Ergebnis übereinstimmt, kann der Schaltflächenwert als gültig betrachtet werden. Etwas wie das:

int old_button = 0;

int getButton()
{
  int i, z, sum
  int button;

  sum = 0;
  for (i=0; i < 4; i++)
  {
     sum += analogRead(5);
  }
  z = sum / 4;
  if (z > 1021) button = 0;                                           
  else if (z > 511 && z < 514) button = 1;                     
  else if (z > 680 && z < 684) button = 2;                
  else if (z > 766 && z < 770) button = 3;                
  else if (z > 817 && z < 822) button = 4;             
  else if (z > 851 && z < 856) button = 5; 
  else if (z > 875 && z < 880) button = 6;
  else button = 0;

  return button;
}


void loop ()
{
  int button, button2, pressed_button;  
  button = getButton();
  if (button != old_button)
  {
      delay(50);        // debounce
      button2 = getButton();

      if (botton == button2)
      {
         old_button = button;
         presed_button = button;
         Serial.println(pressed_button);
      }
   }
}

Da Andy keinen Code bereitstellen wollte, habe ich bei der ADC-Messung eine Mittelung hinzugefügt. Die Mittelung in getButton berücksichtigt also jedes Rauschen, das die analoge Leitung liest, die in den ADC kommt, und die Verzögerung von 50 ms sorgt für die Erkennung des Schalterprellens.

@Mate Ich habe den Code zum Mitteln des ADC-Rauschens zu meiner Antwort hinzugefügt. Danke an Andy aka für den Vorschlag, es war eine gute Ergänzung.

Viele Schalter des von Ihnen verwendeten Stils lassen sich nur schwer gut entprellen, und der Versuch, einen resistiven Multiplexer zu verwenden, wird es nicht einfacher machen. Wenn Sie sich jedoch zwei Port-Pins (einen analogen) leisten können, kann ich Ihnen ein Erfolgsrezept anbieten, das auch dann funktionieren sollte, wenn Ihre Switches ziemlich mies sind. Ich würde vorschlagen, den Stromschienenwiderstand (ignorieren Sie die untere Stromschiene des Steckbretts) links von Ihrem ganz linken zu verschieben und ihn mit einem nicht analogen Anschlussstift zu verbinden. Der gemeinsame Draht oben sollte mit dem analogen Port-Pin verbunden werden. Der Draht vom Widerstand ganz rechts sollte mit Masse verbunden sein.

Wenn Ihr Gerät "inaktiv" ist (Sie glauben nicht, dass irgendwelche Tasten gedrückt werden), stellen Sie den gemeinsamen Ausgang auf hoch und schweben Sie den anderen. Es wird niedrig angezeigt, wenn keine Tasten gedrückt werden, und wird nahe VDD angezeigt, wenn eine Taste gedrückt wird.

Um herauszufinden, welche Taste gedrückt wird, schwimmen Sie den gemeinsamen Draht und treiben Sie den linken Draht hoch. Setzen Sie den gemeinsamen Draht kurz hoch oder niedrig (siehe Hinweis) und schweben Sie ihn erneut, und lesen Sie dann die Spannung an diesem Stift etwas später ab (halten Sie den linken Draht hoch). Sobald die Messung durchgeführt wurde, können Sie, falls gewünscht, den Strom zum linken Kabel ausschalten (schalten Sie es vor dem nächsten Lesezyklus wieder ein).

Während eine Taste gedrückt wird, sollte die Spannung auf dem gemeinsamen Draht ein schöner Bruchteil von VDD sein (wenn es sechs Tasten und sieben Widerstände gibt, sollten die Tasten 1/7, 2/7, 3/7 usw. bis zu 6 anzeigen /7); Die Spannung sollte nicht übermäßig davon beeinflusst werden, ob der gemeinsame Stift kurz hoch oder niedrig gepulst wurde. Wenn keine Taste gedrückt wird, sind die Messwerte, nachdem der Pin hoch gepulst wurde, viel höher als nach dem niedrigen Puls. Dies zeigt an, dass die Taste losgelassen wurde.

Sobald die Taste losgelassen wurde, können Sie zur "Leerlauf"-Konfiguration zurückkehren. Wenn der linke Widerstand hoch getrieben wird, zieht die Widerstandskette Strom, unabhängig davon, ob Tasten gedrückt werden oder nicht, aber wenn der linke Stift schwebend ist und der gemeinsame Draht hoch ist, wird kein Strom gezogen, bis eine Taste gedrückt wird.

Um mit billigen Schaltern gute Ergebnisse zu erzielen, sollten Sie nach jedem kurzzeitigen "Masse" - oder "VDD" -Impuls auf Ihrem gemeinsamen Kabel lange genug verzögern, damit der Schalter, wenn er überhaupt Kontakt herstellt, einen guten Messwert liefert (versuchen Sie es mit einem 100-K-Widerstand parallel zu einem Schalter, und stellen Sie Verzögerung und Empfindlichkeit so ein, dass der Schalter „gerade so“ als gehalten registriert wird). Billige Schalter haben einen Widerstand von weit über einem Meg, wenn sie vollständig losgelassen sind, und weniger als 10 Ohm, wenn sie vollständig gedrückt sind, aber ihr Widerstand kann zwischen diesen Zuständen überall hin und her wandern, und herkömmliches Entprell-Timing hilft nicht. Was hilft, ist eine Schaltung, die einen Tastendruck nicht erkennt, bis der Widerstand ziemlich niedrig wird, und eine Taste als gehalten betrachtet, es sei denn, ihr Widerstand wird viel höher. Für die Schaltung, die ich beschrieben habe,

Das klingt wirklich toll, braucht aber eine Art Grafik.
Stimme voll und ganz zu. Ein Schaltplan (sogar eine grobe Skizze) würde wirklich helfen, die ansonsten hervorragende Antwort zu verdeutlichen.

Ich habe erst kürzlich angefangen, mit Arduino zu arbeiten, und obwohl dies eine alte Frage ist, habe ich diesen Thread gefunden, als ich versuchte, die Anzahl der Schaltflächen zu erweitern, die ich hören konnte.

Ich habe nach der ursprünglichen Fritzing-Illustration gearbeitet und sowohl in Hardware als auch in Software eine leichte Variante erstellt.

Arduino Analog hört auf 6 Drucktasten

Ich habe den Widerstandssatz so modifiziert, dass er unterschiedliche Werte verwendet, um zu versuchen, einen konsistenteren Schritt zwischen den Schaltern zu erzeugen, anstatt die logarithmischen Schritte, die durch die Verwendung derselben Widerstände durchweg erzeugt werden.

Ab 5V sind die Widerstände:

  • 1kΩ
  • 180Ω
  • 240Ω
  • 330Ω
  • 510Ω
  • 800Ω

Dies erzeugt Schritte von etwa 0,5 V zwischen jedem Schalter.

Ich habe auch eine grundlegende Software erstellt, die nach dem gleichen Wert für 3 Messwerte in Folge sucht, bevor sie eine Spannungsänderung bestätigt. Dies eliminiert kleine Schwankungen in der Ablesung.

int sensorPin = A5; // The input port
int sensorValue; // Current reading
int outputValue; // The reported reading
int lastValues[3] = {0,0,0}; // The last 3 readings

void setup() {
  Serial.begin(9600);
}

void loop() {
  // read the value from the sensor:
  sensorValue = analogRead(sensorPin);
  // Initialise variables for checks
  int i;
  int updateOutput = 1;
  // Loop through previous readings
  for( i = 0 ; i<3 ; i++ ){
    // If this historic value doesn't match the current reading,
    // we will not update the output value
    if( lastValues[i] != sensorValue ){
      updateOutput = 0;
    }
    // Shift the array elements to make room for new value
    if( i>0 ){
      lastValues[(i-1)] = lastValues[i];
    }
  }
  // Update if needed
  if( updateOutput == 1 ){
    outputValue = sensorValue;
  }
  // Append the new value
  lastValues[2] = sensorValue;
  // Debugging output
  Serial.print(sensorValue);
  Serial.print(" ");
  Serial.println(outputValue);
}

Offensichtlich lastValueskönnte das Array in jeder gewünschten Länge hergestellt werden - je länger das Array, desto länger muss ein Schalter gedrückt werden, um erkannt zu werden.

In meinen Tests waren die gemeldeten Sensorwerte:

  • 1023: Keine Schaltfläche
  • 0: Taste Nr. 1
  • 196: Taste #2
  • 301: Taste Nr. 3
  • 405: Schaltfläche Nr. 4
  • 508: Taste #5
  • 613: Taste #6

(Getestet nach Diagramm.)

Meine grobe Mathematik legt nahe, dass Sie dies sogar auf 8 Tasten erweitern könnten, indem Sie als nächstes die folgenden Widerstände hinzufügen (die die Spannung wieder in 0,5-V-Schritten fallen lassen sollten):

  • 1,7 kΩ
  • 5kΩ