Please help me to change values over Display Menu with 3 Buttons

Dear all,
I´m working around a Display Menu for my needs and i´m not the best code writer. After Googling and trying a lot of examples i could find and build something that i can use for the start.
The idea is that i can change the value of 2 counters and 2 timers over the sreen with buttons.
How the code is right now it´s possible to change the values individuality. + or - 1000 cycles and + or - 1000 millisec.

unsigned long parameters[numOfScreens] = {1000};

But what i would like to have would be a individual value changing for the 2 counter and that i could choose over a option being 10, 100, 1000 or 10000 steps increasing or decreasing the counters. I have tried already to make it work but i´m reaching my coding limits. I would be thankful for some help. Of couse if there is a better way than the one that i´m going now with my code, i would be also thankful for some suggestions.
Follows down the code that i have until now

#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] = {500};
//////////////////////////////////////////////////////

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]);
}

The code how it´s right now works fine

One possibility:

Call the switches A, B, C. Find a button library you like that has short/long press capability; this will effectively double the number of switch inputs.

A short press on A cycles through the available values subject to change and this is indicated on the LCD by, for example, a flashing cursor or having just one value at a time displayed. A long press on A takes you to a new screen which shows only the selected timer/counter and a series of 10x values. The 10x values are cycled through by short presses on A and indicated by flashing on the LCD as before.

While the selected 10x value is flashing pressing B increments by that amount, C decrements. When the value is correct another long press on A returns you to the previous menu.

consider

#if 0   // my hardware
# include "LiquidCrystal.h"

//Input & Button Logic
const int   numOfInputs = 3;
const int   inputPins [numOfInputs] = { A1, A2, A3 };

#else
# include <LiquidCrystal.h>

//Input & Button Logic
const int   numOfInputs = 3;
const int   inputPins [numOfInputs] = {6,7,8};
#endif

LiquidCrystal lcd (12, 11, 5, 4, 3, 2);

int         inputState     [numOfInputs];
int         lastInputState [numOfInputs];

/////////////////////////////////////////////////////
//LCD Menu Logic
const int   numOfScreens = 4;
int         currentScreen = 0;

#if 0
String      screens[numOfScreens][2] = {
#else
const char *screens [numOfScreens][2] = {
#endif
    { "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]);
    }

    Serial.begin (9600);

    lcd.begin (16, 3);
    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)
{
    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 ();
#if 0
    lcd.print (screens[currentScreen][0]);
    lcd.setCursor (0,1);
    lcd.print (parameters[currentScreen]);
    lcd.print (" ");
    lcd.print (screens[currentScreen][1]);
#else
    char s [40];
    sprintf (s, "%s %4ld %s", screens [currentScreen][0],
        parameters [currentScreen], screens [currentScreen][1]);
    lcd.print (s);
#endif
}

Hi gcjr, thanks for the help. I tried your code. Unfortunately when i push one of the buttons the :::Menu::: on the screen disappear and nothing more happens and nothing more appear on the screen. I am missing something?!

i simulate an LCD screen. i think i forgot the setCursor() call)

#if 0   // my hardware
# include "LiquidCrystal.h"

//Input & Button Logic
const int   numOfInputs = 3;
const int   inputPins [numOfInputs] = { A1, A2, A3 };

#else
# include <LiquidCrystal.h>

//Input & Button Logic
const int   numOfInputs = 3;
const int   inputPins [numOfInputs] = {6,7,8};
#endif

LiquidCrystal lcd (12, 11, 5, 4, 3, 2);

int         inputState     [numOfInputs];
int         lastInputState [numOfInputs];

/////////////////////////////////////////////////////
//LCD Menu Logic
int         currentScreen = 0;

#if 0
const int   numOfScreens = 4;

#if 0
String      screens[numOfScreens][2] = {
#else
const char *screens [numOfScreens][2] = {
#endif
    { "Counter1", "Cycles" },
    { "Counter2", "Cycles" },
    { "Timer1",   "MiliSec." },
    { "Timer2",   "MiliSec." }
};
unsigned long parameters[numOfScreens] = {500};
#endif

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, 3);
    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 ();
#if 0
    lcd.print (screens[currentScreen][0]);
    lcd.setCursor (0,1);
    lcd.print (parameters[currentScreen]);
    lcd.print (" ");
    lcd.print (screens[currentScreen][1]);
#else
    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);
#endif
}

? :)!! :)?
Ok.....i see little by little my code is disappearing and something new is coming :). No problem. Even if I don't understand everything in your code i think it is the right way.

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;

Right now with your code when i press the button it change from " :::Menu:::" to "Counter2" and after nothing more happens.

sorry, i posted some other code i was playing with

presumably this is the same as in my first post with the setCursor() corrections in the 2nd

#if 0   // my hardware
# include "LiquidCrystal.h"

//Input & Button Logic
const int   numOfInputs = 3;
const int   inputPins [numOfInputs] = { A1, A2, A3 };

#else
# include <LiquidCrystal.h>

//Input & Button Logic
const int   numOfInputs = 3;
const int   inputPins [numOfInputs] = {6,7,8};
#endif

LiquidCrystal lcd (12, 11, 5, 4, 3, 2);

int         inputState     [numOfInputs];
int         lastInputState [numOfInputs];

/////////////////////////////////////////////////////
//LCD Menu Logic
const int   numOfScreens = 4;
int         currentScreen = 0;

#if 0
String      screens[numOfScreens][2] = {
#else
const char *screens [numOfScreens][2] = {
#endif
    { "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]);
    }

    Serial.begin (9600);

    lcd.begin (16, 3);
    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)
{
    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 ();
#if 0
    lcd.print (screens[currentScreen][0]);
    lcd.setCursor (0,1);
    lcd.print (parameters[currentScreen]);
    lcd.print (" ");
    lcd.print (screens[currentScreen][1]);
#else

    lcd.setCursor (0,0);
    lcd.print (screens [currentScreen][0]);

    char s [40];
    sprintf (s, "%4ld %s",
        parameters [currentScreen], screens [currentScreen][1]);
    lcd.setCursor (0,1);
    lcd.print (s);
#endif
}

Hi gcjr

I was considering some of your help and my initial code became better to read and understandeble for me: With the following code, it shows all Menus, i can scroll true the Menus and change the value.

#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;
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]);
    }
  Serial.begin (9600);
    lcd.begin (16, 3);
    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)
{
    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]);
}

Only if i want to use in the void printScreen() your suggestion it doesn´t work at me. Look how i´m making it.

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

    char s [40];
    sprintf (s, "%4ld %s",
        parameters [currentScreen], screens [currentScreen][1]);
    lcd.setCursor (0,1);
    lcd.print (s);
}

Like this is shows at the beginning ":::Menu:::", after the button press "Timer2" without value appears and nothing more happen.
What i´m doing wrong?
Thanks

can you post the code that does not work?

Here is the code. Thanks...

#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;
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]);
    }
  Serial.begin (9600);
    lcd.begin (16, 3);
    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)
{
    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.setCursor (0,0);
    lcd.print (screens [currentScreen][0]);
    char s [40];
    sprintf (s, "%4ld %s",
    parameters [currentScreen], screens [currentScreen][1]);
    lcd.setCursor (0,1);
    lcd.print (s);
}

i don't know what to tell you. as i've said, i'm simulating the the LCD using the serial monitor.

the only thing the looks odd to me is lcd.begin (16,3). do you really have an LCD with 3 rows.

but since your code that works successfully writes to the 2nd line of the LCD (i.e. setCursor(0,1)) i doubt the begin() args are the issue.

i hope you see that advantage of using sprintf() instead of multiple print calls. this can be useful in other cases where a single string is formatted but displayed on multiple devices.

i would start with a hardcoded string or possibly with only a 16 character string. but i have no idea.

i took me an hour to chase a math problem yesterday that worked on my laptop but not an arduino.

LCD with 3 rows?!?!.... No I have only two!!! :slight_smile:

And the LCD is also not a real one. I´m using the online simulater Tinkercad | From mind to design in minutes. But I have for real a Oled Display SSD1306. I will try it out on the Oled Display when i´m home

Hi gcjr..... :slight_smile:
Only for info. I tried the code on the Oled Screen and it works but with a little problem. But first, also for info. In the code i changed the "void inputAction(int input)". How it was before it was scrooling backwards. Right now after the change is scrooling forward.
Back to the mind-breaker because of the "void printScreen ()". Right now is working with Oled Screen and with your and mine option. It´s possible to scrool true the menu and change the values. Only with your code the text does not appear clear. What i mean is that in the middle on the text are some strage characters. What could be the problem of characters?
One more Question.
I would like to have more than only one "unsigned long parameters[numOfScreens] " in Code.
What i mean exactly is that each Counter or Timer would have is own "unsigned long parameters[numOfScreens]"

"Counter1", "Cycles" = unsigned long parametersc1[numOfScreens]
"Counter2", "Cycles" = unsigned long parametersc2[numOfScreens]
"Timer1", "MiliSec." = unsigned long parameterst1[numOfScreens]
"Timer2", "MiliSec." = unsigned long parameterst2[numOfScreens]

What would be the right way using the existing Code to make this?

Follows the Code how it´s right now.

Thanks a lot again for your help.... :slight_smile:

#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 printScreen1() {
  display.clearDisplay();
  display.setTextSize(1);             
  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();
}
void printScreen () {
    display.clearDisplay();
    display.setTextSize(1);
    display.setTextColor(SSD1306_WHITE);
    display.setCursor (0,0);
    display.print (screens [currentScreen][0]);
    char s [40];
    sprintf (s, "%4ld %s",
    parameters [currentScreen], screens [currentScreen][1]);
    display.setCursor (0,1);
    display.print (s);
    display.display();
}

if you look at the code i post in reply #4, you'll see that the structure containing the parameter names also include increment, min, max and a value. that code uses the elements of that structure instead of a separate (i.e. parameter [])

it's not clear why you're having problems with using sprintf(). i use this approach using an SSD1306. there are various display modes that construct up to 4 strings passed to dispOled() which invokes ssd1306 functions to update the display. it does invoke a setTextAlignment()

Thanks for the quick response. For me is already late for today. As soon I can, I will continue working on it and also take a look on your code in reply #4. When I will have something, I will let you know. Thanks

Hi gcjr......
At me the Code with the OledDisplay is working. With the LCD i can´t put it work. Anyway i ordered the OledDisplay to use them in my little convoyer projekt. I will lose time with the LCD later. Follows the code for the OledDisplay.

#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;

//////////////////////////////////////////////////////
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]);
    }

    
  // 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:
        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 () {
    display.clearDisplay();
  display.setTextSize(1);  
  display.setTextColor(SSD1306_WHITE);
    char s [40];
    Parameter_s *p = &parameters [idx];

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

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

Like i told before i want to use the Display in my Convoyer Project. For the begining i want to control only the waiting time of the Motor between the right and left turn after stopping at one sensor t each side. I want also to access and change the cycles that the convoyer will work. Right now i will put me on the work to conbine two codes to Code. If you are interested in my Convoyer Code .

#include <Wire.h> //This library allows you to communicate with I2C / TWI devices
#include <Adafruit_SSD1306.h> //This is a library for our Monochrome OLEDs based on SSD1306 drivers
#include <Adafruit_GFX.h> //This is the core graphics library for all displays. 
                          //Providing a common set of graphics primitives (points, lines, circles, etc.).


#define SCREEN_WIDTH 128 // OLED display width, in pixels
#define SCREEN_HEIGHT 32 // OLED display height, in pixels


Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire);


const byte sensorLeftEnd   =  2;
const byte sensorRightEnd  =  3;
const byte startPin        =  4;
const byte stopPin         =  5;
const int upPin            =  6;   
const int downPin          =  7;   
const int enterPin         =  8;
const byte relayLeft       =  11;
const byte relayRight      =  12;


enum {relayOn, relayOff};
enum {waiting, on, right, stopright, left, stopleft, off, zyklusstop, stopEnd};
byte step = waiting;
byte zyklus = 1;

void softversion(void) {
  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("Software version"));
  display.println(F("Conveyer V1.0"));
  display.display();
  //delay(2000);
}

void setup()///Setup
{
    // SSD1306_SWITCHCAPVCC = generate display voltage from 3.3V internally
  if(!display.begin(SSD1306_SWITCHCAPVCC, 0x3C)) { // Address 0x3C for 128x62
    Serial.println(F("SSD1306 allocation failed"));
    for(;;); // Don't proceed, loop forever
  }  
  display.clearDisplay();
  display.display();  
  Serial.begin(9600);
  Serial.println(F("Start...."));
  pinMode(sensorLeftEnd, INPUT);
  pinMode(sensorRightEnd, INPUT);
  pinMode(startPin, INPUT);
  pinMode(stopPin,  INPUT);
  pinMode(upPin,INPUT_PULLUP);
  pinMode(downPin,INPUT_PULLUP);
  pinMode(enterPin,INPUT_PULLUP);
  pinMode(relayLeft, OUTPUT);
  digitalWrite(relayLeft, relayOff);
  pinMode(relayRight, OUTPUT);
  digitalWrite(relayRight, relayOff);
  pinMode(LED_BUILTIN, OUTPUT);
  digitalWrite(LED_BUILTIN, LOW);
}

int more = 0;
int less = 0;
int moreState = 0;
int lessState = 0;
int lastmoreState = 0;
int lastlessState = 0;
unsigned long maxzyklus = 4;

void oledcount() 
{
  display.clearDisplay();
  display.setTextSize(1);                    
  display.setTextColor(WHITE);
  display.setCursor(0,0); 
  display.println("Zyklen");
  display.println(maxzyklus);
  display.display();
}
void loop()///Loop 
{
  Serial.print(F("Cyclen:"));
  Serial.println(zyklus);
  zyklenUpDown();
  conveyor();   
  //softversion(); 
  oledcount();   
}

void zyklenUpDown()///Cyclen change up and down with button
{
 moreState = digitalRead(upPin);
  if(moreState != lastmoreState) {
    if(moreState == LOW) {
      maxzyklus += 1;
    }
  }
  lastmoreState = moreState;
  lessState = digitalRead(downPin);
  if(lessState != lastlessState) {
    if(lessState == LOW) {
      maxzyklus -= 1;
    }
  }
  lastlessState = lessState;
  Serial.println(maxzyklus); 
} 

void conveyor()///Conveyer
{
  static unsigned long lastmillis;
  const unsigned long breakTime = 500; // in ms
  if (digitalRead(stopPin))
  {
    step = off;
  }
  switch (step)
  {
    case waiting: 
    //Serial.println(F("Conveyer waiting()"));
      if (digitalRead(startPin))
      {
        zyklus = 0;
        step = on;
      }
      stop();
      break;
    case on: 
    //Serial.println(F("Convoyer On()"));
      digitalWrite(LED_BUILTIN, HIGH);
      step = right;
      break;
    case right: 
    //Serial.println(F("Right Turning()"));
      rightturn();
      if (digitalRead(sensorRightEnd))
      {
        step = stopright;
        lastmillis = millis();
      }
      break;
    case stopright: 
    //Serial.println(F("Stop Right Turning ()"));
      stop();
      if (millis() - lastmillis > breakTime)
      {
        step = left;
      }
      break;
    case left: 
    //Serial.println(F("Left Turning()"));
      leftturn();
      if (digitalRead(sensorLeftEnd))
      {
        step = stopleft;
        lastmillis = millis();
      }
      break;
    case stopleft: 
    //Serial.println(F("Stop Left Turning()"));
      stop();
      if (millis() - lastmillis > breakTime)
      {
        if (zyklus == maxzyklus)
        {
          step = zyklusstop;
        }
         else
        {
          zyklus++; 
          step = right;
        }
      }
      break;
    case off:  
    //Serial.println(F("Convoyer Off()"));
      digitalWrite(LED_BUILTIN, LOW);
      step = waiting;
     break;  
    case zyklusstop: 
    //Serial.println(F(Cycle Stop()"));
      stop();
      step = zyklusstop;
       if (zyklus == maxzyklus) 
      { 
        if (maxzyklusReadout()) //Query on the Serial Monitor what should happen
        {
          if (zyklus == 0) {
            step = right;
        }
         else
        {
          step = stopEnd; 
        }
        }
      }
      break;
    case stopEnd: 
      step = off;  
      break;
  }
}

bool maxzyklusReadout() //Message on the Serial Monitor maximum cycles reached
{
  char character = '\0';
  Serial.print(F("Maxzyklus reached: "));
  Serial.println(zyklus);
  Serial.println(F("Set Zyklus to 0? Y/N"));
  while ((char(character) != 'Y') && (char(character) != 'N'))
  {
    character = Serial.read();
  }
  if (char(character) == 'Y')
  {
    Serial.println(F("Put to 0"));
    zyklus = 0;
    return true;
  }
  if (char(character) == 'N') {
    Serial.println(F("Put not to 0"));
    return false;
  }
  return false;
}

void stop()///Stop of the motor
{
  digitalWrite(relayRight, relayOff);
  digitalWrite(relayLeft, relayOff);
}

void leftturn()///Motor turns left
{
  digitalWrite(relayRight, relayOff);
  digitalWrite(relayLeft, relayOn);
}

void rightturn()///Motor turns right 
{
  digitalWrite(relayLeft, relayOff);
  digitalWrite(relayRight, relayOn);
}

At this point i want to say "Thank You Very Much for your help...".. You show me how coding can be made. I have a lot to learn. Thanks again

This topic was automatically closed 120 days after the last reply. New replies are no longer allowed.