Suggestions on reducing memory requirements using CRGB

You appear to have defined a 4x4 button matrix, but only specified three pins for the columns. Not sure how the compiler is going to fill out the array of column pins, but leaving one pin uninitialized may lead to unexpected results.

////////////// Setup 3x4 Keypad ///////////////////
const byte ROWS = 4; //four rows
const byte COLS = 4; //four columns

char keys[ROWS][COLS] = {
  {'1', '2', '3', 'A'},
  {'4', '5', '6', 'B'},
  {'7', '8', '9', 'C'},
  {'#', '0', '*', 'D'}
};

byte rowPins[ROWS] = {A0, A1, A2, A3}; //connect to the row pinouts of the keypad
byte colPins[COLS] = {A4, A5, 11}; //connect to the column pinouts of the keypad

Keypad keypad = Keypad( makeKeymap(keys), rowPins, colPins, ROWS, COLS);

Can't be of much help with the display, I've never used a TM1637 so can't test the code with the actual hardware.

Passing the selected text to the type() function should work the same as printing it out.

  type(Array2[keypad_value - 1]);

There should be some error checking on the input from the keypad, otherwise you will inevitably enter a number that exceeds the number of elements in your arrays.

Thank you both! With your help its starting to work as intended.
David, I am removing the other keypad, and yeah..no idea about why I have a 4x4 for a 4x3 keypad. Fixing that now.

Two questions that I think are related to strings and char:

  1. Although the code is working, I ge teh following error and am unsure why are how to fix it:
    C:\Users\Documents\Arduino\Testlayout5e2\Testlayout5e2.ino:88:75: warning: ISO C++ forbids converting a string constant to 'char*' [-Wwrite-strings]

char *Array2[ITEM_ARRAY_SIZE] = {"dog", "cat", "Horse", "Ant", "Firetruck"};

  1. David, the following worked very well: type(Array2[keypad_value - 1]);

For future note, if I wanted to assign (Array2[keypad_value - 1]) to a variable and pass that variable into the "type" function. How would I do that? Type is looking for a string.

DanMan1:
Two questions that I think are related to strings and char:

  1. Although the code is working, I ge teh following error and am unsure why are how to fix it:
    C:\Users\Documents\Arduino\Testlayout5e2\Testlayout5e2.ino:88:75: warning: ISO C++ forbids converting a string constant to 'char*' [-Wwrite-strings]

char *Array2[ITEM_ARRAY_SIZE] = {"dog", "cat", "Horse", "Ant", "Firetruck"};

You can ignore that message without any problems, the compiler is telling you that the array has the type char * but you have populated it with strings (char arrays) instead of char pointers. The compiler understands that it should create the strings separately, then put the pointers to the strings in the array, but you can do it yourself if you really want to eliminate the warning. If you ever decide to store the text in PROGMEM, you will need to use this method, otherwise only the array of char * will be in PROGMEM, the actual text would be stored in dynamic memory.

char text0[] = "dog";
char text1[] = "cat";
char text2[] = "Horse";
char text3[] = "Ant";
char text4[] = "Firetruck";
char *Array2[ITEM_ARRAY_SIZE] = {text0, text1, text2, text3, text4};
  1. David, the following worked very well: type(Array2[keypad_value - 1]);

For future note, if I wanted to assign (Array2[keypad_value - 1]) to a variable and pass that variable into the "type" function. How would I do that? Type is looking for a string.

Since Array2 is an array of char pointers, the simplest way to assign (Array2[keypad_value - 1]) to a variable is to assign it to a char pointer:

char * testing = Array2[keypad_value - 1];

You could also just copy it to another char array and pass that to the function, but unless you plan on doing some editing of the text that is rather wasteful of memory.

As for the function itself, it is generally not a good idea to use the String type on an arduino, that often leads to problems with memory corruption, better to use null terminated char arrays (usually referred to as string with a lower-case "s"). You are only passing the char * to the function anyway, so might as well use that.

void type(char * message) {
  ///Usage type("dog");
  char letter;
  reset();
  //message.toLowerCase();
  //for (int i = 0; i < message.length(); i++) {
  for (byte i = 0; i < strlen(message); i++) {
    letter = message[i];
    //convert upper case to lower case
    // by adding the difference in ASCII representation
    // between the upper case and lower case letters
    if ((letter >= 'A') && (letter <= 'Z')) {
      letter = letter + ('a' - 'A');
    }
    displayLetter(letter);
  }
  reset();
}

DanMan1:
char *Array2[ITEM_ARRAY_SIZE] = {"dog", "cat", "Horse", "Ant", "Firetruck"};

you could have

char Array2[ ITEM_ARRAY_SIZE ][10] = {"dog", "cat", "Horse", "Ant", "Firetruck"};

or

char Array2[ ][10] = {"dog", "cat", "Horse", "Ant", "Firetruck"};

or

// this way allows different length arrays for each string, the above do not

char *dog = "dog";
char *cat = "cat";
char *Horse = "Horse";
char *Ant = "Ant";
char *Firetruck = "Firetruck";

char *Array2[] = { dog, cat, Horse, Ant, Firetruck };  // Array2 is a pointer-to-pointer, base element at **Array2

A C string is a char array, an array of strings is second level. Every level more is an indirection more, 2 levels is pointer to pointers to char and needs ** to dereference Array2 but only * to dereference Array2[x].

Spend idle time learning pointers, make crib notes to refer to when coding (can be text files you keep open with the IDE) and take your time. Pointers are C power tools, with enough RAM/flash an array can be many dimensioned allowing deep table lookups with as many indexes. Yet in every case, every element can be found at the base array address plus an offset. Understand the array and the offsets become a matter of detail, you only need one * to get the value at array+offset no matter how many dimensions (an array of string arrays is chars in 3D, it would be used to organize text data in sets) you're working. And be sure, it takes practice to be able to think in these terms so yes, you will be slow at first.