Skip to content
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

Multiples digits when press any key #22

Closed
joaouzeda opened this issue Jun 13, 2024 · 7 comments
Closed

Multiples digits when press any key #22

joaouzeda opened this issue Jun 13, 2024 · 7 comments
Assignees
Labels
enhancement New feature or request

Comments

@joaouzeda
Copy link

joaouzeda commented Jun 13, 2024

I was having a problem that when a key was pressed it sent multiple digits, my solution was to put a delay in the _getKey4x4() function, as I put below

uint8_t I2CKeyPad::_getKey4x4()
{
  //  key = row + 4 x col
  uint8_t key = 0;

  //  mask = 4 rows as input pull up, 4 columns as output
  uint8_t rows = _read(0xF0);
  //  check if single line has gone low.
  if (rows == 0xF0)      return I2C_KEYPAD_NOKEY;
  else if (rows == 0xE0) key = 0;
  else if (rows == 0xD0) key = 1;
  else if (rows == 0xB0) key = 2;
  else if (rows == 0x70) key = 3;
  else return I2C_KEYPAD_FAIL;

  //  4 columns as input pull up, 4 rows as output
  uint8_t cols = _read(0x0F);
  //  check if single line has gone low.
  if (cols == 0x0F)      return I2C_KEYPAD_NOKEY;
  else if (cols == 0x0E) key += 0;
  else if (cols == 0x0D) key += 4;
  else if (cols == 0x0B) key += 8;
  else if (cols == 0x07) key += 12;
  else return I2C_KEYPAD_FAIL;

  _lastKey = key;

  usleep(50000);

  return key;   //  0..15
}

(updated syntax highlighting)

@RobTillaart
Copy link
Owner

Sorry for the long delay, I missed the notifications.

@RobTillaart RobTillaart self-assigned this Jul 14, 2024
@RobTillaart
Copy link
Owner

@joaouzeda
I will look into it a.s.a.p as I have missed several issues (all within the same time slot) and this one is imho a low priority.
So it might take several days before it will be continued.

Thanks for reporting anyway, appreciated!

@RobTillaart RobTillaart added the enhancement New feature or request label Jul 14, 2024
@RobTillaart
Copy link
Owner

@joaouzeda

I was having a problem that when a key was pressed it sent multiple digits ...

It sounds like a bouncing key, did you get the same digit multiple times?

@RobTillaart
Copy link
Owner

RobTillaart commented Jul 14, 2024

A generic solution could be a parameter (or internal variable), configurable in the interface of the library.

uint8_t I2CKeyPad::_getKey4x4(int debounceDelay = 0)  // default 0 for backwards compatibility
{
  //  key = row + 4 x col
  uint8_t key = 0;

  //  mask = 4 rows as input pull up, 4 columns as output
  uint8_t rows = _read(0xF0);
  //  check if single line has gone low.
  if (rows == 0xF0)      return I2C_KEYPAD_NOKEY;
  else if (rows == 0xE0) key = 0;
  else if (rows == 0xD0) key = 1;
  else if (rows == 0xB0) key = 2;
  else if (rows == 0x70) key = 3;
  else return I2C_KEYPAD_FAIL;

  //  4 columns as input pull up, 4 rows as output
  uint8_t cols = _read(0x0F);
  //  check if single line has gone low.
  if (cols == 0x0F)      return I2C_KEYPAD_NOKEY;
  else if (cols == 0x0E) key += 0;
  else if (cols == 0x0D) key += 4;
  else if (cols == 0x0B) key += 8;
  else if (cols == 0x07) key += 12;
  else return I2C_KEYPAD_FAIL;

  _lastKey = key;

  if (debounceDelay ) delay(debounceDelay ); //  call only if debounceDelay > 0

  return key;   //  0..15
}

Another option could be to have a static timestamp that checks if the last call was less than e.g. 50 millis ago.
if so it could return the last key or some status code e.g. I2C_KEYPAD_TOO_FAST

@RobTillaart
Copy link
Owner

mmm, debounce delay need to work for all four supported key layouts.

Solution should be implemented in a higher layer. something like:

uint8_t I2CKeyPad::getKey()
{
  if (millis() - lastCall) < threshold return TOOFAST

  uint8_t _key = 0;
  if (_mode == I2C_KEYPAD_5x3) _key = _getKey5x3();
  else if (_mode == I2C_KEYPAD_6x2) _key =_getKey6x2();
  else if (_mode == I2C_KEYPAD_8x1) _key = _getKey8x1();
  else _key =  _getKey4x4();  //  default.
  return _key;
}

@RobTillaart
Copy link
Owner

@joaouzeda

Solution implemented in pull request #23

(snippet of new readme.md)

Debouncing threshold

Experimental since version 0.4.1, the library implements a debounce threshold.
If a key bounces, it can trigger multiple interrupts, while the purpose is to act like only one keypress. The debounce threshold prevents reading a key too fast. The default value of the threshold is zero to be backwards compatible. The value is set in microseconds, with a maximum of 65535 ~65 milliseconds, which is about 16 keys per second.

// value in microseconds, max 65535 us

  • void setDebounceThreshold(uint16_t value = 0) set the threshold,
    default to zero to reset its value.
  • uint16_t getDebounceThreshold() return the set threshold.

If a debounce threshold is set, and getKey() is called too fast,
it will return I2C_KEYPAD_THRESHOLD.

@joaouzeda
Copy link
Author

Thank for your answer!

RobTillaart added a commit that referenced this issue Jul 18, 2024
- Fix #21, add section to readme.md
- Fix #22, implement **debounceThreshold**
- add constant **I2C_KEYPAD_THRESHOLD**
- add **uint32_t getLastTimeRead()**
- update **getChar()** to support **I2C_KEYPAD_THRESHOLD**
- update readme.md
- update unit test
- update keywords.txt
- minor edits
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
None yet
Development

No branches or pull requests

2 participants