Forum: Mikrocontroller und Digitale Elektronik Arduino: Finde den Fehler im Sketch nicht, bitte um Hilfe!


von Bastler (Gast)


Lesenswert?

Hi,

ich versuche ein Menü mit drei Tasten und einem Nokia 5110-Display zu 
schreiben, es funktioniert nocht nicht viel so wie es soll, aber das 
muss ich alles noch austüfteln, deswegen machen ich das auch, will mich 
mal an was komplexeres auf Anfänger-Niveau wagen.

Erstmal hier der letzte Versuch und danach die eigentliche Frage:
1
#include <SPI.h>
2
#include <Adafruit_GFX.h>
3
#include <Adafruit_PCD8544.h>
4
5
Adafruit_PCD8544 display = Adafruit_PCD8544(2, 3, 4, 5, 6);
6
7
const int btnPin = 0;
8
const int ledPin =  13;
9
10
const int btnUp = 1;
11
const int btnOk = 2;
12
const int btnDwn = 3;
13
14
const int btnUpL = 928;
15
const int btnUpH = 932;
16
const int btnOkL = 985;
17
const int btnOkH = 1005;
18
const int btnDwnL = 970;
19
const int btnDwnH = 980;
20
21
int ledState = HIGH;
22
int btnState;
23
int lBtnState = LOW;
24
25
long lDbncTime = 0;
26
long dbncDelay = 500;
27
28
//int subMenus = 1;
29
30
void setup() {
31
32
  pinMode(btnPin, INPUT);
33
  pinMode(ledPin, OUTPUT);
34
35
  Serial.begin(9600);
36
  display.begin();
37
  display.setContrast(45);
38
  display.setTextSize(1);
39
  display.setTextColor(BLACK);
40
  display.clearDisplay();
41
42
}
43
44
void loop() {
45
  buttons();
46
}
47
48
void buttons() {
49
  int btnData = analogRead(btnPin);
50
  Serial.println(btnData);
51
  int tmpBtnState = LOW;
52
  if (btnData > btnDwnL && btnData < btnDwnH) tmpBtnState = btnDwn;
53
  else if (btnData > btnOkL && btnData < btnOkH) tmpBtnState = btnOk;
54
  else if (btnData > btnUpL && btnData < btnUpH) tmpBtnState = btnUp;
55
  else tmpBtnState = LOW;
56
  if (tmpBtnState != lBtnState) lDbncTime = millis();
57
  if ((millis() - lDbncTime) > dbncDelay) btnState = tmpBtnState;
58
  lBtnState = tmpBtnState;
59
60
  display.setCursor(10, 10);
61
  display.println("Hauptbild");
62
63
  if (lBtnState == btnOk) mainMenu(1);
64
65
  display.display();
66
}
67
68
void mainMenu(int subMenus) {
69
70
  display.clearDisplay();
71
72
  //buttons();
73
74
  display.setCursor(2, 2);
75
  display.println("SubMenu1");
76
  display.setCursor(13, 2);
77
  display.println("SubMenu2");
78
  display.setCursor(24, 2);
79
  display.println("SubMenu3");
80
  display.setCursor(35, 2);
81
  display.println("Back");
82
  
83
  switch (subMenus) {
84
85
    case 1:
86
      display.clearDisplay();
87
      display.drawRect(0, 0, 84, 11, BLACK);
88
      if (btnState == btnOk) subMenu_0();
89
      break;
90
91
    case 2:
92
      display.clearDisplay();
93
      display.drawRect(0, 11, 84, 11, BLACK);
94
      //if (btnState = btnOk) subMenu_1();
95
      break;
96
97
    case 3:
98
      display.clearDisplay();
99
      display.drawRect(0, 22, 84, 11, BLACK);
100
      //if (btnState = btnOk) subMenu_2();
101
      break;
102
103
    case 4:
104
      display.clearDisplay();
105
      display.drawRect(0, 33, 84, 11, BLACK);
106
      if(lBtnState == btnOk) return;
107
      break;
108
  }
109
110
  switch (lBtnState) {
111
112
    case btnUp:
113
      subMenus = subMenus - 1;
114
      if (subMenus < 1) subMenus = 4;
115
      break;
116
    case btnDwn:
117
      subMenus = subMenus + 1;
118
      if (subMenus > 4) subMenus = 1;
119
      break;
120
  }
121
122
  display.display();
123
}
124
125
void subMenu_0() {
126
127
  display.clearDisplay();
128
  display.setCursor(2, 2);
129
  display.println("Ende!");
130
131
}

(Haupt)Problem: Die buttons-Funktion funktioniert ansich funktionell, 
auch durch die cases im switch(subMenus) zu blättern funktioniert, aber 
seltsamerweise nur solange sie im Loop stehen, das Aufrufen der 
mainMenu-Funktion geht von überall, aber sobald die Funktion läuft, 
passiert nichts beim Tastendruck. Wie man im Code sehen kann, habe ich 
die buttons-Funktion auch nochmal versucht in der mainMenu-Funktion zu 
starten, was theoretisch und praktisch keinen Sinn macht.
Könnt ihr den Fehler erkennen? Ich stehe total auf dem Schlauch.

Nebenproblem: Wenn das switch-statement im Loop ist und funktioniert, 
reagieren die Tasten viel zu schnell, ich kapier nicht wie ich das 
ausbremsen soll, hatte vor und nach dem Speichern vom temporären in den 
letzten Zustand eine Verzögerung eingebaut, aber das hat nicht 
funktioniert.

Ich würde mich sehr freuen, wenn ihr mich ein wenig unterstützen könnt, 
ich weiss, dass hier einige auf solche Fragen sehr allergisch reagieren, 
daher möchte ich extra erwähnen, dass es mir im Grunde reicht, wenn ihr 
mir die Fehler aufzeigt, bin aber klar nicht unglücklich, wenn ihr mir 
zumindest in ganz normalen Worten eine alternative Lösung anbietet.

Vielen Dank im Voraus,

Bastler

von Stefan F. (Gast)


Lesenswert?

> Die buttons-Funktion funktioniert ansich funktionell,
> auch durch die cases im switch(subMenus) zu blättern funktioniert,
> aber seltsamerweise nur solange sie im Loop stehen, das Aufrufen der
> mainMenu-Funktion geht von überall, aber sobald die Funktion läuft,
> passiert nichts beim Tastendruck.

Kannst du dein Problem nochmal auf deutsch beschreiben? Das ist für mich 
total unverständlich. Versuche es mal mit viel kürzeren Sätzen.

von Flip B. (frickelfreak)


Lesenswert?

Bastler schrieb:
> aber sobald die Funktion läuft,
> passiert nichts beim Tastendruck

> if (lBtnState == btnOk) mainMenu(1);

die fkt und alle abfragen in dieser funktion werden nur währen des 
drückens von ok ausgeführt. Mal dir mal deine ganze verschachtelung auf. 
Trenne zwischen status, eingabenverarbeitung  und anzeige, alles muss 
regelmässig gemacht werden.

: Bearbeitet durch User
von Peter D. (peda)


Lesenswert?

Du brauchst eine Flankenerkennung, da Du ja nur eine Aktion bei jedem 
Drücken ausführen willst und nicht solange Du drückst.
Und Entprellen ist auch sinnvoll.
Es scheint, daß Du die Tasten analog mit Spannungsteiler einliest, hier 
mal ein Beispeil dafür:
Beitrag "Tastenmatrix auslesen über nur 2 Leitungen"

von Bastler (Gast)


Lesenswert?

Stefan U. schrieb:
> Kannst du dein Problem nochmal auf deutsch beschreiben? Das ist für mich
> total unverständlich. Versuche es mal mit viel kürzeren Sätzen.

Dafür sind doch die Kommas da, das ist halt das Problem. Wenn ich es im 
Kontext kürzer beschreiben könnte, würde ich das. Die buttons-Funktion 
funktioniert nur im loop, in jeder anderen Funktion nicht.

Flip B. schrieb:
> die fkt und alle abfragen in dieser funktion werden nur währen des
> drückens von ok ausgeführt.

Ne, lBtnState ist nachdem der Taster gedrückt wurde, die Funktion läuft 
dann, dabei wird aber immernoch "Hauptbild" angezeigt und darüber dann 
die Einträge aus der mainMenu-Funktion. Innerhalb der cases reagiert die 
Taste btnOk, aber auch sehr seltsam, wenn ich sie nur kurz drücke, dann 
ruft es die mainMenu-Funktion erneut auf, wenn ich sie länger halte, 
dann das, was im angewählten case steht, die subMenu_0-Funktion. Aber 
ich kann nicht mehr durch die cases switchen.

> Mal dir mal deine ganze verschachtelung auf.

Das habe ich vorher schon, sozusagen, also mir ein Schema aufgestellt, 
deswegen ja, für mich scheint es alles logisch, aber mein Verständnis 
dafür reicht wohl noch nicht aus, um zu erkennen warum.

> Trenne zwischen status, eingabenverarbeitung  und anzeige, alles muss
> regelmässig gemacht werden.

Das verstehe ich nicht.

von Bastler (Gast)


Lesenswert?

Peter D. schrieb:
> Du brauchst eine Flankenerkennung, da Du ja nur eine Aktion bei
> jedem Drücken ausführen willst und nicht solange Du drückst.
> Und Entprellen ist auch sinnvoll.
> Es scheint, daß Du die Tasten analog mit Spannungsteiler einliest, hier
> mal ein Beispeil dafür:
> Beitrag "Tastenmatrix auslesen über nur 2 Leitungen"


Ja, es funktioniert ja nach demselben Prinzip, ein Widerstand hängt 
zwischen Gnd und I/O und zwischen +5V und den Taster-Eingängen jeweils 
einer mit anderem Wert, der Ausgang der Taster hängt wiederum auch am 
I/O bzw. Gnd über den ersten Widerstand. Ich habe doch ein btnState und 
l(ast)BtnState, also während und danach und der Sinn der 
buttons-Funktion ist doch Entprellen.

Dein verlinkter Beitrag ist mir noch zu hoch, soweit bin ich noch nicht, 
aber der Link dazu ist gespeichert, danke dafür.

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.