Guillermo Perez Guillen
Published © CC BY-NC

Classifier and Counter for Objects Controlled with Capsense

Object Classifier System through the use of Capsense with PSoC™ 4100S CapSense, and Object Counter with PSoC™ 62S2 WiFi BT

IntermediateFull instructions provided20 hours161
Classifier and Counter for Objects Controlled with Capsense

Things used in this project

Story

Read more

Custom parts and enclosures

Container

Support

Platform

BOM Cost

Bill of materials cost in excel file

Schematics

Object Classifier

Schematic Diagram

Object Counter

Schematic diagram

Code

main.c

C/C++
Object Classifier Project
Requires PSoC Creator 4.4
The Full Project you can get in the added github repository link
// AUTHOR: GUILLERMO PEREZ GUILLEN

#include "project.h"

int main(void)
{
    CyGlobalIntEnable; /* Enable global interrupts. */
   
     /* Start component */  
    EZI2C_Start();  
    EZI2C_EzI2CSetBuffer1(sizeof(CapSense_dsRam), sizeof(CapSense_dsRam), (uint8 *)&CapSense_dsRam);
    
    CapSense_Start(); 
    CapSense_InitializeAllBaselines();
    CapSense_ScanAllWidgets();
    
    PWM_Start();
    int compare_var = 750;    
    
    for(;;)
    {
        PWM_WriteCompare(compare_var);
        /* Do this only when a scan is done */  
        if(CapSense_NOT_BUSY == CapSense_IsBusy())
        {
            /* Include Tuner */  
            CapSense_RunTuner();
             
            /* Process all widgets */  
            CapSense_ProcessAllWidgets();  

            /* Scan result verification */  

            /* Add any required functionality  based on scanning result */  
            if (CapSense_IsWidgetActive(CapSense_BUTTON0_WDGT_ID))
            {
                for (int i = 1; i <= 1600; i++){  //1600
                    LED_Write(0);    // LED on
                    Pin1_Write(1);
                    Pin2_Write(0);
                    Pin3_Write(1);                
                    Pin4_Write(0);                               
                    CyDelay(2);
                    LED_Write(1);    // LED off
                    Pin1_Write(1);
                    Pin2_Write(0);
                    Pin3_Write(0);                
                    Pin4_Write(1);
                    CyDelay(2);
                    LED_Write(0);    // LED on
                    Pin1_Write(0);
                    Pin2_Write(1);
                    Pin3_Write(0);                
                    Pin4_Write(1);                               
                    CyDelay(2);
                    LED_Write(1);    // LED off
                    Pin1_Write(0);
                    Pin2_Write(1);
                    Pin3_Write(1);                
                    Pin4_Write(0);
                    CyDelay(2);
                }
                
                compare_var = 300;
                PWM_WriteCompare(compare_var);
                CyDelay(1000);
                compare_var = 750;
                PWM_WriteCompare(compare_var);
                CyDelay(1000);
                
                for (int i = 1; i <= 1600; i++){  //1600
                    LED_Write(0);    // LED on
                    Pin1_Write(0);
                    Pin2_Write(1);
                    Pin3_Write(1);                
                    Pin4_Write(0);                               
                    CyDelay(2);
                    LED_Write(1);    // LED off
                    Pin1_Write(0);
                    Pin2_Write(1);
                    Pin3_Write(0);                
                    Pin4_Write(1);
                    CyDelay(2);
                    LED_Write(0);    // LED on
                    Pin1_Write(1);
                    Pin2_Write(0);
                    Pin3_Write(0);                
                    Pin4_Write(1);                               
                    CyDelay(2);
                    LED_Write(1);    // LED off
                    Pin1_Write(1);
                    Pin2_Write(0);
                    Pin3_Write(1);                
                    Pin4_Write(0);
                    CyDelay(2);
                }
            }
            
            else if (CapSense_IsWidgetActive(CapSense_BUTTON1_WDGT_ID))
            {
                for (int i = 1; i <= 1600; i++){  //1600                    
                    LED_Write(0);    // LED on
                    Pin1_Write(0);
                    Pin2_Write(1);
                    Pin3_Write(1);                
                    Pin4_Write(0);                               
                    CyDelay(2);
                    LED_Write(1);    // LED off
                    Pin1_Write(0);
                    Pin2_Write(1);
                    Pin3_Write(0);                
                    Pin4_Write(1);
                    CyDelay(2);
                    LED_Write(0);    // LED on
                    Pin1_Write(1);
                    Pin2_Write(0);
                    Pin3_Write(0);                
                    Pin4_Write(1);                               
                    CyDelay(2);
                    LED_Write(1);    // LED off
                    Pin1_Write(1);
                    Pin2_Write(0);
                    Pin3_Write(1);                
                    Pin4_Write(0);
                    CyDelay(2);
                }
                
                compare_var = 1250;
                PWM_WriteCompare(compare_var);
                CyDelay(1000);
                compare_var = 750;
                PWM_WriteCompare(compare_var);
                CyDelay(1000);
                
                for (int i = 1; i <= 1600; i++){  //1600
                    LED_Write(0);    // LED on
                    Pin1_Write(1);
                    Pin2_Write(0);
                    Pin3_Write(1);                
                    Pin4_Write(0);                               
                    CyDelay(2);
                    LED_Write(1);    // LED off
                    Pin1_Write(1);
                    Pin2_Write(0);
                    Pin3_Write(0);                
                    Pin4_Write(1);
                    CyDelay(2);
                    LED_Write(0);    // LED on
                    Pin1_Write(0);
                    Pin2_Write(1);
                    Pin3_Write(0);                
                    Pin4_Write(1);                               
                    CyDelay(2);
                    LED_Write(1);    // LED off
                    Pin1_Write(0);
                    Pin2_Write(1);
                    Pin3_Write(1);                
                    Pin4_Write(0);
                    CyDelay(2);
                }
            }                     
            else
            {
                LED_Write(1);    // LED off
                Pin1_Write(0);
                Pin2_Write(0);
                Pin3_Write(0);                
                Pin4_Write(0);
                compare_var = 750;
                PWM_WriteCompare(compare_var);                
            }  

            /* Start next scan */  
            CapSense_ScanAllWidgets();  
        } 
    }
}

/* [] END OF FILE */

main.c

C/C++
Object Counter Project
Requires ModusToolbox 3.0
The Full Project you can get in the added github repository link
// AUTHOR: GUILLERMO PEREZ GUILLEN


#include "cy_pdl.h"
#include "cyhal.h"
#include "cybsp.h"
#include "cy_retarget_io.h"
#include "math.h"

/*******************************************************************************
* Macros
*******************************************************************************/
/* Macro for ADC Channel configuration*/
#define SINGLE_CHANNEL 1
#define MULTI_CHANNEL  2

/*
 * Macro to choose between single channel and multiple channel configuration of
 * ADC. Single channel configuration uses channel 0 in single ended mode.
 * Multiple channel configuration uses two channels, channel 0 in single ended
 * mode and channel 1 in differential mode.
 *
 * The default configuration is set to use single channel.
 * To use multiple channel configuration set ADC_EXAMPLE_MODE macro to MULTI_CHANNEL.
 *
 */
//#define ADC_EXAMPLE_MODE SINGLE_CHANNEL
#define ADC_EXAMPLE_MODE MULTI_CHANNEL

/* Channel 0 input pin */
#define VPLUS_CHANNEL_0             (P10_0)

#if ADC_EXAMPLE_MODE == MULTI_CHANNEL

/* Channel 1 VPLUS input pin */
#define VPLUS_CHANNEL_1             (P10_1)

/* Channel 1 VREF input pin */
#define VREF_CHANNEL_1              (P10_2)

/* Number of scans every time ADC read is initiated */
#define NUM_SCAN                    (1)

#endif /* ADC_EXAMPLE_MODE == MULTI_CHANNEL */

/*******************************************************************************
*       Enumerated Types
*******************************************************************************/
/* ADC Channel constants*/
enum ADC_CHANNELS
{
  CHANNEL_0 = 0,
  CHANNEL_1,
  NUM_CHANNELS
} adc_channel;

/*******************************************************************************
* Function Prototypes
*******************************************************************************/
#if ADC_EXAMPLE_MODE == MULTI_CHANNEL

/* Multichannel initialization function */
void adc_multi_channel_init(void);

/* Function to read input voltage from multiple channels */
void adc_multi_channel_process(void);

/* ADC Event Handler */
static void adc_event_handler(void* arg, cyhal_adc_event_t event);

#else /* ADC_EXAMPLE_MODE == SINGLE_CHANNEL */

/* Single channel initialization function*/
void adc_single_channel_init(void);

/* Function to read input voltage from channel 0 */
void adc_single_channel_process(void);

#endif /* ADC_EXAMPLE_MODE == MULTI_CHANNEL */

/*******************************************************************************
* Global Variables
*******************************************************************************/
/* ADC Object */
cyhal_adc_t adc_obj;

/* ADC Channel 0 Object */
cyhal_adc_channel_t adc_chan_0_obj;

/* Default ADC configuration */
const cyhal_adc_config_t adc_config = {
        .continuous_scanning=false, // Continuous Scanning is disabled
        .average_count=1,           // Average count disabled
        .vref=CYHAL_ADC_REF_VDDA,   // VREF for Single ended channel set to VDDA
        .vneg=CYHAL_ADC_VNEG_VSSA,  // VNEG for Single ended channel set to VSSA
        .resolution = 12u,          // 12-bit resolution
        .ext_vref = NC,             // No connection
        .bypass_pin = NC };       // No connection

#if ADC_EXAMPLE_MODE == MULTI_CHANNEL

/* Asynchronous read complete flag, used in Event Handler */
static bool async_read_complete = false;

/* ADC Channel 1 Object */
cyhal_adc_channel_t adc_chan_1_obj;

/* Variable to store results from multiple channels during asynchronous read*/
int32_t result_arr[NUM_CHANNELS * NUM_SCAN] = {0};

#endif /* ADC_EXAMPLE_MODE == MULTI_CHANNEL */

/*******************************************************************************
* Function Name: main
********************************************************************************
* Summary:
* This is the main function for CM4 CPU. It does...
*    1. Configure and initialize ADC.
*    2. Every 200ms read the input voltage and display input voltage on UART.
*
* Parameters:
*  none
*
* Return:
*  int
*
*******************************************************************************/
int main(void)
{
    /* Variable to capture return value of functions */
    cy_rslt_t result;

    /* 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);
    }

    /* Print message */
    /* \x1b[2J\x1b[;H - ANSI ESC sequence for clear screen */
    printf("\x1b[2J\x1b[;H");
    printf("-----------------------------------------------------------\r\n");
    printf("PSoC 6 MCU: ADC using HAL\r\n");
    printf("-----------------------------------------------------------\r\n\n");

#if ADC_EXAMPLE_MODE == MULTI_CHANNEL

    /* Initialize Channel 0 and Channel 1 */
    adc_multi_channel_init();

#else /* ADC_EXAMPLE_MODE == SINGLE_CHANNEL */

    /* Initialize Channel 0 */
    adc_single_channel_init();

#endif /* ADC_EXAMPLE_MODE == MULTI_CHANNEL */

    /* Update ADC configuration */
    result = cyhal_adc_configure(&adc_obj, &adc_config);
    if(result != CY_RSLT_SUCCESS)
    {
        printf("ADC configuration update failed. Error: %ld\n", (long unsigned int)result);
        CY_ASSERT(0);
    }

    for (;;)
    {

#if ADC_EXAMPLE_MODE == MULTI_CHANNEL

        /* Sample input voltage at channel 0 and channel 1*/
        adc_multi_channel_process();

#else  /* ADC_EXAMPLE_MODE == SINGLE_CHANNEL */

        /* Sample input voltage at channel 0 */
        adc_single_channel_process();

#endif /* ADC_EXAMPLE_MODE == MULTI_CHANNEL */

        /* 200ms delay between scans */
        cyhal_system_delay_ms(200);
    }
}

#if ADC_EXAMPLE_MODE == MULTI_CHANNEL

/*******************************************************************************
 * Function Name: adc_multi_channel_init
 *******************************************************************************
 *
 * Summary:
 *  ADC Multichannel initilization. This function initializes and configures
 *  channel 0 and channel 1 of ADC.
 *
 * Parameters:
 *  void
 *
 * Return:
 *  void
 *
 *******************************************************************************/
void adc_multi_channel_init(void)
{
    /* Variable to capture return value of functions */
    cy_rslt_t result;

    /* Initialize ADC. The ADC block which can connect to pin 10[0] is selected */
    result = cyhal_adc_init(&adc_obj, VPLUS_CHANNEL_0, NULL);
    if(result != CY_RSLT_SUCCESS)
    {
        printf("ADC initialization failed. Error: %ld\n", (long unsigned int)result);
        CY_ASSERT(0);
    }

    /* ADC channel configuration */
    const cyhal_adc_channel_config_t channel_config = {
            .enable_averaging = false,  // Disable averaging for channel
            .min_acquisition_ns = 1000, // Minimum acquisition time set to 1us
            .enabled = true };          // Sample this channel when ADC performs a scan

    /* Initialize a channel 0 and configure it to scan P10_0 in single ended mode. */
    result  = cyhal_adc_channel_init_diff(&adc_chan_0_obj, &adc_obj, VPLUS_CHANNEL_0,
                                          CYHAL_ADC_VNEG, &channel_config);
    if(result != CY_RSLT_SUCCESS)
    {
        printf("ADC first channel initialization failed. Error: %ld\n", (long unsigned int)result);
        CY_ASSERT(0);
    }

    /*
     * For multichannel configuration use to same channel configuration structure
     * "channel_config" to configure the second channel.
     * For second channel to be set to differential mode, two inputs from Pins
     * 10.1 and 10.2 are configured to be inputs.
     *
     */

    /* Initialize channel 1 in differential mode with VPLUS and VMINUS input pins */
    result = cyhal_adc_channel_init_diff(&adc_chan_1_obj, &adc_obj, VPLUS_CHANNEL_1,
                                         VREF_CHANNEL_1, &channel_config);
    if(result != CY_RSLT_SUCCESS)
    {
        printf("ADC second channel initialization failed. Error: %ld\n", (long unsigned int)result);
        CY_ASSERT(0);
    }

    /* Register a callback to handle asynchronous read completion */
     cyhal_adc_register_callback(&adc_obj, &adc_event_handler, result_arr);

     /* Subscribe to the async read complete event to process the results */
     cyhal_adc_enable_event(&adc_obj, CYHAL_ADC_ASYNC_READ_COMPLETE, CYHAL_ISR_PRIORITY_DEFAULT, true);

     printf("ADC is configured in multichannel configuration.\r\n\n");
     printf("Channel 0 is configured in single ended mode, connected to pin \r\n");
     printf("P10_0. Provide input voltage at P10_0\r\n");
     printf("Channel 1 is configured in differential mode, connected to pin \r\n");
     printf("P10_1 and P10_2. Provide input voltage at P10_1 and reference \r\n");
     printf("voltage at P10_2\r\n\n");
}

/*******************************************************************************
 * Function Name: adc_multi_channel_process
 *******************************************************************************
 *
 * Summary:
 *  ADC single channel process function. This function reads the input voltage
 *  from channel 0 and channel 1. Prints the input voltage on UART.
 *
 * Parameters:
 *  void
 *
 * Return:
 *  void
 *
 *******************************************************************************/
int32_t bottle_number = 0;
int32_t capacitor_number = 0;

void adc_multi_channel_process(void)
{
    /* Variable to capture return value of functions */
    cy_rslt_t result;

    /* Variable to store ADC conversion result from channel 0 */
    int32_t adc_result_0 = 0;

    /* Variable to store ADC conversion result from channel 1 */
    int32_t adc_result_1 = 0;

    /* Variables distance */

    /* Initiate an asynchronous read operation. The event handler will be called
     * when it is complete. */
    result = cyhal_adc_read_async_uv(&adc_obj, NUM_SCAN, result_arr);
    if(result != CY_RSLT_SUCCESS)
    {
        printf("ADC async read failed. Error: %ld\n", (long unsigned int)result);
        CY_ASSERT(0);
    }

    /*
     * Read data from result list, input voltage in the result list is in
     * microvolts. Convert it millivolts and print input voltage
     *
     */
    adc_result_0 = result_arr[CHANNEL_0]/1000;
    adc_result_1 = result_arr[CHANNEL_1]/1000;

float sensor_left = 28915*pow(adc_result_0, -0.908);
float sensor_right = 58221*pow(adc_result_1, -0.998);
int32_t bottle = sensor_left;
int32_t capacitor = sensor_right;

	if (bottle<70){bottle_number=bottle_number+1;}
	else if (capacitor<70){capacitor_number=capacitor_number+1;}
	else { }

	    printf("Bottle: %3ld \t Capacitor: %3ld\r\n", bottle_number, capacitor_number);

    cyhal_system_delay_ms(10);
    /* Clear async read complete flag */
    async_read_complete = false;
}


/*******************************************************************************
 * Function Name: adc_event_handler
 *******************************************************************************
 *
 * Summary:
 *  ADC event handler. This function handles the asynchronous read complete event
 *  and sets the async_read_complete flag to true.
 *
 * Parameters:
 *  void *arg : pointer to result list
 *  cyhal_adc_event_t event : ADC event type
 *
 * Return:
 *  void
 *
 *******************************************************************************/
static void adc_event_handler(void* arg, cyhal_adc_event_t event)
{
    if(0u != (event & CYHAL_ADC_ASYNC_READ_COMPLETE))
    {
        /* Set async read complete flag to true */
        async_read_complete = true;
    }
}

#else

/*******************************************************************************
 * Function Name: adc_single_channel_init
 *******************************************************************************
 *
 * Summary:
 *  ADC single channel initialization function. This function initializes and
 *  configures channel 0 of ADC.
 *
 * Parameters:
 *  void
 *
 * Return:
 *  void
 *
 *******************************************************************************/
void adc_single_channel_init(void)
{
    /* Variable to capture return value of functions */
    cy_rslt_t result;

    /* Initialize ADC. The ADC block which can connect to pin 10[0] is selected */
    result = cyhal_adc_init(&adc_obj, VPLUS_CHANNEL_0, NULL);
    if(result != CY_RSLT_SUCCESS)
    {
        printf("ADC initialization failed. Error: %ld\n", (long unsigned int)result);
        CY_ASSERT(0);
    }

    /* ADC channel configuration */
    const cyhal_adc_channel_config_t channel_config = {
            .enable_averaging = false,  // Disable averaging for channel
            .min_acquisition_ns = 1000, // Minimum acquisition time set to 1us
            .enabled = true };          // Sample this channel when ADC performs a scan

    /* Initialize a channel 0 and configure it to scan P10_0 in single ended mode. */
    result  = cyhal_adc_channel_init_diff(&adc_chan_0_obj, &adc_obj, VPLUS_CHANNEL_0,
                                          CYHAL_ADC_VNEG, &channel_config);
    if(result != CY_RSLT_SUCCESS)
    {
        printf("ADC single ended channel initialization failed. Error: %ld\n", (long unsigned int)result);
        CY_ASSERT(0);
    }

    printf("ADC is configured in single channel configuration\r\n\n");
    printf("Provide input voltage at pin P10_0. \r\n\n");
}

/*******************************************************************************
 * Function Name: adc_single_channel_process
 *******************************************************************************
 *
 * Summary:
 *  ADC single channel process function. This function reads the input voltage
 *  and prints the input voltage on UART.
 *
 * Parameters:
 *  void
 *
 * Return:
 *  void
 *
 *******************************************************************************/
void adc_single_channel_process(void)
{
    /* Variable to store ADC conversion result from channel 0 */
    int32_t adc_result_0 = 0;

    /* Read input voltage, convert it to millivolts and print input voltage */
    adc_result_0 = cyhal_adc_read_uv(&adc_chan_0_obj)/1000;
    printf("Channel 0 input: %4ldmV\r\n", (long int)adc_result_0);
}

#endif /* ADC_EXAMPLE_MODE == MULTI_CHANNEL */

/* [] END OF FILE */

classifier-and-counter-for-objects-controlled-with-capsense

Projects: 1) Object Classifier (PSoC Creator 4.4) 2) Object Counter (ModusToolbox 3.0)

Credits

Guillermo Perez Guillen

Guillermo Perez Guillen

54 projects • 63 followers
Electronics and Communications Engineer (ECE): 12 prizes in Hackster / Hackaday Prize Finalist 2021-22-23 / 3 prizes in element14

Comments