Keypad program does not work with LCD

Board: STM NUCLEO-F411RE
Libraries used:
mbed.h
Keypad.h (keypad | Mbed)
TextLCD (https://os.mbed.com/users/simon/code/TextLCD/#308d188a2d3a373e0f0757e2cc852a163d21101b)

Warning: ‘wait_ms’ is deprecated: ‘wait_ms’ is deprecated in favor of explicit sleep functions. To sleep, ‘wait_ms’ should be replaced by ‘ThisThread::sleep_for’ (C++) or ‘thread_sleep_for’ (C). If you wish to wait (without sleeping), call ‘wait_us’. ‘wait_us’ is safe to call from ISR context. [since mbed-os-5.14] [-Wdeprecated-declarations] in “main.cpp”, Line: 44, Col: 5

When I compile there are no errors, only warnings for the deprecated functions. After I upload the program to the board, the LCD is blank and even when I press on the keypad, it is still blank. Please help to troubleshoot this.

The program:


// AES_C - LCD display with keypad calc

#include "mbed.h"
#include "TextLCD.h"
#include "Keypad.h"

volatile int flag;
unsigned int Index;

TextLCD lcd(PC_0, PC_1, PC_2, PC_3, PC_4, PC_5); // rs, e, d4-d7

// keypad interface
//              r0    r1    r2    r3    c0     c1    c2     c3    
Keypad keypad(PC_9, PC_8, PC_7, PC_6, PC_13, PC_12, PC_11, PC_10);

// The character table

char KeyTable[ ] = 
{
    '1', '2', '3', '+',     // r3
    '4', '5', '6', '-',     // r2
    '7', '8', '9', '*',     // r1
    'C', '0', 'E', '/',     // r0
};

//   c3   c2   c1   c0

unsigned int KeyPadISR(unsigned int index)
{
    Index = index; //check the index is another variable
    flag = 1;
    return 0;
}

void LCDClear()
{
    lcd.cls();
    wait_ms(500); // millisecond
}

void LCDCursor(int column, int row)
{
    lcd.locate(column, row);
    wait_ms(500); // millisecond
}

int Calculate(int n)
{
    int total = 0; 
    lcd.printf("No %d: ", n);
    while(1)
    {
        if (flag == 1)
        {
            if(KeyTable[Index] != 'E') 
            {
                total = total*10+KeyTable[Index] - '0';
                lcd.printf("%c", KeyTable[Index]);
                flag = 0; 
            }
            else
            {
                flag = 0;
                break;
            }
        }
       // if (flag == 0)
        //break;
    }
    return total;
}

// Main Program

int main() 
{
    int no1, no2, res;
    char Op;

    //lcd.printf("Hello World!\n");
    //wait_ms(5000); // millisecond
    keypad.attach(&KeyPadISR); // replaced it with attach
    keypad.start();
    wait_ms(1000); // millisecond
    
    
    while(1)
    {   
        LCDClear();
        lcd.printf("CALCULATOR");
        wait_ms(5000); // millisecond
        LCDClear();
        LCDCursor(0, 0);
        no1 = Calculate(1);
        LCDCursor(0, 1);
        no2 = Calculate(2);
        
        LCDClear();
        LCDCursor(0, 0);
        lcd.printf("Op: ");
        while(1)
        {
            if(flag == 1)
            {
                Op = KeyTable[Index]; 
                flag = 0;
                break;
            }
        }

        switch(Op)
        {
            case '+':
                res = no1 + no2;
                break;
            case '-':
                res = no1 - no2;
                break;
             case '*':
                res = no1 * no2;
                break;
            case '/':
                res = no1 / no2;
                break;                                       
        }
    
        LCDCursor(0, 0);
        lcd.printf("%c ", Op);
        LCDCursor(0, 1);
        lcd.printf("Res = %d", res);
        wait_ms(5000); // millisecond

    }
}
1 Like

Hello,

did you check for a serial out from Nucleo or bahavior of LED1? Because there can be a MbedOS crash.
What MbedOs do you use?

BR, Jan


I think the mbed os version is 6.11. When I tested with another program that just prints “hello world”, it works. I just can’t seem to make this code work, is there anything wrong with it that makes the printf statements not visible? LCD works fine, the keypad part of the code only I am not sure.

+1 for checking serial and LED pattern, I would also suspect something goes wrong with the configuration - wrong pin, configuration mismatch or something related. I see lcd and keypad are global objects so their init happens very early.

1 Like

Oh ok, so I should test with just a button and LED first? As for pin config, I follow according to the code, but I suspect maybe I need to declare which pins are output and input. The weird thing is that it doesn’t even print “CALCULATOR”. I did notice when I press reset, it appears very briefly, not in seconds as intended. Could you test it on your side, to see whether the problem is reproducible?

To be honest, I do not understand how you can use wait_ms(xxx) function in combination with MbedOS 6.11. All wait functions (exclude wait_us) are not part of MbedOS any more, were removed in first release of MbedOS 6.0.0 .

use of undeclared identifier 'wait_ms'
/src/main.cpp:81:21: error: use of undeclared identifier 'wait_ms'
                    wait_ms(500);
                    ^
1 error generated.
Internal error.
Build failed

If you are able to use wait_ms(xxx), then the MbedOS in your project can not be MbedOS6+, it should be replaced with thread_sleep_for(5000).

Do modification of the main like bellow. I add two printf functions - Debugging using printf() statements - Debugging and testing | Mbed OS 6 Documentation

int main() 
{
    //This will print MbedOs version to default debug console and also inform you about Main started
    printf("F_Running on Mbed OS %d.%d.%d.\n", MBED_MAJOR_VERSION, MBED_MINOR_VERSION, MBED_PATCH_VERSION);
    int no1, no2, res;
    char Op;

    //lcd.printf("Hello World!\n");
    //wait_ms(5000); // millisecond
    keypad.attach(&KeyPadISR); // replaced it with attach
    keypad.start();
    wait_ms(1000); // millisecond
    
    //This will print "loop" string to default debug console and inform you about program step into while loop
    printf("loop\n")
    while(1)
    {   
        LCDClear();
        lcd.printf("CALCULATOR");
        wait_ms(5000); // millisecond
        LCDClear();
        LCDCursor(0, 0);
        no1 = Calculate(1);
        LCDCursor(0, 1);
        no2 = Calculate(2);
        
        LCDClear();
        LCDCursor(0, 0);
        lcd.printf("Op: ");
        while(1)
        {
            if(flag == 1)
            {
                Op = KeyTable[Index]; 
                flag = 0;
                break;
            }
        }

        switch(Op)
        {
            case '+':
                res = no1 + no2;
                break;
            case '-':
                res = no1 - no2;
                break;
             case '*':
                res = no1 * no2;
                break;
            case '/':
                res = no1 / no2;
                break;                                       
        }
    
        LCDCursor(0, 0);
        lcd.printf("%c ", Op);
        LCDCursor(0, 1);
        lcd.printf("Res = %d", res);
        wait_ms(5000); // millisecond

    }
}

Run a Serial terminal app on your PC and connect to Virtual COM Port of your ST-Link

BR, Jan

After a week of troubleshooting, I managed to solve it. As mentioned, the problem was that mbed os 6+ deprecated many functions used by old libraries. So by making all the changes to those libraries, I managed to run my code using mbed os 6.6.0 . Some of the modification that I had to make:

  1. Replace all the wait() functions with wait_us in the .cpp files.
  2. In the TextLCD.h file had to add #include Stream as mbed os 6+ does not include it by default.
  3. Changed the Keypad library form (keypad - An interrupt-driven interface to 4x4 keypad. | Mbed) to a library that is more reliable (Keypad - 3x4 keypad library (Extended not only 3x4 but 4x4… | Mbed).

Updated code:

/*
 * Mbed Application program
 *
 * Copyright (c) 2020,'21 Kenji Arai / JH1PJL
 *  http://www7b.biglobe.ne.jp/~kenjia/
 *  https://os.mbed.com/users/kenjiArai/
 *      Created:    April      5th, 2020
 *      Revised:    February  18th, 2021
 */

// The following code was modified by following the sample 4x4 code provided 
//by author Kenji Arai

//  Include --------------------------------------------------------------------
#include "mbed.h"
#include "Keypad.h"
#include "TextLCD.h"

//  Definition -----------------------------------------------------------------
#if (MBED_MAJOR_VERSION == 2) || (MBED_MAJOR_VERSION == 5)
#   define  WAIT_100MS()     {wait_us(100000);}
#else
#   define  WAIT_100MS()     {ThisThread::sleep_for(100ms);}
#endif

volatile int flag;
uint32_t key_num;
char key_char;

//  LCD ---------------------------------------------------------------------
TextLCD lcd(PC_0, PC_1, PC_2, PC_3, PC_4, PC_5); // rs, e, d4-d7

//              X    Y    Z   W    A   B   C   D   OUT(XYZW), IN(ABCD)
Keypad      key(PC_9, PC_8, PC_7, PC_6, PC_13, PC_12, PC_11, PC_10);

//  RAM ------------------------------------------------------------------------

//  ROM / Constant data --------------------------------------------------------
//                          X*A = *, X*B = 7, X*C = 4, X*D = 1
//                          Y*A = 0, Y*B = 8, Y*C = 5, Y*D = 2
//                          Z*A = #, Z*B = 9, Z*C = 6, Z*D = 3
//                          W*A = A, W*B = B, W*C = C, W*D = D
//                          key_table[0]=? is not used!
//const char *const key_table = "?*7410852#963DCBA";
const char *const key_table = "?123+456-789*C0E/";
//                              1234567890123456

//  Function prototypes --------------------------------------------------------
extern void print_revision(void);

void LCDClear()
{
    lcd.cls();
    wait_us(500000); // millisecond
}

void LCDCursor(int column, int row)
{
    lcd.locate(column, row);
    wait_us(500000); // millisecond
}

int Calculate(int n)
{
    int total = 0;
    
    lcd.printf("No %d: ", n);

    

    while(1)
    {
        while ((key_num = key.read()) != 0) {
        printf(" %c\r\n", *(key_table + key_num));
        key_char = *(key_table + key_num);
        flag = 1;
        }
        WAIT_100MS();

        if (flag == 1)
        {
            if(key_char != 'E') 
            {
                total = total*10+key_char - '0';
                lcd.printf("%c", key_char);
                flag = 0; 
            }
            else
            {
                flag = 0;
                break;
            }
        }
        //if (key_char == 'E')
        //{
          //  key_char = 'K';
            //break;
        //}
    }
    return total;
}


int main()
{
    uint32_t key_num;
    uint32_t counter = 0;
    int no1, no2, res;
    char Op;

    print_revision();
    //printf("Start Key-Pad test 4x4 keys\r\n");
    while(true) {

        LCDClear();
        lcd.printf("CALCULATOR");
        wait_us(5000000); // millisecond
        LCDClear();
        LCDCursor(0, 0);
        no1 = Calculate(1);
        LCDCursor(0, 1);
        no2 = Calculate(2);
        
        LCDClear();
        LCDCursor(0, 0);
        lcd.printf("Op: ");


        while(1)
        {
            while ((key_num = key.read()) != 0) {
                printf(" %c\r\n", *(key_table + key_num));
                key_char = *(key_table + key_num);
                flag = 1;
            }
            WAIT_100MS();
            if(flag == 1)
            {
                Op = key_char; 
                flag = 0;
                break;
            }
        }

        switch(Op)
        {
            case '+':
                res = no1 + no2;
                break;
            case '-':
                res = no1 - no2;
                break;
             case '*':
                res = no1 * no2;
                break;
            case '/':
                res = no1 / no2;
                break;                                       
        }

        LCDCursor(0, 0);
        lcd.printf("%c ", Op);
        LCDCursor(0, 1);
        lcd.printf("Res = %d", res);
        wait_us(5000000); // millisecond

    
    
    }
}