0.4.0 I2CKeyPad

This commit is contained in:
Rob Tillaart 2023-11-11 17:08:08 +01:00
parent ac95aef851
commit 8cf136ecad
20 changed files with 273 additions and 115 deletions

View File

@ -6,11 +6,18 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/)
and this project adheres to [Semantic Versioning](http://semver.org/).
## [0.4.0] - 2023-11-09
- simplify begin()
- added I2Ckeypad_Wire1_ESP32.ino
- update readme.md
- minor edits
----
## [0.3.3] - 2022-11-12
- Add RP2040 support to build-CI.
- Add CHANGELOG.md
## [0.3.2] - 2022-09-19
- experimental version
- add 5x3, 6x2 and 8x1 support

View File

@ -1,11 +1,9 @@
//
// FILE: I2CKeyPad.cpp
// AUTHOR: Rob Tillaart
// VERSION: 0.3.3
// VERSION: 0.4.0
// PURPOSE: Arduino library for 4x4 KeyPad connected to an I2C PCF8574
// URL: https://github.com/RobTillaart/I2CKeyPad
//
// HISTORY: see changelog.md
#include "I2CKeyPad.h"
@ -20,20 +18,8 @@ I2CKeyPad::I2CKeyPad(const uint8_t deviceAddress, TwoWire *wire)
}
#if defined(ESP8266) || defined(ESP32)
bool I2CKeyPad::begin(uint8_t sda, uint8_t scl)
{
_wire->begin(sda, scl);
// enable interrupts
_read(0xF0);
return isConnected();
}
#endif
bool I2CKeyPad::begin()
{
_wire->begin();
// enable interrupts
_read(0xF0);
return isConnected();
@ -145,9 +131,9 @@ uint8_t I2CKeyPad::_getKey4x4()
else if (rows == 0x70) key = 3;
else return I2C_KEYPAD_FAIL;
// 4 columns as input pull up, 4 rows as output
// 4 columns as input pull up, 4 rows as output
uint8_t cols = _read(0x0F);
// check if single line has gone low.
// 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;
@ -157,7 +143,7 @@ uint8_t I2CKeyPad::_getKey4x4()
_lastKey = key;
return key; // 0..15
return key; // 0..15
}
@ -189,7 +175,7 @@ uint8_t I2CKeyPad::_getKey5x3()
_lastKey = key;
return key; // 0..14
return key; // 0..14
}
@ -211,9 +197,9 @@ uint8_t I2CKeyPad::_getKey6x2()
else if (rows == 0x7C) key = 5;
else return I2C_KEYPAD_FAIL;
// 2 columns as input pull up, 6 rows as output
// 2 columns as input pull up, 6 rows as output
uint8_t cols = _read(0x03);
// check if single line has gone low.
// check if single line has gone low.
if (cols == 0x03) return I2C_KEYPAD_NOKEY;
else if (cols == 0x02) key += 0;
else if (cols == 0x01) key += 6;
@ -221,7 +207,7 @@ uint8_t I2CKeyPad::_getKey6x2()
_lastKey = key;
return key; // 0..11
return key; // 0..11
}
@ -247,9 +233,9 @@ uint8_t I2CKeyPad::_getKey8x1()
_lastKey = key;
return key; // 0..7
return key; // 0..7
}
// -- END OF FILE --
// -- END OF FILE --

View File

@ -2,7 +2,7 @@
//
// FILE: I2CKeyPad.h
// AUTHOR: Rob Tillaart
// VERSION: 0.3.3
// VERSION: 0.4.0
// PURPOSE: Arduino library for 4x4 KeyPad connected to an I2C PCF8574
// URL: https://github.com/RobTillaart/I2CKeyPad
@ -11,7 +11,7 @@
#include "Wire.h"
#define I2C_KEYPAD_LIB_VERSION (F("0.3.3"))
#define I2C_KEYPAD_LIB_VERSION (F("0.4.0"))
#define I2C_KEYPAD_NOKEY 16
#define I2C_KEYPAD_FAIL 17
@ -28,9 +28,7 @@ class I2CKeyPad
public:
I2CKeyPad(const uint8_t deviceAddress, TwoWire *wire = &Wire);
#if defined(ESP8266) || defined(ESP32)
bool begin(uint8_t sda, uint8_t scl);
#endif
// call Wire.begin() first!
bool begin();
// get raw key's 0..15
@ -69,5 +67,5 @@ protected:
};
// -- END OF FILE --
// -- END OF FILE --

View File

@ -2,8 +2,11 @@
[![Arduino CI](https://github.com/RobTillaart/I2CKeyPad/workflows/Arduino%20CI/badge.svg)](https://github.com/marketplace/actions/arduino_ci)
[![Arduino-lint](https://github.com/RobTillaart/I2CKeyPad/actions/workflows/arduino-lint.yml/badge.svg)](https://github.com/RobTillaart/I2CKeyPad/actions/workflows/arduino-lint.yml)
[![JSON check](https://github.com/RobTillaart/I2CKeyPad/actions/workflows/jsoncheck.yml/badge.svg)](https://github.com/RobTillaart/I2CKeyPad/actions/workflows/jsoncheck.yml)
[![GitHub issues](https://img.shields.io/github/issues/RobTillaart/I2CKeyPad.svg)](https://github.com/RobTillaart/I2CKeyPad/issues)
[![License: MIT](https://img.shields.io/badge/license-MIT-green.svg)](https://github.com/RobTillaart/I2CKeyPad/blob/master/LICENSE)
[![GitHub release](https://img.shields.io/github/release/RobTillaart/I2CKeyPad.svg?maxAge=3600)](https://github.com/RobTillaart/I2CKeyPad/releases)
[![PlatformIO Registry](https://badges.registry.platformio.org/packages/robtillaart/library/I2CKeyPad.svg)](https://registry.platformio.org/libraries/robtillaart/I2CKeyPad)
# I2CKeyPad
@ -18,7 +21,13 @@ Smaller keypads, meaning less columns or rows (4x3) can be read with it too.
Since 0.3.2 the library allows a 5x3, 6x2 or 8x1 or smaller keypad to be connected too.
Relates to https://github.com/RobTillaart/I2CKeyPad8x8. which is an 8x8 version using PCF8575.
#### Related
Relates strongly to https://github.com/RobTillaart/I2CKeyPad8x8. which is an 8x8 version using **PCF8575**.
- https://github.com/RobTillaart/AnalogKeypad
- https://github.com/RobTillaart/I2CKeyPad8x8
- https://github.com/WK-Software56/AdvKeyPad (derived work with keyboard alike interface)
## Connection
@ -45,12 +54,17 @@ It might take some trying to get the correct pins connected.
## Interface
- **I2CKEYPAD(const uint8_t deviceAddress, TwoWire \*wire = &Wire)**
```cpp
#include "I2CKeyPad.h"
```
#### Base
- **I2CKeyPad(const uint8_t deviceAddress, TwoWire \*wire = &Wire)**
The constructor sets the device address and optionally
allows to selects the I2C bus to use.
- **bool begin()** The return value shows if the PCF8574 with the given address is connected properly.
- **bool begin(uint8_t sda, uint8_t scl)** for ESP32.
The return value shows if the PCF8574 with the given address is connected properly.
Call wire.begin() first!
- **bool isConnected()** returns false if the PCF8574 cannot be connected to.
- **uint8_t getKey()** Returns default 0..15 for regular keys,
Returns 16 if no key is pressed and 17 in case of an error.
@ -141,5 +155,24 @@ See examples
## Future
#### Must
- update documentation
#### Should
- test key mapping functions.
#### Could
#### Wont
## Support
If you appreciate my libraries, you can support the development and maintenance.
Improve the quality of the libraries by providing issues and Pull Requests, or
donate through PayPal or GitHub sponsors.
Thank you,

View File

@ -13,7 +13,7 @@
// IRQ pin 2
// SDA A4
// SCL A5
// 4x4 or smaller keypad.
// 4x4 or smaller keypad.
// notes
@ -36,7 +36,7 @@
// however it is more efficient to reset the flag only after the
// keypress is handled.
//
// Note: multiple keypresses are not queued.
// Note: multiple keypresses are not queued.
////////////////////////////////////////////////////////////////////////
@ -49,7 +49,7 @@
const uint8_t KEYPAD_ADDRESS = 0x20;
I2CKeyPad keyPad(KEYPAD_ADDRESS);
char keys[] = "123A456B789C*0#DNF"; // N = NoKey, F = Fail (e.g. >1 keys pressed)
char keys[] = "123A456B789C*0#DNF"; // N = NoKey, F = Fail (e.g. > 1 keys pressed)
// volatile for IRQ var
volatile bool keyChange = false;
@ -67,13 +67,13 @@ void setup()
Serial.println(__FILE__);
// NOTE: PCF8574 will generate an interrupt on key press and release.
// NOTE: PCF8574 will generate an interrupt on key press and release.
pinMode(3, INPUT_PULLUP);
attachInterrupt(1, keyChanged, FALLING);
keyChange = false;
Wire.begin();
Wire.setClock(100000);
if (keyPad.begin() == false)
{
Serial.println("\nERROR: cannot communicate to keypad.\nPlease reboot.\n");
@ -81,8 +81,6 @@ void setup()
}
measurePolling();
Wire.setClock(100000);
}
@ -91,7 +89,7 @@ void loop()
if (keyChange)
{
uint8_t index = keyPad.getKey();
// only after keyChange is handled it is time reset the flag
// only after keyChange is handled it is time reset the flag
keyChange = false;
if (index != 16)
{
@ -109,7 +107,7 @@ void loop()
void measurePolling()
{
// measure time to check isPressed() by polling.
// measure time to check isPressed() by polling.
// CLOCK TIME (us)
// ---------------------
@ -126,7 +124,7 @@ void measurePolling()
Wire.setClock(clock);
for (int i = 0; i < 1; i++)
{
// reference time for keyPressed check UNO ~
// reference time for keyPressed check UNO ~
uint32_t start = micros();
uint8_t index = keyPad.isPressed();
uint32_t stop = micros();
@ -144,5 +142,5 @@ void measurePolling()
}
// -- END OF FILE --
// -- END OF FILE --

View File

@ -41,7 +41,7 @@ void loop()
{
uint32_t now = millis();
// adjust keymap if needed
char keys[] = "1234567890ABCDE NF"; // N = NoKey, F = Fail
char keys[] = "1234567890ABCDE NF"; // N = NoKey, F = Fail
if (now - lastKeyPressed >= 100)
{
@ -62,4 +62,4 @@ void loop()
}
// -- END OF FILE --
// -- END OF FILE --

View File

@ -41,7 +41,7 @@ void loop()
{
uint32_t now = millis();
// adjust keymap if needed
char keys[] = "1234567890ABC NF"; // N = NoKey, F = Fail
char keys[] = "1234567890ABC NF"; // N = NoKey, F = Fail
if (now - lastKeyPressed >= 100)
{
@ -62,4 +62,4 @@ void loop()
}
// -- END OF FILE --
// -- END OF FILE --

View File

@ -6,7 +6,6 @@
//
// PCF8574
// pin p0-p7 rows
//
#include "Wire.h"
@ -41,7 +40,7 @@ void loop()
{
uint32_t now = millis();
// adjust keymap if needed
char keys[] = "12345678 NF"; // N = NoKey, F = Fail
char keys[] = "12345678 NF"; // N = NoKey, F = Fail
if (now - lastKeyPressed >= 100)
{
@ -62,4 +61,4 @@ void loop()
}
// -- END OF FILE --
// -- END OF FILE --

View File

@ -0,0 +1,28 @@
platforms:
rpipico:
board: rp2040:rp2040:rpipico
package: rp2040:rp2040
gcc:
features:
defines:
- ARDUINO_ARCH_RP2040
warnings:
flags:
packages:
rp2040:rp2040:
url: https://github.com/earlephilhower/arduino-pico/releases/download/global/package_rp2040_index.json
compile:
# Choosing to run compilation tests on 2 different Arduino platforms
platforms:
# - uno
# - due
# - zero
# - leonardo
# - m4
- esp32
# - esp8266
# - mega2560
# - rpipico

View File

@ -0,0 +1,111 @@
//
// FILE: I2Ckeypad_Wire1_ESP32.ino
// AUTHOR: Rob Tillaart
// PURPOSE: demo reading a larger value from the keyPad
// URL: https://github.com/RobTillaart/I2CKeyPad
//
// PCF8574
// pin p0-p3 rows
// pin p4-p7 columns
// 4x4 or smaller keypad.
#include "Wire.h"
#include "I2CKeyPad.h"
const uint8_t KEYPAD_ADDRESS = 0x38;
I2CKeyPad keyPad(KEYPAD_ADDRESS, &Wire1);
uint32_t start, stop;
uint32_t lastKeyPressed = 0;
uint32_t value = 0;
void setup()
{
Serial.begin(115200);
Serial.println(__FILE__);
Wire1.begin(22, 23); // adjust pins if needed
Wire1.setClock(400000);
if (keyPad.begin() == false)
{
Serial.println("\nERROR: cannot communicate to keypad.\nPlease reboot.\n");
while(1);
}
}
void loop()
{
uint32_t now = millis();
if (now - lastKeyPressed >= 100)
{
lastKeyPressed = now;
start = micros();
char c = handleKeyPadValue(value);
if (value > 125000) value = 125000; // some sample max.
stop = micros();
Serial.print(millis());
Serial.print("\t");
Serial.print(value);
Serial.print("\t");
Serial.print((char) c);
Serial.print("\t");
Serial.println(stop - start);
}
}
// handleKeyPadValue is used to read a uint32_t from the keypad
// every digit must be pressed separately
// the last key pressed is also returned.
//
// 0..9 adds to the number
// * means remove last digit
// # resets to zero
// ABCD are not mapped.
char handleKeyPadValue(uint32_t &value)
{
char v[19] = "123A456B789C*0#DNF"; // N = NoKey, F = Fail
static uint8_t lastKey = 0;
uint8_t idx = keyPad.getKey();
char c = v[idx];
if (lastKey != c)
{
lastKey = c;
switch (c)
{
case '0' ... '9':
value *= 10;
value += c - '0';
break;
case '*':
if (value > 0) value /= 10;
break;
case '#':
value = 0;
break;
case 'A' ... 'D':
// e.g. store value in EEPROM
break;
case 'F':
Serial.println("FAIL");
break;
case 'N':
Serial.println("NOKEY");
break;
default:
break;
}
}
return c;
}
// -- END OF FILE --

View File

@ -39,7 +39,7 @@ void setup()
void loop()
{
uint32_t now = millis();
char keys[] = "123A456B789C*0#DNF"; // N = NoKey, F = Fail
char keys[] = "123A456B789C*0#DNF"; // N = NoKey, F = Fail
if (now - lastKeyPressed >= 100)
{
@ -60,5 +60,5 @@ void loop()
}
// -- END OF FILE --
// -- END OF FILE --

View File

@ -4,10 +4,10 @@
// PURPOSE: demo
// URL: https://github.com/RobTillaart/I2CKeyPad
//
// PCF8574
// PCF8574
// pin p0-p3 rows
// pin p4-p7 columns
// 4x4 or smaller keypad.
// 4x4 or smaller keypad.
#include "Wire.h"
@ -55,7 +55,7 @@ void loop()
Serial.print("\t");
Serial.print(index);
Serial.print("\t");
Serial.print((char)"123A456B789C*0#DNF"[index]); // NoKey, Fail
Serial.print((char)"123A456B789C*0#DNF"[index]); // NoKey, Fail
Serial.print("\t");
Serial.print(lastKey);
Serial.print("\t");
@ -68,5 +68,5 @@ void loop()
}
// -- END OF FILE --
// -- END OF FILE --

View File

@ -4,10 +4,10 @@
// PURPOSE: demo reading a larger value from the keyPad
// URL: https://github.com/RobTillaart/I2CKeyPad
//
// PCF8574
// PCF8574
// pin p0-p3 rows
// pin p4-p7 columns
// 4x4 or smaller keypad.
// 4x4 or smaller keypad.
#include "Wire.h"
@ -47,7 +47,7 @@ void loop()
start = micros();
char c = handleKeyPadValue(value);
if (value > 125000) value = 125000; // some sample max.
if (value > 125000) value = 125000; // some sample max.
stop = micros();
Serial.print(millis());
Serial.print("\t");
@ -60,17 +60,17 @@ void loop()
}
// handleKeyPadValue is used to read a uint32_t from the keypad
// every digit must be pressed separately
// the last key pressed is also returned.
// handleKeyPadValue is used to read a uint32_t from the keypad
// every digit must be pressed separately
// the last key pressed is also returned.
//
// 0..9 adds to the number
// * means remove last digit
// # resets to zero
// ABCD are not mapped.
// 0..9 adds to the number
// * means remove last digit
// # resets to zero
// ABCD are not mapped.
char handleKeyPadValue(uint32_t &value)
{
char v[19] = "123A456B789C*0#DNF"; // N = NoKey, F = Fail
char v[19] = "123A456B789C*0#DNF"; // N = NoKey, F = Fail
static uint8_t lastKey = 0;
uint8_t idx = keyPad.getKey();
@ -92,7 +92,7 @@ char handleKeyPadValue(uint32_t &value)
value = 0;
break;
case 'A' ... 'D':
// e.g. store value in EEPROM
// e.g. store value in EEPROM
break;
case 'F':
Serial.println("FAIL");
@ -108,5 +108,5 @@ char handleKeyPadValue(uint32_t &value)
}
// -- END OF FILE --
// -- END OF FILE --

View File

@ -4,10 +4,10 @@
// PURPOSE: demo key mapping
// URL: https://github.com/RobTillaart/I2CKeyPad
//
// PCF8574
// PCF8574
// pin p0-p3 rows
// pin p4-p7 columns
// 4x4 or smaller keypad.
// 4x4 or smaller keypad.
#include "Wire.h"

View File

@ -4,10 +4,10 @@
// PURPOSE: demo key mapping
// URL: https://github.com/RobTillaart/I2CKeyPad
//
// PCF8574
// PCF8574
// pin p0-p3 rows
// pin p4-p7 columns
// 4x4 or smaller keypad.
// 4x4 or smaller keypad.
//
@ -20,7 +20,7 @@ const uint8_t KEYPAD_ADDRESS = 0x38;
I2CKeyPad keyPad(KEYPAD_ADDRESS);
// minimal calculator layout
char calculator_layout[19] = "789+456-123 0 NF"; // N = NoKey, F = Fail
char calculator_layout[19] = "789+456-123 0 NF"; // N = NoKey, F = Fail
int32_t sum = 0;
int32_t val = 0;
@ -73,5 +73,5 @@ void loop()
}
// -- END OF FILE --
// -- END OF FILE --

View File

@ -4,10 +4,10 @@
// PURPOSE: demo key mapping
// URL: https://github.com/RobTillaart/I2CKeyPad
//
// PCF8574
// PCF8574
// pin p0-p3 rows
// pin p4-p7 columns
// 4x4 or smaller keypad.
// 4x4 or smaller keypad.
#include "Wire.h"
@ -20,8 +20,8 @@ I2CKeyPad keyPad(KEYPAD_ADDRESS);
// two different lay out styles of a nummeric keyPad
char phone_layout[19] = "123A456B789C*0#DNF"; // N = NoKey, F = Fail
char calculator_layout[19] = "789A456B123C*0#DNF"; // N = NoKey, F = Fail
char phone_layout[19] = "123A456B789C*0#DNF"; // N = NoKey, F = Fail
char calculator_layout[19] = "789A456B123C*0#DNF"; // N = NoKey, F = Fail
void setup()
@ -60,5 +60,5 @@ void loop()
}
// -- END OF FILE --
// -- END OF FILE --

View File

@ -4,10 +4,10 @@
// PURPOSE: demo reading until specific keyPress
// URL: https://github.com/RobTillaart/I2CKeyPad
//
// PCF8574
// PCF8574
// pin p0-p3 rows
// pin p4-p7 columns
// 4x4 or smaller keypad.
// 4x4 or smaller keypad.
//
// This demo doesn't use the build in key mapping.
//
@ -64,14 +64,14 @@ void loop()
//
// until = end character
// buffer = buffer to fill
// length = length of buffer (including '\0'
// timeout = timeout in milliseconds
// returns 0 = success
// -1 = keyPad fail
// -2 = timeout
// -3 = buffer overflow
// until = end character
// buffer = buffer to fill
// length = length of buffer (including '\0'
// timeout = timeout in milliseconds
// returns 0 = success
// -1 = keyPad fail
// -2 = timeout
// -3 = buffer overflow
int readKeyPadUntil(char until, char * buffer, uint8_t length, uint16_t timeout)
{
char keymap[19] = "123A456B789C*0#DNF"; // ... NoKey Fail }
@ -99,7 +99,7 @@ int readKeyPadUntil(char until, char * buffer, uint8_t length, uint16_t timeout)
// handle end conditions
if ( key == until) return 0;
if ( key == 'F') return -1; // failed to read;
if ( key == 'F') return -1; // failed to read;
if (bufferIndex == length) return -3;
// add key to buffer
@ -116,5 +116,5 @@ int readKeyPadUntil(char until, char * buffer, uint8_t length, uint16_t timeout)
}
// -- END OF FILE --
// -- END OF FILE --

View File

@ -4,13 +4,12 @@
// PURPOSE: demo reading until specific keyPress - using build in key mapping
// URL: https://github.com/RobTillaart/I2CKeyPad
//
// PCF8574
// PCF8574
// pin p0-p3 rows
// pin p4-p7 columns
// 4x4 or smaller keypad.
// 4x4 or smaller keypad.
//
// This demo doesn't use the build in key mapping.
//
#include "Wire.h"
@ -67,15 +66,14 @@ void loop()
}
//
// until = end character
// buffer = buffer to fill
// length = length of buffer (including '\0'
// timeout = timeout in milliseconds
// returns 0 = success
// -1 = keyPad fail
// -2 = timeout
// -3 = buffer overflow
// until = end character
// buffer = buffer to fill
// length = length of buffer (including '\0'
// timeout = timeout in milliseconds
// returns 0 = success
// -1 = keyPad fail
// -2 = timeout
// -3 = buffer overflow
//
int readKeyPadUntil(char until, char * buffer, uint8_t length, uint16_t timeout)
{
@ -90,15 +88,15 @@ int readKeyPadUntil(char until, char * buffer, uint8_t length, uint16_t timeout)
{
char ch = keyPad.getChar();
if (ch == 'N') lastChar = 'N';
else if (ch == until) return 0; // success
else if (ch == 'F') return -1; // keyPad fail
else if (ch == until) return 0; // success
else if (ch == 'F') return -1; // keyPad fail
else
{
if (ch != lastChar)
{
lastChar = ch;
if ( bufferIndex == length ) return -3; // overflow
// add key to buffer
if ( bufferIndex == length ) return -3; // overflow
// add key to buffer
buffer[bufferIndex++] = ch;
buffer[bufferIndex] = 0;
}
@ -109,5 +107,5 @@ int readKeyPadUntil(char until, char * buffer, uint8_t length, uint16_t timeout)
}
// -- END OF FILE --
// -- END OF FILE --

View File

@ -15,9 +15,9 @@
"type": "git",
"url": "https://github.com/RobTillaart/I2CKeyPad.git"
},
"version": "0.3.3",
"version": "0.4.0",
"license": "MIT",
"frameworks": "arduino",
"frameworks": "*",
"platforms": "*",
"headers": "I2CKeyPad.h"
}

View File

@ -1,5 +1,5 @@
name=I2CKeyPad
version=0.3.3
version=0.4.0
author=Rob Tillaart <rob.tillaart@gmail.com>
maintainer=Rob Tillaart <rob.tillaart@gmail.com>
sentence=Arduino library for a KeyPad connected to a PCF8574.