Looking for a simple way to display and cycle through text on lcd display

I'm trying to program a super basic pokedex (yeah from pokemon) from an arduino uno and a 16,2 lcd display but I'm having a bit of trouble with the code. Basically all I'm looking to do is have the lcd screen display one page at a time like this

Line 1 NA: (name) NO:000
Line 2 TypeA:(type) TypeB:(type)

Stumbling my way through youtube tutorials I thought a good way to do this would be to use to use the switch case function (structure?) and wire 2 buttons for scrolling back and forth trough the pages. This is where I started having trouble. i can't figure out how to make a push button switch the case that is currently being displayed.

I have very limited knowledge when it comes to arduino and only understand how to use the more basic functions such as digital read and write and initializing pins so I'm sure I both sound like an idiot and am going about this completely wrong. And I apologies in advance for the "code" below (I think its readable). Thanks for any and all help!

#include <LiquidCrystal.h>

LiquidCrystal lcd (1, 2, 4, 5, 6, 7);


int pin13 = 13;
int pin12 = 12;

int pin11 = 11;
int pin10 = 10;

int pin9 = 9;
int pin8 = 8;

int pokemonvalue = 0;
void setup() {

  lcd.begin(16, 2);
  pinMode(pin8, INPUT);
  pinMode(pin9, OUTPUT);
  lcd.print("Pokedex V 0.1");
  delay(3000);
  lcd.clear();
 digitalWrite (pin9, HIGH);
}

void loop() {
  
 
  if (pin8 = HIGH) {
    lcd.clear();

// This is where I wanted to clear the display if pin 8 gets pulled high and show the next or previous case.
// but I couldn't figure out the function

  
}

  }

  lcd.scrollDisplayLeft();

  delay (400);




  switch (pokemonvalue) {


    case 0:
      lcd.setCursor(2, 0);
      lcd.print ("Na:Bulbasaur No:001");
      lcd.setCursor(2, 1);
      lcd.print ("TypeA:Grass TypeB:Poison");

      break;

    case 2:
      lcd.setCursor(2, 0);
      lcd.print ("Na:Ivysaur No:002");
      lcd.setCursor(2, 1);
      lcd.print ("TypeA:Grass TypeB:Poison");

    case 3:
      lcd.print ("Venusaur ");
      break;

    case 4:
      lcd.print ("");
      break;

    case 5:
      lcd.print ("");
      break;

    case 6:
      lcd.print ("");
      break;

    case 7:
      lcd.print ("");
      break;

    case 8:
      lcd.print ("");
      break;

    case 9:
      lcd.print ("");
      break;

    case 10:
      lcd.print ("");
      break;



  }
}

If You read the first topics telling how to use this Forum You would use code tags for the attached code. That way more helpers can read the code. Smartphones etc.have no IDE and can't download and see the code.

My bad, I believe its fixed now.

if (pin8 = HIGH)

= for assignment == for comparison

if (pin8 == HIGH)

Look at the state change detection example to see how to count button presses. The use buttonPushCounter in your switch structure to select which screen to show.

lcd.print ("TypeA:Grass TypeB:Poison");

Be careful to remember that a line is only 16 characters long. The text will not wrap like you might expect.

LiquidCrystal lcd (1, 2, 4, 5, 6, 7);

I would not use pin 1 for the LCD. It is the hardware serial TX pin. I know that you are not using serial, but at some point you may want to as serial prints are your best debugging tool. If you are low on digital pins, the analog input pins (A0-A5) are really digital pins with analog read as a special function.

Thank you for the advice and suggestions groundfungus! I'm currently re writing most of it no and I will definitely look into fixing all that too.

For the amount of text you want to display, a 20x4 LCD would work better, then each item could go on a separate line.

So I've restarted a few times and I finally have the switch case working the way I wanted but when I started filling out the cases I started to get low space warnings. I have cut out what I was able to but there is no way its all going to fit the way I have done it. I have also noticed that the lcd will display the current case number before the first character on the first row of text as it scrolls to the left.

Unfortunately I think I'm stuck abandoning the case switch approach all together due to the memory issue. Does anyone know of a better way to have a button to cycle through text on an lcd display?

Here is the updated code, I have cut out most of the 151 cases for easier reading but everything else is there.

#include <LiquidCrystal.h>
LiquidCrystal lcd (8, 2, 4, 5, 6, 7);
int down = 9;//down button
int up = 10;//up button
int upstate;
int downstate;
int pokemonvalue = 0; //current pokemon displayed

void setup() {
  lcd.begin(16, 2);
  pinMode(down, INPUT_PULLUP);
  pinMode(up, INPUT_PULLUP);
  lcd.print("Pokedex V 0.8"); //this line is just a starup message
  delay(3000);
  lcd.clear();
  lcd.print(pokemonvalue);

}

void loop() {

  downstate = digitalRead(down);
  upstate = digitalRead(up);
  lcd.scrollDisplayLeft();
  delay (500);
    lcd.setCursor(3, 0);
  if (downstate == LOW) {
    lcd.clear();
    switch (pokemonvalue ++);
    lcd.print(pokemonvalue);
  }
  if (upstate == LOW) {
    lcd.clear();
    switch (pokemonvalue --);
    lcd.print(pokemonvalue);
  }
  if (downstate = HIGH)
    if (upstate = HIGH)


      switch (pokemonvalue) {

        default:
          lcd.print("Error!");
          break;

        case 0:
          lcd.print ("  Bulbasaur 001 ");
          lcd.setCursor(2, 1);
          lcd.print ("  Type:Gr Po");
          break;


        case 1:
          lcd.print ("  Ivysaur 002");
          lcd.setCursor(2, 1);
          lcd.print ("  Type:Gr Po");
          break;

        case 2:

          lcd.print ("  Venusaur 003");
          lcd.setCursor(2, 1);
          lcd.print ("  Type:");
          break;
}

Enclose the quoted text in the lcd.print statements in the F() macro, that will store it in program memory instead of ram.

Would be easy to store all the text in an array, then use pokemonvalue as the index of the array, but I'll have to wait till I'm on a computer to type out the example of how to do that in program memory.

@david_2018
Being an UNO user..
May I jump in and ask a question? I know the link to Arduino Reference but where can I read about the F-macro? Maybe there are more useful Macros that I don't know about, "somewhere".

Railroader:
@david_2018
Being an UNO user..
May I jump in and ask a question? I know the link to Arduino Reference but where can I read about the F-macro? Maybe there are more useful Macros that I don't know about, "somewhere".

I think I first ran across the F() macro in someone's answer to a quest on this forum, and the rest I learned from google (which mostly gives references to discussions on here), not really sure if there is a reference page on it.

Now for the long-winded example of how to store the text in an array in program memory. (I'll get to the reason why I want to do that at the end):

To store the text in an array in dynamic ram is easy:

const char * lcdtext[][2] = {
  {"  Bulbasaur 001 ", "  Type:Gr Po"},
  {"  Ivysaur 002", "  Type:Gr Po"},
  {"  Venusaur 003", "  Type:"}
};

That will allow you to access the text as lcdtext[pokemonvalue][0] and lcdtext[pokemonvalue][1] when printing it to the LCD.
What that code does is create an array of char pointers, that point to where the actual text is stored in memory, while also doing all the work of storing the individual text strings in memory and keeping track of where they are.

Normally you tell the compiler to store something in program memory by using PROGMEM:

const char * const lcdtext[][2] PROGMEM = {
  {"  Bulbasaur 001 ", "  Type:Gr Po"},
  {"  Ivysaur 002", "  Type:Gr Po"},
  {"  Venusaur 003", "  Type:"}
};

To retrieve the values from PROGMEM, you then would use (char *)pgm_read_word(&lcdtext[pokemonvalue][0]) , which tells the compiler to read a two-byte value (a word) from the lcdtext array, and to treat that value as a char *. That will work fine in a print statement, except that the actual text is not being stored in program memory, only the array of pointers to the text.

To store the text itself in program memory, you need to store each line of text separately, giving each a unique name, then create the array of characters pointers from that:

const char text0a[] PROGMEM = "  Bulbasaur 001 ";
const char text0b[] PROGMEM = "  Type:Gr Po";
const char text1a[] PROGMEM = "  Ivysaur 002";
const char text1b[] PROGMEM = "  Type:Gr Po";
const char text2a[] PROGMEM = "  Venusaur 003";
const char text2b[] PROGMEM = "  Type:";

const char * const lcdtext[][2] PROGMEM = {{text0a, text0b}, {text1a, text1b}, {text2a, text2b}};

Now when you want to reference the text in a print command, you would use (__FlashStringHelper *)pgm_read_word(&lcdtext[pokemonvalue][0]) , with __FlashStringHelper * serving the same purpose as char * above, but specifying to the compiler that the memory pointed to is in program memory.

Now for the reason for creating the array. Instead of using a very large, repetitive switch...case structure to print out text for each value of pokemonvalue, it is much simpler to put the text in an array, and use pokemonvalue to specify which element of the array you want to print. The entire switch...case statement can be replace with three lines of code:

      lcd.println((__FlashStringHelper *)pgm_read_word(&lcdtext[pokemonvalue][0]));
      lcd.setCursor(2, 1);
      lcd.println((__FlashStringHelper *)pgm_read_word(&lcdtext[pokemonvalue][1]));

Your code posted earlier today them becomes:

#include <LiquidCrystal.h>
LiquidCrystal lcd (8, 2, 4, 5, 6, 7);
int down = 9;//down button
int up = 10;//up button
int upstate;
int downstate;
int pokemonvalue = 0; //current pokemon displayed

const char text0a[] PROGMEM = "  Bulbasaur 001 ";
const char text0b[] PROGMEM = "  Type:Gr Po";
const char text1a[] PROGMEM = "  Ivysaur 002";
const char text1b[] PROGMEM = "  Type:Gr Po";
const char text2a[] PROGMEM = "  Venusaur 003";
const char text2b[] PROGMEM = "  Type:";

const char * const lcdtext[][2] PROGMEM = {{text0a, text0b}, {text1a, text1b}, {text2a, text2b}};

void setup() {
  lcd.begin(16, 2);
  pinMode(down, INPUT_PULLUP);
  pinMode(up, INPUT_PULLUP);
  lcd.print(F("Pokedex V 0.8")); //this line is just a starup message
  delay(3000);
  lcd.clear();
  lcd.print(pokemonvalue);
}

void loop() {
  downstate = digitalRead(down);
  upstate = digitalRead(up);
  lcd.scrollDisplayLeft();
  delay (500);
  lcd.setCursor(3, 0);
  if (downstate == LOW) {
    lcd.clear();
    switch (pokemonvalue ++);
    lcd.print(pokemonvalue);
  }
  if (upstate == LOW) {
    lcd.clear();
    switch (pokemonvalue --);
    lcd.print(pokemonvalue);
  }
  if (downstate == HIGH) {
    if (upstate == HIGH) {
      lcd.println((__FlashStringHelper *)pgm_read_word(&lcdtext[pokemonvalue][0]));
      lcd.setCursor(2, 1);
      lcd.println((__FlashStringHelper *)pgm_read_word(&lcdtext[pokemonvalue][1]));
    }
  }
}

david_2018:
I think I first ran across the F() macro in someone's answer to a quest on this forum, and the rest I learned from google (which mostly gives references to discussions on here), not really sure if there is a reference page on it.

Now for the long-winded example of how to store the text in an array in program memory. (I'll get to the reason why I want to do that at the end):

To store the text in an array in dynamic ram is easy:

const char * lcdtext[][2] = {

{"  Bulbasaur 001 ", "  Type:Gr Po"},
  {"  Ivysaur 002", "  Type:Gr Po"},
  {"  Venusaur 003", "  Type:"}
};



That will allow you to access the text as lcdtext[pokemonvalue][0] and lcdtext[pokemonvalue][1] when printing it to the LCD.
What that code does is create an array of char pointers, that point to where the actual text is stored in memory, while also doing all the work of storing the individual text strings in memory and keeping track of where they are.

Normally you tell the compiler to store something in program memory by using PROGMEM:



const char * const lcdtext[][2] PROGMEM = {
  {"  Bulbasaur 001 ", "  Type:Gr Po"},
  {"  Ivysaur 002", "  Type:Gr Po"},
  {"  Venusaur 003", "  Type:"}
};



To retrieve the values from PROGMEM, you then would use (char *)pgm_read_word(&lcdtext[pokemonvalue][0]) , which tells the compiler to read a two-byte value (a word) from the lcdtext array, and to treat that value as a char *. That will work fine in a print statement, except that the actual text is not being stored in program memory, only the array of pointers to the text.

To store the text itself in program memory, you need to store each line of text separately, giving each a unique name, then create the array of characters pointers from that:



const char text0a[] PROGMEM = "  Bulbasaur 001 ";
const char text0b[] PROGMEM = "  Type:Gr Po";
const char text1a[] PROGMEM = "  Ivysaur 002";
const char text1b[] PROGMEM = "  Type:Gr Po";
const char text2a[] PROGMEM = "  Venusaur 003";
const char text2b[] PROGMEM = "  Type:";

const char * const lcdtext[][2] PROGMEM = {{text0a, text0b}, {text1a, text1b}, {text2a, text2b}};




Now when you want to reference the text in a print command, you would use (__FlashStringHelper *)pgm_read_word(&lcdtext[pokemonvalue][0]) , with __FlashStringHelper * serving the same purpose as char * above, but specifying to the compiler that the memory pointed to is in program memory.

Now for the reason for creating the array. Instead of using a very large, repetitive switch...case structure to print out text for each value of pokemonvalue, it is much simpler to put the text in an array, and use pokemonvalue to specify which element of the array you want to print. The entire switch...case statement can be replace with three lines of code:


lcd.println((__FlashStringHelper *)pgm_read_word(&lcdtext[pokemonvalue][0]));
      lcd.setCursor(2, 1);
      lcd.println((__FlashStringHelper *)pgm_read_word(&lcdtext[pokemonvalue][1]));




Your code posted earlier today them becomes:


#include <LiquidCrystal.h>
LiquidCrystal lcd (8, 2, 4, 5, 6, 7);
int down = 9;//down button
int up = 10;//up button
int upstate;
int downstate;
int pokemonvalue = 0; //current pokemon displayed

const char text0a[] PROGMEM = "  Bulbasaur 001 ";
const char text0b[] PROGMEM = "  Type:Gr Po";
const char text1a[] PROGMEM = "  Ivysaur 002";
const char text1b[] PROGMEM = "  Type:Gr Po";
const char text2a[] PROGMEM = "  Venusaur 003";
const char text2b[] PROGMEM = "  Type:";

const char * const lcdtext[][2] PROGMEM = {{text0a, text0b}, {text1a, text1b}, {text2a, text2b}};

void setup() {
  lcd.begin(16, 2);
  pinMode(down, INPUT_PULLUP);
  pinMode(up, INPUT_PULLUP);
  lcd.print(F("Pokedex V 0.8")); //this line is just a starup message
  delay(3000);
  lcd.clear();
  lcd.print(pokemonvalue);
}

void loop() {
  downstate = digitalRead(down);
  upstate = digitalRead(up);
  lcd.scrollDisplayLeft();
  delay (500);
  lcd.setCursor(3, 0);
  if (downstate == LOW) {
    lcd.clear();
    switch (pokemonvalue ++);
    lcd.print(pokemonvalue);
  }
  if (upstate == LOW) {
    lcd.clear();
    switch (pokemonvalue --);
    lcd.print(pokemonvalue);
  }
  if (downstate == HIGH) {
    if (upstate == HIGH) {
      lcd.println((__FlashStringHelper *)pgm_read_word(&lcdtext[pokemonvalue][0]));
      lcd.setCursor(2, 1);
      lcd.println((__FlashStringHelper *)pgm_read_word(&lcdtext[pokemonvalue][1]));
    }
  }
}

Thank you so much! This fixes the problem perfectly. Now I just need to finish Filling out all the pokemon info.