Bitte hilft mir, die Werte über das Anzeigemenü mit 3 Tasten zu ändern

Hallo zusammen,
Ich bin dabei eine Display-Menü zu erstellen. Nachdem ich GeGoogelt und viele Beispiele ausprobiert habe, konnte ich etwas finden und zurecht bauen, das ich für den Start verwenden kann.
Die Idee ist, dass ich den Wert von 2, 3 , 4 usw. Zählern und 2, 3, 4 usw.Timern über den Bildschirm mit schlalter verändern kann.
Wie der Code gerade ist, ist es möglich, Individuell der Werte zu ändern. + oder - 1000 Zyklen und + oder - 1000 Millisekunden.

unsigned long parameters[numOfScreens] = {1000};

Aber was ich gerne hätte, wäre eine individuelle Wertänderung für den die Zähler, und dass ich eine Option wählen könnte, wo es 10, 100, 1000 oder 10000 Schritte zum Erhöhen oder Verringern der Zähler hätte. Ich habe bereits versucht, es zum laufen zu bringen, aber ich habe schon mein Limit der Coding Kentnisse erreichet. Ich wäre dankbar für etwas Hilfe. Natürlich, wenn es einen besseren Weg gibt als den, den ich jetzt mit meinem Code gehe, wäre ich auch für einige Vorschläge dankbar.
Folgt der Code, den ich bis jetzt habe.

#include <LiquidCrystal.h>
LiquidCrystal lcd(12, 11, 5, 4, 3, 2);

//Input & Button Logic
const int numOfInputs = 3;
const int inputPins[numOfInputs] = {6,7,8};
int inputState[numOfInputs];
int lastInputState[numOfInputs] = {LOW,LOW,LOW};
bool inputFlags[numOfInputs] = {LOW,LOW,LOW};
long lastDebounceTime[numOfInputs] = {0,0,0};
long debounceDelay = 5;

/////////////////////////////////////////////////////
//LCD Menu Logic
const int numOfScreens = 4;
int currentScreen = 0;
String screens[numOfScreens][2] = { {"Counter1", "Cycles"}, {"Counter2", "Cycles"}, {"Timer1","MiliSec."}, {"Timer2","MiliSec."}};

unsigned long parameters[numOfScreens] = {1000};
//////////////////////////////////////////////////////

void setup() 
{
  for(int i = 0; i < numOfInputs; i++) {
    pinMode(inputPins[i], INPUT);
    digitalWrite(inputPins[i], HIGH); // pull-up 20k
  }
  Serial.begin(9600);
  lcd.begin(16, 3);
  lcd.setCursor(0,0);
  lcd.print(":::Menu:::");
  lcd.setCursor(5,1);
}
//////////////////////////////////////////////////////

void loop() 
{
  setInputFlags();
  resolveInputFlags();
}
//////////////////////////////////////////////////////

void setInputFlags() 
{
  for(int i = 0; i < numOfInputs; i++) {
    int reading = digitalRead(inputPins[i]);
    if (reading != lastInputState[i]) {
      lastDebounceTime[i] = millis();
    }
    if ((millis() - lastDebounceTime[i]) > debounceDelay) {
      if (reading != inputState[i]) {
        inputState[i] = reading;
        if (inputState[i] == HIGH) {
          inputFlags[i] = HIGH;
        }
      }
    }
    lastInputState[i] = reading;
  }
}
/////////////////////////////////////////////////////

void resolveInputFlags() 
{
  for(int i = 0; i < numOfInputs; i++) {
    if(inputFlags[i] == HIGH) {
      inputAction(i);
      inputFlags[i] = LOW;
      printScreen();
    }
  }
}
///////////////////////////////////////////////////////

void inputAction(int input) 
{
  if(input == 0) {if (currentScreen == 0) {currentScreen = numOfScreens-1;}
     else{currentScreen--;}}

  else if(input == 1) {
    parameterChange(0);
  }else if(input == 2) {
    parameterChange(1);
  }
}
////////////////////////////////////////////////////////

void parameterChange(int key) {
  if(key == 0) {
    parameters[currentScreen] = parameters[currentScreen]+500;
  }else if(key == 1) {
    parameters[currentScreen] = parameters[currentScreen]-500;
  }
}
////////////////////////////////////////////////////////

void printScreen() {
  lcd.clear();
  lcd.print(screens[currentScreen][0]);
  lcd.setCursor(0,1);
  lcd.print(parameters[currentScreen]);
  lcd.print(" ");
  lcd.print(screens[currentScreen][1]);
}

Hallo,

du könntest die OneButton Lib nehmen. Damit kannst Du click, doppel-click, lang-gerückt auswerten. z.B
click 1er Sprung
dclick 10er Sprung
lang-drücken läuft schnell

Heinz

Hallo,

hab mit mal Deinen Sketch angesehen, hier ist doch das was Du ändern willst.

void parameterChange(int key) {
  if(key == 0) {
    parameters[currentScreen] = parameters[currentScreen]+500;
  }else if(key == 1) {
    parameters[currentScreen] = parameters[currentScreen]-500;
  }

aus den 500 musst Du eine neue Variable machen die Du irgendwie änderst. Ich könnte mit das mit der OneButton Lib gut vorstellen.

Heinz

void parameterChange(int key) {
  if(key == 0) {
    parameters[currentScreen] = parameters[currentScreen]+500;
  }else if(key == 1) {
    parameters[currentScreen] = parameters[currentScreen]-500;
  }

Ich weiß das ich es hier verändern kann. :slight_smile:
Werde mir die OneButton Lib anschauen und sehen ob Sie mir weiterhelfen kann.
Danke für die schnellen Tip und Hilfe

OK.... Ich sehe das dieses Problem mit dem color tags wenn man einen Code hier über Smartphone posted immer noch existiert.... :o :confused:

Dann musst Du ihn korrigieren. So ist er nicht lesbar.

Gruß Tommy

Korrigiert.... Tommy56. :slight_smile:

Danke.

Gruß Tommy

Hallo
werden alle "screens" dargestellt, wenn du Taste 1 bedienst ?

Morgen paulpaulson,
Momentan mit Taste 1 an pin 6 werden die screens nacheinander aufgerufen und angezeigt. Ja alle screens werden dargestellt. Mit Taste 2 an pin 7 und Taster 3 an pin 8 kann ich die Werte direkt verändern.

Moin
nach dem zweiten Kaffee am Morgen verstehe ich auch diese Zeile :slight_smile:

 if(input == 0) {if (currentScreen == 0) {currentScreen = numOfScreens-1;}
     else{currentScreen--;}}

Ist das deine Absicht rückwärts durch die "screens" = Menues zu wandern?

Morgen paul paulson nein ist nicht Absicht rückwärts durch die "screens" zu wandern. Ist einfach momentan so wie ich es ingekriegt habe uberhaupt durch die menu zu wandern. Sicherlich werde ich das noch verbessern mussen. Momentan mein Ziel ist was anderes. Wie ich schon am Anfang des Post erwahnt habe

unsigned long parameters[numOfScreens] = {1000};

Benutze ich jetzt um die Wete in hallen Menu zu verhandern.

void parameterChange(int key) {
  if(key == 0) {
    parameters[currentScreen] = parameters[currentScreen]+500;
  }else if(key == 1) {
    parameters[currentScreen] = parameters[currentScreen]-500;
  }
}

Ich mochte individuelle Wertänderung für die Zähler und Timer inkriegen.
Sowas wie z.B: Counter1 uber "unsigned long parameters1[numOfScreens] = {10000};"
Counter2 uber "unsigned long parameters2[numOfScreens] = {500};"
Timer1 uber "unsigned long parameters3[numOfScreens] = {500};"
usw.

Moin
tausche die folgende Funktion aus, dann läuft das auch vorwärts :slight_smile:

void inputAction(int input)
{

  switch (input)
  {
  case 0: currentScreen=(currentScreen+1)%numOfScreens; break; 
  case 1:  parameterChange(0); break;
  case 2:  parameterChange(1); break;
  }
/*  
  if (input == 0) {
    if (currentScreen == 0) {
      currentScreen = numOfScreens - 1;
    }
    else {
      currentScreen--;
    } 
  }
    else if (input == 1) {
    parameterChange(0);
  } else if (input == 2) {
    parameterChange(1);
  }
*/    
}
////////////////////////////////////////////////////////

Die Menuesteuerung, dass heißt die Auswahl von 1,10,100,1000 usw, als Inkrement schaue ich mir an.
Oder nimmst du die o.g. Bilblothek?

Bin gerade bei der Arbeit. Werde so schnell wie moglich deine Funktion ausprobieren. Die o.g. Biblothek könnte ich benutzen, haber so würde ich nicht sehen was darinter steckt. Währe gut die Auswahl als Inkrement ohne die Biblothek zu machen. Um zu verstehen wie es läuft und was da drinne steckt. Kann die Biblothek immer noch spater ausprobrieren.

paulpaulson:
Moin
tausche die folgende Funktion aus, dann läuft das auch vorwärts :slight_smile:

void inputAction(int input)

{

switch (input)
 {
 case 0: currentScreen=(currentScreen+1)%numOfScreens; break;
 case 1:  parameterChange(0); break;
 case 2:  parameterChange(1); break;
 }
/*  
 if (input == 0) {
   if (currentScreen == 0) {
     currentScreen = numOfScreens - 1;
   }
   else {
     currentScreen--;
   }
 }
   else if (input == 1) {
   parameterChange(0);
 } else if (input == 2) {
   parameterChange(1);
 }
*/    
}
////////////////////////////////////////////////////////



Die Menuesteuerung, dass heißt die Auswahl von 1,10,100,1000 usw, als Inkrement schaue ich mir an. 
Oder nimmst du die o.g. Bilblothek?

Läuft vorwärts jetzt...Danke

Hallo,

ich hab den Sketch und das was Du möchtest noch nicht ganz verstanden. Du hast 3 parameter in einem Array

parameters( )

parameters(0) soll mit 10
parameters(1) soll mit 100
parameters(2) soll mit 1000

verändert werden ?

dann lege ein neues Array an increment()

unsigned long increment[3] {10,100,1000};

.
.
 
void parameterChange(int key) {
  if(key == 0) {
    parameters[currentScreen] = parameters[currentScreen] + increment[currentScreen];
  }else if(key == 1) {
    parameters[currentScreen] = parameters[currentScreen] - increment[currentScreen];
  }
}

vermutlich ist das aber nicht das was Du willst. Du willst Increment dynamisch ändern. Wenn der Taster gedrückt wird soll increment mit 1 starten, und sich nach 1 s auf 100 und nach 5s auf 1000 ändern. Sows in der Art.

Heinz

Rentner:
Hallo,

ich hab den Sketch und das was Du möchtest noch nicht ganz verstanden. Du hast 3 parameter in einem Array

parameters( )

parameters(0) soll mit 10
parameters(1) soll mit 100
parameters(2) soll mit 1000

verändert werden ?

dann lege ein neues Array an increment()

unsigned long increment[3] {10,100,1000};

.
.

void parameterChange(int key) {
 if(key == 0) {
   parameters[currentScreen] = parameters[currentScreen] + increment[currentScreen];
 }else if(key == 1) {
   parameters[currentScreen] = parameters[currentScreen] - increment[currentScreen];
 }
}




vermutlich ist das aber nicht das was Du willst. Du willst Increment dynamisch ändern. Wenn der Taster gedrückt wird soll increment mit 1 starten, und sich nach 1 s auf 100 und nach 5s auf 1000 ändern. Sows in der Art.

Heinz

Hallo Rentner ... genau das ist was ich möchte.
In der Schwissenzeit habe ich versucht genau das was du als Beispiel gebracht hast im mein Code einzubinden.
Nur gelingt es mir nicht so ganz. Jetz habe dazu noch ein anderes problem bekommen. Nach einschalten des Arduinos erscheint mir am Display ":::Menu:::". Drucke ich einen Taster geht es in den Untermenu "Counter2" und von da geht es nichts mehr weiter.
So sieht momentan mein Code aus.

#include <LiquidCrystal.h>
LiquidCrystal lcd(12, 11, 5, 4, 3, 2);
const int numOfInputs = 3;
const int inputPins[numOfInputs] = {6,7,8};
int         inputState     [numOfInputs];
int         lastInputState [numOfInputs];
/////////////////////////////////////////////////////
//LCD Menu Logic
const int   numOfScreens = 4;
int         currentScreen = 0;

//////////////////////////////////////////////////////
struct Parameter_s {
    const char*     name;
    const char*     units;

    long            delta;
    long            min;;
    long            max;
    long            val;
} parameters [] = {
    { "Counter1", "cyc",  500, 0, 4000 },
    { "Counter2", "cyc",  250, 0, 2000 },
    { "Timer1",   "msec", 10,  0, 100  },
    { "Timer2",   "msec", 250, 0, 2000 },
};

#define N_SCREENS   (sizeof(parameters)/sizeof(Parameter_s))

int idx = 0;

void setup()
{
    for (int i = 0; i < numOfInputs; i++) {
        pinMode (inputPins[i], INPUT_PULLUP);
        lastInputState [i] = digitalRead (inputPins[i]);
    }
    Serial.begin (9600);
    lcd.begin (16, 2);
    lcd.setCursor (0,0);
    lcd.print ("   :::Menu:::");
    lcd.setCursor (5,1);
}
//////////////////////////////////////////////////////
void loop()
{
  chkInputs ();
}
//////////////////////////////////////////////////////
void chkInputs ()
{
    for (int i = 0; i < numOfInputs; i++) {
        int reading = digitalRead (inputPins[i]);

        if (lastInputState[i] != reading) {
            lastInputState[i] = reading;

            if (LOW == reading)  {
                inputAction (i);
                printScreen ();
            }
           delay (10);     // debounce
        }
    }
}
/////////////////////////////////////////////////////
void inputAction (int input)
{
    switch (input) {
    case 0:
        idx++;
        idx %= N_SCREENS;
        break;

    case 1:
        parameterChange (0);
        break;

    case 2:
        parameterChange (1);
        break;
    }
}
////////////////////////////////////////////////////////
void
parameterChange (int key)
{
    Parameter_s *p = &parameters [idx];

    switch (key)  {
    case 0:
        p->val += p->delta;
        if (p->val > p->max)
            p->val = p->max;
        break;

    case 1:
        p->val -= p->delta;
        if (p->val < p->min)
            p->val = p->min;
        break;
    }
}
////////////////////////////////////////////////////////

void printScreen () {
    lcd.clear ();
    char s [40];
    Parameter_s *p = &parameters [idx];

    lcd.setCursor (0,0);
    lcd.print (p->name);

    sprintf (s, "%4ld %s", p->val, p->units);
    lcd.setCursor (0,1);
    lcd.print (s);
}

Hat jemand eine idee was ich falsch mache...
Danke

Hallo
bei mir werkt der Sketch.
Ich habe den auf die folgende Hardware angepasst:
Hardware: Arduino UNO, LCD16x2 mit I2c

:o :slight_smile: :slight_smile: :o ..... paulpaulsonich ich glau, ich werde mich erschießen. Bei mir am LCD16x2 kriege ich es nicht zum laufen. Ab den Code fuer ein Oled display angepasst und dort scheint er zu arbeiten, nur dah habe ich auch ein problem. Und zwar wird de text mit komischen characteren zwischen drinne angezeigt und es ist nicht 100 % lessbar. Haber das naviegieren zwischen den Menus und verandern der Werte mit den Tastern scheint zu funktionieren: Nur wie gesagt das ablesen ist nicht gut....Dieser Code ist ein vereinfachte version von dem was ich will. Die "struct Parameter_s" ich z.B noch nich drinne. Was kann ihr falsch sein?

#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>

#define SCREEN_WIDTH 128 // OLED display width, in pixels
#define SCREEN_HEIGHT 32 // OLED display height, in pixels
#define OLED_RESET     LED_BUILTIN // Reset pin # (or -1 if sharing Arduino reset pin)
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);
#define LOGO_HEIGHT   16
#define LOGO_WIDTH    100

const int numOfInputs = 3;
const int inputPins[numOfInputs] = {6,7,8};
int         inputState     [numOfInputs];
int         lastInputState [numOfInputs];
/////////////////////////////////////////////////////
//LCD Menu Logic
const int   numOfScreens = 4;
int         currentScreen = 0;
const char *screens [numOfScreens][2] =
{
    { "Counter1", "Cycles" },
    { "Counter2", "Cycles" },
    { "Timer1",   "MiliSec." },
    { "Timer2",   "MiliSec." }
};
unsigned long parameters[numOfScreens] = {500};
//////////////////////////////////////////////////////
void setup()
{
    for (int i = 0; i < numOfInputs; i++) {
        pinMode (inputPins[i], INPUT_PULLUP);
        lastInputState [i] = digitalRead (inputPins[i]);
    }

    
  // SSD1306_SWITCHCAPVCC = generate display voltage from 3.3V internally
  if(!display.begin(SSD1306_SWITCHCAPVCC, 0x3C)) { // Address 0x3C for 128x32
    Serial.println(F("SSD1306 allocation failed"));
    for(;;); // Don't proceed, loop forever
  }
 display.clearDisplay();
  display.setTextSize(1);             // Normal 1:1 pixel scale
  display.setTextColor(SSD1306_WHITE);        // Draw white text
  display.setCursor(0,0);             // Start at top-left corner
  display.println(F("     :::MENU:::"));
  display.display();
}
//////////////////////////////////////////////////////
void loop()
{
  chkInputs ();
}
//////////////////////////////////////////////////////
void chkInputs ()
{
    for (int i = 0; i < numOfInputs; i++) {
        int reading = digitalRead (inputPins[i]);

        if (lastInputState[i] != reading) {
            lastInputState[i] = reading;

            if (LOW == reading)  {
                inputAction (i);
                printScreen ();
            }
           delay (10);     // debounce
        }
    }
}
/////////////////////////////////////////////////////
void inputAction(int input)
{
  switch (input)
  {
  case 0:  currentScreen=(currentScreen+1)%numOfScreens; break;
  case 1:  parameterChange(0); break;
  case 2:  parameterChange(1); break;
  }  
}
////////////////////////////////////////////////////////
void parameterChange(int key) {
  if(key == 0) {
    parameters[currentScreen] = parameters[currentScreen]+500;
  }else if(key == 1) {
    parameters[currentScreen] = parameters[currentScreen]-500;
  }
}
////////////////////////////////////////////////////////
void printScreen() {
  display.clearDisplay();
  display.setTextSize(1);             // Normal 1:1 pixel scale
  display.setTextColor(SSD1306_WHITE);
  display.print(screens[currentScreen][0]);
  display.setCursor(0,0);
  display.print(parameters[currentScreen]);
  display.print(" ");
  display.print(screens[currentScreen][1]);
  display.display();
}

Moin,
hier kommt der Sketch, der für die I²C Schnittstelle angepasst worden ist.

#include <LiquidCrystal_I2C.h>
LiquidCrystal_I2C lcd(0x27, 16, 2); // I2C address 0x27, 16 column and 2 rows
const int numOfInputs = 3;
const int inputPins[numOfInputs] = {6,7,8};
int         inputState     [numOfInputs];
int         lastInputState [numOfInputs];
/////////////////////////////////////////////////////
//LCD Menu Logic
const int   numOfScreens = 4;
int         currentScreen = 0;

//////////////////////////////////////////////////////
struct Parameter_s {
    const char*     name;
    const char*     units;
    long            delta;
    long            min;;
    long            max;
    long            val;
} parameters [] = {
    { "Counter1", "cyc",  500, 0, 4000 },
    { "Counter2", "cyc",  250, 0, 2000 },
    { "Timer1",   "msec", 10,  0, 100  },
    { "Timer2",   "msec", 250, 0, 2000 },
};
#define N_SCREENS   (sizeof(parameters)/sizeof(Parameter_s))
int idx = 0;
void setup()
{
    for (int i = 0; i < numOfInputs; i++) {
        pinMode (inputPins[i], INPUT_PULLUP);
        lastInputState [i] = digitalRead (inputPins[i]);
    }
    Serial.begin (9600);
    lcd.init(); // initialize the lcd
    lcd.backlight();
    lcd.setContrast(255);
    lcd.setCursor (0,0);
    lcd.print ("   :::Menu:::");
    lcd.setCursor (5,1);
}
//////////////////////////////////////////////////////
void loop()
{
  chkInputs ();
}
//////////////////////////////////////////////////////
void chkInputs ()
{
    for (int i = 0; i < numOfInputs; i++) {
        int reading = digitalRead (inputPins[i]);
        if (lastInputState[i] != reading) {
            lastInputState[i] = reading;
            if (LOW == reading)  {
                inputAction (i);
                printScreen ();
            }
           delay (10);     // debounce
        }
    }
}
/////////////////////////////////////////////////////
void inputAction (int input)
{
    switch (input) {
    case 0:
        idx++;
        idx %= N_SCREENS;
        break;
    case 1:
        parameterChange (0);
        break;
    case 2:
        parameterChange (1);
        break;
    }
}
////////////////////////////////////////////////////////
void
parameterChange (int key)
{
    Parameter_s *p = &parameters [idx];
    switch (key)  {
    case 0:
        p->val += p->delta;
        if (p->val > p->max)
            p->val = p->max;
        break;
    case 1:
        p->val -= p->delta;
        if (p->val < p->min)
            p->val = p->min;
        break;
    }
}
////////////////////////////////////////////////////////
void printScreen () {
    lcd.clear ();
    char s [40];
    Parameter_s *p = &parameters [idx];
    lcd.setCursor (0,0);
    lcd.print (p->name);
    sprintf (s, "%4ld %s", p->val, p->units);
    lcd.setCursor (0,1);
    lcd.print (s);
}