Ja - weiß ich und ich habe schon 1000 Sachen überprüft und getestet... Aber ich komme keinen Millimeter weiter...
Dann baue mal ein paar prints ein und zeige die Ausgaben
Fehler gefunden !!!
Hauptproblem war die "Verkettung" von Umständen.
Beim Drücken wird in jedem displayMenu(0,1,2)Select der Marker für die nächste Ebene gesetzt. Deshalb lief das DIng einfach durch.
Ich habe displayMenu(0+1)Select rausgeschmissen und bei "buttonPressed(BTN_SELECT)" definiert was passieren soll und den Problempunkt displayMenu(2)Select übersprungen.
Kann sein, daß der Code nicht "Profi-Programmierquaöität hat - aber jetzt funktioniert es...
Änderung:
if (buttonPressed(BTN_SELECT)) {
if (menuPage == 0) {
menuPage = 1;
menuIndex = 0;
myGLCD.clrScr();
displayMenu1();
goto ENDE;
}
if (menuPage == 1 and menuIndex != 2) {
menuPage = 2;
menuIndex = 0;
myGLCD.clrScr();
displayMenu2();
goto ENDE;
}
if (menuPage == 1 and menuIndex == 2) {
menuPage = 0;
menuIndex = 0;
myGLCD.clrScr();
displayMenu0();
goto ENDE;
}
if (menuPage == 2) {
Selecting = !Selecting;
displayMenu2Select();
}
delay(200);
ENDE:;
}
GESAMTCODE
`[code]
#include <UTFT.h>
#include <EEPROM.h>
// Declare which fonts we will be using
extern uint8_t SmallFont[];
extern uint8_t BigFont[];
// Initialize display
//SDI=11 SCL=12 /CS =10 /RST=8 D/C=9
UTFT myGLCD(ST7735S_4L_80160, 11, 12, 10, 8, 9);
// Buttons (anpassen)
const int BTN_MENU = 3;
const int BTN_UP = 4;
const int BTN_DOWN = 5;
const int BTN_SELECT = 6;
int i;
bool Selecting = false;
int values[2];
String menu0Items[] = {"Menu 0-1"};
String menu1Items[] = {"Menu 1-1", "Menu 1-2", "EXIT"};
String menu2Items[] = {"Menu 2-1", "Menu 2-2", "EXIT"};
int menuIndex = 0; // Pos im Menü nach Upload
int menuPage = 0;
int maxMenu0Items = 0;// Auswahl Menüseite nach Upload
int maxMenu1Items = 2; // Einträge jeder Menüseite, 1 = 2 Einträge
int maxMenu2Items = 2; // Einträge jeder Menüseite, 2 = 3 Einträge
void setup() {
Serial.begin(9600);
// Setup the LCD
myGLCD.InitLCD(1);
myGLCD.clrScr();
myGLCD.setFont(SmallFont);
myGLCD.setColor(255, 255, 255);
pinMode(BTN_MENU, INPUT_PULLUP);
pinMode(BTN_UP, INPUT_PULLUP);
pinMode(BTN_DOWN, INPUT_PULLUP);
pinMode(BTN_SELECT, INPUT_PULLUP);
EEPROM.update(0, 1); // INITIALISIERUNG DES EEPROM Platzes, nach 1. Upload auskommentieren
EEPROM.update(1, 1); // INITIALISIERUNG DES EEPROM Platzes, nach 1. Upload auskommentieren
if (menuPage == 0) displayMenu0();
if (menuPage == 1) displayMenu1();
if (menuPage == 2) displayMenu2();
}
void loop() {
if (buttonPressed(BTN_UP)) {
if (!Selecting) {
menuIndex = (menuIndex - 1);
if (menuIndex < 0) menuIndex = 0;
if (menuPage == 0) displayMenu0();
if (menuPage == 1) displayMenu1();
if (menuPage == 2) displayMenu2();
} else {
values[menuIndex]++;
if (menuPage == 2) displayMenu2Select();
}
delay(200);
}
if (buttonPressed(BTN_DOWN)) {
if (!Selecting) {
menuIndex = (menuIndex + 1);
if (menuPage == 0) {
if (menuIndex > maxMenu1Items) menuIndex = maxMenu0Items;
displayMenu0();
}
if (menuPage == 1) {
if (menuIndex > maxMenu1Items) menuIndex = maxMenu1Items;
displayMenu1();
}
if (menuPage == 2) {
if (menuIndex > maxMenu2Items) menuIndex = maxMenu2Items;
displayMenu2();
}
} else {
values[menuIndex]--;
if (menuPage == 2) displayMenu2Select();
}
delay(200);
}
if (buttonPressed(BTN_SELECT)) {
if (menuPage == 0) {
menuPage = 1;
menuIndex = 0;
myGLCD.clrScr();
displayMenu1();
goto ENDE;
}
if (menuPage == 1 and menuIndex != 2) {
menuPage = 2;
menuIndex = 0;
myGLCD.clrScr();
displayMenu2();
goto ENDE;
}
if (menuPage == 1 and menuIndex == 2) {
menuPage = 0;
menuIndex = 0;
myGLCD.clrScr();
displayMenu0();
goto ENDE;
}
if (menuPage == 2) {
Selecting = !Selecting;
displayMenu2Select();
}
delay(200);
ENDE:;
}
}
bool buttonPressed(int pin) {
return digitalRead(pin) == LOW;
}
void displayMenu0() {
myGLCD.setColor(255, 255, 255);
for (i = 0; i <= maxMenu0Items; ++i)
if (menuIndex == i) {
myGLCD.setColor(0, 0, 255);
myGLCD.print(menu0Items[i], 15, i * 15 + 20);
}
else {
myGLCD.setColor(255, 255, 255);
myGLCD.print(menu0Items[i], 15, i * 15 + 20);
}
}
void displayMenu1() {
myGLCD.setColor(255, 255, 255);
for (i = 0; i <= maxMenu1Items; ++i)
if (menuIndex == i) {
myGLCD.setColor(0, 0, 255);
myGLCD.print(menu1Items[i], 15, i * 15 + 20);
}
else {
myGLCD.setColor(255, 255, 255);
myGLCD.print(menu1Items[i], 15, i * 15 + 20);
}
}
void displayMenu2() {
values[0] = EEPROM.read(0);
values[1] = EEPROM.read(1);
myGLCD.setColor(255, 255, 255);
for (i = 0; i <= maxMenu2Items; ++i) {
if (menuIndex == i) {
myGLCD.setColor(0, 0, 255);
myGLCD.print(menu2Items[i], 15, i * 15 + 20);
}
else {
myGLCD.setColor(255, 255, 255);
myGLCD.print(menu2Items[i], 15, i * 15 + 20);
}
if (i < maxMenu2Items) {
if (values[menuIndex] == 0 ) {
myGLCD.setColor(255, 0, 0);
myGLCD.print("OFF", 90, i * 15 + 20);
}
if (values[menuIndex] == 1 ) {
myGLCD.setColor(0, 255, 0);
myGLCD.print("ON ", 90, i * 15 + 20);
}
}
}
}
void displayMenu2Select() {
if (menuIndex == 0) {
values[menuIndex] = 1 - values[menuIndex];
if (values[menuIndex] == 0 ) {
myGLCD.setColor(255, 0, 0);
myGLCD.print("OFF", 90, menuIndex * 15 + 20);
}
if (values[menuIndex] == 1 ) {
myGLCD.setColor(0, 255, 0);
myGLCD.print("ON ", 90, menuIndex * 15 + 20);
}
EEPROM.update(0, values[menuIndex]);
Selecting = 0;
}
if (menuIndex == 1) {
values[menuIndex] = 1 - values[menuIndex];
if (values[menuIndex] == 0 ) {
myGLCD.setColor(255, 0, 0);
myGLCD.print("OFF", 90, menuIndex * 15 + 20);
}
if (values[menuIndex] == 1 ) {
myGLCD.setColor(0, 255, 0);
myGLCD.print("ON ", 90, menuIndex * 15 + 20);
}
EEPROM.update(1, values[menuIndex]);
Selecting = 0;
}
if (menuIndex == maxMenu2Items) {
Selecting = 0;
menuPage = 1;
menuIndex = 0;
myGLCD.clrScr();
displayMenu1();
}
}
[/code]`
Könntest Du bitte beim Gesamtcode die Codetags noch mal prüfen?
Wahrscheinlich die ' davor und danach weg.
Gruß Tommy
Goto ist stark verpönt.
Mach es besser so
if (menuPage == 0) {
menuPage = 1;
menuIndex = 0;
myGLCD.clrScr();
displayMenu1();
} else if (menuPage == 1 and menuIndex != 2) {
menuPage = 2;
menuIndex = 0;
myGLCD.clrScr();
displayMenu2();
}
Das ist historisch!
Aus den BASIC Anfangszeiten.
Heutzutage kann man die GOTO Vorbehalte so ziemlich vergessen.
Goto nutzen, wenn es Sinn macht.
Ich finde den Menücode unübersichtlich.
Ich würde da mehr in Strukturen, Arrays und Zustandsautomaten denken.
Hier mal eine Idee für die ersten 2 Punkte:
Du hast immer die Gefahr von Spagetticode. Also in welchen Situationen macht es Sinn?
Ich halte das Konstrukt nicht nur für fehleranfällig, sondern unglaublich aufwändig bei nur einer Erweiterung um einen weiteren Menupunkt.
Du versuchst hier etwas zu machen, was Dir C++ bereits zur Verfügung stellt!
Für beide Probleme heißt die Lösung switch / case
Und das ist so einfach!
if (buttonPressed(BTN_SELECT))
{
myGLCD.clrScr();
switch (menuPage)
{
case 0:
menuPage = 1;
menuIndex = 0;
displayMenu1();
break;
case 1:
if (menuIndex != 2)
{
menuPage = 2;
menuIndex = 0;
displayMenu2();
}
else
{
menuPage = 0;
menuIndex = 0;
displayMenu0();
}
break;
case 2:
Selecting = !Selecting;
displayMenu2Select();
break;
}
}
Schau an, was mit myGLCD.clrScr(); passiert ist.
Dein delay(200) gehört unbedingt da raus und ein softwareseitiges Entprellen gehört in die ButtonAbfrage.
Ym2C
Das BASIC Schreckgespenst!
Das ist doch nur eine Projektion, schlechter Erfahrungen, auf C/C++ die daran ganz unschuldig sind.
Das Netz, und auch gute Bücher, sind voll von diesen Erklärungen/Vorschlägen.
In C und auch in AVR C++ haben wir keine Exceptions.
Wo man eigentlich eine Exception werfen wollte, muss man das mit einer komplizierten if/else Kaskade umschiffen, oder ein heilendes Goto einstreuen.
Dann kann Goto den Bau von endlichen Automaten vereinfachen.
Der Bau von Automaten, basierend auf switch/case, verhindert meist die sonstige Anwendung switch/case innerhalb dieser Automaten. Auch sind verschachtelte switch/case nicht nur unübersichtlich, sondern auch fehlerträchtig.
Hier, im Anhang, mal mein Multitasking Dingen, welches im Kern auf Goto basiert.
CooperativeTask.zip (10,6 KB)
Siehe auch:
Ich hätte da ein paar Kritikpunkte:
- In
int interp_cgoto(unsigned char* code, int initval)wird die Ablaufsteuerung in einem #define versteckt. Es ist daher nicht offensichtlich das der Code nicht von Oben nach Unten durchlaufen wird. - Bei ungültigen Eingaben crashed
int interp_cgoto(unsigned char* code, int initval).int interp_switch(unsigned char* code, int initval)hat dagegen den Default-Zweig in man Fehlerbehandlung machen kann. - #define debuggen <-> Breakpoint im Default-Zweig setzen
Bei sowas bin ich bei dir:
void function() {
alloc(res1);
if (test(res1) == fail) goto cleanup;
alloc(res2);
if (test(res2) == fail) goto cleanup;
alloc(res3);
if (test(res3) == fail) goto cleanup;
doIt(rews1, res2, res3);
cleanup:
if (res3) free(res3);
if (res2) free(res2);
if (res1) free(res1);
}
Für fremden Code kann ich keine Verantwortung übernehmen.
Wollte damit nur zeigen, dass ich nicht der einzige bin, der Goto nicht mit einem Haufen Vorurteile überschüttet.
Meine Ansicht:
Goto ist ein gültiges Sprachmittel.
Mit jedem Sprachmittel kann man sich selber in den Fuß schießen.
Ins besondere fällt mit hier im Forum immer wieder auf, wie sich Leute in ihren eigenen if Konstruktionen verirren.
Sicher, aber ich hab das Gefühl, das es mit goto besonders leicht geht.
Das schiebe ich auf fehlende Gedanken bezüglich der Softwarearchitektur.
Wer einmal begriffen hat, wie ein Hammer funktioniert, für den sieht alles wie ein Nagel aus.
Gefühl... Gefühle...
Ich will gar nicht wissen wie viele Fehlurteile auf irrationalen Gefühle beruhen. Manchmal tödliche.
Das alte BASIC Goto hat sich seinen Ruf redlich erworben.
Aber wir reden her über das C++ Goto.
Natürlich kann man das eine auf das andere projizieren.
Aber das ist weit von der Realität entfernt.