google-coral

How to use a wireless controller on the Google Coral Dev Board?


With the Jetson Nano I connected a PS4 controller via bluetooth and the device showed up under /dev/input/js0. However when I connect the controller via bluetooth to my Coral board, I am seeing nothing at that location, maybe because of Mendel instead of Ubuntu? What is the recommended way to connect a PS4 controller and access it from C++? Is there a different joystick I should use?


Solution

  • After doing some research I learned about the difference between joydev and evdev on linux. It seems my PS4 controller showed up as a joydev device on the Jetson, whereas on the Coral running Mendel it showed up as an evdev device. I found some example C++ code for evdev devices from Croepha / David Butler here: https://handmade.network/forums/t/3673-modern_way_to_read_gamepad_input_with_c_on_linux

    I modified this code for the PS4 controller like this:

    void runJoystick() {
        auto gamepad = open("/dev/input/event4", O_RDONLY | O_NONBLOCK); //todo use /proc/bus/input/devices instead
        assert(gamepad != -1);
        std::cout << "Running joystick" << std::endl;
    
        while (m_still_running) {
            struct input_event events[8];  // 8 events per frame is pretty extreme, more like 1 or 2, sometimes as high as 4
            auto r1 = read(gamepad, events, sizeof events);
            if (r1 != -1) {
                int new_event_count = r1 / sizeof(struct input_event);
                for (int evi = 0; evi < new_event_count; evi++) {
                    auto& ev = events[evi];
    
                    switch (ev.type) {
                        case EV_ABS: {
                            switch (ev.code) {
                                case ABS_X: {  // left x
                                    // std::cout << "type " << ev.code << "value:" << ev.value << std::endl;
                                } break;
                                case ABS_Y: {  // left y
                                    // std::cout << "type " << ev.code << "value:" << ev.value << std::endl;
                                } break;
                                case ABS_Z: {  // right x
                                    // std::cout << "type " << ev.code << "value:" << ev.value << std::endl;
                                } break;
                                case ABS_RZ: {  // right y
                                    // std::cout << "type " << ev.code << "value:" << ev.value << std::endl;
                                } break;
                            }
                        } break;
                        case EV_KEY: {
                            switch (ev.code) {
                                case BTN_A: {  // square
                                    std::cout << "Square ";
                                } break;
                                case BTN_B: {  // x
                                    std::cout << "X ";
                                } break;
                                case BTN_C: {  // circle
                                    std::cout << "Circle ";
                                } break;
                                case BTN_X: {  // triangle
                                    std::cout << "Triangle ";
                                } break;
                            }
    
                            if (ev.value) {
                                std::cout << "Pressed " << std::endl;
                            } else {
                                std::cout << "Released " << std::endl;
                            }
    
                        } break;
                    }
                }
            }
    
            assert(r1 != -1 || errno == EWOULDBLOCK || errno == EAGAIN);
            std::this_thread::sleep_for(std::chrono::milliseconds(20));
        }
    }