0

I've been searching for a while, and I don't achieve to find any way to get the input keys of my keyboard, to use them in my program...

Context : I'm starting on robotics, and C++, and I'd simply like to command a motor. The idea is that "if I press the up arrow, the motor turns, if I press the down arrow, the motor stops" and that's it, no need to validate something or anything like that...

I am with raspbian, through VNC (controlling from my real computer), and the actual code is executed in the terminal.

I'll see later on to make that more complex.

I went through 20 or more pages and didn't find anything helpful... Isn't there an easy way to do something that seems so basically useful?

Some spoke about conio library, but apparently it's outdated, curses/ncurses took its place,but I didn't achieve to find/have anything working... http://www.cplusplus.com/forum/general/74211/

Create a function to check for key press in unix using ncurses

Capture characters from standard input without waiting for enter to be pressed

This is apparently C code, and not C++, moreover, I don't really understand that... How to detect key presses in a Linux C GUI program without prompting the user?

This, maybe? But it makes no sense to me (beginner in C++) How can I get the keyboard state in Linux?

here they speak of "allegro", but apparently, it don't work on the PI 45 yet... and no idea how to install that anyway http://www.cplusplus.com/forum/general/47357/

Does someone knows a simple little code that I can copy-past to do that, or any way? I'm quite shocked to not have something similar to windows C++ programming where it seems so simple

I mean something like "Keyboard.GetKeyStates(Key)"

I'll continue my research anyway, but please, help !

EDIT :

Apparently, the library SDL (SDL2) can help me do this... I tried to implement it, it doesn't give any result...

Here is the code I got up to now (I deleted a good part that is useless in here), basically, it's a copy-past from internet SDL official web page :

#include <iostream>
#include <wiringPi.h>   //Raspberry pi GPIO Library
#include <cstdio>
#include <csignal>
#include <ctime>
#include <chrono>   //library for counting time
#include <thread>   //for "this thread sleep"
#include <SDL2/SDL.h>   //for getting the keyboard buttons events

bool RUNNING = true;    // global flag used to exit from the main loop

/*XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
  GPIO Pins definition
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX*/
int SPser = 13, SPclk = 19, SPrclk = 26; //Define the output pins used
int Optocoupler = 17; //define the input pins used

/*XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
  SDL definition
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX*/

    //void PrintKeyInfo( SDL_KeyboardEvent *key );
    //void PrintModifiers( SDLMod mod );

//SOME CODE

// Callback handler if CTRL-C signal is detected
void my_handler(int s) {
    std::cout << "Detected CTRL-C signal no. " << s << '\n';
    RUNNING = false;
}

//###################################################################################
int main(int argc, char *args[]) {
    // Initialize wiringPi and allow the use of BCM pin numbering
    wiringPiSetupGpio();

    //Initialize SDL
    if (SDL_Init(SDL_INIT_EVENTS) != 0) {
        SDL_Log("Unable to initialize SDL: %s", SDL_GetError());
        return 1;
    }
    else
    {
        SDL_Log("SDL initialized");
    }
    SDL_Event event;

    // Register a callback function to be called if the user presses CTRL-C
    std::signal(SIGINT, my_handler);

    while(RUNNING) 
    {

    while( SDL_PollEvent( &event ) )
    {
    std::cout << "SDL While \n" << '\n';
        //When the user presses a key
        switch( event.type )
        {
        case SDL_KEYDOWN:
        std::cout << "Key press detected \n" << '\n';
            //printf( "Key press detected\n" );
        break;

        case SDL_KEYUP:
        std::cout << "Key release detected \n" << '\n';
            //printf( "Key release detected\n" );
        break;

        default:
        break;
        }
    }
//std::cout << "Works??" << '\n';

    /*for( i = 0; i <= 15; i++ )
    {
        //std::cout << "data input i =" << i << '\n';
        if (i==0){
        //std::cout << "if array " << i << '\n';
        DataArr[i]=1;
        DataArr[15]=0;
        }
        else{
            j=i-1;
            DataArr[j]=0;
            DataArr[i]=1;
            //std::cout << "in else i" << i << " and j " << j << '\n';
        }
    SendData(DataArr);
    }*/
    }
    std::cout << "Program ended ...\n";
}

As I followed "dumbly" the tutorial, this should work, but the while loop is never entered as the "std::cout << "SDL While \n" << '\n';" is never shown...

But, as it achieve to compile, I guess the SDL library was installed correctly and things work...

When executing the code, it writes "SDL initialized", then, nothing... pressing keys do nothing

I'm still not sure how to check if the library is installed correctly, but when I type in de command prompt "sudo apt-get install libsdl2-dev", it shows a few lines and says "0 upgraded, 0 newly installed, 0 to remove and 0 not upgraded"

zepeu
  • 81
  • 2
  • 16
  • OS? Windowing system (if any)? How's the keyboard attached? USB? GPIO? Network? – genpfault Feb 13 '20 at 20:44
  • @genpfault I edited the question : I am with raspbian, through VNC (controlling from my real computer), and the actual code is executed in the terminal. – zepeu Feb 14 '20 at 09:37
  • 1
    If you have X running on your Pi, you should be able to type `xev` (X-event-monitor) and then push the Up/Down Arrow keys to get the *key-code* being used on your keyboard. On my laptop, UpArrow is `111`, DownArrow is `116`, LeftArrow is `113` and RightArrow is `114`. – David C. Rankin Feb 16 '20 at 12:16
  • @DavidC.Rankin I have no idea what X is or if it is running on my Rpi... Is it "Native" on it, or does it has to be installed? – zepeu Feb 16 '20 at 12:33
  • Well, I wrote "xev" in the terminal, I would say that X is installed... – zepeu Feb 16 '20 at 12:34
  • You will want to be on the actual pi and not ssh'ed into it (though xev will run). Generally from your desktop, open an `zterm` and then type `xev`. Put the cursor in the little white window (let the cursor stop moving), then in the xterm, type whatever key you want and you will get 2 4-5 ;line blocks of text for each keypress (one for key-down and one for key-up) that will contain the key-code for the key you just pressed. (along with a lot of additional information) – David C. Rankin Feb 16 '20 at 13:02
  • @DavidC.Rankin uh? Well... OK... But I'm obliged to build up an X window and access it if I want to get the key inputs? Can't I just use the "XGrabKeyboard(display, grab_window, owner_events, pointer_mode, keyboard_mode, time);"? I'm reading the documentation, I got hard times to understand... the "display" is a display created by X, I guess? My terminal isn't considered as a display... And I have absolutely NO NEED of another display or something like that, I use the terminal just to check my things correctly, and the keyboard is there for testing purpose only... – zepeu Feb 16 '20 at 13:11
  • Well, I'm bored of that stuff, I have strictly no idea how to do this, I'll go with a simple getch() and validate with enter each time. This is really not convenient, but I want to go further in my programming. If someone can tell me how to do this with SDL, X or anything else, you're welcome to do it. – zepeu Feb 16 '20 at 15:32

1 Answers1

2

If you are on linux, you should use termios to stop the buffering

#include <termios.h>

void set_no_buffer()
{
     struct termios term;
     tcgetattr(0, &term);
     term.c_lflag &= ~ICANON;
     tcsetattr(0, TCSANOW, &term);
}

and then getchar() to get a character without entering

FloweyTF
  • 323
  • 3
  • 11
  • Thank you for your answer :) Small question : Imagine I have a "while(1)" loop that last 5 seconds, the "getchar()" at the beginning and I press a button after 2 sec. Will it will be considered after 5 sec, on the next looping or not at all as I don't press the button anymore when the "getchar" will be read? (I can't try your code before Monday, I'll give you the bounty soon ;) ) – zepeu Feb 21 '20 at 09:43
  • getchar will wait for a keystroke (but no buffer means it will return after exactly one keystroke). You need to use a thread if you want this in the background. – FloweyTF Feb 21 '20 at 18:42