├── .gitignore ├── lib ├── CMakeLists.txt ├── mpr121.c └── include │ └── mpr121.h ├── examples ├── hello_mpr121 │ ├── CMakeLists.txt │ ├── hello_mpr121.c │ └── pico_sdk_import.cmake └── sensor_values │ ├── CMakeLists.txt │ ├── pico_sdk_import.cmake │ └── sensor_values.c ├── README.md └── LICENSE /.gitignore: -------------------------------------------------------------------------------- 1 | .vscode 2 | **/.history 3 | **/build/* 4 | *.swp 5 | html 6 | docs 7 | -------------------------------------------------------------------------------- /lib/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | add_library(pico-mpr121 INTERFACE) 2 | 3 | target_include_directories(pico-mpr121 4 | INTERFACE 5 | ${CMAKE_CURRENT_LIST_DIR}/include 6 | ) 7 | 8 | target_link_libraries(pico-mpr121 9 | INTERFACE 10 | hardware_i2c 11 | ) 12 | 13 | target_sources(pico-mpr121 14 | INTERFACE 15 | ${CMAKE_CURRENT_LIST_DIR}/mpr121.c 16 | ${CMAKE_CURRENT_LIST_DIR}/include/mpr121.h 17 | ) 18 | -------------------------------------------------------------------------------- /examples/hello_mpr121/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # Generated Cmake Pico project file 2 | 3 | cmake_minimum_required(VERSION 3.13) 4 | 5 | set(CMAKE_C_STANDARD 11) 6 | set(CMAKE_CXX_STANDARD 17) 7 | 8 | # Pull in Raspberry Pi Pico SDK (must be before project) 9 | include(pico_sdk_import.cmake) 10 | 11 | # Add pico-mpr121 directory 12 | add_subdirectory(../../lib mpr121) 13 | 14 | project(touch C CXX ASM) 15 | pico_sdk_init() 16 | add_executable(hello_mpr121 hello_mpr121.c) 17 | 18 | # This stdio configuration alows to see the Pico output when connected to a 19 | # picoprobe. Enable usb and disable uart for standalone operation (direct USB 20 | # connection). 21 | pico_enable_stdio_uart(hello_mpr121 0) 22 | pico_enable_stdio_usb(hello_mpr121 1) 23 | 24 | # Standard and additional libraries. 25 | target_link_libraries(hello_mpr121 26 | pico_stdlib 27 | hardware_i2c 28 | pico-mpr121 29 | ) 30 | 31 | pico_add_extra_outputs(hello_mpr121) 32 | -------------------------------------------------------------------------------- /examples/sensor_values/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # Generated Cmake Pico project file 2 | 3 | cmake_minimum_required(VERSION 3.13) 4 | 5 | set(CMAKE_C_STANDARD 11) 6 | set(CMAKE_CXX_STANDARD 17) 7 | 8 | # Pull in Raspberry Pi Pico SDK (must be before project) 9 | include(pico_sdk_import.cmake) 10 | 11 | # Add pico-mpr121 directory 12 | add_subdirectory(../../lib mpr121) 13 | 14 | project(touch C CXX ASM) 15 | pico_sdk_init() 16 | add_executable(sensor_values sensor_values.c) 17 | 18 | # This stdio configuration alows to see the Pico output when connected to a 19 | # picoprobe. Enable usb and disable uart for standalone operation (direct USB 20 | # connection). 21 | pico_enable_stdio_uart(sensor_values 0) 22 | pico_enable_stdio_usb(sensor_values 1) 23 | 24 | # Standard and additional libraries. 25 | target_link_libraries(sensor_values 26 | pico_stdlib 27 | hardware_i2c 28 | pico-mpr121 29 | ) 30 | 31 | pico_add_extra_outputs(sensor_values) 32 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # pico-mpr121 2 | 3 | A C library for using an MPR121-based touch sensor with the Raspberry Pi 4 | Pico 5 | 6 | The [MPR121][nxp] is a capacitive touch sensor controller with 12 7 | electrodes. While NXP have now discontinued this sensor, touch sensor 8 | boards based on this chip are still available, e.g. [Adafruit product 9 | 1982][ada1982] and [Seeed Studio Grove I2C Touch Sensor][seeed]. 10 | 11 | [ada1982]: https://www.adafruit.com/product/1982 12 | 13 | [nxp]: https://www.nxp.com/products/no-longer-manufactured/proximity-capacitive-touch-sensor-controller:MPR121 14 | 15 | [seeed]: https://wiki.seeedstudio.com/Grove-I2C_Touch_Sensor/ 16 | 17 | 18 | ## Wiring 19 | 20 | MPR121 | Pico 21 | -------|----- 22 | SDA | SDA (e.g. pin 8) 23 | SCL | SCL (e.g. pin 9) 24 | VDD | 3V3(OUT) 25 | GND | GND 26 | 27 | 28 | ## Software 29 | 30 | 1. Configure `CMakeLists.txt` in your base project to include the path 31 | to the **pico-mpr121** library. Add **pico-mpr121** to the list of 32 | target libraries. E.g. if the **pico-mpr121** library is located one 33 | directory above (`../`) the current one your `CMakeLists.txt` file 34 | should include 35 | ```cmake 36 | . 37 | . 38 | . 39 | include(pico_sdk_import.cmake) 40 | add_subdirectory(../pico-mpr121/lib mpr121) 41 | 42 | target_link_libraries(touch 43 | pico_stdlib 44 | hardware_i2c 45 | pico-mpr121 46 | ) 47 | . 48 | . 49 | . 50 | ``` 51 | 52 | 2. Use the library; see the examples directory. 53 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | BSD 3-Clause License 2 | 3 | Copyright (c) 2021-2023, Antonio González 4 | All rights reserved. 5 | 6 | Redistribution and use in source and binary forms, with or without 7 | modification, are permitted provided that the following conditions are met: 8 | 9 | 1. Redistributions of source code must retain the above copyright notice, this 10 | list of conditions and the following disclaimer. 11 | 12 | 2. Redistributions in binary form must reproduce the above copyright notice, 13 | this list of conditions and the following disclaimer in the documentation 14 | and/or other materials provided with the distribution. 15 | 16 | 3. Neither the name of the copyright holder nor the names of its 17 | contributors may be used to endorse or promote products derived from 18 | this software without specific prior written permission. 19 | 20 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 21 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 22 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 23 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 24 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 25 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 26 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 27 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 28 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 29 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 30 | -------------------------------------------------------------------------------- /examples/hello_mpr121/hello_mpr121.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2021-2023 Antonio González 3 | * 4 | * SPDX-License-Identifier: BSD-3-Clause 5 | */ 6 | 7 | /* MPR121 hello_mpr121 example. 8 | 9 | When a sensor (electrode) is touched, the on-board LED lights on and the 10 | sensor number is printed. 11 | */ 12 | 13 | #include 14 | #include "pico/stdlib.h" 15 | #include "hardware/i2c.h" 16 | #include "mpr121.h" 17 | 18 | // I2C definitions: port and pin numbers 19 | #define I2C_PORT i2c0 20 | #define I2C_SDA 20 21 | #define I2C_SCL 21 22 | 23 | // I2C definitions: address and frequency 24 | #define MPR121_ADDR 0x5A 25 | #define MPR121_I2C_FREQ 100000 26 | 27 | // Touch and release thresholds 28 | #define MPR121_TOUCH_THRESHOLD 16 29 | #define MPR121_RELEASE_THRESHOLD 10 30 | 31 | int main() { 32 | stdio_init_all(); 33 | 34 | // Setup the on-board LED 35 | const uint LED_PIN = PICO_DEFAULT_LED_PIN; 36 | gpio_init(LED_PIN); 37 | gpio_set_dir(LED_PIN, GPIO_OUT); 38 | 39 | // Initialise I2C 40 | i2c_init(I2C_PORT, MPR121_I2C_FREQ); 41 | gpio_set_function(I2C_SDA, GPIO_FUNC_I2C); 42 | gpio_set_function(I2C_SCL, GPIO_FUNC_I2C); 43 | gpio_pull_up(I2C_SDA); 44 | gpio_pull_up(I2C_SCL); 45 | 46 | // Initialise and configure the touch sensor 47 | struct mpr121_sensor mpr121; 48 | mpr121_init(I2C_PORT, MPR121_ADDR, &mpr121); 49 | mpr121_set_thresholds(MPR121_TOUCH_THRESHOLD, 50 | MPR121_RELEASE_THRESHOLD, &mpr121); 51 | 52 | // Initialise data variables 53 | uint16_t touched; 54 | 55 | while (1) { 56 | // Bits 11-0 in the value returned by this function are flags 57 | // set when the electrodes are touched 58 | mpr121_touched(&touched, &mpr121); 59 | 60 | // If a touch is detected, light on the LED and print a pattern 61 | // representing the electrodes (0 to 11) where 1 means touched. 62 | if (touched > 0) { 63 | gpio_put(LED_PIN, 1); 64 | for (uint8_t electrode = 0; electrode < 12; electrode++) { 65 | printf("%c ", ((touched >> electrode) & 1) ? '1' : '.'); 66 | } 67 | printf("\n"); 68 | } else { 69 | gpio_put(LED_PIN, 0); 70 | } 71 | 72 | // Pause for these many ms. 73 | sleep_ms(50); 74 | } 75 | 76 | return 0; 77 | } 78 | -------------------------------------------------------------------------------- /examples/hello_mpr121/pico_sdk_import.cmake: -------------------------------------------------------------------------------- 1 | # This is a copy of /external/pico_sdk_import.cmake 2 | 3 | # This can be dropped into an external project to help locate this SDK 4 | # It should be include()ed prior to project() 5 | 6 | if (DEFINED ENV{PICO_SDK_PATH} AND (NOT PICO_SDK_PATH)) 7 | set(PICO_SDK_PATH $ENV{PICO_SDK_PATH}) 8 | message("Using PICO_SDK_PATH from environment ('${PICO_SDK_PATH}')") 9 | endif () 10 | 11 | if (DEFINED ENV{PICO_SDK_FETCH_FROM_GIT} AND (NOT PICO_SDK_FETCH_FROM_GIT)) 12 | set(PICO_SDK_FETCH_FROM_GIT $ENV{PICO_SDK_FETCH_FROM_GIT}) 13 | message("Using PICO_SDK_FETCH_FROM_GIT from environment ('${PICO_SDK_FETCH_FROM_GIT}')") 14 | endif () 15 | 16 | if (DEFINED ENV{PICO_SDK_FETCH_FROM_GIT_PATH} AND (NOT PICO_SDK_FETCH_FROM_GIT_PATH)) 17 | set(PICO_SDK_FETCH_FROM_GIT_PATH $ENV{PICO_SDK_FETCH_FROM_GIT_PATH}) 18 | message("Using PICO_SDK_FETCH_FROM_GIT_PATH from environment ('${PICO_SDK_FETCH_FROM_GIT_PATH}')") 19 | endif () 20 | 21 | set(PICO_SDK_PATH "${PICO_SDK_PATH}" CACHE PATH "Path to the Raspberry Pi Pico SDK") 22 | set(PICO_SDK_FETCH_FROM_GIT "${PICO_SDK_FETCH_FROM_GIT}" CACHE BOOL "Set to ON to fetch copy of SDK from git if not otherwise locatable") 23 | set(PICO_SDK_FETCH_FROM_GIT_PATH "${PICO_SDK_FETCH_FROM_GIT_PATH}" CACHE FILEPATH "location to download SDK") 24 | 25 | if (NOT PICO_SDK_PATH) 26 | if (PICO_SDK_FETCH_FROM_GIT) 27 | include(FetchContent) 28 | set(FETCHCONTENT_BASE_DIR_SAVE ${FETCHCONTENT_BASE_DIR}) 29 | if (PICO_SDK_FETCH_FROM_GIT_PATH) 30 | get_filename_component(FETCHCONTENT_BASE_DIR "${PICO_SDK_FETCH_FROM_GIT_PATH}" REALPATH BASE_DIR "${CMAKE_SOURCE_DIR}") 31 | endif () 32 | FetchContent_Declare( 33 | pico_sdk 34 | GIT_REPOSITORY https://github.com/raspberrypi/pico-sdk 35 | GIT_TAG master 36 | ) 37 | if (NOT pico_sdk) 38 | message("Downloading Raspberry Pi Pico SDK") 39 | FetchContent_Populate(pico_sdk) 40 | set(PICO_SDK_PATH ${pico_sdk_SOURCE_DIR}) 41 | endif () 42 | set(FETCHCONTENT_BASE_DIR ${FETCHCONTENT_BASE_DIR_SAVE}) 43 | else () 44 | message(FATAL_ERROR 45 | "SDK location was not specified. Please set PICO_SDK_PATH or set PICO_SDK_FETCH_FROM_GIT to on to fetch from git." 46 | ) 47 | endif () 48 | endif () 49 | 50 | get_filename_component(PICO_SDK_PATH "${PICO_SDK_PATH}" REALPATH BASE_DIR "${CMAKE_BINARY_DIR}") 51 | if (NOT EXISTS ${PICO_SDK_PATH}) 52 | message(FATAL_ERROR "Directory '${PICO_SDK_PATH}' not found") 53 | endif () 54 | 55 | set(PICO_SDK_INIT_CMAKE_FILE ${PICO_SDK_PATH}/pico_sdk_init.cmake) 56 | if (NOT EXISTS ${PICO_SDK_INIT_CMAKE_FILE}) 57 | message(FATAL_ERROR "Directory '${PICO_SDK_PATH}' does not appear to contain the Raspberry Pi Pico SDK") 58 | endif () 59 | 60 | set(PICO_SDK_PATH ${PICO_SDK_PATH} CACHE PATH "Path to the Raspberry Pi Pico SDK" FORCE) 61 | 62 | include(${PICO_SDK_INIT_CMAKE_FILE}) 63 | -------------------------------------------------------------------------------- /examples/sensor_values/pico_sdk_import.cmake: -------------------------------------------------------------------------------- 1 | # This is a copy of /external/pico_sdk_import.cmake 2 | 3 | # This can be dropped into an external project to help locate this SDK 4 | # It should be include()ed prior to project() 5 | 6 | if (DEFINED ENV{PICO_SDK_PATH} AND (NOT PICO_SDK_PATH)) 7 | set(PICO_SDK_PATH $ENV{PICO_SDK_PATH}) 8 | message("Using PICO_SDK_PATH from environment ('${PICO_SDK_PATH}')") 9 | endif () 10 | 11 | if (DEFINED ENV{PICO_SDK_FETCH_FROM_GIT} AND (NOT PICO_SDK_FETCH_FROM_GIT)) 12 | set(PICO_SDK_FETCH_FROM_GIT $ENV{PICO_SDK_FETCH_FROM_GIT}) 13 | message("Using PICO_SDK_FETCH_FROM_GIT from environment ('${PICO_SDK_FETCH_FROM_GIT}')") 14 | endif () 15 | 16 | if (DEFINED ENV{PICO_SDK_FETCH_FROM_GIT_PATH} AND (NOT PICO_SDK_FETCH_FROM_GIT_PATH)) 17 | set(PICO_SDK_FETCH_FROM_GIT_PATH $ENV{PICO_SDK_FETCH_FROM_GIT_PATH}) 18 | message("Using PICO_SDK_FETCH_FROM_GIT_PATH from environment ('${PICO_SDK_FETCH_FROM_GIT_PATH}')") 19 | endif () 20 | 21 | set(PICO_SDK_PATH "${PICO_SDK_PATH}" CACHE PATH "Path to the Raspberry Pi Pico SDK") 22 | set(PICO_SDK_FETCH_FROM_GIT "${PICO_SDK_FETCH_FROM_GIT}" CACHE BOOL "Set to ON to fetch copy of SDK from git if not otherwise locatable") 23 | set(PICO_SDK_FETCH_FROM_GIT_PATH "${PICO_SDK_FETCH_FROM_GIT_PATH}" CACHE FILEPATH "location to download SDK") 24 | 25 | if (NOT PICO_SDK_PATH) 26 | if (PICO_SDK_FETCH_FROM_GIT) 27 | include(FetchContent) 28 | set(FETCHCONTENT_BASE_DIR_SAVE ${FETCHCONTENT_BASE_DIR}) 29 | if (PICO_SDK_FETCH_FROM_GIT_PATH) 30 | get_filename_component(FETCHCONTENT_BASE_DIR "${PICO_SDK_FETCH_FROM_GIT_PATH}" REALPATH BASE_DIR "${CMAKE_SOURCE_DIR}") 31 | endif () 32 | FetchContent_Declare( 33 | pico_sdk 34 | GIT_REPOSITORY https://github.com/raspberrypi/pico-sdk 35 | GIT_TAG master 36 | ) 37 | if (NOT pico_sdk) 38 | message("Downloading Raspberry Pi Pico SDK") 39 | FetchContent_Populate(pico_sdk) 40 | set(PICO_SDK_PATH ${pico_sdk_SOURCE_DIR}) 41 | endif () 42 | set(FETCHCONTENT_BASE_DIR ${FETCHCONTENT_BASE_DIR_SAVE}) 43 | else () 44 | message(FATAL_ERROR 45 | "SDK location was not specified. Please set PICO_SDK_PATH or set PICO_SDK_FETCH_FROM_GIT to on to fetch from git." 46 | ) 47 | endif () 48 | endif () 49 | 50 | get_filename_component(PICO_SDK_PATH "${PICO_SDK_PATH}" REALPATH BASE_DIR "${CMAKE_BINARY_DIR}") 51 | if (NOT EXISTS ${PICO_SDK_PATH}) 52 | message(FATAL_ERROR "Directory '${PICO_SDK_PATH}' not found") 53 | endif () 54 | 55 | set(PICO_SDK_INIT_CMAKE_FILE ${PICO_SDK_PATH}/pico_sdk_init.cmake) 56 | if (NOT EXISTS ${PICO_SDK_INIT_CMAKE_FILE}) 57 | message(FATAL_ERROR "Directory '${PICO_SDK_PATH}' does not appear to contain the Raspberry Pi Pico SDK") 58 | endif () 59 | 60 | set(PICO_SDK_PATH ${PICO_SDK_PATH} CACHE PATH "Path to the Raspberry Pi Pico SDK" FORCE) 61 | 62 | include(${PICO_SDK_INIT_CMAKE_FILE}) 63 | -------------------------------------------------------------------------------- /examples/sensor_values/sensor_values.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2021-2023 Antonio González 3 | * 4 | * SPDX-License-Identifier: BSD-3-Clause 5 | */ 6 | 7 | 8 | /* MPR121 sensor_values example. 9 | 10 | In this example only one touch sensor (electrode) is enabled. Then, this 11 | electrode is polled at 100-ms intervals and 12 | 13 | 1. If the sensor has been touched, the on-board LED lights up. 14 | 15 | 2. Three values are read from that sensor and printed: (i) whether the 16 | sensor has been touched (`is_touched`, bool), (ii) The baseline sensor 17 | value (`baseline`, uint8), and (iii) the filtered value of the sensor 18 | (`filtered`, uint8). It is possible to plot these values in real time 19 | (e.g. with MicroDAQ, https://github.com/antgon/microdaq) to visualise, 20 | debug, and tune the touch sensor. 21 | */ 22 | 23 | #include 24 | #include "pico/stdlib.h" 25 | #include "hardware/i2c.h" 26 | #include "mpr121.h" 27 | 28 | // I2C definitions: port and pin numbers 29 | #define I2C_PORT i2c0 30 | #define I2C_SDA 20 31 | #define I2C_SCL 21 32 | 33 | // MPR121 I2C definitions: address and frequency. 34 | #define MPR121_ADDR 0x5A 35 | #define MPR121_I2C_FREQ 100000 36 | 37 | // Touch and release thresholds. 38 | #define MPR121_TOUCH_THRESHOLD 16 39 | #define MPR121_RELEASE_THRESHOLD 10 40 | 41 | int main() { 42 | stdio_init_all(); 43 | 44 | // Setup the default, on-board LED. 45 | const uint LED_PIN = PICO_DEFAULT_LED_PIN; 46 | gpio_init(LED_PIN); 47 | gpio_set_dir(LED_PIN, GPIO_OUT); 48 | 49 | // Initialise I2C. 50 | i2c_init(I2C_PORT, MPR121_I2C_FREQ); 51 | gpio_set_function(I2C_SDA, GPIO_FUNC_I2C); 52 | gpio_set_function(I2C_SCL, GPIO_FUNC_I2C); 53 | gpio_pull_up(I2C_SDA); 54 | gpio_pull_up(I2C_SCL); 55 | 56 | // Initialise and autoconfigure the touch sensor. 57 | struct mpr121_sensor mpr121; 58 | mpr121_init(I2C_PORT, MPR121_ADDR, &mpr121); 59 | mpr121_set_thresholds(MPR121_TOUCH_THRESHOLD, 60 | MPR121_RELEASE_THRESHOLD, &mpr121); 61 | 62 | // Enable only one touch sensor (electrode 0). 63 | mpr121_enable_electrodes(1, &mpr121); 64 | 65 | // Initialise data variables. 66 | const uint8_t electrode = 0; 67 | bool is_touched; 68 | uint16_t baseline, filtered; 69 | 70 | while(1) { 71 | // Check if the electrode has been touched, and read the 72 | // baseline and filtered data values (useful for debugging and 73 | // tuning the sensor). 74 | mpr121_is_touched(electrode, &is_touched, &mpr121); 75 | mpr121_baseline_value(electrode, &baseline, &mpr121); 76 | mpr121_filtered_data(electrode, &filtered, &mpr121); 77 | 78 | // Switch on the on-board LED if the electrode has been touched. 79 | if (is_touched) { 80 | gpio_put(LED_PIN, 1); 81 | } else { 82 | gpio_put(LED_PIN, 0); 83 | } 84 | 85 | // Print the data. 86 | printf("%d %d %d\n", baseline, filtered, is_touched); 87 | 88 | // Pause for 100 ms. 89 | sleep_ms(100); 90 | } 91 | 92 | return 0; 93 | } 94 | -------------------------------------------------------------------------------- /lib/mpr121.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2021-2023 Antonio González 3 | * 4 | * SPDX-License-Identifier: BSD-3-Clause 5 | */ 6 | 7 | #include "mpr121.h" 8 | 9 | void mpr121_init(i2c_inst_t *i2c_port, uint8_t i2c_addr, 10 | mpr121_sensor_t *sensor) { 11 | sensor->i2c_port = i2c_port; 12 | sensor->i2c_addr = i2c_addr; 13 | 14 | // Enter stop mode by setting ELEPROX_EN and ELE_EN bits to zero. 15 | // This is needed because register write operations can only take 16 | // place in stop mode. 17 | mpr121_write(MPR121_ELECTRODE_CONFIG_REG, 0x00, sensor); 18 | 19 | // Writing 0x80 (SOFT_RESET) with 0x63 asserts soft reset. 20 | mpr121_write(MPR121_SOFT_RESET_REG, 0x63, sensor); 21 | 22 | // == Capacitance sensing settings (AN2889), Filtering and ========= 23 | // timing settings (AN3890) 24 | 25 | // These settings are configured in two registers: the Filter and 26 | // Global CDC CDT Configuration registers (0x5C, 0x5D). 27 | // 28 | // Charge-discharge current (CDC) and charge-discharge time (CDT) 29 | // can be configured globally or on a per-electrode basis. Here, 30 | // The global CDC and CDT values are set to their defaults, and then 31 | // these values are overriden by independently configuring each 32 | // electrode (auto-configuration). 33 | 34 | // Filter/global CDC configuration register (0x5C) 35 | // 36 | // First filter iterations (FFI), bits 7-6. Number of samples taken 37 | // as input to the first level of filtering. Default is 0b00 (sets 38 | // samples taken to 6) 39 | // 40 | // Charge-discharge current (CDC), bits 5-0. Sets the value of 41 | // charge-discharge current applied to the electrode. Max is 63 µA 42 | // in 1 µA steps. Default is 0b010000 (16 µA) 43 | // 44 | // AFE configuration register default, 0b00010000 = 0x10 45 | mpr121_write(MPR121_AFE_CONFIG_REG, 0x10, sensor); 46 | 47 | // Filter/global CDC configuration register (0x5D) 48 | // 49 | // Charge discharge time (CDT), bits 7-5. Selects the global value 50 | // of charge time applied to electrode. The maximum is 32 μs, 51 | // programmable as 2^(n-2) μs. Default is 0b001 (time is set to 52 | // 0.5 µs) 53 | // 54 | // Second filter iterations (SFI), bits 4-3. Selects the number of 55 | // samples taken for the second level filter. Default is 0b00 56 | // (number of samples is set to 4) 57 | // 58 | // Electrode sample interval (ESI), bits 2-0. Controls the sampling 59 | // rate of the device. The maximum is 128 ms, programmable to 2^n 60 | // ms. Decrease this value for better response time, increase to 61 | // save power. Default is 0b100 (period set to 16 ms). 62 | // 63 | // Filter configuration register default, 0b00100100 = 0x24 64 | // I do not need power saving features but I want fast responses, 65 | // so I set this to 0x20. 66 | mpr121_write(MPR121_FILTER_CONFIG_REG, 0x20, sensor); 67 | 68 | // Auto-configuration 69 | // 70 | // Sets automatically charge current (CDC) and time (CDT) values for 71 | // each electrode. 72 | // 73 | // Autoconfig USL register: the upper limit for the 74 | // auto-configuration. This value (and those that follow below) 75 | // were calculated based on Vdd = 3.3 V and following the equations 76 | // in NXP Application Note AN3889. 77 | // USL = 201 = 0xC9 78 | mpr121_write(MPR121_AUTOCONFIG_USL_REG, 0xC9, sensor); 79 | 80 | // Autoconfig target level register: the target level for the 81 | // auto-configuration baseline search. 82 | // TL = 181 = 0xB5 83 | mpr121_write(MPR121_AUTOCONFIG_TARGET_REG, 0xB5, sensor); 84 | 85 | // Autoconfig LSL register: the lower limit for the 86 | // auto-configuration. 87 | // LSL = 131 = 0x83 88 | mpr121_write(MPR121_AUTOCONFIG_LSL_REG, 0x83, sensor); 89 | 90 | // Autoconfiguration control register. Default value is 0b00001011 = 91 | // 0x0B, where: 92 | // 93 | // First filter iterations (FFI), bits 7-6. Must be the same value 94 | // of FFI as in register MPR121_AFE_CONFIG_REG (0x5C) above; 95 | // default is 0b00. 96 | // 97 | // Retry, bits 5-4. Default is disabled, 0b00. 98 | // 99 | // Baseline value adjust (BVA), bits 3-2. This value must be the 100 | // same as the CL (calibration lock) value in the Electrode 101 | // Configuration Register, below, i.e. 0b10. 102 | // 103 | // Automatic Reconfiguration Enable (ARE), bit 1. Default is 0b1, 104 | // enabled. 105 | // 106 | // Automatic Reconfiguration Enable (ACE), bit 0. Default is 0b1, 107 | // enabled. 108 | mpr121_write(MPR121_AUTOCONFIG_CONTROL_0_REG, 0x0B, sensor); 109 | 110 | // == Baseline system (AN3891) ===================================== 111 | 112 | // Maximum Half Delta (MHD): Determines the largest magnitude of 113 | // variation to pass through the baseline filter. The range of the 114 | // effective value is 1~63. 115 | mpr121_write(MPR121_MAX_HALF_DELTA_RISING_REG, 0x01, sensor); 116 | mpr121_write(MPR121_MAX_HALF_DELTA_FALLING_REG, 0x01, sensor); 117 | 118 | // Noise Half Delta (NHD): Determines the incremental change when 119 | // non-noise drift is detected. The range of the effective value is 120 | // 1~63. 121 | mpr121_write(MPR121_NOISE_HALF_DELTA_RISING_REG, 0x01, sensor); 122 | mpr121_write(MPR121_NOISE_HALF_DELTA_FALLING_REG, 0x01, sensor); 123 | mpr121_write(MPR121_NOISE_HALF_DELTA_TOUCHED_REG, 0x01, sensor); 124 | 125 | // Noise Count Limit (NCL): Determines the number of samples 126 | // consecutively greater than the Max Half Delta value. This is 127 | // necessary to determine that it is not noise. The range of the 128 | // effective value is 0~255. 129 | mpr121_write(MPR121_NOISE_COUNT_LIMIT_RISING_REG, 0x00, sensor); 130 | mpr121_write(MPR121_NOISE_COUNT_LIMIT_FALLING_REG, 0xFF, sensor); 131 | mpr121_write(MPR121_NOISE_COUNT_LIMIT_TOUCHED_REG, 0x00, sensor); 132 | 133 | // Filter Delay Count Limit (FDL): Determines the operation rate of 134 | // the filter. A larger count limit means the filter delay is 135 | // operating more slowly. The range of the effective value is 0~255. 136 | mpr121_write(MPR121_FILTER_DELAY_COUNT_RISING_REG, 0x00, sensor); 137 | mpr121_write(MPR121_FILTER_DELAY_COUNT_FALLING_REG, 0x02, sensor); 138 | mpr121_write(MPR121_FILTER_DELAY_COUNT_TOUCHED_REG, 0x00, sensor); 139 | 140 | // == Debounce and thresholds (AN3892) ============================= 141 | 142 | // Debounce. Value range for each is 0~7. 143 | // Bits 2-0, debounce touch (DT). 144 | // Bits 6-4, debounce release (DR). 145 | mpr121_write(MPR121_DEBOUNCE_REG, 0x00, sensor); 146 | 147 | // Touch and release threshold values for all electrodes. 148 | for (uint8_t i=0; i<12; i++) { 149 | mpr121_write(MPR121_TOUCH_THRESHOLD_REG + i * 2, 0x0F, sensor); 150 | mpr121_write(MPR121_RELEASE_THRESHOLD_REG + i * 2, 0x0A, sensor); 151 | } 152 | 153 | // Electrode Configuration Register (ECR, 0x5E). This must be the 154 | // last register to write to because setting ELEPROX_EN and/or 155 | // ELE_EN to non-zero puts the sensor in Run Mode. 156 | // 157 | // Calibration lock (CL), bits 7-6. The default on reset is 0b00 158 | // (CL enabled). Here I set this instead to 0b10 because this 159 | // enables baseline tracking with initial baseline value loaded 160 | // with the 5 high bits of the first electrode data value, which 161 | // makes the sensor stabilise sooner. Note that ths value must 162 | // match BVA bits in the Auto-configure Control Register above. 163 | // 164 | // Proximity enable (ELEPROX_EN), bits 5-4. Default, 0b00 165 | // (proximity detection disabled). 166 | // 167 | // Electrode enabled (ELE_EN), bits 3-0. Default, 0b1100 (enable 168 | // all 12 electrodes). 169 | mpr121_write(MPR121_ELECTRODE_CONFIG_REG, 0x8C, sensor); 170 | } -------------------------------------------------------------------------------- /lib/include/mpr121.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2021-2023 Antonio González 3 | * 4 | * SPDX-License-Identifier: BSD-3-Clause 5 | */ 6 | 7 | #ifndef _MPR121_H_ 8 | #define _MPR121_H_ 9 | 10 | #include "pico.h" 11 | #include "hardware/i2c.h" 12 | 13 | /** \file mpr121.h 14 | * \brief Library for using an MPR121-based touch sensor with the 15 | * Raspberry Pi Pico 16 | * 17 | */ 18 | 19 | typedef struct mpr121_sensor { 20 | i2c_inst_t *i2c_port; 21 | uint8_t i2c_addr; 22 | // uint8_t i2c_sda; 23 | // uint8_t ic2_scl; 24 | } mpr121_sensor_t; 25 | 26 | /*! \brief MPR121 register map 27 | */ 28 | enum mpr121_register { 29 | MPR121_TOUCH_STATUS_REG = 0x00u, 30 | MPR121_OUT_OF_RANGE_STATUS_0_REG = 0x02u, 31 | MPR121_OUT_OF_RANGE_STATUS_1_REG = 0x03u, 32 | MPR121_ELECTRODE_FILTERED_DATA_REG = 0x04u, 33 | MPR121_BASELINE_VALUE_REG = 0x1Eu, 34 | // Registers 0x2B ~ 0x7F are control and configuration registers 35 | MPR121_MAX_HALF_DELTA_RISING_REG = 0x2Bu, 36 | MPR121_NOISE_HALF_DELTA_RISING_REG = 0x2Cu, 37 | MPR121_NOISE_COUNT_LIMIT_RISING_REG = 0x2Du, 38 | MPR121_FILTER_DELAY_COUNT_RISING_REG = 0x2Eu, 39 | MPR121_MAX_HALF_DELTA_FALLING_REG = 0x2Fu, 40 | MPR121_NOISE_HALF_DELTA_FALLING_REG = 0x30u, 41 | MPR121_NOISE_COUNT_LIMIT_FALLING_REG = 0x31u, 42 | MPR121_FILTER_DELAY_COUNT_FALLING_REG = 0x32u, 43 | MPR121_NOISE_HALF_DELTA_TOUCHED_REG = 0x33u, 44 | MPR121_NOISE_COUNT_LIMIT_TOUCHED_REG = 0x34u, 45 | MPR121_FILTER_DELAY_COUNT_TOUCHED_REG = 0x35u, 46 | // (ELEPROX 0x36 .. 0x40) 47 | MPR121_TOUCH_THRESHOLD_REG = 0x41u, 48 | MPR121_RELEASE_THRESHOLD_REG = 0x42u, 49 | // (ELEPROX 0x59 .. 0x5A) 50 | MPR121_DEBOUNCE_REG = 0x5Bu, 51 | MPR121_AFE_CONFIG_REG = 0x5Cu, 52 | MPR121_FILTER_CONFIG_REG = 0x5Du, 53 | MPR121_ELECTRODE_CONFIG_REG = 0x5Eu, 54 | MPR121_ELECTRODE_CURRENT_REG = 0x5Fu, 55 | MPR121_ELECTRODE_CHARGE_TIME_REG = 0x6Cu, 56 | MPR121_GPIO_CTRL_0_REG = 0x73u, 57 | MPR121_GPIO_CTRL_1_REG = 0x74u, 58 | MPR121_GPIO_DATA_REG = 0x75u, 59 | MPR121_GPIO_DIRECTION_REG = 0x76u, 60 | MPR121_GPIO_ENABLE_REG = 0x77u, 61 | MPR121_GPIO_DATA_SET_REG = 0x78u, 62 | MPR121_GPIO_DATA_CLEAR_REG = 0x79u, 63 | MPR121_GPIO_DATA_TOGGLE_REG = 0x7Au, 64 | MPR121_AUTOCONFIG_CONTROL_0_REG = 0x7Bu, 65 | MPR121_AUTOCONFIG_CONTROL_1_REG = 0x7Cu, 66 | MPR121_AUTOCONFIG_USL_REG = 0x7Du, 67 | MPR121_AUTOCONFIG_LSL_REG = 0x7Eu, 68 | MPR121_AUTOCONFIG_TARGET_REG = 0x7Fu, 69 | MPR121_SOFT_RESET_REG = 0x80u 70 | }; 71 | 72 | /*! \brief Initialise the MPR121 and configure registers 73 | * 74 | * The default parameters used here to configure the sensor are as in 75 | * the MPR121 Quick Start Guide (AN3944). 76 | * 77 | * \param i2c_port The I2C instance, either i2c0 or i2c1 78 | * \param i2c_addr The I2C address of the MPR121 device 79 | * \param sensor Pointer to the structure that stores the MPR121 info 80 | */ 81 | void mpr121_init(i2c_inst_t *i2c_port, uint8_t i2c_addr, 82 | mpr121_sensor_t *sensor); 83 | 84 | /*! \brief Write a value to the specified register 85 | * 86 | * \param reg The register address 87 | * \param val The value to write 88 | * \param sensor Pointer to the structure that stores the MPR121 info 89 | */ 90 | static void mpr121_write(enum mpr121_register reg, uint8_t val, 91 | mpr121_sensor_t *sensor) { 92 | uint8_t buf[] = {reg, val}; 93 | i2c_write_blocking(sensor->i2c_port, sensor->i2c_addr, buf, 2, 94 | false); 95 | } 96 | 97 | /*! \brief Read a byte from the specified register 98 | * 99 | * \param reg The register address 100 | * \param dst Pointer to buffer to receive data 101 | * \param sensor Pointer to the structure that stores the MPR121 info 102 | */ 103 | static void mpr121_read(enum mpr121_register reg, uint8_t *dst, 104 | mpr121_sensor_t *sensor) { 105 | i2c_write_blocking(sensor->i2c_port, sensor->i2c_addr, ®, 1, 106 | true); 107 | i2c_read_blocking(sensor->i2c_port, sensor->i2c_addr, dst, 1, 108 | false); 109 | } 110 | 111 | /*! \brief Read a 2-byte value from the specified register 112 | * 113 | * \param reg The register address 114 | * \param dst Pointer to buffer to receive data 115 | * \param sensor Pointer to the structure that stores the MPR121 info 116 | */ 117 | static void mpr121_read16(enum mpr121_register reg, uint16_t *dst, 118 | mpr121_sensor_t *sensor) { 119 | uint8_t vals[2]; 120 | i2c_write_blocking(sensor->i2c_port, sensor->i2c_addr, ®, 1, 121 | true); 122 | i2c_read_blocking(sensor->i2c_port, sensor->i2c_addr, vals, 2, 123 | false); 124 | *dst = vals[1] << 8 | vals[0]; 125 | } 126 | 127 | /*! \brief Set touch and release thresholds for all electrodes 128 | * 129 | * A touch is detected when the difference between the baseline and the 130 | * filtered data is greater than the touch threshold. A release 131 | * condition occurs when this difference is lesser than the release 132 | * threshold. 133 | * 134 | * This function sets the same touch and release threshold values to all 135 | * electrodes. 136 | * 137 | * Touch threshold must be larger than release threshold. 138 | * 139 | * \param touch Touch threshold in the range 0--255 140 | * \param release Release threshold in the range 0--255 141 | * \param sensor Pointer to the structure that stores the MPR121 info 142 | */ 143 | static void mpr121_set_thresholds(uint8_t touch, uint8_t release, 144 | mpr121_sensor_t *sensor) { 145 | uint8_t config; 146 | mpr121_read(MPR121_ELECTRODE_CONFIG_REG, &config, sensor); 147 | if (config != 0){ 148 | // Stop mode 149 | mpr121_write(MPR121_ELECTRODE_CONFIG_REG, 0x00, sensor); 150 | } 151 | 152 | for (uint8_t i=0; i<12; i++) { 153 | mpr121_write(MPR121_TOUCH_THRESHOLD_REG + i * 2, touch, sensor); 154 | mpr121_write(MPR121_RELEASE_THRESHOLD_REG + i * 2, release, 155 | sensor); 156 | } 157 | 158 | if (config != 0){ 159 | mpr121_write(MPR121_ELECTRODE_CONFIG_REG, config, sensor); 160 | } 161 | } 162 | 163 | /*! \brief Set touch and release thresholds for one electrode 164 | * 165 | * A touch is detected when the difference between the baseline and the 166 | * filtered data is greater than the touch threshold. A release 167 | * condition occurs when this difference is lesser than the release 168 | * threshold. 169 | * 170 | * This function sets touch and release threshold values to the selected 171 | * electrode. 172 | * 173 | * Touch threshold must be larger than release threshold. 174 | * 175 | * \param electrode Electrode number (0--11) 176 | * \param touch Touch threshold in the range 0--255 177 | * \param release Release threshold in the range 0--255 178 | * \param sensor Pointer to the structure that stores the MPR121 info 179 | */ 180 | static void mpr121_set_thresholds_ele(uint8_t electrode, uint8_t touch, 181 | uint8_t release, 182 | mpr121_sensor_t *sensor) { 183 | uint8_t config; 184 | mpr121_read(MPR121_ELECTRODE_CONFIG_REG, &config, sensor); 185 | if (config != 0){ 186 | // Stop mode 187 | mpr121_write(MPR121_ELECTRODE_CONFIG_REG, 0x00, sensor); 188 | } 189 | 190 | mpr121_write(MPR121_TOUCH_THRESHOLD_REG + (electrode * 2), touch, 191 | sensor); 192 | mpr121_write(MPR121_RELEASE_THRESHOLD_REG + (electrode * 2), 193 | release, sensor); 194 | 195 | if (config != 0){ 196 | mpr121_write(MPR121_ELECTRODE_CONFIG_REG, config, sensor); 197 | } 198 | } 199 | 200 | /*! \brief Set debounce touch and release 201 | * 202 | * Debounce determines the number (1 to 8) of consecutive touch 203 | * (release) detections before an interrupt is triggered and a touch 204 | * (release) is reported. 205 | * 206 | * \param touch Debounce touch value, range 0--7 207 | * \param release Debounce release value, range 0--7 208 | * \param sensor Pointer to the structure that stores the MPR121 info 209 | */ 210 | static void mpr121_set_debounce(uint8_t touch, uint8_t release, 211 | mpr121_sensor_t *sensor) { 212 | uint8_t config; 213 | mpr121_read(MPR121_ELECTRODE_CONFIG_REG, &config, sensor); 214 | if (config != 0){ 215 | // Stop mode 216 | mpr121_write(MPR121_ELECTRODE_CONFIG_REG, 0x00, sensor); 217 | } 218 | 219 | // Debounce applies to all electrodes; the values cannot set 220 | // independently for each electrode, as with e.g. thresholds. 221 | // Bits 2-0, debounce touch (DT). 222 | // Bits 6-4, debounce release (DR). 223 | uint8_t debounce = (release << 4) | (touch); 224 | mpr121_write(MPR121_DEBOUNCE_REG, debounce, sensor); 225 | 226 | if (config != 0){ 227 | mpr121_write(MPR121_ELECTRODE_CONFIG_REG, config, sensor); 228 | } 229 | } 230 | 231 | /*! \brief Enable only the number of electrodes specified 232 | * 233 | * \param nelec Number of electrodes to enable 234 | * \param sensor Pointer to the structure that stores the MPR121 info 235 | * 236 | * E.g. if `nelec` is 3, electrodes 0 to 2 will be enabled; if `nelec` 237 | * is 6, electrodes 0 to 5 will be enabled. From the datasheet: 238 | * "Enabling specific channels will save the scan time and sensing 239 | * field power spent on the unused channels." 240 | */ 241 | static void mpr121_enable_electrodes(uint8_t nelec, 242 | mpr121_sensor_t *sensor){ 243 | uint8_t config; 244 | mpr121_read(MPR121_ELECTRODE_CONFIG_REG, &config, sensor); 245 | 246 | // Clear bits 3-0, which controls the operation of the 12 247 | // electrodes. 248 | config &= ~0x0f; 249 | 250 | // Set number of electrodes enabled 251 | config |= nelec; 252 | 253 | mpr121_write(MPR121_ELECTRODE_CONFIG_REG, 0x00, sensor); 254 | mpr121_write(MPR121_ELECTRODE_CONFIG_REG, config, sensor); 255 | } 256 | 257 | /*! \brief Read the touch/release status of all 13 input channels 258 | * 259 | * \param dst Pointer to buffer to receive data 260 | * \param sensor Pointer to the structure that stores the MPR121 info 261 | * 262 | * In the value read, bits 11-0 represent electrodes 11 to 0, 263 | * respectively, and bit 12 is the proximity detection channel. Each 264 | * bit represent the status of these channels: 1 if the channel is 265 | * touched, 0 if it is released. 266 | */ 267 | static void mpr121_touched(uint16_t *dst, mpr121_sensor_t *sensor) { 268 | mpr121_read16(MPR121_TOUCH_STATUS_REG, dst, sensor); 269 | *dst &= 0x0fff; 270 | } 271 | 272 | /*! \brief Determine whether an electrode has been touched 273 | * 274 | * \param electrode Electrode number 275 | * \param dst Pointer to buffer to receive data 276 | * \param sensor Pointer to the structure that stores the MPR121 info 277 | */ 278 | static void mpr121_is_touched(uint8_t electrode, bool *dst, 279 | mpr121_sensor_t *sensor){ 280 | uint16_t touched; 281 | mpr121_touched(&touched, sensor); 282 | *dst = (bool) ((touched >> electrode) & 1); 283 | } 284 | 285 | /*! \brief Read an electrode's filtered data value 286 | * 287 | * \param electrode Electrode number 288 | * \param dst Pointer to buffer to receive data 289 | * \param sensor Pointer to the structure that stores the MPR121 info 290 | * 291 | * The data range of the filtered data is 0 to 1024. 292 | * \sa mpr121_baseline_value 293 | */ 294 | static void mpr121_filtered_data(uint8_t electrode, uint16_t *dst, 295 | mpr121_sensor_t *sensor){ 296 | mpr121_read16(MPR121_ELECTRODE_FILTERED_DATA_REG + (electrode * 2), 297 | dst, sensor); 298 | // Filtered data is 10-bit 299 | *dst &= 0x3ff; 300 | } 301 | 302 | /*! \brief Read an electrode's baseline value 303 | * 304 | * \param electrode Electrode number 305 | * \param dst Pointer to buffer to receive data 306 | * \param sensor Pointer to the structure that stores the MPR121 info 307 | * 308 | * From the MPR112 datasheet: 309 | * > Along with the 10-bit electrode filtered data output, each channel 310 | * > also has a 10-bit baseline value. These values are the output of 311 | * > the internal baseline filter operation tracking the slow-voltage 312 | * > variation of the background capacitance change. Touch/release 313 | * > detection is made based on the comparison between the 10-bit 314 | * > electrode filtered data and the 10-bit baseline value. 315 | * 316 | * > Although internally the baseline value is 10-bit, users can only 317 | * > access the 8 MSB of the 10-bit baseline value through the baseline 318 | * > value registers. 319 | * 320 | * \sa mpr121_filtered_data 321 | */ 322 | static void mpr121_baseline_value(uint8_t electrode, uint16_t *dst, 323 | mpr121_sensor_t *sensor){ 324 | uint8_t baseline; 325 | mpr121_read(MPR121_BASELINE_VALUE_REG + electrode, &baseline, 326 | sensor); 327 | // From the datasheet: Although internally the baseline value is 328 | // 10-bit, users can only access the 8 MSB of the 10-bit baseline 329 | // value through the baseline value registers. The read out from the 330 | // baseline register must be left shift two bits before comparing it 331 | // with the 10-bit electrode data. 332 | *dst = baseline << 2; 333 | } 334 | 335 | /*! \brief Set the Max Half Delta 336 | * 337 | * The Max Half Delta determines the largest magnitude of variation to 338 | * pass through the third level filter. See application note MPR121 339 | * Baseline System (AN3891) for details. 340 | * 341 | * \param rising Value in the range 1~63 342 | * \param falling Value in the range 1~63 343 | * \param sensor Pointer to the structure that stores the MPR121 info 344 | */ 345 | static void mpr121_set_max_half_delta(uint8_t rising, uint8_t falling, 346 | mpr121_sensor_t *sensor) { 347 | // Read current configuration then enter stop mode 348 | uint8_t config; 349 | mpr121_read(MPR121_ELECTRODE_CONFIG_REG, &config, sensor); 350 | mpr121_write(MPR121_ELECTRODE_CONFIG_REG, 0x00, sensor); 351 | // Write MHD values 352 | mpr121_write(MPR121_MAX_HALF_DELTA_RISING_REG, rising, sensor); 353 | mpr121_write(MPR121_MAX_HALF_DELTA_FALLING_REG, falling, sensor); 354 | // Re-enable electrodes 355 | mpr121_write(MPR121_ELECTRODE_CONFIG_REG, config, sensor); 356 | } 357 | 358 | /*! \brief Set the Noise Half Delta 359 | * 360 | * The Noise Half Delta determines the incremental change when 361 | * non-noise drift is detected. See application note MPR121 Baseline 362 | * System (AN3891) for details. 363 | * 364 | * \param rising Value in the range 1~63 365 | * \param falling Value in the range 1~63 366 | * \param touched Value in the range 1~63 367 | * \param sensor Pointer to the structure that stores the MPR121 info 368 | */ 369 | static void mpr121_set_noise_half_delta(uint8_t rising, uint8_t falling, 370 | uint8_t touched, mpr121_sensor_t *sensor) { 371 | // Read current configuration then enter stop mode 372 | uint8_t config; 373 | mpr121_read(MPR121_ELECTRODE_CONFIG_REG, &config, sensor); 374 | mpr121_write(MPR121_ELECTRODE_CONFIG_REG, 0x00, sensor); 375 | // Write NHD values 376 | mpr121_write(MPR121_NOISE_HALF_DELTA_RISING_REG, rising, sensor); 377 | mpr121_write(MPR121_NOISE_HALF_DELTA_FALLING_REG, falling, sensor); 378 | mpr121_write(MPR121_NOISE_HALF_DELTA_TOUCHED_REG, touched, sensor); 379 | // Re-enable electrodes 380 | mpr121_write(MPR121_ELECTRODE_CONFIG_REG, config, sensor); 381 | } 382 | 383 | /*! \brief Set the Noise Count Limit 384 | * 385 | * The Noise Count Limit determines the number of samples consecutively 386 | * greater than the Max Half Delta necessary before it can be 387 | * determined that it is non-noise. See application note MPR121 Baseline 388 | * System (AN3891) for details. 389 | * 390 | * \param rising Value in the range 0~255 391 | * \param falling Value in the range 0~255 392 | * \param touched Value in the range 0~255 393 | * \param sensor Pointer to the structure that stores the MPR121 info 394 | */ 395 | static void mpr121_set_noise_count_limit(uint8_t rising, 396 | uint8_t falling, uint8_t touched, mpr121_sensor_t *sensor) { 397 | // Read current configuration then enter stop mode 398 | uint8_t config; 399 | mpr121_read(MPR121_ELECTRODE_CONFIG_REG, &config, sensor); 400 | mpr121_write(MPR121_ELECTRODE_CONFIG_REG, 0x00, sensor); 401 | // Write new NCL values 402 | mpr121_write(MPR121_NOISE_COUNT_LIMIT_RISING_REG, rising, sensor); 403 | mpr121_write(MPR121_NOISE_COUNT_LIMIT_FALLING_REG, falling, sensor); 404 | mpr121_write(MPR121_NOISE_COUNT_LIMIT_TOUCHED_REG, touched, sensor); 405 | // Re-enable electrodes 406 | mpr121_write(MPR121_ELECTRODE_CONFIG_REG, config, sensor); 407 | } 408 | 409 | /*! \brief Set the Filter Delay Limit 410 | * 411 | * The Filter Delay Limit determines the rate of operation of the 412 | * filter. A larger number makes it operate slower. See application 413 | * note MPR121 Baseline System (AN3891) for details. 414 | * 415 | * \param rising Value in the range 0~255 416 | * \param falling Value in the range 0~255 417 | * \param touched Value in the range 0~255 418 | * \param sensor Pointer to the structure that stores the MPR121 info 419 | */ 420 | static void mpr121_set_filter_delay_limit(uint8_t rising, 421 | uint8_t falling, uint8_t touched, mpr121_sensor_t *sensor) { 422 | // Read current configuration then enter stop mode 423 | uint8_t config; 424 | mpr121_read(MPR121_ELECTRODE_CONFIG_REG, &config, sensor); 425 | mpr121_write(MPR121_ELECTRODE_CONFIG_REG, 0x00, sensor); 426 | // Write new FDL values 427 | mpr121_write(MPR121_FILTER_DELAY_COUNT_RISING_REG, rising, sensor); 428 | mpr121_write(MPR121_FILTER_DELAY_COUNT_FALLING_REG, falling, 429 | sensor); 430 | mpr121_write(MPR121_FILTER_DELAY_COUNT_TOUCHED_REG, touched, 431 | sensor); 432 | // Re-enable electrodes 433 | mpr121_write(MPR121_ELECTRODE_CONFIG_REG, config, sensor); 434 | } 435 | 436 | #endif 437 | --------------------------------------------------------------------------------