Skip to content

Commit c774c00

Browse files
committed
add example / readme
1 parent a7ec573 commit c774c00

File tree

2 files changed

+295
-0
lines changed

2 files changed

+295
-0
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,222 @@
1+
/*
2+
I2C Expander signal readings using KeyDetector library with SparkFun Qwiic Directional Pad.
3+
4+
Demonstrates how to use KeyDetector to trigger action based on digital signal readings from
5+
a SparkFun Qwiic Directional Pad which uses a PCA9554 8-bit I2C GPIO expander.
6+
7+
The SparkFun Qwiic Directional Pad has 5 buttons:
8+
- Up (pin 4)
9+
- Down (pin 5)
10+
- Left (pin 6)
11+
- Right (pin 7)
12+
- Center/Select (pin 3)
13+
14+
Connection:
15+
- Connect the Qwiic Directional Pad to your Arduino/ESP32/etc using a Qwiic cable
16+
or connect directly to the I2C pins (SDA/SCL)
17+
18+
Additional info about KeyDetector library available on GitHub:
19+
https://github.com/Spirik/KeyDetector
20+
21+
This example code is in the public domain.
22+
*/
23+
24+
#include <Arduino.h>
25+
#include <KeyDetector.h>
26+
#include <SparkFun_I2C_Expander_Arduino_Library.h>
27+
28+
// Define signal identifiers for five buttons
29+
#define KEY_UP 1
30+
#define KEY_DOWN 2
31+
#define KEY_LEFT 3
32+
#define KEY_RIGHT 4
33+
#define KEY_SELECT 5
34+
35+
// D-Pad pins on the PCA9554
36+
const byte pinSelect = 3;
37+
const byte pinUp = 4;
38+
const byte pinDown = 5;
39+
const byte pinLeft = 6;
40+
const byte pinRight = 7;
41+
42+
const int keyPressDelay = 500; // Delay after key press event triggered and before continuous press is detected, ms
43+
const int keyPressRepeatDelay = 250; // Delay between "remains pressed" message is printed, ms
44+
45+
long keyPressTime = 0; // Variable to hold time of the key press event
46+
long now; // Variable to hold current time taken with millis() function at the beginning of loop()
47+
48+
// Implementation of the I2CExpander interface for PCA9554
49+
class PCA9554Expander : public I2CExpander {
50+
private:
51+
SFE_PCA95XX io;
52+
53+
public:
54+
PCA9554Expander() : io() {}
55+
56+
bool begin() override {
57+
return io.begin();
58+
}
59+
60+
void pinMode(uint8_t pin, uint8_t mode) override {
61+
io.pinMode(pin, mode);
62+
}
63+
64+
void digitalWrite(uint8_t pin, uint8_t val) override {
65+
io.digitalWrite(pin, val);
66+
}
67+
68+
int digitalRead(uint8_t pin) override {
69+
return io.isConnected() ? io.digitalRead(pin) == LOW : HIGH;
70+
}
71+
};
72+
73+
// Create PCA9554 expander instance
74+
PCA9554Expander dpadExpander;
75+
76+
// Create array of Key objects that will link defined key identifiers with pins on the expander
77+
// Note: We set ioType to KEY_IO_TYPE_I2C_EXPANDER and pass our expander object
78+
// Also set pullup to true since the D-Pad buttons are active LOW
79+
Key keys[] = {
80+
{KEY_UP, pinUp, -1, KEY_IO_TYPE_I2C_EXPANDER, &dpadExpander},
81+
{KEY_DOWN, pinDown, -1, KEY_IO_TYPE_I2C_EXPANDER, &dpadExpander},
82+
{KEY_LEFT, pinLeft, -1, KEY_IO_TYPE_I2C_EXPANDER, &dpadExpander},
83+
{KEY_RIGHT, pinRight, -1, KEY_IO_TYPE_I2C_EXPANDER, &dpadExpander},
84+
{KEY_SELECT, pinSelect, -1, KEY_IO_TYPE_I2C_EXPANDER, &dpadExpander}
85+
};
86+
87+
// Create KeyDetector object with 10ms debounce and pullup set to true
88+
KeyDetector dpad(keys, sizeof(keys)/sizeof(Key), 10, 16, true);
89+
90+
void setup() {
91+
// Serial communications setup
92+
Serial.begin(115200);
93+
while (!Serial) {
94+
; // Wait for serial port to connect (needed for native USB port only)
95+
}
96+
97+
Serial.println("SparkFun Qwiic Directional Pad Example with KeyDetector");
98+
99+
// Initialize the I2C expander
100+
if (!dpadExpander.begin()) {
101+
Serial.println("Failed to initialize PCA9554 expander! Check connections.");
102+
while (1); // Halt if we can't communicate with the expander
103+
}
104+
105+
dpadExpander.pinMode(pinUp, INPUT);
106+
dpadExpander.pinMode(pinDown, INPUT);
107+
dpadExpander.pinMode(pinLeft, INPUT);
108+
dpadExpander.pinMode(pinRight, INPUT);
109+
dpadExpander.pinMode(pinSelect, INPUT);
110+
111+
Serial.println("PCA9554 expander initialized successfully.");
112+
Serial.println("Press any button on the D-Pad...");
113+
}
114+
115+
void loop() {
116+
// Get current time to use later on
117+
now = millis();
118+
119+
// Check the current state of input signal
120+
dpad.detect();
121+
122+
// When button press is detected ("triggered"), print corresponding message
123+
// and save current time as a time of the key press event
124+
switch (dpad.trigger) {
125+
case KEY_UP:
126+
Serial.println("UP pressed!");
127+
keyPressTime = now;
128+
break;
129+
case KEY_DOWN:
130+
Serial.println("DOWN pressed!");
131+
keyPressTime = now;
132+
break;
133+
case KEY_LEFT:
134+
Serial.println("LEFT pressed!");
135+
keyPressTime = now;
136+
break;
137+
case KEY_RIGHT:
138+
Serial.println("RIGHT pressed!");
139+
keyPressTime = now;
140+
break;
141+
case KEY_SELECT:
142+
Serial.println("SELECT pressed!");
143+
keyPressTime = now;
144+
break;
145+
}
146+
147+
// When button release is detected, print message
148+
switch (dpad.triggerRelease) {
149+
case KEY_UP:
150+
Serial.println("UP released.");
151+
break;
152+
case KEY_DOWN:
153+
Serial.println("DOWN released.");
154+
break;
155+
case KEY_LEFT:
156+
Serial.println("LEFT released.");
157+
break;
158+
case KEY_RIGHT:
159+
Serial.println("RIGHT released.");
160+
break;
161+
case KEY_SELECT:
162+
Serial.println("SELECT released.");
163+
break;
164+
}
165+
166+
// After keyPressDelay passed since keyPressTime, handle continuous press
167+
if (now > keyPressTime + keyPressDelay) {
168+
// Determine currently pressed button and print message with repeat delay
169+
switch (dpad.current) {
170+
case KEY_UP:
171+
Serial.println("UP held down...");
172+
delay(keyPressRepeatDelay);
173+
break;
174+
case KEY_DOWN:
175+
Serial.println("DOWN held down...");
176+
delay(keyPressRepeatDelay);
177+
break;
178+
case KEY_LEFT:
179+
Serial.println("LEFT held down...");
180+
delay(keyPressRepeatDelay);
181+
break;
182+
case KEY_RIGHT:
183+
Serial.println("RIGHT held down...");
184+
delay(keyPressRepeatDelay);
185+
break;
186+
case KEY_SELECT:
187+
Serial.println("SELECT held down...");
188+
delay(keyPressRepeatDelay);
189+
break;
190+
}
191+
}
192+
193+
// Also demonstrate detection of simultaneous key presses (if secondary key detected)
194+
if (dpad.secondary != KEY_NONE) {
195+
String primaryKey, secondaryKey;
196+
197+
// Determine name of primary key
198+
switch (dpad.current) {
199+
case KEY_UP: primaryKey = "UP"; break;
200+
case KEY_DOWN: primaryKey = "DOWN"; break;
201+
case KEY_LEFT: primaryKey = "LEFT"; break;
202+
case KEY_RIGHT: primaryKey = "RIGHT"; break;
203+
case KEY_SELECT: primaryKey = "SELECT"; break;
204+
}
205+
206+
// Determine name of secondary key
207+
switch (dpad.secondary) {
208+
case KEY_UP: secondaryKey = "UP"; break;
209+
case KEY_DOWN: secondaryKey = "DOWN"; break;
210+
case KEY_LEFT: secondaryKey = "LEFT"; break;
211+
case KEY_RIGHT: secondaryKey = "RIGHT"; break;
212+
case KEY_SELECT: secondaryKey = "SELECT"; break;
213+
}
214+
215+
if (dpad.previousSecondary != dpad.secondary) {
216+
Serial.print("Multiple buttons pressed: ");
217+
Serial.print(primaryKey);
218+
Serial.print(" + ");
219+
Serial.println(secondaryKey);
220+
}
221+
}
222+
}
+73
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
# Example-05: I2C Expander with SparkFun Qwiic Directional Pad
2+
3+
This example demonstrates how to use the KeyDetector library with the SparkFun Qwiic Directional Pad, which uses a PCA9554 8-bit I2C GPIO expander chip.
4+
5+
## Hardware Requirements
6+
7+
- Arduino board (or any other compatible board like ESP32, ESP8266, etc.)
8+
- [SparkFun Qwiic Directional Pad](https://www.sparkfun.com/products/15316)
9+
- Qwiic cable or I2C connection wires
10+
11+
## Wiring
12+
13+
The SparkFun Qwiic Directional Pad can be connected to your Arduino/board in one of two ways:
14+
15+
### Option 1: Using Qwiic Connector (Recommended)
16+
If your board has a Qwiic connector or you have a Qwiic shield, simply connect the D-Pad to your board using a Qwiic cable.
17+
18+
### Option 2: Manual I2C Connection
19+
If your board doesn't have a Qwiic connector, connect the D-Pad to your board using the following connections:
20+
21+
- D-Pad GND → Arduino GND
22+
- D-Pad 3.3V → Arduino 3.3V
23+
- D-Pad SDA → Arduino SDA (A4 on most Arduinos)
24+
- D-Pad SCL → Arduino SCL (A5 on most Arduinos)
25+
26+
## Button Mapping
27+
28+
The SparkFun Qwiic Directional Pad has 5 buttons mapped to the following pins on the PCA9554 chip:
29+
30+
- Up: Pin 4
31+
- Down: Pin 5
32+
- Left: Pin 6
33+
- Right: Pin 7
34+
- Center/Select: Pin 3
35+
36+
## Active Low Logic
37+
38+
The buttons on the D-Pad are active LOW, meaning they are pulled up by default and pressing them connects the pin to ground. This example takes care of this by setting the `pullup` parameter to `true` in the KeyDetector constructor.
39+
40+
## Features Demonstrated
41+
42+
This example demonstrates:
43+
44+
1. Implementation of the `I2CExpander` interface for the PCA9554 chip
45+
2. Reading button states from the I2C expander
46+
3. Detecting button press, release, and held states
47+
4. Handling simultaneous button presses
48+
5. Sending button events to the Serial monitor
49+
50+
## Serial Output
51+
52+
Open the Serial Monitor at 115200 baud to see the button press, release, and held events. The example will print:
53+
- When a button is pressed
54+
- When a button is released
55+
- When a button is held down
56+
- When multiple buttons are pressed simultaneously
57+
58+
## Troubleshooting
59+
60+
If the example doesn't work:
61+
62+
1. Check your I2C connections
63+
2. Verify that the I2C address is correct (0x27 by default)
64+
3. Make sure the D-Pad is properly powered (3.3V)
65+
4. Check if your Arduino can communicate with the D-Pad using an I2C scanner sketch
66+
67+
## Further Customization
68+
69+
You can modify the example to:
70+
- Change the debounce delay (currently 10ms)
71+
- Adjust the key press and repeat delays
72+
- Add custom actions for different button combinations
73+
- Integrate with other I2C devices using the same Wire interface

0 commit comments

Comments
 (0)