-
Notifications
You must be signed in to change notification settings - Fork 932
Add Example Code for 4x4 Keypad with Raspberry Pi Pico #542
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: develop
Are you sure you want to change the base?
Changes from 2 commits
79b986c
8a653c7
b30685b
f787419
139d981
b80d96d
52a7f7b
c56503e
7324b2a
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
set(TARGET_NAME keypad) | ||
add_executable(${TARGET_NAME} | ||
keypad.c | ||
) | ||
|
||
# pull in common dependencies | ||
target_link_libraries(keypad pico_stdlib) | ||
|
||
if (PICO_CYW43_SUPPORTED) | ||
target_link_libraries(${TARGET_NAME} pico_cyw43_arch_none) | ||
endif() | ||
lurch marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
# Enable printing via USB serial | ||
pico_enable_stdio_usb(${TARGET_NAME} 1) | ||
pico_enable_stdio_uart(${TARGET_NAME} 0) | ||
|
||
# create map/bin/hex file etc. | ||
pico_add_extra_outputs(${TARGET_NAME}) | ||
|
||
# add url via pico_set_program_url | ||
example_auto_set_url(${TARGET_NAME}) |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,96 @@ | ||
/** | ||
* Copyright (c) 2020 Raspberry Pi (Trading) Ltd. | ||
* | ||
* SPDX-License-Identifier: BSD-3-Clause | ||
*/ | ||
|
||
#include <stdio.h> | ||
#include "pico/stdlib.h" | ||
|
||
|
||
#define KEYPAD_NUM_ROWS 4 | ||
#define KEYPAD_NUM_COLUMNS 4 | ||
#define NO_KEY_PRESSED '\0' // Just a character that unlikely be | ||
// present in keyboards, so it can by used | ||
lurch marked this conversation as resolved.
Show resolved
Hide resolved
|
||
// to determine if no key is pressed. | ||
#define READ_MS_DELAY 10 // Delay between lectures to avoid noise | ||
lurch marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
|
||
const uint8_t keypad_rows_pins[KEYPAD_NUM_ROWS] = { | ||
10, | ||
11, | ||
12, | ||
13, | ||
}; | ||
|
||
|
||
const uint8_t keypad_columns_pins[KEYPAD_NUM_COLUMNS] = { | ||
18, // GP18 | ||
19, // GP19 | ||
20, // GP20 | ||
21, // GP21 | ||
}; | ||
|
||
|
||
const char keypad_keys[KEYPAD_NUM_ROWS][KEYPAD_NUM_COLUMNS] = { | ||
{'1', '2', '3', 'A'}, | ||
{'4', '5', '6', 'B'}, | ||
{'7', '8', '9', 'C'}, | ||
{'*', '0', '#', 'D'}, | ||
}; | ||
|
||
|
||
void pico_keypad_init(void){ | ||
jcarranz97 marked this conversation as resolved.
Show resolved
Hide resolved
|
||
// Initialize GPIOs | ||
//Initialize row pins as GPIO_OUT | ||
for (int i=0; i < KEYPAD_NUM_ROWS; i++){ | ||
uint8_t pin_number = keypad_rows_pins[i]; | ||
gpio_init(pin_number); | ||
gpio_set_dir(pin_number, GPIO_OUT); | ||
gpio_put(pin_number, 0); // Make sure GPIO_OUT is LOW | ||
} | ||
//Initialize column pins as GPIO_IN | ||
for (int i=0; i < KEYPAD_NUM_COLUMNS; i++){ | ||
uint8_t pin_number = keypad_columns_pins[i]; | ||
gpio_init(pin_number); | ||
gpio_set_dir(pin_number, GPIO_IN); | ||
} | ||
} | ||
|
||
|
||
char get_keypad_value(void){ | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I wonder if it's worth trying to detect if multiple keys are being pressed (and signal that as an error condition), rather than just assuming that the first key detected is the only key pressed? 🤔 There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I was thinking about the same but allow multiple keys pressed at the same time, but did not find an "simple" way of doing this ... This is what I have in mind, let me know what you think about this. Enhanced Keypad changes
Summary of Changes:
For a raw diff of the changes, you can view this link. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Please let me know if you agree with this implementation. I have created the There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Does that actually work? I thought that for these simple matrix keypads, if more than one key is pressed at a time you can't actually reliably detect which keys have been pressed? 🤷 There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yes, this method is also working. A keypad is a matrix of buttons arranged in rows and columns, typically used in devices like old phones or security systems. Each button on the keypad connects a unique row and column. When a key is pressed, it completes a circuit between a specific row and column, which can be detected by a microcontroller like the Raspberry Pi Pico. To detect which key is pressed, the microcontroller sequentially sets each row to a high voltage (1) and checks the voltage on each column. If pressing a key connects the active row to a column, the microcontroller detects the column as high (1). By knowing which row and column are connected, the microcontroller can determine which key was pressed. I went ahead and merged this enhanced code. I think it is a more complete example. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
I'm afraid I'm still not convinced, see e.g. https://arduino.stackexchange.com/questions/50869/4x4-matrix-keypad-multiple-inputs-cause-extra-readings |
||
// Iterate over key and rows to identify which key is pressed. | ||
// When iterating rows, the GPIO_OUT associted to the row needs to be set | ||
// to HIGH, and then iterate the columns to determine the GPIO_IN. | ||
for (int row=0; row < KEYPAD_NUM_ROWS; row++){ | ||
gpio_put(keypad_rows_pins[row], 1); | ||
for (int column=0; column < KEYPAD_NUM_COLUMNS; column++){ | ||
sleep_ms(READ_MS_DELAY); | ||
if(gpio_get(keypad_columns_pins[column])){ | ||
// If the pin is HIGH, this means this is a matching row and | ||
// column, so we put the row pin to LOW and return the pressed | ||
// key by using the bidimensional array keypad_keys. | ||
gpio_put(keypad_rows_pins[row], 0); | ||
return keypad_keys[row][column]; | ||
} | ||
} | ||
gpio_put(keypad_rows_pins[row], 0); | ||
} | ||
return NO_KEY_PRESSED; | ||
} | ||
|
||
|
||
int main() { | ||
stdio_init_all(); | ||
pico_keypad_init(); | ||
while (true) { | ||
char key = get_keypad_value(); | ||
if (key == NO_KEY_PRESSED){ | ||
printf("No key pressed\n"); | ||
} | ||
else{ | ||
printf("Key '%c' pressed\n", key); | ||
} | ||
sleep_ms(500); | ||
} | ||
} |
Uh oh!
There was an error while loading. Please reload this page.