Hey Leute,
ich steh gerade glaub ich mega auf dem Schlauch....
Mein Display ist zur Auswahl von Cocktails da. Ich habe bis jetzt 6
Strings in denen verschiedene stehen. Jetzt soll über die Taster Down
und Up alle angezeigt werden.
Ich dachte es mir so:
case btnUP:
{
lcd.setCursor(0,0);
lcd.print(myStrings[i]);
i--;
lcd.setCursor(0,1);
lcd.print(myStrings[i]);
i--;
break;
}
case btnDOWN:
{
lcd.setCursor(0,0);
lcd.print(myStrings[i]);
i++;
lcd.setCursor(0,1);
lcd.print(myStrings[i]);
i++;
break;
}
Nur leider zählt er beim zweiten nicht hoch und nicht runter.... er
zeigt mir in der ersten Zeile String 1 an und in der 2. Zeile String 2,
dass funktioniert.
Hat jemand eine Idee????
Vielen vielen Dank
es sieht so aus, ohne den ganzen Code zu kennen, als ob nur
einmal btnDOWN bzw. btnUP angesprungen wird.
Der Fehler liegt wahrscheinlich in der Tastenabfrage oder
Aufruf des Unterprogramms.
case btnUP:
{
lcd.setCursor(0,0);
lcd.print(myStrings[i]);
i--;
lcd.setCursor(0,1);
lcd.print(myStrings[i]);
i--;
if (i==0) i=6; // Nach Menüpunkt 1 dann Menüpunkt 6
break;
}
case btnDOWN:
{
lcd.setCursor(0,0);
lcd.print(myStrings[i]);
i++;
lcd.setCursor(0,1);
lcd.print(myStrings[i]);
i++;
if (i==7) i=1; // Nach Menüpunkt 6 dann Menüpunkt 1
break;
}
Katrina N. schrieb:> else if (x < 400) {
Ich würde zusätzlich noch folgende Bedingung hinzufügen:
else if ((x<400) && (x>200)) {
Genauso natürlich auch bei den anderen Schleifen:
else if ((x<600) && (x>400)) {
else if ((x<800) && (x>600)) {
Ansonsten sind bei einem Wert von sagen wir mal x=500 die Bedingungen
von 3 Schleifen erfüllt, ob dies gewünscht ist, ist fraglich.
@Mandi
vielen Dank, das denke ich auch, dass es nur einmal aufgerufen wird.
Mit deiner Erweiterung funktioniert es jedoch auch noch nicht.
@Carl Drexler
an "A0" hängen die 1er Eingänge der Schalter UP, Right, Down
Hubert schrieb:> Ich würde zusätzlich noch folgende Bedingung hinzufügen:>> else if ((x<400) && (x>200)) {
Die sind ueberfluessig und auch noch falsch, weil ein Wert von 200 nun
gar keinem Bereich mehr zugeordnet ist.
Katrina N. schrieb:> Hat jemand eine Idee????
Ja, fang nochmal von vorne an:
- Poste den aktuellen, kompletten Sourcecode und nicht Fragmente aus
verschiedenen Ansaetzen.
- Erklaere genau, was die Anforderungen sind und wie die Loesung
funktionieren soll.
- Erklaere genau, wie du testest und was dabei passiert.
Haeltst du dich daran, kann man dir helfen. Aber wahrscheinlich findest
du das Problem dann sogar selbst.
Alles klar also nochmal von Anfang an:
hier mein aktueller Code für das Display mit Ansteuerung vom Arduino
Mega:
// include the library code:
#include <LiquidCrystal.h>
// initialize the library with the numbers of the interface pins
LiquidCrystal lcd(8, 9, 4, 5, 6, 7);
char* myStrings[]={"GinTonic ", "JackyCola ", "WodkaBull
",
"WodkaLemon ", "CaptainCola ","Wasser "};
void setup() {
// set up the LCD's number of columns and rows:
lcd.begin(16, 2);
// Print a message to the LCD.
lcd.setCursor(0,0);
lcd.print("Cocktailwahl ");
}
void loop() {
int x;
int i;
x = analogRead (0);
lcd.setCursor(0,0);
if (x < 60) {
lcd.clear();
lcd.print ("Abbruch ");
}
else if (x < 200) {
lcd.clear();
lcd.print ("GIN ");
}
else if (x < 400) {
lcd.clear();
lcd.setCursor(0,0);
lcd.print(myStrings[i]);
i++;
lcd.setCursor(0,1);
lcd.print(myStrings[i]);
i++;
if (i==7) i=1;
}
else if (x < 600) {
lcd.clear();
lcd.print ("Bestaetigung ");
}
else if (x < 800) {
lcd.clear();
lcd.print ("Welcome ");
}
}
Ziel ist:
Eine Auswahl von Cocktails, die auf meinem 16*2 Display mit den Buttons
Up and Down angezeigt werden sollen.
Problem:
Laden funktioniert, die Buttons Right, Left, Up und Select
funktionieren.
Bei Down zeigt er mir aktuelle nur den String 1 in Zeile 1 an und String
2 in Zeile 2 bei erneutem rücken von Down sollte eigentlich dann String
3 in Zeile 1 und String 4 in Zeile 2 stehen.
Vielen Dank schon mal
Du hast die Variable i zwar angelegt, aber nicht initialisiert. Damit
ist ihr Wert unbestimmt (wenn es eine lokale Variable ist). Das passt so
nicht.
Als globale Variable sollte ihr Initialwert laut C-Standard gleich Null
sein, wenn man keine explizite Zuweisung vornimmt. Trotzdem ist es
besser wenn man einen sinnvollen Startwert hinschreibt. Zumal als
Anfänger(in) sollte man sich das angewöhnen :-)
Katrina N. schrieb:> Ja das ist mir schon klar mit der 0, die ist auch da gewesen.
Dann postest Du also nicht den Code, der aktuell bei Dir läuft. Somit
ist es sinnlos Dir helfen zu wollen. Schade auch. :-(
Ich würde erstmal das Ergebnis von analogRead ausgeben, um
sicherzustellen das die A/D-Wandlung die erwarteten Werte liefert.
Weiter wird im Bereich x zwischen 200 und 400 die variable I so schnell
inkrementiert wie die Loop()-Funktion aufgerufen wird, so das beim
loslassen dann eigentlich nur ein zufälliger Wert in I steht. Vermutlich
soll doch bei jedem Betätigen die Variable I nur einmal weitergestellt
werden.
Was gibt analogRead zurück wenn keine Taste betätigt wird ?
Da nur 6 Strings im Array sind werden diese von 0 .. 5 indiziert. Daher
muss es
if (i==6) i=0;
heissen
SloJo schrieb:> else if ((x<400) && (x>200)) {
Richtig, es muss wie folgt heißen: else if ((x<400) && (x>=200)) {
Jedoch musst du mir noch erklären, warum es deiner Meinung nach nicht
gebraucht wird.
Hubert schrieb:> Richtig, es muss wie folgt heißen: else if ((x<400) && (x>=200)) {>> Jedoch musst du mir noch erklären, warum es deiner Meinung nach nicht> gebraucht wird.
Ich muss zwar nicht, aber ich tue es trotzdem: Er kommt sowieso nicht in
den else-Zweig, wenn x < 200 ist. Also brauchst du es da nicht mehr
abpruefen.
Mandi schrieb:> delay(250);
Der Ansatz das Ganze mit delay zu lösen ist doch mist. So wie es jetzt
ist, wird 4 mal pro Sekunde weitergeschaltet, dass ist für die meisten
zu schnell. Und was Passiert eigentlich, wenn der Aufruf zu einem
Zeitpunkt einer steigenden/fallenden Flanke erfolgt? dann wird aufeinmal
Abbruch gemacht, obwohl Button Down gedrückt wurde!
Mach eine ordentliche Routine, wo die Tastenabfrage gemacht wird. Diese
wird in einem festen Zyklus ausgeführt (ca. 50 bis 100 ms). In der
Routine wird der ADC eingelesen und aus dem Ergebnis eine Zuordnung zu
Button gemacht und mit dem Wert aus dem vorherigen Zyklus verglichen.
Wenn die gleich sind, wird das Ergebnis weiterverarbeitet. Den Zyklus
erzeugst du am besten mit einem Timer (keine Angst, da gibt es eine Lib
für). Im Interrupt setzt du ein Flag. Das Flag wird in der Loop dann
einfach über eine if-Abfrage abgefragt, und wenn es gesetzt wurde wird
die Einleseroutine ausgeführt und anschließend das Flag zurückgesetzt.
Katrina N. schrieb:> Leider immer noch kein Erfolg......
Trenn erstmal deine Aufgaben. Kümmer dich erstmal darum, dass das
einlesen der Taster funktioniert. Mach das in einer eigenen Funktion.
Dann mach eine Funktion die auf die Taster reagiert.
Teste das alles mit Ausgabe der wichtigsten Variablen über
Serial.println.
Zum Schluss baust du deinen LCD Text mit ein und fertig.
Karl schrieb:> Trenn erstmal deine Aufgaben. Kümmer dich erstmal darum, dass das> einlesen der Taster funktioniert. Mach das in einer eigenen Funktion.> Dann mach eine Funktion die auf die Taster reagiert.> Teste das alles mit Ausgabe der wichtigsten Variablen über> Serial.println.> Zum Schluss baust du deinen LCD Text mit ein und fertig.
Vielen Dank Karl.
Meine Taster funktionieren ja nur nicht die Ausgabe wenn ich den Taster
zwei mal drücke, das sich dann der Text ändert.
Da würde ich mich eher daran
http://www.dfrobot.com/wiki/index.php?title=Arduino_LCD_KeyPad_Shield_(SKU:_DFR0009)
halten und dort meine Logik einbauen.
Bei den Tasten, wo nichts passieren soll, belässt Du es in der
CASE-Anweisung einfach bei einem BREAK.
Ich würde auch nicht jedesmal ein lcd.clear() hinpacken, das macht die
Display-Ausgabe nur "unruhig". Einfach überschreiben (mit ausreichend
Leerzeichen am Ende) tut es auch und verhindert das "Flackern".
Schau dir das hier mal an: https://code.google.com/p/u8glib/wiki/tmenu
Abfragen der Taster könnte wie folgt aussehen. Dabei wird jeweils nur
ein "Click" erkannt. Bevor eine weitere Taste erkannt wird, muss der
gedrückte Schalter zuerst losgelassen werden. Die entsprechenden
Analogwerde musst du halt noch anpassen.
1
/*-----( Declare Constants )-----*/
2
#define btnRIGHT 0
3
#define btnUP 1
4
#define btnDOWN 2
5
#define btnLEFT 3
6
#define btnSELECT 4
7
#define btnNONE 5
8
9
/*-----( Declare Variables )-----*/
10
intadc_key_prev=0;
11
intadc_key_current=0;
12
13
voidloop(){
14
adc_key_in=read_LCD_buttons();
15
if(adc_key_prev!=adc_key_current){
16
/*
17
dein code hier
18
*/
19
adc_key_prev=adc_key_current;
20
}
21
}
22
23
intread_LCD_buttons(){
24
intadc_key_in=analogRead(0);// read the value from the sensor
25
delay(5);//switch debounce delay. Increase this delay if incorrect switch selections are returned.
26
intk=(analogRead(0)-adc_key_in);//gives the button a slight range to allow for a little contact resistance noise
27
if(5<abs(k))returnbtnNONE;// double checks the keypress. If the two readings are not equal +/-k value after debounce delay, it tries again.
28
// my buttons when read are centered at these valies: 0, 144, 329, 504, 741
29
// we add approx 50 to those values and check to see if we are close
30
if(adc_key_in>1000)returnbtnNONE;// We make this the 1st option for speed reasons since it will be the most likely result
31
if(adc_key_in<50)returnbtnRIGHT;
32
if(adc_key_in<195)returnbtnUP;
33
if(adc_key_in<380)returnbtnDOWN;
34
if(adc_key_in<555)returnbtnLEFT;
35
if(adc_key_in<790)returnbtnSELECT;
36
returnbtnNONE;// when all others fail, return this...
Hey danke an euch alle bin jetzt schon einen rießen Großen Schritt
weitergekommen das mit Down geht bis auf das letzte up hängt sich noch
auf. hier mein Aktuelles Skript:
// include the library code:
#include <LiquidCrystal.h>
// initialize the library with the numbers of the interface pins
LiquidCrystal lcd(8, 9, 4, 5, 6, 7);
char* buttons[]={"Abbruch ","Bestaetigung ","Welcome
"};
char* myStrings[]={ // So uebersichtlich
"GinTonic ",
"JackyCola ",
"WodkaBull ",
"WodkaLemon ",
"CaptainCola ",
"Wasser "};
int i=0;
void setup() {
// set up the LCD's number of columns and rows:
lcd.begin(16, 2);
// Print a message to the LCD.
lcd.setCursor(0,0);
lcd.print(" WELCOME ");
lcd.setCursor(0,1);
lcd.print(" Cocktailwahl ");
}
void loop() {
int x;
x = analogRead (0);
lcd.setCursor(0,0);
if ((x >= 0) && (x < 50)) {
lcd.setCursor(0,1);
lcd.print (buttons[0]);
}
else if ((x >= 50) && (x < 148)) {
lcd.print ("UP ");
// lcd.setCursor(0,0);
// lcd.print(myStrings[i]);
// i--;
// lcd.setCursor(0,1);
// lcd.print(myStrings[i]);
// i--;
}
else if ((x >= 304) && (x < 456)) {
lcd.setCursor(0,0);
lcd.print(myStrings[i]);
i++;
lcd.setCursor(0,1);
lcd.print(myStrings[i]);
i++;
}
else if ((x >= 456) && (x < 690)) {
lcd.setCursor(0,1);
lcd.print (buttons[1]);
}
else if ((x >= 148) && (x < 304)) {
lcd.setCursor(0,1);
lcd.print (buttons[2]);
}
if (i==6)
{ i=0;
lcd.setCursor(0,0); // und weiter gets,
lcd.print (" Cocktailwahl ");
}
}
Ich war jetzt einfach nur froh, dass es geklappt hat @Dieter F.
Eine Frage wie kann ich es verhindern, das er bei längerem Drücken
trotzdem weiterzählt? Wollen die Taster jetzt über Digitale Eingänge
schalten, ist es dann weg?
Katrina N. schrieb:> Eine Frage wie kann ich es verhindern, das er bei längerem Drücken> trotzdem weiterzählt?
In diesem Fall würde ich ganz einfach nach jeder vollständigen Ausgabe
ein Delay mit 500 - 1000 ms setzen, also z.B.
1
...
2
lcd.setCursor(0,0);
3
lcd.print(myStrings[i]);
4
i++;
5
lcd.setCursor(0,1);
6
lcd.print(myStrings[i]);
7
i++;
8
delay(500);
9
...
Dann hat derjenige, der auf die Taste drückt, nach der vollständigen
Ausgabe des neuen Display-Inhaltes (er sieht das Ergebnis des
Tastendrucks) noch 500 ms Zeit, den Finger von der Taste zu nehmen. Die
erforderliche Zeit musst Du halt ausprobieren.
Mal 2 dumme Fragen:
1. Es stehen im Display immer 2 Getränke zum Auswahl, welche von Beiden
krieg ich serviert wenn ich auf "Bestätigung" drücke?
2. Was passiert wenn mal eine ungerade Anzahl an Getränken zur Auswahl
stehen soll (also z.B. 5 oder 7, statt 6)?
Dieter F. schrieb:> In diesem Fall würde ich ganz einfach nach jeder vollständigen Ausgabe> ein Delay mit 500 - 1000 ms setzen, also z.B.
Genau, am besten gleich 1000 ms, dann dauert es bei 10 Getränken min 10
s bis ich habe, was ich will. Schon mal ein PC/Smartphone benutzt, wo
man nach jeder Aktion 0,5 bis 1 s warten muss, bis etwas passiert? Das
würde jeder Nutzer als unbrauchbar wegfeuern!
Karl schrieb:> Genau, am besten gleich 1000 ms, dann dauert es bei 10 Getränken min 10> s bis ich habe, was ich will. Schon mal ein PC/Smartphone benutzt, wo> man nach jeder Aktion 0,5 bis 1 s warten muss, bis etwas passiert? Das> würde jeder Nutzer als unbrauchbar wegfeuern!
Bei 500 ms dauert es 5 Sekunden einmal durchzuscrollen. Außerdem
solltest Du wenigstens vollständig zitieren:
Dieter F. schrieb:> Dann hat derjenige, der auf die Taste drückt, nach der vollständigen> Ausgabe des neuen Display-Inhaltes (er sieht das Ergebnis des> Tastendrucks) noch 500 ms Zeit, den Finger von der Taste zu nehmen. Die> erforderliche Zeit musst Du halt ausprobieren.
Aber Du kannst ja gerne eine bessere Lösung vorschlagen :-)
Dieter F. schrieb:> Aber Du kannst ja gerne eine bessere Lösung vorschlagen :-)
Alle Delays raus und dann eine anständige Tastenentprellung rein. Alles
andere ist Pfusch.
avr schrieb:> Alle Delays raus und dann eine anständige Tastenentprellung rein. Alles> andere ist Pfusch.
Ah ja, dann zeigt doch mal ein Beispiel der Entprellung für das "LCD
Keypad Shield", welches die Tastendrücke anhand des Einflusses des
Widerstandswerts (liegt eine "Dekade" dahinter) auswertet. Ich bin
gespannt ...
Dieter F. schrieb:> Ah ja, dann zeigt doch mal ein Beispiel der Entprellung für das "LCD> Keypad Shield", welches die Tastendrücke anhand des Einflusses des> Widerstandswerts (liegt eine "Dekade" dahinter) auswertet. Ich bin> gespannt ...
In Pseudo code:
Dieter F. schrieb:> Ah ja, dann zeigt doch mal ein Beispiel der Entprellung für das "LCD> Keypad Shield", welches die Tastendrücke anhand des Einflusses des> Widerstandswerts (liegt eine "Dekade" dahinter) auswertet. Ich bin> gespannt ...
Was man entprellt ist doch völlig egal. Man hat hier eine Information,
die angibt welcher Taster gedrückt ist. Diese Information kann aber
"prellen". Sobald man eindeutig, den Tastendruck und das Loslassen
erkennt, kann man mit diesen Event das Menü aufbauen.
Pseusocode habt ihr ja schon wieder bekommen. Ich finde bei solchen
Sachen wie Entprellung, zu dem es auch sehr viel im Internet schon zu
lesen gibt, hätte man sich auch selbst mal Gedanken machen können.
Hallo, Katrina
Die Lösung ist nicht ganz, in deinem sine, hoffe aber das Dir weiter
hilft.
Es geht wunderbar, auch OHNE: delay() und Tastenentprellung!
Finde heraus: Welcher Taster? Für was gut ist?
Gruß.