From d480ecea20a60ba9f44b2fb4b88bee9739985f89 Mon Sep 17 00:00:00 2001 From: Kirk Benell Date: Mon, 1 Dec 2025 14:08:08 -0700 Subject: [PATCH 1/5] in progress work for an SPI config example - get/set config values; status: set values do not set --- .../Example09_ConfigSPI.ino | 405 ++++++++++++++++++ 1 file changed, 405 insertions(+) create mode 100644 examples/Example09_ConfigSPI/Example09_ConfigSPI.ino diff --git a/examples/Example09_ConfigSPI/Example09_ConfigSPI.ino b/examples/Example09_ConfigSPI/Example09_ConfigSPI.ino new file mode 100644 index 0000000..33c50d8 --- /dev/null +++ b/examples/Example09_ConfigSPI/Example09_ConfigSPI.ino @@ -0,0 +1,405 @@ +/* + *--------------------------------------------------------------------------------- + * + * Copyright (c) 2025, SparkFun Electronics Inc. + * + * SPDX-License-Identifier: MIT + * + *--------------------------------------------------------------------------------- + */ + +/* + * Example using the SparkFun FPC2534 Fingerprint sensor library to demonstrate the fingerprint + * enrollment and identification of the sensor. The example provides the user with the following options: + * - Enroll a new fingerprint + * - Delete all existing fingerprints + * - Validate a fingerprint + * + * This version of this example uses the SPI interface to communicate with the sensor. + * + * Example Setup: + * - Connect the SparkFun Qwiic FPC2534 Fingerprint sensor to your microcontroller using hook-up wires ... + * setup for SPI communication. Note the CS PIN number - this needs to be defined below. + * - Connect the RST pin on the sensor to a digital pin on your microcontroller. This is used by the + * example to "reset the sensor" on startup. + * - Connect the IRQ pin on the sensor to a digital pin on your microcontroller. The sensor triggers + * an interrupt on this pin when it has data to send. + * - Update the IRQ_PIN and RST_PIN defines below to match the pins you are using. + * + * Operation: + * - The sensor object is initialized with the CS pin and the interrupt pin. This examples uses the default SPI bus. + * - The example registers several callback functions with the sensor library. These functions are called as + * messages are received from the sensor. + * - Once running, the example prevents a menu with the following options: + * 1) Enroll a new fingerprint + * 2) Erase all existing fingerprint templates + * 3) Validate a fingerprint + * + * Once an optoin is selected (enter the menu number), the example performs the requested operation. + * + * - When registering a new fingerprint, the example prompts the user to place and remove their finger repeatedly + * until the fingerprint is fully enrolled. The example prints out the number of samples remaining as + * reported by the sensor. Normally 12 samples are needed to fully enroll a fingerprint. + * - When deleting all fingerprints, the example sends the delete command to the sensor. If successful, + * the example resets its internal count of enrolled fingerprints to zero. + * - When validating a fingerprint, the example prompts the user to place their finger on the sensor. + * If the fingerprint matches an enrolled fingerprint, the example prints out the ID of the matched + * fingerprint template. + * + *--------------------------------------------------------------------------------- + */ + +#include + +#include "SparkFun_FPC2534.h" + +//---------------------------------------------------------------------------- +// User Config - +//---------------------------------------------------------------------------- +// UPDATE THESE DEFINES TO MATCH YOUR HARDWARE SETUP +// +// These are the pins the CS, IRQ and RST pins of the sensor are connected to the microcontroller. +// +// NOTE: The IRQ pin must be an interrupt-capable pin on your microcontroller +// +// Example pins for various SparkFun boards: +// +// ESP32 thing plus +// #define IRQ_PIN 16 +// #define RST_PIN 21 +// #define CS_PIN + +// ESP32 thing plus C +// #define IRQ_PIN 32 +// #define RST_PIN 14 +// #define CS_PIN + +// ESP32 IoT RedBoard +// #define IRQ_PIN 26 +// #define RST_PIN 27 +// #define CS_PIN 25 + +// rp2350 thing plus +// #define IRQ_PIN 11 +// #define RST_PIN 12 +// #define CS_PIN + +// rp2350 RedBoard IoT +#define IRQ_PIN 29 +#define RST_PIN 28 +#define CS_PIN 21 + +// Declare our sensor object. Note the SPI version of the sensor class is used. +SfeFPC2534SPI mySensor; + +// flag used to indicate if config has been set.... +#define CONFIG_BEGIN 0 +#define CONFIG_REQUESTED 1 +#define CONFIG_RECEIVED 2 +#define CONFIG_SET 3 +#define CONFIG_VERIFY 4 +#define CONFIG_RESET 5 +#define CONFIG_COMPLETE 6 +#define CONFIG_EXIT 255 + +uint8_t configState = CONFIG_BEGIN; + +fpc_system_config_t the_config = {0}; +bool deviceIdle = false; +//------------------------------------------------------------------------------------ +// Callback functions the library calls +//------------------------------------------------------------------------------------ + +//---------------------------------------------------------------------------- +// on_error() +// +// Called if the sensor library detects/encounters an error +// +static void on_error(uint16_t error) +{ + Serial.print("[ERROR]\tSensor Error Code: "); + Serial.println(error); + + // this could indicated the sensor communications is out of synch - a reset might be needed + reset_sensor(); +} + +//---------------------------------------------------------------------------- +// on_is_ready_change() +// +// Called when the device ready state changes +// +static void on_is_ready_change(bool isReady) +{ + // On startup the device isn't immediately ready. A message is sent when it is. + // The Library will call this function when that happens + + if (isReady) + { + Serial.println("[STARTUP]\tFPC2534 Device is ready"); + + Serial.println("[INFO]\t\tRequesting system configuration..."); + // Request the configuration from the connected device. + fpc_result_t rc = mySensor.requestGetSystemConfig(FPC_SYS_CFG_TYPE_DEFAULT); + if (rc != FPC_RESULT_OK) + { + Serial.print("[ERROR]\tGet config request failed - error: "); + Serial.println(rc); + } + else + configState = CONFIG_REQUESTED; + } +} + +//---------------------------------------------------------------------------- +// on_status() +// +// Called when the sensor sends a status message +// +static void on_status(uint16_t event, uint16_t state) +{ + Serial.print("[STATUS]\tEvent: 0x"); + Serial.print(event, HEX); + Serial.print(" State: 0x"); + Serial.println(state, HEX); + + deviceIdle = (event == EVENT_IDLE); +} +static void update_config(fpc_system_config_t &new_config) +{ + // The current values haven't been received yet + if (configState < CONFIG_RECEIVED) + return; + + fpc_result_t rc = mySensor.setSystemConfig(&new_config); + if (rc != FPC_RESULT_OK) + { + Serial.print("[ERROR]\tSet config request failed - error: "); + Serial.println(rc); + } +} +//---------------------------------------------------------------------------- +static void update_config_max_fails(uint8_t max_fails) +{ + // The current values haven't been received yet + if (configState < CONFIG_RECEIVED) + return; + // copy over the current defaults + fpc_system_config_t new_config = the_config; + + // update the value of max consecutive fails + new_config.idfy_max_consecutive_fails = max_fails; + + Serial.println(); + delay(500); + Serial.print("[INFO]\t\tSetting Max Fails To: "); + + Serial.println(new_config.idfy_max_consecutive_fails); + + update_config(new_config); +} +//---------------------------------------------------------------------------- +static void print_config(fpc_system_config_t &cfg) +{ + + Serial.print(" Version:\t\t\t "); + Serial.println(cfg.version); + Serial.print(" Finger Scan Interval (ms):\t "); + Serial.println(cfg.finger_scan_interval_ms); + Serial.print(" System Flags:\t\t\t 0x"); + Serial.println(cfg.sys_flags, HEX); + Serial.print(" UART Delay Before IRQ (ms):\t "); + Serial.println(cfg.uart_delay_before_irq_ms); + Serial.print(" UART Baudrate:\t\t 0x"); + Serial.println(cfg.uart_baudrate, HEX); + Serial.print(" Max Consecutive Identify Fails: "); + Serial.println(cfg.idfy_max_consecutive_fails); + Serial.print(" Identify Lockout Time (s):\t "); + Serial.println(cfg.idfy_lockout_time_s); + Serial.print(" Idle Time Before Sleep (ms):\t "); + Serial.println(cfg.idle_time_before_sleep_ms); + Serial.print(" Enroll Touches:\t\t "); + Serial.println(cfg.enroll_touches); + Serial.print(" Enroll Immobile Touches:\t "); + Serial.println(cfg.enroll_immobile_touches); + Serial.print(" I2C Address (7bit):\t\t 0x"); + Serial.println(cfg.i2c_address, HEX); +} +//---------------------------------------------------------------------------- +// on_system_config_get() +void on_system_config_get(fpc_system_config_t *cfg) +{ + if (cfg == NULL) + { + Serial.println("[ERROR]\tInvalid configuration data received"); + return; + } + // first print the config + Serial.println("[CONFIG]\tSystem Configuration Received:"); + print_config(*cfg); + + if (configState == CONFIG_REQUESTED) + { + // stash our current config as the default + the_config = *cfg; + + configState = CONFIG_RECEIVED; + } + else if (configState == CONFIG_VERIFY) + { + // verify the set worked + if (cfg->idfy_max_consecutive_fails == the_config.idfy_max_consecutive_fails + 1) + { + Serial.println("[INFO]\t\tConfiguration update verified successfully."); + configState = CONFIG_RESET; + } + else + { + Serial.println("[ERROR]\tConfiguration update verification failed."); + } + } +} +//------------------------------------------------------------------------------------ +// Callbacks +// +// Define our command callbacks structure - callback methods are assigned in setup +static sfDevFPC2534Callbacks_t cmd_cb = {0}; + +//------------------------------------------------------------------------------------ +// reset_sensor() +// +// Simple function to toggle the reset pin of the sensor +// +void reset_sensor(void) +{ + // Reset the sensor by toggling the reset pin. + // + // clear out our data buffer + mySensor.clearData(); + pinMode(RST_PIN, OUTPUT); + digitalWrite(RST_PIN, LOW); // Set reset pin low + delay(10); // Wait for 10 ms + + digitalWrite(RST_PIN, HIGH); // Set reset pin high + delay(250); // Wait for sensor to initialize +} + +//------------------------------------------------------------------------------------ +// setup() +// +void setup() +{ + delay(2000); + + // Set up serial communication for debugging + Serial.begin(115200); // Set baud rate to 115200 + while (!Serial) + { + ; // Wait for serial port to connect. Needed for native USB port only + } + Serial.println(); + Serial.println("----------------------------------------------------------------"); + Serial.println(" SparkFun FPC2534 Fingerprint Config Example - SPI"); + Serial.println("----------------------------------------------------------------"); + Serial.println(); + + // Configure the CS ping + pinMode(CS_PIN, OUTPUT); + digitalWrite(CS_PIN, HIGH); // Set CS pin high as a start off point. + + // Initialize the SPI communication + SPI.begin(); + + // The sensor is available - Initialize the sensor library + if (!mySensor.begin(CS_PIN, IRQ_PIN)) + { + Serial.println("[ERROR]\tFPC2534 not found. Check wiring. HALT."); + while (1) + delay(1000); + } + Serial.println("[STARTUP]\tFPC2534 initialized."); + + // setup our callback functions structure + cmd_cb.on_error = on_error; + cmd_cb.on_status = on_status; + cmd_cb.on_is_ready_change = on_is_ready_change; + cmd_cb.on_system_config_get = on_system_config_get; + + // set the callbacks for the sensor library to call + mySensor.setCallbacks(cmd_cb); + + // One last reset of the sensor = observation shows that this is needed after the above device ping... + reset_sensor(); + + // Ready to go! + Serial.println("[STARTUP]\tFingerprint system initialized."); +} + +//------------------------------------------------------------------------------------ +void loop() +{ + + // Call the library to process the next response from the sensor. The library will call our above + // callback functions as events occur. + fpc_result_t rc = mySensor.processNextResponse(); + if (rc != FPC_RESULT_OK && rc != FPC_PENDING_OPERATION) + { + Serial.print("[ERROR] Processing Error: "); + Serial.println(rc); + // Hmm - reset the sensor and start again? + reset_sensor(); + } + else if (deviceIdle) + { + // if we have the config, and haven't updated it yet, do so now + if (configState == CONFIG_RECEIVED) + { + // update the max fails value + update_config_max_fails(the_config.idfy_max_consecutive_fails + 1); + configState = CONFIG_SET; + } + else if (configState == CONFIG_SET) + { + // Get the new value of the config to verify the set worked + Serial.println("[INFO]\t\tRequesting system configuration..."); + // Request the configuration from the connected device. + fpc_result_t rc = mySensor.requestGetSystemConfig(FPC_SYS_CFG_TYPE_DEFAULT); + if (rc != FPC_RESULT_OK) + { + Serial.print("[ERROR]\tGet config request failed - error: "); + Serial.println(rc); + } + else + configState = CONFIG_VERIFY; + } + else if (configState == CONFIG_RESET) + { + // Reset to defaults + fpc_result_t rc = mySensor.setSystemConfig(&the_config); + if (rc != FPC_RESULT_OK) + { + Serial.print("[ERROR]\tSet config request failed - error: "); + Serial.println(rc); + } + else + Serial.println("[INFO]\t\tSet config to the original value"); + configState = CONFIG_COMPLETE; + } + else if (configState == CONFIG_COMPLETE) + { + // Get the new value of the config to verify the set worked + Serial.println("[INFO]\t\tRequesting final configuration..."); + // Request the configuration from the connected device. + fpc_result_t rc = mySensor.requestGetSystemConfig(FPC_SYS_CFG_TYPE_DEFAULT); + if (rc != FPC_RESULT_OK) + { + Serial.print("[ERROR]\tGet config request failed - error: "); + Serial.println(rc); + } + else + configState = CONFIG_EXIT; + } + } + + delay(200); +} \ No newline at end of file From 1ec08f11d9c25fee8d64c96f0f898be57566d679 Mon Sep 17 00:00:00 2001 From: Kirk Benell Date: Mon, 1 Dec 2025 14:29:49 -0700 Subject: [PATCH 2/5] i2c example of config -- same issue - set is not taking --- .../Example07_ConfigI2C.ino | 419 ++++++++++++++++++ 1 file changed, 419 insertions(+) create mode 100644 examples/Example07_ConfigI2C/Example07_ConfigI2C.ino diff --git a/examples/Example07_ConfigI2C/Example07_ConfigI2C.ino b/examples/Example07_ConfigI2C/Example07_ConfigI2C.ino new file mode 100644 index 0000000..9cbf6f0 --- /dev/null +++ b/examples/Example07_ConfigI2C/Example07_ConfigI2C.ino @@ -0,0 +1,419 @@ +/* + *--------------------------------------------------------------------------------- + * + * Copyright (c) 2025, SparkFun Electronics Inc. + * + * SPDX-License-Identifier: MIT + * + *--------------------------------------------------------------------------------- + */ + +/* + * Example using the SparkFun FPC2534 Fingerprint sensor library to demonstrate the fingerprint + * enrollment and identification of the sensor. The example provides the user with the following options: + * - Enroll a new fingerprint + * - Delete all existing fingerprints + * - Validate a fingerprint + * + * This version of this example uses the SPI interface to communicate with the sensor. + * + * Example Setup: + * - Connect the SparkFun Qwiic FPC2534 Fingerprint sensor to your microcontroller using hook-up wires ... + * setup for SPI communication. Note the CS PIN number - this needs to be defined below. + * - Connect the RST pin on the sensor to a digital pin on your microcontroller. This is used by the + * example to "reset the sensor" on startup. + * - Connect the IRQ pin on the sensor to a digital pin on your microcontroller. The sensor triggers + * an interrupt on this pin when it has data to send. + * - Update the IRQ_PIN and RST_PIN defines below to match the pins you are using. + * + * Operation: + * - The sensor object is initialized with the CS pin and the interrupt pin. This examples uses the default SPI bus. + * - The example registers several callback functions with the sensor library. These functions are called as + * messages are received from the sensor. + * - Once running, the example prevents a menu with the following options: + * 1) Enroll a new fingerprint + * 2) Erase all existing fingerprint templates + * 3) Validate a fingerprint + * + * Once an optoin is selected (enter the menu number), the example performs the requested operation. + * + * - When registering a new fingerprint, the example prompts the user to place and remove their finger repeatedly + * until the fingerprint is fully enrolled. The example prints out the number of samples remaining as + * reported by the sensor. Normally 12 samples are needed to fully enroll a fingerprint. + * - When deleting all fingerprints, the example sends the delete command to the sensor. If successful, + * the example resets its internal count of enrolled fingerprints to zero. + * - When validating a fingerprint, the example prompts the user to place their finger on the sensor. + * If the fingerprint matches an enrolled fingerprint, the example prints out the ID of the matched + * fingerprint template. + * + *--------------------------------------------------------------------------------- + */ + +#include +#include + +#include "SparkFun_FPC2534.h" + +//---------------------------------------------------------------------------- +// User Config - +//---------------------------------------------------------------------------- +// UPDATE THESE DEFINES TO MATCH YOUR HARDWARE SETUP +// +// These are the pins the IRQ and RST pins of the sensor are connected to the microcontroller. +// +// NOTE: The IRQ pin must be an interrupt-capable pin on your microcontroller +// +// Example pins tested for various SparkFun boards: + +// ESP32 thing plus +// #define IRQ_PIN 16 +// #define RST_PIN 21 +// #define I2C_BUS 0 + +// ESP32 thing plus C +// #define IRQ_PIN 32 +// #define RST_PIN 14 +// #define I2C_BUS 0 + +// ESP32 IoT RedBoard +#define IRQ_PIN 26 +#define RST_PIN 27 +#define I2C_BUS 0 + +// rp2350 thing plus +// #define IRQ_PIN 11 +// #define RST_PIN 12 +// #define I2C_BUS 0 + +// rp2350 RedBoard IoT +// #define IRQ_PIN 29 +// #define RST_PIN 28 +// #define I2C_BUS 0 + +// Declare our sensor object. Note the SPI version of the sensor class is used. +SfeFPC2534I2C mySensor; + +// flag used to indicate if config has been set.... +#define CONFIG_BEGIN 0 +#define CONFIG_REQUESTED 1 +#define CONFIG_RECEIVED 2 +#define CONFIG_SET 3 +#define CONFIG_VERIFY 4 +#define CONFIG_RESET 5 +#define CONFIG_COMPLETE 6 +#define CONFIG_EXIT 255 + +uint8_t configState = CONFIG_BEGIN; + +fpc_system_config_t the_config = {0}; +bool deviceIdle = false; +//------------------------------------------------------------------------------------ +// Callback functions the library calls +//------------------------------------------------------------------------------------ + +//---------------------------------------------------------------------------- +// on_error() +// +// Called if the sensor library detects/encounters an error +// +static void on_error(uint16_t error) +{ + Serial.print("[ERROR]\tSensor Error Code: "); + Serial.println(error); + + // this could indicated the sensor communications is out of synch - a reset might be needed + reset_sensor(); +} + +//---------------------------------------------------------------------------- +// on_is_ready_change() +// +// Called when the device ready state changes +// +static void on_is_ready_change(bool isReady) +{ + // On startup the device isn't immediately ready. A message is sent when it is. + // The Library will call this function when that happens + + if (isReady) + { + Serial.println("[STARTUP]\tFPC2534 Device is ready"); + + Serial.println("[INFO]\t\tRequesting system configuration..."); + // Request the configuration from the connected device. + fpc_result_t rc = mySensor.requestGetSystemConfig(FPC_SYS_CFG_TYPE_DEFAULT); + if (rc != FPC_RESULT_OK) + { + Serial.print("[ERROR]\tGet config request failed - error: "); + Serial.println(rc); + } + else + configState = CONFIG_REQUESTED; + } +} + +//---------------------------------------------------------------------------- +// on_status() +// +// Called when the sensor sends a status message +// +static void on_status(uint16_t event, uint16_t state) +{ + Serial.print("[STATUS]\tEvent: 0x"); + Serial.print(event, HEX); + Serial.print(" State: 0x"); + Serial.println(state, HEX); + + deviceIdle = (event == EVENT_IDLE); +} +static void update_config(fpc_system_config_t &new_config) +{ + // The current values haven't been received yet + if (configState < CONFIG_RECEIVED) + return; + + fpc_result_t rc = mySensor.setSystemConfig(&new_config); + if (rc != FPC_RESULT_OK) + { + Serial.print("[ERROR]\tSet config request failed - error: "); + Serial.println(rc); + } +} +//---------------------------------------------------------------------------- +static void update_config_max_fails(uint8_t max_fails) +{ + // The current values haven't been received yet + if (configState < CONFIG_RECEIVED) + return; + // copy over the current defaults + fpc_system_config_t new_config = the_config; + + // update the value of max consecutive fails + new_config.idfy_max_consecutive_fails = max_fails; + + Serial.println(); + delay(500); + Serial.print("[INFO]\t\tSetting Max Fails To: "); + + Serial.println(new_config.idfy_max_consecutive_fails); + + update_config(new_config); +} +//---------------------------------------------------------------------------- +static void print_config(fpc_system_config_t &cfg) +{ + + Serial.print(" Version:\t\t\t "); + Serial.println(cfg.version); + Serial.print(" Finger Scan Interval (ms):\t "); + Serial.println(cfg.finger_scan_interval_ms); + Serial.print(" System Flags:\t\t\t 0x"); + Serial.println(cfg.sys_flags, HEX); + Serial.print(" UART Delay Before IRQ (ms):\t "); + Serial.println(cfg.uart_delay_before_irq_ms); + Serial.print(" UART Baudrate:\t\t 0x"); + Serial.println(cfg.uart_baudrate, HEX); + Serial.print(" Max Consecutive Identify Fails: "); + Serial.println(cfg.idfy_max_consecutive_fails); + Serial.print(" Identify Lockout Time (s):\t "); + Serial.println(cfg.idfy_lockout_time_s); + Serial.print(" Idle Time Before Sleep (ms):\t "); + Serial.println(cfg.idle_time_before_sleep_ms); + Serial.print(" Enroll Touches:\t\t "); + Serial.println(cfg.enroll_touches); + Serial.print(" Enroll Immobile Touches:\t "); + Serial.println(cfg.enroll_immobile_touches); + Serial.print(" I2C Address (7bit):\t\t 0x"); + Serial.println(cfg.i2c_address, HEX); +} +//---------------------------------------------------------------------------- +// on_system_config_get() +void on_system_config_get(fpc_system_config_t *cfg) +{ + if (cfg == NULL) + { + Serial.println("[ERROR]\tInvalid configuration data received"); + return; + } + // first print the config + Serial.println("[CONFIG]\tSystem Configuration Received:"); + print_config(*cfg); + + if (configState == CONFIG_REQUESTED) + { + // stash our current config as the default + the_config = *cfg; + + configState = CONFIG_RECEIVED; + } + else if (configState == CONFIG_VERIFY) + { + // verify the set worked + if (cfg->idfy_max_consecutive_fails == the_config.idfy_max_consecutive_fails + 1) + { + Serial.println("[INFO]\t\tConfiguration update verified successfully."); + configState = CONFIG_RESET; + } + else + { + Serial.println("[ERROR]\tConfiguration update verification failed."); + } + } +} +//------------------------------------------------------------------------------------ +// Callbacks +// +// Define our command callbacks structure - callback methods are assigned in setup +static sfDevFPC2534Callbacks_t cmd_cb = {0}; + +//------------------------------------------------------------------------------------ +// reset_sensor() +// +// Simple function to toggle the reset pin of the sensor +// +void reset_sensor(void) +{ + // Reset the sensor by toggling the reset pin. + // + // clear out our data buffer + mySensor.clearData(); + pinMode(RST_PIN, OUTPUT); + digitalWrite(RST_PIN, LOW); // Set reset pin low + delay(10); // Wait for 10 ms + + digitalWrite(RST_PIN, HIGH); // Set reset pin high + delay(250); // Wait for sensor to initialize +} + +//------------------------------------------------------------------------------------ +// setup() +// +void setup() +{ + delay(2000); + + // Set up serial communication for debugging + Serial.begin(115200); // Set baud rate to 115200 + while (!Serial) + { + ; // Wait for serial port to connect. Needed for native USB port only + } + Serial.println(); + Serial.println("----------------------------------------------------------------"); + Serial.println(" SparkFun FPC2534 Fingerprint Config Example - SPI"); + Serial.println("----------------------------------------------------------------"); + Serial.println(); + + // Initialize the I2C communication + Wire.begin(); + + // Reset the sensor to ensure it's in a known state - by default this also triggers the + // sensor to send a status message + reset_sensor(); + + // Is the sensor there - on the I2C bus? + Wire.beginTransmission(kFPC2534DefaultAddress); + if (Wire.endTransmission() != 0) + { + Serial.println("[ERROR]\tTouch Sensor FPC2534 not found on I2C bus. HALT"); + while (1) + { + delay(1000); // Wait indefinitely if device is not found + } + } + else + Serial.println("[STARTUP]\tTouch Sensor FPC2534 found on I2C bus"); + + // The sensor is available - Initialize the sensor library + if (!mySensor.begin(kFPC2534DefaultAddress, Wire, I2C_BUS, IRQ_PIN)) + { + Serial.println("[ERROR]\tFPC2534 not found. Check wiring. HALT."); + while (1) + delay(1000); + } + Serial.println("[STARTUP]\tFPC2534 initialized."); + + // setup our callback functions structure + cmd_cb.on_error = on_error; + cmd_cb.on_status = on_status; + cmd_cb.on_is_ready_change = on_is_ready_change; + cmd_cb.on_system_config_get = on_system_config_get; + + // set the callbacks for the sensor library to call + mySensor.setCallbacks(cmd_cb); + + // One last reset of the sensor = observation shows that this is needed after the above device ping... + reset_sensor(); + + // Ready to go! + Serial.println("[STARTUP]\tFingerprint system initialized."); +} + +//------------------------------------------------------------------------------------ +void loop() +{ + + // Call the library to process the next response from the sensor. The library will call our above + // callback functions as events occur. + fpc_result_t rc = mySensor.processNextResponse(); + if (rc != FPC_RESULT_OK && rc != FPC_PENDING_OPERATION) + { + Serial.print("[ERROR] Processing Error: "); + Serial.println(rc); + // Hmm - reset the sensor and start again? + reset_sensor(); + } + else if (deviceIdle) + { + // if we have the config, and haven't updated it yet, do so now + if (configState == CONFIG_RECEIVED) + { + // update the max fails value + update_config_max_fails(the_config.idfy_max_consecutive_fails + 1); + configState = CONFIG_SET; + } + else if (configState == CONFIG_SET) + { + // Get the new value of the config to verify the set worked + Serial.println("[INFO]\t\tRequesting system configuration..."); + // Request the configuration from the connected device. + fpc_result_t rc = mySensor.requestGetSystemConfig(FPC_SYS_CFG_TYPE_DEFAULT); + if (rc != FPC_RESULT_OK) + { + Serial.print("[ERROR]\tGet config request failed - error: "); + Serial.println(rc); + } + else + configState = CONFIG_VERIFY; + } + else if (configState == CONFIG_RESET) + { + // Reset to defaults + fpc_result_t rc = mySensor.setSystemConfig(&the_config); + if (rc != FPC_RESULT_OK) + { + Serial.print("[ERROR]\tSet config request failed - error: "); + Serial.println(rc); + } + else + Serial.println("[INFO]\t\tSet config to the original value"); + configState = CONFIG_COMPLETE; + } + else if (configState == CONFIG_COMPLETE) + { + // Get the new value of the config to verify the set worked + Serial.println("[INFO]\t\tRequesting final configuration..."); + // Request the configuration from the connected device. + fpc_result_t rc = mySensor.requestGetSystemConfig(FPC_SYS_CFG_TYPE_DEFAULT); + if (rc != FPC_RESULT_OK) + { + Serial.print("[ERROR]\tGet config request failed - error: "); + Serial.println(rc); + } + else + configState = CONFIG_EXIT; + } + } + + delay(200); +} \ No newline at end of file From 37d00986398993d1ce1e4b84d52d54491f12bc0c Mon Sep 17 00:00:00 2001 From: Kirk Benell Date: Wed, 3 Dec 2025 14:19:08 -0700 Subject: [PATCH 3/5] cleanup the conf samples - sync code - set still fails for unknown reasons --- .../Example07_ConfigI2C.ino | 168 ++++++++--------- .../Example09_ConfigSPI.ino | 170 ++++++++---------- 2 files changed, 150 insertions(+), 188 deletions(-) diff --git a/examples/Example07_ConfigI2C/Example07_ConfigI2C.ino b/examples/Example07_ConfigI2C/Example07_ConfigI2C.ino index 9cbf6f0..9c36eae 100644 --- a/examples/Example07_ConfigI2C/Example07_ConfigI2C.ino +++ b/examples/Example07_ConfigI2C/Example07_ConfigI2C.ino @@ -9,42 +9,13 @@ */ /* - * Example using the SparkFun FPC2534 Fingerprint sensor library to demonstrate the fingerprint - * enrollment and identification of the sensor. The example provides the user with the following options: - * - Enroll a new fingerprint - * - Delete all existing fingerprints - * - Validate a fingerprint + * Example using the SparkFun FPC2534 Fingerprint sensor library to demonstrate the configuration + * capabilities of the sensor. The example retrieves the current system configuration from the sensor, + * modifies one of the configuration values, and sends the updated configuration back to the sensor. * - * This version of this example uses the SPI interface to communicate with the sensor. + * NOTE: Currently, the set of the updated values fails. * - * Example Setup: - * - Connect the SparkFun Qwiic FPC2534 Fingerprint sensor to your microcontroller using hook-up wires ... - * setup for SPI communication. Note the CS PIN number - this needs to be defined below. - * - Connect the RST pin on the sensor to a digital pin on your microcontroller. This is used by the - * example to "reset the sensor" on startup. - * - Connect the IRQ pin on the sensor to a digital pin on your microcontroller. The sensor triggers - * an interrupt on this pin when it has data to send. - * - Update the IRQ_PIN and RST_PIN defines below to match the pins you are using. - * - * Operation: - * - The sensor object is initialized with the CS pin and the interrupt pin. This examples uses the default SPI bus. - * - The example registers several callback functions with the sensor library. These functions are called as - * messages are received from the sensor. - * - Once running, the example prevents a menu with the following options: - * 1) Enroll a new fingerprint - * 2) Erase all existing fingerprint templates - * 3) Validate a fingerprint - * - * Once an optoin is selected (enter the menu number), the example performs the requested operation. - * - * - When registering a new fingerprint, the example prompts the user to place and remove their finger repeatedly - * until the fingerprint is fully enrolled. The example prints out the number of samples remaining as - * reported by the sensor. Normally 12 samples are needed to fully enroll a fingerprint. - * - When deleting all fingerprints, the example sends the delete command to the sensor. If successful, - * the example resets its internal count of enrolled fingerprints to zero. - * - When validating a fingerprint, the example prompts the user to place their finger on the sensor. - * If the fingerprint matches an enrolled fingerprint, the example prints out the ID of the matched - * fingerprint template. + * This version of this example uses the I2C interface to communicate with the sensor. * *--------------------------------------------------------------------------------- */ @@ -159,13 +130,9 @@ static void on_is_ready_change(bool isReady) // static void on_status(uint16_t event, uint16_t state) { - Serial.print("[STATUS]\tEvent: 0x"); - Serial.print(event, HEX); - Serial.print(" State: 0x"); - Serial.println(state, HEX); - deviceIdle = (event == EVENT_IDLE); } +//---------------------------------------------------------------------------- static void update_config(fpc_system_config_t &new_config) { // The current values haven't been received yet @@ -209,6 +176,8 @@ static void print_config(fpc_system_config_t &cfg) Serial.println(cfg.finger_scan_interval_ms); Serial.print(" System Flags:\t\t\t 0x"); Serial.println(cfg.sys_flags, HEX); + Serial.print(" Allows Factory Reset:\t\t "); + Serial.println((cfg.sys_flags & CFG_SYS_FLAG_ALLOW_FACTORY_RESET) ? "Yes" : "No"); Serial.print(" UART Delay Before IRQ (ms):\t "); Serial.println(cfg.uart_delay_before_irq_ms); Serial.print(" UART Baudrate:\t\t 0x"); @@ -248,16 +217,18 @@ void on_system_config_get(fpc_system_config_t *cfg) } else if (configState == CONFIG_VERIFY) { - // verify the set worked + // verify the config set worked if (cfg->idfy_max_consecutive_fails == the_config.idfy_max_consecutive_fails + 1) - { Serial.println("[INFO]\t\tConfiguration update verified successfully."); - configState = CONFIG_RESET; - } else { + Serial.println(); Serial.println("[ERROR]\tConfiguration update verification failed."); + Serial.println(); } + + // back to entry state + configState = CONFIG_RESET; } } //------------------------------------------------------------------------------------ @@ -284,7 +255,62 @@ void reset_sensor(void) digitalWrite(RST_PIN, HIGH); // Set reset pin high delay(250); // Wait for sensor to initialize } +//------------------------------------------------------------------------------------ +// Process the simple sequece of steps for the demo. + +void process_demo_steps(void) +{ + // if we have the config, and haven't updated it yet, do so now + if (configState == CONFIG_RECEIVED) + { + // update the max fails value + update_config_max_fails(the_config.idfy_max_consecutive_fails + 1); + + configState = CONFIG_SET; + } + else if (configState == CONFIG_SET) + { + // Get the new value of the config to verify the set worked + Serial.println("[INFO]\t\tRequesting system configuration..."); + // Request the configuration from the connected device. + fpc_result_t rc = mySensor.requestGetSystemConfig(FPC_SYS_CFG_TYPE_DEFAULT); + if (rc != FPC_RESULT_OK) + { + Serial.print("[ERROR]\tGet config request failed - error: "); + Serial.println(rc); + } + else + configState = CONFIG_VERIFY; + } + else if (configState == CONFIG_RESET) + { + // Reset to defaults + fpc_result_t rc = mySensor.setSystemConfig(&the_config); + if (rc != FPC_RESULT_OK) + { + Serial.print("[ERROR]\tSet config request failed - error: "); + Serial.println(rc); + } + else + Serial.println("[INFO]\t\tSet config to the original value"); + configState = CONFIG_COMPLETE; + } + else if (configState == CONFIG_COMPLETE) + { + // Get the new value of the config to verify the set worked + Serial.println("[INFO]\t\tRequesting final configuration..."); + // Request the configuration from the connected device. + fpc_result_t rc = mySensor.requestGetSystemConfig(FPC_SYS_CFG_TYPE_DEFAULT); + if (rc != FPC_RESULT_OK) + { + Serial.print("[ERROR]\tGet config request failed - error: "); + Serial.println(rc); + } + else + configState = CONFIG_EXIT; + } +} //------------------------------------------------------------------------------------ // setup() // @@ -300,7 +326,10 @@ void setup() } Serial.println(); Serial.println("----------------------------------------------------------------"); - Serial.println(" SparkFun FPC2534 Fingerprint Config Example - SPI"); + Serial.println(" SparkFun FPC2534 Fingerprint Config Example - I2C"); + Serial.println(); + Serial.println(" **NOTE** Currently the `setSystemConfig` command fails to set the updated values."); + Serial.println(); Serial.println("----------------------------------------------------------------"); Serial.println(); @@ -364,56 +393,7 @@ void loop() reset_sensor(); } else if (deviceIdle) - { - // if we have the config, and haven't updated it yet, do so now - if (configState == CONFIG_RECEIVED) - { - // update the max fails value - update_config_max_fails(the_config.idfy_max_consecutive_fails + 1); - configState = CONFIG_SET; - } - else if (configState == CONFIG_SET) - { - // Get the new value of the config to verify the set worked - Serial.println("[INFO]\t\tRequesting system configuration..."); - // Request the configuration from the connected device. - fpc_result_t rc = mySensor.requestGetSystemConfig(FPC_SYS_CFG_TYPE_DEFAULT); - if (rc != FPC_RESULT_OK) - { - Serial.print("[ERROR]\tGet config request failed - error: "); - Serial.println(rc); - } - else - configState = CONFIG_VERIFY; - } - else if (configState == CONFIG_RESET) - { - // Reset to defaults - fpc_result_t rc = mySensor.setSystemConfig(&the_config); - if (rc != FPC_RESULT_OK) - { - Serial.print("[ERROR]\tSet config request failed - error: "); - Serial.println(rc); - } - else - Serial.println("[INFO]\t\tSet config to the original value"); - configState = CONFIG_COMPLETE; - } - else if (configState == CONFIG_COMPLETE) - { - // Get the new value of the config to verify the set worked - Serial.println("[INFO]\t\tRequesting final configuration..."); - // Request the configuration from the connected device. - fpc_result_t rc = mySensor.requestGetSystemConfig(FPC_SYS_CFG_TYPE_DEFAULT); - if (rc != FPC_RESULT_OK) - { - Serial.print("[ERROR]\tGet config request failed - error: "); - Serial.println(rc); - } - else - configState = CONFIG_EXIT; - } - } + process_demo_steps(); delay(200); } \ No newline at end of file diff --git a/examples/Example09_ConfigSPI/Example09_ConfigSPI.ino b/examples/Example09_ConfigSPI/Example09_ConfigSPI.ino index 33c50d8..683b407 100644 --- a/examples/Example09_ConfigSPI/Example09_ConfigSPI.ino +++ b/examples/Example09_ConfigSPI/Example09_ConfigSPI.ino @@ -9,42 +9,13 @@ */ /* - * Example using the SparkFun FPC2534 Fingerprint sensor library to demonstrate the fingerprint - * enrollment and identification of the sensor. The example provides the user with the following options: - * - Enroll a new fingerprint - * - Delete all existing fingerprints - * - Validate a fingerprint + * Example using the SparkFun FPC2534 Fingerprint sensor library to demonstrate the configuration + * capabilities of the sensor. The example retrieves the current system configuration from the sensor, + * modifies one of the configuration values, and sends the updated configuration back to the sensor. * - * This version of this example uses the SPI interface to communicate with the sensor. - * - * Example Setup: - * - Connect the SparkFun Qwiic FPC2534 Fingerprint sensor to your microcontroller using hook-up wires ... - * setup for SPI communication. Note the CS PIN number - this needs to be defined below. - * - Connect the RST pin on the sensor to a digital pin on your microcontroller. This is used by the - * example to "reset the sensor" on startup. - * - Connect the IRQ pin on the sensor to a digital pin on your microcontroller. The sensor triggers - * an interrupt on this pin when it has data to send. - * - Update the IRQ_PIN and RST_PIN defines below to match the pins you are using. - * - * Operation: - * - The sensor object is initialized with the CS pin and the interrupt pin. This examples uses the default SPI bus. - * - The example registers several callback functions with the sensor library. These functions are called as - * messages are received from the sensor. - * - Once running, the example prevents a menu with the following options: - * 1) Enroll a new fingerprint - * 2) Erase all existing fingerprint templates - * 3) Validate a fingerprint - * - * Once an optoin is selected (enter the menu number), the example performs the requested operation. + * NOTE: Currently, the set of the updated values fails. * - * - When registering a new fingerprint, the example prompts the user to place and remove their finger repeatedly - * until the fingerprint is fully enrolled. The example prints out the number of samples remaining as - * reported by the sensor. Normally 12 samples are needed to fully enroll a fingerprint. - * - When deleting all fingerprints, the example sends the delete command to the sensor. If successful, - * the example resets its internal count of enrolled fingerprints to zero. - * - When validating a fingerprint, the example prompts the user to place their finger on the sensor. - * If the fingerprint matches an enrolled fingerprint, the example prints out the ID of the matched - * fingerprint template. + * This version of this example uses the SPI interface to communicate with the sensor. * *--------------------------------------------------------------------------------- */ @@ -158,13 +129,10 @@ static void on_is_ready_change(bool isReady) // static void on_status(uint16_t event, uint16_t state) { - Serial.print("[STATUS]\tEvent: 0x"); - Serial.print(event, HEX); - Serial.print(" State: 0x"); - Serial.println(state, HEX); - deviceIdle = (event == EVENT_IDLE); } + +//---------------------------------------------------------------------------- static void update_config(fpc_system_config_t &new_config) { // The current values haven't been received yet @@ -208,6 +176,8 @@ static void print_config(fpc_system_config_t &cfg) Serial.println(cfg.finger_scan_interval_ms); Serial.print(" System Flags:\t\t\t 0x"); Serial.println(cfg.sys_flags, HEX); + Serial.print(" Allows Factory Reset:\t\t "); + Serial.println((cfg.sys_flags & CFG_SYS_FLAG_ALLOW_FACTORY_RESET) ? "Yes" : "No"); Serial.print(" UART Delay Before IRQ (ms):\t "); Serial.println(cfg.uart_delay_before_irq_ms); Serial.print(" UART Baudrate:\t\t 0x"); @@ -238,6 +208,7 @@ void on_system_config_get(fpc_system_config_t *cfg) Serial.println("[CONFIG]\tSystem Configuration Received:"); print_config(*cfg); + // result of our initial request to get the config if (configState == CONFIG_REQUESTED) { // stash our current config as the default @@ -247,16 +218,18 @@ void on_system_config_get(fpc_system_config_t *cfg) } else if (configState == CONFIG_VERIFY) { - // verify the set worked + // verify the config set worked if (cfg->idfy_max_consecutive_fails == the_config.idfy_max_consecutive_fails + 1) - { Serial.println("[INFO]\t\tConfiguration update verified successfully."); - configState = CONFIG_RESET; - } else { + Serial.println(); Serial.println("[ERROR]\tConfiguration update verification failed."); + Serial.println(); } + + // back to entry state + configState = CONFIG_RESET; } } //------------------------------------------------------------------------------------ @@ -283,7 +256,62 @@ void reset_sensor(void) digitalWrite(RST_PIN, HIGH); // Set reset pin high delay(250); // Wait for sensor to initialize } +//------------------------------------------------------------------------------------ +// Process the simple sequece of steps for the demo. +void process_demo_steps(void) +{ + + // if we have the config, and haven't updated it yet, do so now + if (configState == CONFIG_RECEIVED) + { + // update the max fails value + update_config_max_fails(the_config.idfy_max_consecutive_fails + 1); + + configState = CONFIG_SET; + } + else if (configState == CONFIG_SET) + { + // Get the new value of the config to verify the set worked + Serial.println("[INFO]\t\tRequesting system configuration..."); + // Request the configuration from the connected device. + fpc_result_t rc = mySensor.requestGetSystemConfig(FPC_SYS_CFG_TYPE_DEFAULT); + if (rc != FPC_RESULT_OK) + { + Serial.print("[ERROR]\tGet config request failed - error: "); + Serial.println(rc); + } + else + configState = CONFIG_VERIFY; + } + else if (configState == CONFIG_RESET) + { + // Reset to defaults + fpc_result_t rc = mySensor.setSystemConfig(&the_config); + if (rc != FPC_RESULT_OK) + { + Serial.print("[ERROR]\tSet config request failed - error: "); + Serial.println(rc); + } + else + Serial.println("[INFO]\t\tSet config to the original value"); + configState = CONFIG_COMPLETE; + } + else if (configState == CONFIG_COMPLETE) + { + // Get the new value of the config to verify the set worked + Serial.println("[INFO]\t\tRequesting final configuration..."); + // Request the configuration from the connected device. + fpc_result_t rc = mySensor.requestGetSystemConfig(FPC_SYS_CFG_TYPE_DEFAULT); + if (rc != FPC_RESULT_OK) + { + Serial.print("[ERROR]\tGet config request failed - error: "); + Serial.println(rc); + } + else + configState = CONFIG_EXIT; + } +} //------------------------------------------------------------------------------------ // setup() // @@ -300,6 +328,9 @@ void setup() Serial.println(); Serial.println("----------------------------------------------------------------"); Serial.println(" SparkFun FPC2534 Fingerprint Config Example - SPI"); + Serial.println(); + Serial.println(" **NOTE** Currently the `setSystemConfig` command fails to set the updated values."); + Serial.println(); Serial.println("----------------------------------------------------------------"); Serial.println(); @@ -328,7 +359,7 @@ void setup() // set the callbacks for the sensor library to call mySensor.setCallbacks(cmd_cb); - // One last reset of the sensor = observation shows that this is needed after the above device ping... + // Reset the sensor to start fresh reset_sensor(); // Ready to go! @@ -350,56 +381,7 @@ void loop() reset_sensor(); } else if (deviceIdle) - { - // if we have the config, and haven't updated it yet, do so now - if (configState == CONFIG_RECEIVED) - { - // update the max fails value - update_config_max_fails(the_config.idfy_max_consecutive_fails + 1); - configState = CONFIG_SET; - } - else if (configState == CONFIG_SET) - { - // Get the new value of the config to verify the set worked - Serial.println("[INFO]\t\tRequesting system configuration..."); - // Request the configuration from the connected device. - fpc_result_t rc = mySensor.requestGetSystemConfig(FPC_SYS_CFG_TYPE_DEFAULT); - if (rc != FPC_RESULT_OK) - { - Serial.print("[ERROR]\tGet config request failed - error: "); - Serial.println(rc); - } - else - configState = CONFIG_VERIFY; - } - else if (configState == CONFIG_RESET) - { - // Reset to defaults - fpc_result_t rc = mySensor.setSystemConfig(&the_config); - if (rc != FPC_RESULT_OK) - { - Serial.print("[ERROR]\tSet config request failed - error: "); - Serial.println(rc); - } - else - Serial.println("[INFO]\t\tSet config to the original value"); - configState = CONFIG_COMPLETE; - } - else if (configState == CONFIG_COMPLETE) - { - // Get the new value of the config to verify the set worked - Serial.println("[INFO]\t\tRequesting final configuration..."); - // Request the configuration from the connected device. - fpc_result_t rc = mySensor.requestGetSystemConfig(FPC_SYS_CFG_TYPE_DEFAULT); - if (rc != FPC_RESULT_OK) - { - Serial.print("[ERROR]\tGet config request failed - error: "); - Serial.println(rc); - } - else - configState = CONFIG_EXIT; - } - } + process_demo_steps(); delay(200); } \ No newline at end of file From 9405cc82064892e85b756290d0fbad15c4b15b04 Mon Sep 17 00:00:00 2001 From: Kirk Benell Date: Wed, 3 Dec 2025 14:27:38 -0700 Subject: [PATCH 4/5] uart version of config --- .../Example08_ConfigUART.ino | 389 ++++++++++++++++++ 1 file changed, 389 insertions(+) create mode 100644 examples/Example08_ConfigUART/Example08_ConfigUART.ino diff --git a/examples/Example08_ConfigUART/Example08_ConfigUART.ino b/examples/Example08_ConfigUART/Example08_ConfigUART.ino new file mode 100644 index 0000000..ad6c30c --- /dev/null +++ b/examples/Example08_ConfigUART/Example08_ConfigUART.ino @@ -0,0 +1,389 @@ +/* + *--------------------------------------------------------------------------------- + * + * Copyright (c) 2025, SparkFun Electronics Inc. + * + * SPDX-License-Identifier: MIT + * + *--------------------------------------------------------------------------------- + */ + +/* + * Example using the SparkFun FPC2534 Fingerprint sensor library to demonstrate the configuration + * capabilities of the sensor. The example retrieves the current system configuration from the sensor, + * modifies one of the configuration values, and sends the updated configuration back to the sensor. + * + * NOTE: Currently, the set of the updated values fails. + * + * This version of this example uses the SPI interface to communicate with the sensor. + * + *--------------------------------------------------------------------------------- + */ + +#include + +#include "SparkFun_FPC2534.h" + +//---------------------------------------------------------------------------- +// User Config - +//---------------------------------------------------------------------------- +// Define the pins being used for operation +// +// The FPC2534 uses one pin for reset, No interrupt pin is needed for UART operation +// +// The following pin definitions were used for testing - but can be modified as needed. +// +// ESP32 thing plus +// #define RST_PIN 21 + +// ESP32 thing plus C +// #define RST_PIN 14 + +// RP2350 thing plus +#define RST_PIN 12 + +// IoT RedBoard - RP2350 +// #define RST_PIN 29 + +//---------------------------------------------------------------------------------- +// NOTE: +// This example makes use of the Serial1 hardware serial port for communication with the FPC2534. If the board +// being used does not have a Serial1 port, you will need to modify the code to use SoftwareSerial or another +// serial port available on your board. + +// Declare our sensor object. Note the SPI version of the sensor class is used. +SfeFPC2534UART mySensor; + +// flag used to indicate if config has been set.... +#define CONFIG_BEGIN 0 +#define CONFIG_REQUESTED 1 +#define CONFIG_RECEIVED 2 +#define CONFIG_SET 3 +#define CONFIG_VERIFY 4 +#define CONFIG_RESET 5 +#define CONFIG_COMPLETE 6 +#define CONFIG_EXIT 255 + +uint8_t configState = CONFIG_BEGIN; + +fpc_system_config_t the_config = {0}; +bool deviceIdle = false; +//------------------------------------------------------------------------------------ +// Callback functions the library calls +//------------------------------------------------------------------------------------ + +//---------------------------------------------------------------------------- +// on_error() +// +// Called if the sensor library detects/encounters an error +// +static void on_error(uint16_t error) +{ + Serial.print("[ERROR]\tSensor Error Code: "); + Serial.println(error); + + // this could indicated the sensor communications is out of synch - a reset might be needed + reset_sensor(); +} + +//---------------------------------------------------------------------------- +// on_is_ready_change() +// +// Called when the device ready state changes +// +static void on_is_ready_change(bool isReady) +{ + // On startup the device isn't immediately ready. A message is sent when it is. + // The Library will call this function when that happens + + if (isReady) + { + Serial.println("[STARTUP]\tFPC2534 Device is ready"); + + Serial.println("[INFO]\t\tRequesting system configuration..."); + // Request the configuration from the connected device. + fpc_result_t rc = mySensor.requestGetSystemConfig(FPC_SYS_CFG_TYPE_DEFAULT); + if (rc != FPC_RESULT_OK) + { + Serial.print("[ERROR]\tGet config request failed - error: "); + Serial.println(rc); + } + else + configState = CONFIG_REQUESTED; + } +} + +//---------------------------------------------------------------------------- +// on_status() +// +// Called when the sensor sends a status message +// +static void on_status(uint16_t event, uint16_t state) +{ + deviceIdle = (event == EVENT_IDLE); +} + +//---------------------------------------------------------------------------- +static void update_config(fpc_system_config_t &new_config) +{ + // The current values haven't been received yet + if (configState < CONFIG_RECEIVED) + return; + + fpc_result_t rc = mySensor.setSystemConfig(&new_config); + if (rc != FPC_RESULT_OK) + { + Serial.print("[ERROR]\tSet config request failed - error: "); + Serial.println(rc); + } +} +//---------------------------------------------------------------------------- +static void update_config_max_fails(uint8_t max_fails) +{ + // The current values haven't been received yet + if (configState < CONFIG_RECEIVED) + return; + // copy over the current defaults + fpc_system_config_t new_config = the_config; + + // update the value of max consecutive fails + new_config.idfy_max_consecutive_fails = max_fails; + + Serial.println(); + delay(500); + Serial.print("[INFO]\t\tSetting Max Fails To: "); + + Serial.println(new_config.idfy_max_consecutive_fails); + + update_config(new_config); +} +//---------------------------------------------------------------------------- +static void print_config(fpc_system_config_t &cfg) +{ + + Serial.print(" Version:\t\t\t "); + Serial.println(cfg.version); + Serial.print(" Finger Scan Interval (ms):\t "); + Serial.println(cfg.finger_scan_interval_ms); + Serial.print(" System Flags:\t\t\t 0x"); + Serial.println(cfg.sys_flags, HEX); + Serial.print(" Allows Factory Reset:\t\t "); + Serial.println((cfg.sys_flags & CFG_SYS_FLAG_ALLOW_FACTORY_RESET) ? "Yes" : "No"); + Serial.print(" UART Delay Before IRQ (ms):\t "); + Serial.println(cfg.uart_delay_before_irq_ms); + Serial.print(" UART Baudrate:\t\t 0x"); + Serial.println(cfg.uart_baudrate, HEX); + Serial.print(" Max Consecutive Identify Fails: "); + Serial.println(cfg.idfy_max_consecutive_fails); + Serial.print(" Identify Lockout Time (s):\t "); + Serial.println(cfg.idfy_lockout_time_s); + Serial.print(" Idle Time Before Sleep (ms):\t "); + Serial.println(cfg.idle_time_before_sleep_ms); + Serial.print(" Enroll Touches:\t\t "); + Serial.println(cfg.enroll_touches); + Serial.print(" Enroll Immobile Touches:\t "); + Serial.println(cfg.enroll_immobile_touches); + Serial.print(" I2C Address (7bit):\t\t 0x"); + Serial.println(cfg.i2c_address, HEX); +} +//---------------------------------------------------------------------------- +// on_system_config_get() +void on_system_config_get(fpc_system_config_t *cfg) +{ + if (cfg == NULL) + { + Serial.println("[ERROR]\tInvalid configuration data received"); + return; + } + // first print the config + Serial.println("[CONFIG]\tSystem Configuration Received:"); + print_config(*cfg); + + // result of our initial request to get the config + if (configState == CONFIG_REQUESTED) + { + // stash our current config as the default + the_config = *cfg; + + configState = CONFIG_RECEIVED; + } + else if (configState == CONFIG_VERIFY) + { + // verify the config set worked + if (cfg->idfy_max_consecutive_fails == the_config.idfy_max_consecutive_fails + 1) + Serial.println("[INFO]\t\tConfiguration update verified successfully."); + else + { + Serial.println(); + Serial.println("[ERROR]\tConfiguration update verification failed."); + Serial.println(); + } + + // back to entry state + configState = CONFIG_RESET; + } +} +//------------------------------------------------------------------------------------ +// Callbacks +// +// Define our command callbacks structure - callback methods are assigned in setup +static sfDevFPC2534Callbacks_t cmd_cb = {0}; + +//------------------------------------------------------------------------------------ +// reset_sensor() +// +// Simple function to toggle the reset pin of the sensor +// +void reset_sensor(void) +{ + // Reset the sensor by toggling the reset pin. + // + // clear out our data buffer + mySensor.clearData(); + pinMode(RST_PIN, OUTPUT); + digitalWrite(RST_PIN, LOW); // Set reset pin low + delay(10); // Wait for 10 ms + + digitalWrite(RST_PIN, HIGH); // Set reset pin high + delay(250); // Wait for sensor to initialize +} +//------------------------------------------------------------------------------------ +// Process the simple sequece of steps for the demo. + +void process_demo_steps(void) +{ + + // if we have the config, and haven't updated it yet, do so now + if (configState == CONFIG_RECEIVED) + { + // update the max fails value + update_config_max_fails(the_config.idfy_max_consecutive_fails + 1); + + configState = CONFIG_SET; + } + else if (configState == CONFIG_SET) + { + // Get the new value of the config to verify the set worked + Serial.println("[INFO]\t\tRequesting system configuration..."); + // Request the configuration from the connected device. + fpc_result_t rc = mySensor.requestGetSystemConfig(FPC_SYS_CFG_TYPE_DEFAULT); + if (rc != FPC_RESULT_OK) + { + Serial.print("[ERROR]\tGet config request failed - error: "); + Serial.println(rc); + } + else + configState = CONFIG_VERIFY; + } + else if (configState == CONFIG_RESET) + { + // Reset to defaults + fpc_result_t rc = mySensor.setSystemConfig(&the_config); + if (rc != FPC_RESULT_OK) + { + Serial.print("[ERROR]\tSet config request failed - error: "); + Serial.println(rc); + } + else + Serial.println("[INFO]\t\tSet config to the original value"); + configState = CONFIG_COMPLETE; + } + else if (configState == CONFIG_COMPLETE) + { + // Get the new value of the config to verify the set worked + Serial.println("[INFO]\t\tRequesting final configuration..."); + // Request the configuration from the connected device. + fpc_result_t rc = mySensor.requestGetSystemConfig(FPC_SYS_CFG_TYPE_DEFAULT); + if (rc != FPC_RESULT_OK) + { + Serial.print("[ERROR]\tGet config request failed - error: "); + Serial.println(rc); + } + else + configState = CONFIG_EXIT; + } +} +//------------------------------------------------------------------------------------ +// setup() +// +void setup() +{ + delay(2000); + + // Set up serial communication for debugging + Serial.begin(115200); // Set baud rate to 115200 + while (!Serial) + { + ; // Wait for serial port to connect. Needed for native USB port only + } + Serial.println(); + Serial.println("----------------------------------------------------------------"); + Serial.println(" SparkFun FPC2534 Fingerprint Config Example - SPI"); + Serial.println(); + Serial.println(" **NOTE** Currently the `setSystemConfig` command fails to set the updated values."); + Serial.println(); + Serial.println("----------------------------------------------------------------"); + Serial.println(); + + // The internal UART buffer can fill up quickly and overflow. As such, increase its size. + // This example is supporting ESP32 and RP2040 based boards - adjust as needed for other platforms. +#if defined(ARDUINO_ARCH_RP2040) + Serial1.setFIFOSize(512); +#elif defined(ESP32) + Serial1.setRxBufferSize(512); +#endif + + Serial1.begin(921600, SERIAL_8N1); + delay(100); + for (uint32_t startMS = millis(); !Serial1 && (millis() - startMS < 5000);) // Wait for the serial port to be ready + delay(200); + Serial.println("[STARTUP]\tSerial1 started for FPC2534 communication."); + + // Reset the sensor to ensure it's in a known state - by default this also triggers the + // sensor to send a status message + reset_sensor(); + + // Initialize the sensor library + if (!mySensor.begin(Serial1)) + { + Serial.println("[ERROR]\tFPC2534 not found. Check wiring. HALT."); + while (1) + delay(1000); + } + Serial.println("[STARTUP]\tFPC2534 initialized."); + + // setup our callback functions structure + cmd_cb.on_error = on_error; + cmd_cb.on_status = on_status; + cmd_cb.on_is_ready_change = on_is_ready_change; + cmd_cb.on_system_config_get = on_system_config_get; + + // set the callbacks for the sensor library to call + mySensor.setCallbacks(cmd_cb); + + // Reset the sensor to start fresh + reset_sensor(); + + // Ready to go! + Serial.println("[STARTUP]\tFingerprint system initialized."); +} + +//------------------------------------------------------------------------------------ +void loop() +{ + + // Call the library to process the next response from the sensor. The library will call our above + // callback functions as events occur. + fpc_result_t rc = mySensor.processNextResponse(); + if (rc != FPC_RESULT_OK && rc != FPC_PENDING_OPERATION) + { + Serial.print("[ERROR] Processing Error: "); + Serial.println(rc); + // Hmm - reset the sensor and start again? + reset_sensor(); + } + else if (deviceIdle) + process_demo_steps(); + + delay(200); +} \ No newline at end of file From 3b649ef463b0f5b4de4a8515037569ff75fe4fef Mon Sep 17 00:00:00 2001 From: Kirk Benell Date: Wed, 3 Dec 2025 14:27:58 -0700 Subject: [PATCH 5/5] BAD WIRE --- examples/Example04_EnrollUART/Example04_EnrollUART.ino | 1 - 1 file changed, 1 deletion(-) diff --git a/examples/Example04_EnrollUART/Example04_EnrollUART.ino b/examples/Example04_EnrollUART/Example04_EnrollUART.ino index b49af6c..f94be8b 100644 --- a/examples/Example04_EnrollUART/Example04_EnrollUART.ino +++ b/examples/Example04_EnrollUART/Example04_EnrollUART.ino @@ -9,7 +9,6 @@ */ #include -#include #include "SparkFun_FPC2534.h"