In this lab, participants will interface with the Infineon PSoC 6 microcontroller's CAPSENSE hardware to implement capacitive sensing for both buttons and sliders. By harnessing the CAPSENSE capabilities, participants will design touch-based interfaces that react to user inputs. Additionally, they will utilize the Capsense Tuner tool to monitor, calibrate, and fine-tune the capacitive sensing parameters, ensuring optimal responsiveness and accuracy. This hands-on exercise aims to provide participants with a comprehensive understanding of capacitive touch technologies, emphasizing the importance of tuning and calibration in delivering a seamless user experience.
The code example features a 5-segment CAPSENSE™ slider and two CAPSENSE™ buttons. Button 0 turns the LED ON, button 1 turns the LED OFF, and the slider controls the brightness of the LED. The code example also demonstrates monitoring CAPSENSE™ data using the CAPSENSE™ tuner GUI tool. This project uses the CAPSENSE™ Middleware Library.
main.c
#include "cybsp.h"
#include "cyhal.h"
#include "cycfg.h"
#include "cycfg_capsense.h"
#include "led.h"
#include "cy_retarget_io.h"
/*******************************************************************************
* Macros
*******************************************************************************/
#define CAPSENSE_INTR_PRIORITY (7u)
#define EZI2C_INTR_PRIORITY (6u) /* EZI2C interrupt priority must be
* higher than CapSense interrupt */
/*******************************************************************************
* Function Prototypes
*******************************************************************************/
static uint32_t initialize_capsense(void);
static void process_touch(void);
static void initialize_capsense_tuner(void);
static void capsense_isr(void);
static void capsense_callback();
void handle_error(void);
/*******************************************************************************
* Global Variables
*******************************************************************************/
cy_stc_scb_ezi2c_context_t ezi2c_context;
cyhal_ezi2c_t sEzI2C;
cyhal_ezi2c_slave_cfg_t sEzI2C_sub_cfg;
cyhal_ezi2c_cfg_t sEzI2C_cfg;
volatile bool capsense_scan_complete = false;
/*******************************************************************************
* Function Name: handle_error
********************************************************************************
* Summary:
* User defined error handling function
*
* Parameters:
* void
*
* Return:
* void
*
*******************************************************************************/
void handle_error(void)
{
/* Disable all interrupts. */
__disable_irq();
CY_ASSERT(0);
}
/*******************************************************************************
* Function Name: main
********************************************************************************
* Summary:
* System entrance point. This function performs
* - initial setup of device
* - initialize CapSense
* - initialize tuner communication
* - scan touch input continuously and update the LED accordingly.
*
* Return:
* int
*
*******************************************************************************/
int main(void)
{
cy_rslt_t result;
#if defined (CY_DEVICE_SECURE)
cyhal_wdt_t wdt_obj;
/* Clear watchdog timer so that it doesn't trigger a reset */
result = cyhal_wdt_init(&wdt_obj, cyhal_wdt_get_max_timeout_ms());
CY_ASSERT(CY_RSLT_SUCCESS == result);
cyhal_wdt_free(&wdt_obj);
#endif
/* Initialize the device and board peripherals */
result = cybsp_init();
/* Board init failed. Stop program execution */
if (result != CY_RSLT_SUCCESS)
{
CY_ASSERT(0);
}
/* Enable global interrupts */
__enable_irq();
/* Initialize retarget-io to use the debug UART port */
result = cy_retarget_io_init(CYBSP_DEBUG_UART_TX, CYBSP_DEBUG_UART_RX,
CY_RETARGET_IO_BAUDRATE);
/* retarget-io init failed. Stop program execution */
if (result != CY_RSLT_SUCCESS)
{
CY_ASSERT(0);
}
/* \x1b[2J\x1b[;H - ANSI ESC sequence for clear screen */
printf("\x1b[2J\x1b[;H");
printf("**********************************************************\r\n");
printf("PSoC 6 MCU: CAPSENSE buttons and slider\r\n");
printf("**********************************************************\r\n");
initialize_led();
initialize_capsense_tuner();
result = initialize_capsense();
if (CYRET_SUCCESS != result)
{
/* Halt the CPU if CapSense initialization failed */
CY_ASSERT(0);
}
/* Initiate first scan */
Cy_CapSense_ScanAllWidgets(&cy_capsense_context);
for (;;)
{
if (capsense_scan_complete)
{
/* Process all widgets */
Cy_CapSense_ProcessAllWidgets(&cy_capsense_context);
/* Process touch input */
process_touch();
/* Establishes synchronized operation between the CapSense
* middleware and the CapSense Tuner tool.
*/
Cy_CapSense_RunTuner(&cy_capsense_context);
/* Initiate next scan */
Cy_CapSense_ScanAllWidgets(&cy_capsense_context);
capsense_scan_complete = false;
}
}
}
/*******************************************************************************
* Function Name: process_touch
********************************************************************************
* Summary:
* Gets the details of touch position detected, processes the touch input
* and updates the LED status.
*
*******************************************************************************/
static void process_touch(void)
{
uint32_t button0_status;
uint32_t button1_status;
cy_stc_capsense_touch_t *slider_touch_info;
uint16_t slider_pos;
uint8_t slider_touch_status;
bool led_update_req = false;
static uint32_t button0_status_prev;
static uint32_t button1_status_prev;
static uint16_t slider_pos_prev;
static led_data_t led_data = {LED_ON, LED_MAX_BRIGHTNESS};
/* Get button 0 status */
button0_status = Cy_CapSense_IsSensorActive(
CY_CAPSENSE_BUTTON0_WDGT_ID,
CY_CAPSENSE_BUTTON0_SNS0_ID,
&cy_capsense_context);
/* Get button 1 status */
button1_status = Cy_CapSense_IsSensorActive(
CY_CAPSENSE_BUTTON1_WDGT_ID,
CY_CAPSENSE_BUTTON1_SNS0_ID,
&cy_capsense_context);
/* Get slider status */
slider_touch_info = Cy_CapSense_GetTouchInfo(
CY_CAPSENSE_LINEARSLIDER0_WDGT_ID, &cy_capsense_context);
slider_touch_status = slider_touch_info->numPosition;
slider_pos = slider_touch_info->ptrPosition->x;
/* Detect new touch on Button0 */
if ((0u != button0_status) &&
(0u == button0_status_prev))
{
led_data.state = LED_ON;
led_update_req = true;
}
/* Detect new touch on Button1 */
if ((0u != button1_status) &&
(0u == button1_status_prev))
{
led_data.state = LED_OFF;
led_update_req = true;
}
/* Detect the new touch on slider */
if ((0 != slider_touch_status) &&
(slider_pos != slider_pos_prev))
{
led_data.brightness = (slider_pos * 100)
/ cy_capsense_context.ptrWdConfig[CY_CAPSENSE_LINEARSLIDER0_WDGT_ID].xResolution;
led_update_req = true;
}
/* Update the LED state if requested */
if (led_update_req)
{
update_led_state(&led_data);
}
/* Update previous touch status */
button0_status_prev = button0_status;
button1_status_prev = button1_status;
slider_pos_prev = slider_pos;
}
/*******************************************************************************
* Function Name: initialize_capsense
********************************************************************************
* Summary:
* This function initializes the CapSense and configure the CapSense
* interrupt.
*
*******************************************************************************/
static uint32_t initialize_capsense(void)
{
uint32_t status = CYRET_SUCCESS;
/* CapSense interrupt configuration parameters */
static const cy_stc_sysint_t capSense_intr_config =
{
.intrSrc = csd_interrupt_IRQn,
.intrPriority = CAPSENSE_INTR_PRIORITY,
};
/* Capture the CSD HW block and initialize it to the default state. */
status = Cy_CapSense_Init(&cy_capsense_context);
if (CYRET_SUCCESS != status)
{
return status;
}
/* Initialize CapSense interrupt */
cyhal_system_set_isr(csd_interrupt_IRQn, csd_interrupt_IRQn, CAPSENSE_INTR_PRIORITY, &capsense_isr);
NVIC_ClearPendingIRQ(capSense_intr_config.intrSrc);
NVIC_EnableIRQ(capSense_intr_config.intrSrc);
/* Initialize the CapSense firmware modules. */
status = Cy_CapSense_Enable(&cy_capsense_context);
if (CYRET_SUCCESS != status)
{
return status;
}
/* Assign a callback function to indicate end of CapSense scan. */
status = Cy_CapSense_RegisterCallback(CY_CAPSENSE_END_OF_SCAN_E,
capsense_callback, &cy_capsense_context);
if (CYRET_SUCCESS != status)
{
return status;
}
return status;
}
/*******************************************************************************
* Function Name: capsense_isr
********************************************************************************
* Summary:
* Wrapper function for handling interrupts from CapSense block.
*
*******************************************************************************/
static void capsense_isr(void)
{
Cy_CapSense_InterruptHandler(CYBSP_CSD_HW, &cy_capsense_context);
}
/*******************************************************************************
* Function Name: capsense_callback()
********************************************************************************
* Summary:
* This function sets a flag to indicate end of a CapSense scan.
*
* Parameters:
* cy_stc_active_scan_sns_t* : pointer to active sensor details.
*
*******************************************************************************/
void capsense_callback(cy_stc_active_scan_sns_t * ptrActiveScan)
{
capsense_scan_complete = true;
}
/*******************************************************************************
* Function Name: initialize_capsense_tuner
********************************************************************************
* Summary:
* Initializes interface between Tuner GUI and PSoC 6 MCU.
*
*******************************************************************************/
static void initialize_capsense_tuner(void)
{
cy_rslt_t result;
/* Configure Capsense Tuner as EzI2C Slave */
sEzI2C_sub_cfg.buf = (uint8 *)&cy_capsense_tuner;
sEzI2C_sub_cfg.buf_rw_boundary = sizeof(cy_capsense_tuner);
sEzI2C_sub_cfg.buf_size = sizeof(cy_capsense_tuner);
sEzI2C_sub_cfg.slave_address = 8U;
sEzI2C_cfg.data_rate = CYHAL_EZI2C_DATA_RATE_400KHZ;
sEzI2C_cfg.enable_wake_from_sleep = false;
sEzI2C_cfg.slave1_cfg = sEzI2C_sub_cfg;
sEzI2C_cfg.sub_address_size = CYHAL_EZI2C_SUB_ADDR16_BITS;
sEzI2C_cfg.two_addresses = false;
result = cyhal_ezi2c_init(&sEzI2C, CYBSP_I2C_SDA, CYBSP_I2C_SCL, NULL, &sEzI2C_cfg);
if (result != CY_RSLT_SUCCESS)
{
handle_error();
}
}
Build Application
Launches Application
Result
Open CAPSENSE Tuner
🎉 Congratulations! You can now complete this lab
Supported toolchains (make variable 'TOOLCHAIN')
GNU Arm® embedded compiler v10.3.1 (GCC_ARM) - Default value of TOOLCHAIN