ich bin Anfänger und möchte mit dem analogen Eingang Tasten abfragen. Dabei sollen die Tasten eine Variablen Wert verändern. Eine Zahl von 0 bis max. 1000 soll verändert werden. Bei 0 angefangen.
Wenn Taste links dann -100
Wenn Taste rechts dann +100
Wenn Tast up +10
Wenn Taste down -10
Bei Select Wert in die Variable eintragen und Programm starten.
Dabei sollten die Tasten entprellt sein. Ich habe schon ein Beispiel Code hier im Forum gefunden bekommen Ihn aber nicht abgeändert zum laufen.
Das Beispiel habe ich hier aus dem Forum, ich möchte es verändern nur schlugen alle meine Versuche fehl. Die library time.h mit der Zeitfunktion wird von mir nicht benötigt. Ich möchte nur mit den analogen Tasten eine Variable wie beschrieben ändern.
dann schließ den Taster einfach an GND und den analogen Port an.
Nen Pullup Widerstand oder
pinMode(A0,INPUT); digitalWrite(A0,HIGH);
um den internen Pullupwiderstand zu aktivieren.
Entprellen entweder mit ner lib oder je nach Tastern und Wunsch,
mit einem timeout nach dem flankenwechsel
Ich habe hier noch einmal vom Arduino LCD KeyPad Shield (SKU: DFR0009) den Beispielcode eingefügt. Hier fehlt aber noch die Tastenentprellung. Ich bekomme es nicht wie im anderen Code eingebaut. Die Variablen könnte ich ja mit in die case schleife einsetzen.
Bei den LCD Keypads werden über verschiedene Widerstände unterschiedliche Analogwerte erzeugt. Und von dem Zusatand "keine Taste" unterschieden. (Den Schaltplan bei DFROBOT hast du sicher auch gefunden...)
Man kann damit natürlich in der Praxis nicht die 1024 verschiedenen Ergebnisse eines analogRead exakt erzeugen, aber 6 deutlich unterschiedliche Werte für vier Richtungs-Taster, Select und "No Key" sollten machbar sein.
Wenn der Benutzer 2 Tasten gleichzeitigt drückt, ist das sein kein Problem.
switch / case geht in C nur mit exaktem Vergleich, daher wird in keypad libraries erstmal mit einer Reihe von if
der aktuelle Taster ermittelt, bevor dein Beispiel case btnRight:
zum tragen kommt.
Siehe den Sample Code
Tastenentprellung ist bei analogRead nicht ganz so kritisch...
„wert“ wird nicht sauber berechnet, da die Dauer des Tastendrucks Einfluss nimmt, als würde der Taster prellen, seriell sieht man auch dass die Taste mehrmals abgefragt wird.
Ich denke mit der unteren Funktion bekomme ich es sauber hin, weiß aber nicht wie ich sie einfügen soll.
#define DEBOUNCETIME 10
int buttonPressed()
// this function returns true only once per single button pressed
// use this function in your program sketch
{
static boolean buttonFired;
static long buttonDownSince;
int State=readPadButtons();
if (State==btnNONE)
{ // this button is not pressed at this time
buttonFired=false;
buttonDownSince=0;
}
else if (buttonDownSince==0)
{ // button is pressed but DEBOUNCETIME did not yet started counting
buttonFired=false;
buttonDownSince=millis();
}
if (millis()-buttonDownSince>=DEBOUNCETIME && buttonFired==false)
{ // button is pressed and DEBOUNCETIME passed, so fire the button
buttonFired=true;
return(State); // return button
}
}
Hier mein jetziger Code.
code:
//Sample using LiquidCrystal library
#include <LiquidCrystal.h>
/*******************************************************
*
* This program will test the LCD panel and the buttons
* Mark Bramwell, July 2010
*
********************************************************/
// select the pins used on the LCD panel
LiquidCrystal lcd(8, 9, 4, 5, 6, 7);
// define some values used by the panel and buttons
int lcd_key = 0;
int adc_key_in = 0;
#define btnRIGHT 0
#define btnUP 1
#define btnDOWN 2
#define btnLEFT 3
#define btnSELECT 4
#define btnNONE 5
int wert = 0;
// read the buttons
int read_LCD_buttons()
{
adc_key_in = analogRead(7); // read the value from the sensor
// my buttons when read are centered at these valies: 0, 144, 329, 504, 741
// we add approx 50 to those values and check to see if we are close
if (adc_key_in > 1000) return btnNONE; // We make this the 1st option for speed reasons since it will be the most likely result
// For V1.1 us this threshold
if (adc_key_in < 50) return btnRIGHT;
if (adc_key_in < 250) return btnUP;
if (adc_key_in < 450) return btnDOWN;
if (adc_key_in < 650) return btnLEFT;
if (adc_key_in < 850) return btnSELECT;
// For V1.0 comment the other threshold and use the one below:
/*
if (adc_key_in < 50) return btnRIGHT;
if (adc_key_in < 195) return btnUP;
if (adc_key_in < 380) return btnDOWN;
if (adc_key_in < 555) return btnLEFT;
if (adc_key_in < 790) return btnSELECT;
*/
return btnNONE; // when all others fail, return this...
}
void setup()
{
lcd.begin(16, 2); // start the library
lcd.setCursor(0,0);
lcd.print("Push the buttons"); // print a simple message
}
void loop()
{
lcd.setCursor(9,1); // move cursor to second line "1" and 9 spaces over
lcd.print (wert);
//lcd.print(millis()/1000); // display seconds elapsed since power-up
lcd.setCursor(0,1); // move to the begining of the second line
lcd_key = read_LCD_buttons(); // read the buttons
switch (lcd_key) // depending on which button was pushed, we perform an action
{
case btnRIGHT:
{
lcd.print("RIGHT ");
wert=wert +100;
lcd.print(wert);
break;
}
case btnLEFT:
{
lcd.print("LEFT ");
wert=wert -100;
break;
}
case btnUP:
{
lcd.print("UP ");
wert=wert +10;
break;
}
case btnDOWN:
{
lcd.print("DOWN ");
wert=wert -10;
break;
}
case btnSELECT:
{
lcd.print("SELECT");
break;
}
case btnNONE:
{
lcd.print("NONE ");
break;
}
}
}
Wenn du Code Tags zufügst,
(Bereich markieren , dann den # Button anklicken )
füg bitte auch gleich die Implementierung von readPadButtons() ein...
Und/Oder kläre, wann du buttonPressed() verwenden willst, und welche Werte dies in den verschiedenen Zweigen zurückliefert.
Ich fürchte, oft willst du eigentlich btnNONE zurückliefern, weil es noch zappeln könnte, aber es ist undefiniert, was buttonPressed zurückliefert.
Leider in C zulässig ...
Das könntest du als Prellen interpretieren, obwohl es erst duch deinen Code erzeugt wird
Das Keypad-Shield ist eine Kombination aus einem LCD-Display mit sechs Buttons, die über ein Widerstandsarray angeschlossen sind und über nur einen analogen Anschluß abgefragt werden können.
In dem von mir geposteten Beispiel-Sketch kann man mit dem SELECT Button auf dem Shield umschalten zwischen:
Normalbetrieb (in dem Fall damals: "Zeitanzeige")
Zeit einstellen (rechts/links Stunde, up/down Minute)
Datum einstellen (rechts/links Monat, up/down Tag)
Jahr einstellen
Eine ganz simple Sache, für Leute, denen ein full-featured Menü zu aufwändig ist und die trotzdem mit ihrem LCD-Keypad-Shield eine Anzeigefunktion und eine zusätzliche Einstellfunktion haben möchten.
Wenn man das dort von mir vollständig und funktionsfähig gepostete (man braucht nur die Time-Library) Programmierbeispiel verstanden hat, sollte es eigentlich nicht besonders schwierig sein, das umzuschreiben auf
eine andere Anzeige im Normalbetrieb (statt einer "Zeitanzeige")
und mit Änderungen sollte es dann auch möglich sein, dass statt
Stunde
Minute
Tag
Monat
Jahr
andere Variablen im Programm-Sketch eingestellt werden können.
Bei Problemen mit der Anpassung bitte möglichst detailliert schildern, was es werden und wie es ablaufen soll.
Aus dem Ausgangsposting meine ich zu entnehmen, dass es nicht eine "Einstellung im laufenden Betrieb" werden soll, so wie man bei einer Uhr die Zeit nachstellt oder bei einem Temperaturregler die Solltemperatur, sondern vom Ablauf her so etwas wie ein Computerspiel: Wenn der Controller startet, soll man erst etwas einstellen können, und dann beim Drücken auf einen Button startet erst das eigentliche Programm und läuft bis "Game Over" bzw. bis wieder Reset gedrückt wird, also die manuelle Einstellung immer zuerst, bevor irgendwas anderes passiert. Habe ich das so richtig verstanden?
Ich habe jetzt ein delay von 200 bei jeder Tasten Abfrage eingefügt das passt jetzt. Wenn ich die Taste kurz antippe wird der Wert hochgezählt beim Festhalten der Taste folgen mehrere Schritte. Die Einstellungen müssen nicht im laufenden Programm vorgenommen werden. Ich habe mir einen Lichtschranken trigger zum Fotografieren gebaut und wollte mit der variablen „WERT“ beim Programmstart die Verzögerung einstellen. Vielen Dank für Eure Unterstützung.