espressif / esp-matter

Espressif's SDK for Matter
Apache License 2.0
708 stars 161 forks source link

Matrix keypad library (CON-370) #31

Closed jonsmirl closed 1 year ago

jonsmirl commented 2 years ago

Is there a library implementing 4x4 matrix keypads somewhere? We need single click, double click, long press, etc -- just like the ESP IOT Button library but using a keypad matrix. I expected this to be in the ESP IOT solution but I don't see it there.

Like how this is wired... https://programmer.ink/think/stm32-4-4-matrix-keyboard-external-interrupt-trigger-mode.html

Could you please ask the IOT people to add keypad matrix support so that we don't have to write our own? https://espressif-docs.readthedocs-hosted.com/projects/espressif-esp-iot-solution/en/latest/input_device/button.html It should be able to handle any config up to 4x4 like 2x4, 3x3, 3x4, etc.

Looks like the Arduino library has this and the Espressif one doesn't.

jonsmirl commented 2 years ago

This library needs to be interrupt based, the Arduino one is polled. The stm example linked above is interrupt based.

jonsmirl commented 2 years ago

This technique has electrical issues. I am getting cross talk between the buttons due to the high frequency scanning. It may not be workable.

jonsmirl commented 2 years ago

I deleted the previous code, it did not work for more than 2x2 due to cross talk issues on the wires. I am implementing a different technique using interrupts that does not rely on high frequency scanning.

jonsmirl commented 2 years ago

This is my second attempt at matrix keypad support. This is diff off from the espressif_button component (IOT Button). This version is interrupt based. It has a problem with occasionally losing edge interrupts, but it detects that condition and recovers. Please test, improve code, etc. You have my full permission to add this code to IDF which I recommend doing. Arduino, ST, NXP, etc all include matrix keypad support in their IDF.

matrix.zip

static uint8_t key;

static void button_down(void *arg) {
    ESP_LOGI(TAG, "button_down %x", key);
}
static void button_up(void *arg) {
    ESP_LOGI(TAG, "button_up %x", key);
}
static void button_repeat(void *arg) {
    ESP_LOGI(TAG, "button_repeat %x", key);
}
static void button_single(void *arg) {
    ESP_LOGI(TAG, "button_single %x", key);
}
static void button_double(void *arg) {
    ESP_LOGI(TAG, "button_double %x", key);
}
static void button_long_start(void *arg) {
    ESP_LOGI(TAG, "button_long_start %x", key);
}
static void button_long_hold(void *arg) {
    ESP_LOGI(TAG, "button_long_hold %x", key);
}

app_driver_handle_t app_driver_switch_init()
{
    button_config_t cfg = {
        .type = BUTTON_TYPE_MATRIX,
        .matrix_button_config = {
            .row = {4, 5, 7, 0xff},
            .column = {1, 2, 3, 0xff},
            .pKey = &key,
        },
    };
    button_handle_t matrix = iot_button_create(&cfg);
    iot_button_register_cb(matrix, BUTTON_PRESS_DOWN, button_down);
    iot_button_register_cb(matrix, BUTTON_PRESS_UP, button_up);
    iot_button_register_cb(matrix, BUTTON_PRESS_REPEAT, button_repeat);
    iot_button_register_cb(matrix, BUTTON_SINGLE_CLICK, button_single);
    iot_button_register_cb(matrix, BUTTON_DOUBLE_CLICK, button_double);
    iot_button_register_cb(matrix, BUTTON_LONG_PRESS_START, button_long_start);
    iot_button_register_cb(matrix, BUTTON_LONG_PRESS_HOLD, button_long_hold);
InfiniteYuan commented 2 years ago

Thank you for your suggestion.

We'll mark it TODO.

jonsmirl commented 1 year ago

I have solved this locally. I just gave up on using interrupts and resorted polling. That is easy to implement.