1+
2+ /*
3+ * ---------------------------------------------------------------------------------
4+ * Copyright (c) 2025, SparkFun Electronics Inc.
5+ *
6+ * SPDX-License-Identifier: MIT
7+ * ---------------------------------------------------------------------------------
8+ */
9+
10+ /*
11+ * Example using the SparkFun FPC2534 Fingerprint sensor library to demonstrate navigation mode
12+ * of the sensor. This example uses the SPI interface to communicate with the sensor.
13+ *
14+ * Example Setup:
15+ * - Connect the SparkFun Qwiic FPC2534 Fingerprint sensor to your microcontroller using SPI.
16+ * - Connect the RST pin on the sensor to a digital pin on your microcontroller. This is used by the
17+ * example to "reset the sensor" on startup.
18+ * - Connect the IRQ pin on the sensor to a digital pin on your microcontroller. The sensor triggers
19+ * an interrupt on this pin when it has data to send.
20+ * - Update the IRQ_PIN and RST_PIN defines below to match the pins you are using.
21+ *
22+ * Operation:
23+
24+ * - The example registers several callback functions with the sensor library. These functions are called as
25+ * messages are received from the sensor.
26+ * - The example places the sensor in navigation mode. In this mode, the sensor detects simple gestures
27+ * such as left, right, up, down swipes, as well as press and long-press events.
28+ * - The example prints out messages to the serial console as events are received from the sensor.
29+ * - On a press event, the example toggles the on-board LED of the sensor on and off.
30+ * - On a long-press event, the example requests the firmware version from the sensor and prints it out when received.
31+ *
32+
33+ *---------------------------------------------------------------------------------
34+ */
35+ #include < Arduino.h>
36+
37+ #include " SparkFun_FPC2534.h"
38+
39+ // ----------------------------------------------------------------------------
40+ // User Config -
41+ // ----------------------------------------------------------------------------
42+ // UPDATE THESE DEFINES TO MATCH YOUR HARDWARE SETUP
43+ //
44+ // These are the pins the IRQ and RST pins of the sensor are connected to the microcontroller.
45+ //
46+ // NOTE: The IRQ pin must be an interrupt-capable pin on your microcontroller
47+ //
48+ // Example pins tested for various SparkFun boards:
49+
50+ // // ESP32 thing plus
51+ // #define IRQ_PIN 16
52+ // #define RST_PIN 21
53+ // #define I2C_BUS 0
54+
55+ // ESP32 thing plus C
56+ // #define IRQ_PIN 32
57+ // #define RST_PIN 14
58+ // #define I2C_BUS 0
59+
60+ // ESP32 IoT RedBoard
61+ #define IRQ_PIN 26
62+ #define RST_PIN 27
63+ #define CS_PIN 6
64+
65+ // rp2350 thing plus
66+ // #define IRQ_PIN 11
67+ // #define RST_PIN 12
68+ // #define I2C_BUS 0
69+
70+ // rp2350 RedBoard IoT
71+ // #define IRQ_PIN 29
72+ // #define RST_PIN 28
73+ // #define I2C_BUS 0
74+
75+ // State flags to manage sensor startup/state
76+ bool startNavigation = true ;
77+
78+ // Used to track LED state
79+ bool ledState = false ;
80+
81+ // Declare our sensor object. Note the SPI version of the sensor class is used.
82+ SfeFPC2534SPI mySensor;
83+
84+ // ------------------------------------------------------------------------------------
85+ // Callback functions the library calls
86+ // ------------------------------------------------------------------------------------
87+ // Unlike a majority of Arduino Sensor libraries, the FPC2534 library is event/callback driven.
88+ // The library calls functions you define when events occur. This allows your code to respond
89+ // to messages from the sensor. These messages are ready by calling the processNextResponse() function
90+ // in your main loop.
91+ // ----------------------------------------------------------------------------
92+ // on_error()
93+ //
94+ // Call if the sensor library detects/encounters an error
95+ //
96+ static void on_error (uint16_t error)
97+ {
98+ // Just print the error code
99+ Serial.print (" [ERROR] code:\t " );
100+ Serial.println (error);
101+ }
102+
103+ // ----------------------------------------------------------------------------
104+ // on_is_ready_change()
105+ //
106+ // Call when the device ready state changes
107+ //
108+ static void on_is_ready_change (bool isReady)
109+ {
110+ // On startup the device isn't immediately ready. A message is sent when it is.
111+ // The Library will call this function when that happens
112+
113+ if (isReady)
114+ {
115+ Serial.println (" [STARTUP]\t FPC2534 Device is ready" );
116+
117+ // do we need to start navigation mode?
118+ if (mySensor.currentMode () != STATE_NAVIGATION && startNavigation)
119+ {
120+ // Place the sensor in Navigation mode and print out a menue.
121+ startNavigation = false ;
122+ fpc_result_t rc = mySensor.startNavigationMode (0 );
123+
124+ // error?
125+ if (rc != FPC_RESULT_OK)
126+ {
127+ Serial.print (" [ERROR]\t Failed to start navigation mode - error:" );
128+ Serial.println (rc);
129+ return ;
130+ }
131+
132+ Serial.println (" [SETUP]\t Sensor In Navigation mode." );
133+ Serial.println ();
134+ Serial.println (" \t - Swipe Up, Down, Left, Right to see events." );
135+ Serial.println (" \t - Press to toggle LED on/off." );
136+ Serial.println (" \t - Long Press to get firmware version." );
137+ Serial.println ();
138+ }
139+ else
140+ Serial.println (" [STATUS] \t FPC2534 Device is NOT ready" );
141+ }
142+ }
143+
144+ // ----------------------------------------------------------------------------
145+ // on_version()
146+ //
147+ // Call when the sensor sends a version string
148+ //
149+ static void on_version (char *version)
150+ {
151+ // just print the version string
152+ Serial.print (" \t\t " );
153+ Serial.println (version);
154+ }
155+
156+ // ----------------------------------------------------------------------------
157+ // on_navigation()
158+ //
159+ // Call when the sensor sends a navigation event
160+ //
161+ static void on_navigation (uint16_t gesture)
162+ {
163+ Serial.print (" [NAVIGATION]\t " );
164+ switch (gesture)
165+ {
166+ case CMD_NAV_EVENT_NONE:
167+ Serial.println (" NONE" );
168+ break ;
169+ case CMD_NAV_EVENT_UP:
170+ Serial.println (" UP" );
171+ break ;
172+ case CMD_NAV_EVENT_DOWN:
173+ Serial.println (" DOWN" );
174+ break ;
175+ case CMD_NAV_EVENT_RIGHT:
176+ Serial.println (" RIGHT" );
177+ break ;
178+ case CMD_NAV_EVENT_LEFT:
179+ Serial.println (" LEFT" );
180+ break ;
181+ case CMD_NAV_EVENT_PRESS:
182+ // Toggle the on-board LED
183+ Serial.print (" PRESS -> {LED " );
184+ Serial.print (ledState ? " OFF" : " ON" );
185+ Serial.println (" }" );
186+ ledState = !ledState;
187+ mySensor.setLED (ledState);
188+ break ;
189+
190+ case CMD_NAV_EVENT_LONG_PRESS:
191+ // Request the firmware version from the sensor. The sensor will respond
192+ // with a version event that will call our on_version() function above.
193+ Serial.println (" LONG PRESS -> {Get Version}" );
194+ mySensor.requestVersion ();
195+ break ;
196+ default :
197+ Serial.println (" UNKNOWN" );
198+ break ;
199+ }
200+ }
201+
202+ // ------------------------------------------------------------------------------------
203+ // Fill in the library callback structure with our callback functions
204+ //
205+ // This is passed to the library so it knows what functions to call when events occur.
206+ static sfDevFPC2534Callbacks_t cmd_cb = {0 };
207+
208+ // ------------------------------------------------------------------------------------
209+ // reset_sensor()
210+ //
211+ // Simple function to toggle the reset pin of the sensor
212+ //
213+ void reset_sensor (void )
214+ {
215+ // Reset the sensor by toggling the reset pin
216+ pinMode (RST_PIN, OUTPUT);
217+ digitalWrite (RST_PIN, LOW); // Set reset pin low
218+ delay (10 ); // Wait for 10 ms
219+ digitalWrite (RST_PIN, HIGH); // Set reset pin high
220+ delay (250 ); // Wait for sensor to initialize
221+ }
222+
223+ // ------------------------------------------------------------------------------------
224+ // setup()
225+ //
226+ void setup ()
227+ {
228+ delay (2000 );
229+
230+ // Set up serial communication for debugging
231+ Serial.begin (115200 ); // Set baud rate to 115200
232+ while (!Serial)
233+ {
234+ ; // Wait for serial port to connect. Needed for native USB port only
235+ }
236+ Serial.println ();
237+ Serial.println (" ----------------------------------------------------------------" );
238+ Serial.println (" SparkFun FPC2534 Navigation Example - I2C" );
239+ Serial.println (" ----------------------------------------------------------------" );
240+ Serial.println ();
241+
242+ // Configure the CS ping
243+ pinMode (CS_PIN, OUTPUT);
244+ digitalWrite (CS_PIN, HIGH); // Set CS pin high as a start off point.
245+
246+ // Initialize the SPI communication
247+ SPI.begin ();
248+
249+ // The sensor is available - Initialize the sensor library
250+ if (!mySensor.begin (CS_PIN, IRQ_PIN))
251+ {
252+ Serial.println (" [ERROR]\t FPC2534 not found. Check wiring. HALT." );
253+ while (1 )
254+ delay (1000 );
255+ }
256+ Serial.println (" [STARTUP]\t FPC2534 initialized." );
257+
258+ // Setup our callback functions structure
259+ cmd_cb.on_error = on_error;
260+ cmd_cb.on_version = on_version;
261+ cmd_cb.on_navigation = on_navigation;
262+ cmd_cb.on_is_ready_change = on_is_ready_change;
263+
264+ // set the callbacks for the sensor library to call
265+ mySensor.setCallbacks (cmd_cb);
266+
267+ // One last reset of the sensor = observation shows that this is needed after the above device ping...
268+ reset_sensor ();
269+
270+ // Ready to go!
271+ Serial.println (" [STARTUP]\t Fingerprint system initialized." );
272+ }
273+
274+ // ------------------------------------------------------------------------------------
275+ void loop ()
276+ {
277+
278+ // Call the library to process the next response from the sensor. The library will call our above
279+ // callback functions as events occur.
280+ fpc_result_t rc = mySensor.processNextResponse ();
281+ if (rc != FPC_RESULT_OK && rc != FPC_PENDING_OPERATION)
282+ {
283+ Serial.print (" [ERROR] Sensor Processing Error: " );
284+ Serial.println (rc);
285+ }
286+
287+ delay (200 );
288+ }
0 commit comments