Hi,
For those that might need it, I wanted to show you how to use the " KEYES AD Keyboard", using 5 Volts at VCC which looks like this:
(I've annotated the buttons on top, for more clarity)
For starters, I had to measure the value received by analogRead()
for each key, and since I bought two of them I was expecting slight differences between them, and indeed there were (see below); I measured the ADC readings in 10 bit, 12 bit and 14 bit resolutions.
Here are the two tables with ADC readings and corresponding voltages:
D1 = Device 1
D2 = Device 2
Column nomenclature is Device@ADCResolution
ADC Readings Table 5 Volts at VCC:
Switch | D1@10b | D1@12b | D1@14b | D2@10b | D2@12b | D2@14b |
---|---|---|---|---|---|---|
SW1 | 0 | 0 | 0 | 0 | 0 | 0 |
SW2 | 144 | 577 | 2310 | 146 | 588 | 2530 |
SW3 | 324 | 1300 | 5190 | 328 | 1315 | 5260 |
SW4 | 498 | 1990 | 7980 | 499 | 1995 | 7990 |
SW5 | 734 | 2940 | 11750 | 737 | 2950 | 11800 |
Nothing | 1023 | 4095 | 16380 | 1023 | 4095 | 16380 |
Voltage Table 5 Volts at VCC:
Switch | D1@10b Voltage (V) | D1@12b Voltage (V) | D1@14b Voltage (V) | D2@10b Voltage (V) | D2@12b Voltage (V) | D2@14b Voltage (V) |
---|---|---|---|---|---|---|
SW1 | 0.000 | 0.000 | 0.000 | 0.000 | 0.000 | 0.000 |
SW2 | 0.704 | 0.705 | 0.705 | 0.714 | 0.718 | 0.772 |
SW3 | 1.584 | 1.587 | 1.584 | 1.603 | 1.606 | 1.605 |
SW4 | 2.434 | 2.430 | 2.435 | 2.439 | 2.436 | 2.439 |
SW5 | 3.587 | 3.590 | 3.586 | 3.602 | 3.602 | 3.601 |
Nothing | 5.000 | 5.000 | 5.000 | 5.000 | 5.000 | 5.000 |
Here are each of the voltages charted per button, compared using the 3 resolutions, pretty much the values correlate as expected:
Why AceButton
?
First time I saw it, was on the factory demo of Lily's T3S3 LoRa32, I liked it was responsive for single click, double clicks or even long clicks, handling all that for you...!
So, how to use it with AceButton
?...
Here is the code for that:
#include <AceButton.h>
using namespace ace_button;
static const uint8_t BUTTON_PIN = A0;
// Create 5 AceButton objects, with specific names for each button.
static const uint8_t NUM_BUTTONS = 5;
static AceButton btnLeft(nullptr, 0); // Left button (SW1)
static AceButton btnUp(nullptr, 1); // Up button (SW2)
static AceButton btnDown(nullptr, 2); // Down button (SW3)
static AceButton btnRight(nullptr, 3); // Right button (SW4)
static AceButton btnSelect(nullptr, 4); // Select button (SW5)
static AceButton* const BUTTONS[NUM_BUTTONS] = {
&btnLeft, &btnUp, &btnDown, &btnRight, &btnSelect
};
// Define specific ADC thresholds based on resolution (10-bit, 12-bit, or 14-bit)
static const uint16_t LEVELS_10BIT[] = { 0, 144, 324, 498, 734, 1023 }; // 10-bit resolution
static const uint16_t LEVELS_12BIT[] = { 0, 577, 1300, 1990, 2940, 4095 }; // 12-bit resolution
static const uint16_t LEVELS_14BIT[] = { 0, 2310, 5190, 7980, 11750, 16380 }; // 14-bit resolution
// Pointer to the button config object
LadderButtonConfig* buttonConfig = nullptr;
// Function to dynamically update levels based on resolution
void setLevelsBasedOnResolution(uint8_t resolution) {
delete buttonConfig; // Delete the previous buttonConfig instance if it exists
switch (resolution) {
case 10: // 10-bit resolution
buttonConfig = new LadderButtonConfig(BUTTON_PIN, NUM_BUTTONS + 1, LEVELS_10BIT, NUM_BUTTONS, BUTTONS);
Serial.println("Using 10-bit resolution ADC levels.");
break;
case 12: // 12-bit resolution
buttonConfig = new LadderButtonConfig(BUTTON_PIN, NUM_BUTTONS + 1, LEVELS_12BIT, NUM_BUTTONS, BUTTONS);
Serial.println("Using 12-bit resolution ADC levels.");
break;
case 14: // 14-bit resolution
buttonConfig = new LadderButtonConfig(BUTTON_PIN, NUM_BUTTONS + 1, LEVELS_14BIT, NUM_BUTTONS, BUTTONS);
Serial.println("Using 14-bit resolution ADC levels.");
break;
default: // Fallback to 10-bit if unknown
buttonConfig = new LadderButtonConfig(BUTTON_PIN, NUM_BUTTONS + 1, LEVELS_10BIT, NUM_BUTTONS, BUTTONS);
Serial.println("Unknown resolution, using 10-bit by default.");
break;
}
// Reassign the event handler and enable features after reinitializing buttonConfig
buttonConfig->setEventHandler(handleEvent);
buttonConfig->setFeature(ButtonConfig::kFeatureClick);
buttonConfig->setFeature(ButtonConfig::kFeatureDoubleClick);
buttonConfig->setFeature(ButtonConfig::kFeatureLongPress);
buttonConfig->setFeature(ButtonConfig::kFeatureRepeatPress);
}
// Event handler for each button press.
void handleEvent(AceButton* button, uint8_t eventType, uint8_t buttonState) {
Serial.print(F("Button: "));
// Identify which button was pressed
switch (button->getPin()) {
case 0:
Serial.print("Left");
break;
case 1:
Serial.print("Up");
break;
case 2:
Serial.print("Down");
break;
case 3:
Serial.print("Right");
break;
case 4:
Serial.print("Select");
break;
default:
Serial.print("Unknown");
break;
}
Serial.print(F(" - Event Type: "));
// Handle each event type
switch (eventType) {
case AceButton::kEventPressed:
Serial.println("Pressed");
break;
case AceButton::kEventReleased:
Serial.println("Released");
break;
case AceButton::kEventClicked:
Serial.println("Click");
break;
case AceButton::kEventDoubleClicked:
Serial.println("Double Click");
break;
case AceButton::kEventLongPressed:
Serial.println("Long Press");
break;
case AceButton::kEventRepeatPressed:
Serial.println("Repeat Press");
break;
default:
Serial.println("Unknown Event");
break;
}
}
void setup() {
delay(1000);
Serial.begin(115200);
while (!Serial);
pinMode(BUTTON_PIN, INPUT);
// Set ADC levels based on device resolution (example: 10-bit resolution)
setLevelsBasedOnResolution(10); // Adjust the parameter (10, 12, 14) based on your current resolution
}
// Call checkButtons every 5ms or faster for debounce.
void checkButtons() {
static unsigned long prev = millis();
unsigned long now = millis();
if (now - prev > 5) {
buttonConfig->checkButtons();
prev = now;
}
}
void loop() {
checkButtons();
}
Example output:
15:15:54.569 -> Button: Up - Event Type: Pressed
15:15:54.661 -> Button: Up - Event Type: Click
15:15:54.661 -> Button: Up - Event Type: Released
15:15:55.748 -> Button: Up - Event Type: Pressed
15:15:55.840 -> Button: Up - Event Type: Click
15:15:55.840 -> Button: Up - Event Type: Released
15:15:55.933 -> Button: Up - Event Type: Pressed
15:15:56.025 -> Button: Up - Event Type: Double Click
15:15:56.025 -> Button: Up - Event Type: Released
15:15:56.953 -> Button: Up - Event Type: Pressed
15:15:57.958 -> Button: Up - Event Type: Long Press
15:15:57.958 -> Button: Up - Event Type: Repeat Press
15:15:58.130 -> Button: Up - Event Type: Repeat Press
15:15:58.361 -> Button: Up - Event Type: Repeat Press
15:15:58.538 -> Button: Up - Event Type: Repeat Press
15:15:58.765 -> Button: Up - Event Type: Repeat Press
I hope this helps you on whatever project you have and with the ADC resolution you might have on your board.
Perhaps you ordered this board and are waiting for it to do something similar?. if so, I hope the values I've measured help you out to continue your development while waiting.