element14 Community
element14 Community
    Register Log In
  • Site
  • Search
  • Log In Register
  • Community Hub
    Community Hub
    • What's New on element14
    • Feedback and Support
    • Benefits of Membership
    • Personal Blogs
    • Members Area
    • Achievement Levels
  • Learn
    Learn
    • Ask an Expert
    • eBooks
    • element14 presents
    • Learning Center
    • Tech Spotlight
    • STEM Academy
    • Webinars, Training and Events
    • Learning Groups
  • Technologies
    Technologies
    • 3D Printing
    • FPGA
    • Industrial Automation
    • Internet of Things
    • Power & Energy
    • Sensors
    • Technology Groups
  • Challenges & Projects
    Challenges & Projects
    • Design Challenges
    • element14 presents Projects
    • Project14
    • Arduino Projects
    • Raspberry Pi Projects
    • Project Groups
  • Products
    Products
    • Arduino
    • Avnet Boards Community
    • Dev Tools
    • Manufacturers
    • Multicomp Pro
    • Product Groups
    • Raspberry Pi
    • RoadTests & Reviews
  • About Us
  • Store
    Store
    • Visit Your Store
    • Choose another store...
      • Europe
      •  Austria (German)
      •  Belgium (Dutch, French)
      •  Bulgaria (Bulgarian)
      •  Czech Republic (Czech)
      •  Denmark (Danish)
      •  Estonia (Estonian)
      •  Finland (Finnish)
      •  France (French)
      •  Germany (German)
      •  Hungary (Hungarian)
      •  Ireland
      •  Israel
      •  Italy (Italian)
      •  Latvia (Latvian)
      •  
      •  Lithuania (Lithuanian)
      •  Netherlands (Dutch)
      •  Norway (Norwegian)
      •  Poland (Polish)
      •  Portugal (Portuguese)
      •  Romania (Romanian)
      •  Russia (Russian)
      •  Slovakia (Slovak)
      •  Slovenia (Slovenian)
      •  Spain (Spanish)
      •  Sweden (Swedish)
      •  Switzerland(German, French)
      •  Turkey (Turkish)
      •  United Kingdom
      • Asia Pacific
      •  Australia
      •  China
      •  Hong Kong
      •  India
      •  Korea (Korean)
      •  Malaysia
      •  New Zealand
      •  Philippines
      •  Singapore
      •  Taiwan
      •  Thailand (Thai)
      • Americas
      •  Brazil (Portuguese)
      •  Canada
      •  Mexico (Spanish)
      •  United States
      Can't find the country/region you're looking for? Visit our export site or find a local distributor.
  • Translate
  • Profile
  • Settings
At The Core Design Challenge
  • Challenges & Projects
  • Design Challenges
  • At The Core Design Challenge
  • More
  • Cancel
At The Core Design Challenge
Blog AtTheCore: Blog #3 - PWM and Capsense on Cortex M0+
  • Blog
  • Forum
  • Documents
  • Leaderboard
  • Polls
  • Files
  • Members
  • Mentions
  • Sub-Groups
  • Tags
  • More
  • Cancel
  • New
Join At The Core Design Challenge to participate - click to join for free!
  • Share
  • More
  • Cancel
Group Actions
  • Group RSS
  • More
  • Cancel
Engagement
  • Author Author: navadeepganeshu
  • Date Created: 22 Apr 2023 6:41 PM Date Created
  • Views 656 views
  • Likes 5 likes
  • Comments 1 comment
  • infineon
  • element14
  • PSoC 62S4 pioneer kit
  • modustoolbox
  • Embedded Systems
  • microcontroller
  • More At The Core Design Challenge
Related
Recommended

AtTheCore: Blog #3 - PWM and Capsense on Cortex M0+

navadeepganeshu
navadeepganeshu
22 Apr 2023
AtTheCore: Blog #3 - PWM and Capsense on Cortex M0+

Table of Contents

  • Introduction
  • Configuring Capsense
    • Capsense Configurator
    • Capsense Tuner
    • Schematic
  • Extending for 2-channel PWM
    •  led.h
    • led.c
  • Toggle Button Control Logic
    • main.c (CM0+)
  • Sneak Peek
  • Did you miss?
  • References

Introduction

After seeing the sensor interface and serial write on Cortex M4 (CM4) core ((+) AtTheCore: Blog #2 - Interfacing LED Bar with ALS), this blog is about capsense button, slider interfacing and using PWM to control the duty cycle output of the signal channel all on Cortex M0+ (CM0+) core. This is the main building block of the project involving touch and motor control feature integration. The project requires 2 PWM channels for motor control via the IFX007T motor control shield and the configuration, linking with capsense is discussed here and upcoming is the testing and some scope views Slight smile

Configuring Capsense

Capsese is an interesting feature offered in many of Infineon's PSoC MCUs which is a capacitive touch sensing solution involving no physical pushbuttons or mechanical switch. This particular CY8CKIT-062S4 comes with 2 Capsense buttons and one Capsense slider. The IDE comes with integrated tools for configuring and tuning the Capsense application specific to the user.

image

image

Capsense Configurator

image

Capsense Tuner

image

The slider consists of multiple capsense units integrated sequentially and based on the touch signal weight as in the above plot, it judges the sliding movement.

Schematic

image

The capsense initialization is done at the beginning of the program and the main for loop (Cortex M0+) runs the following routine:

        if (capsense_scan_complete)
        {
            /* Process all widgets */
            Cy_CapSense_ProcessAllWidgets(&cy_capsense_context);

            /* Process touch input */
            process_touch();

            /* Initiate next scan */
            Cy_CapSense_ScanAllWidgets(&cy_capsense_context);

            capsense_scan_complete = false;
         }

Extending for 2-channel PWM

The basic capsense example comes with the implementation of LED brightness control and for this project, it is extended to 2 channels. Initially, here I am using 2 onboard LEDs to configure and test out the functionality of PWM with the slider. Additional LED and PWM channel is added in the code as in the prototype definition.

 led.h

/*******************************************************************************
* Function prototypes
*******************************************************************************/
void initialize_led(void);
void update_led1_state(led_data_t *led1_data);
void update_led2_state(led_data_t *led2_data);

led.c

void update_led1_state(led_data_t *led1_data)
{
    if ((led1_state_cur == LED_OFF) && (led1_data->state == LED_ON))
    {
        /* Enable PWM */
        Cy_TCPWM_PWM_Enable(PWM1_HW, PWM1_NUM);

        #if(CY_IP_MXTCPWM_VERSION > 1)
        {
            /* Start PWM */
            Cy_TCPWM_TriggerStart_Single(PWM1_HW, PWM1_NUM);
        }
        #else
        {
            /* Start PWM */
            Cy_TCPWM_TriggerStart(PWM1_HW, PWM1_MASK);
        }
        #endif

        led1_state_cur = LED_ON;
        led1_data->brightness = LED_MAX_BRIGHTNESS;
    }
    else if ((led1_state_cur == LED_ON) && (led1_data->state == LED_OFF))
    {
        /* Disable PWM to turn off the LED */
        Cy_TCPWM_PWM_Disable(PWM1_HW, PWM1_NUM);
        led1_state_cur = LED_OFF;
        led1_data->brightness = 0;
    }
    else
    {
    }

    if ((LED_ON == led1_state_cur) || ((LED_OFF == led1_state_cur) && (led1_data->brightness > 0)))
    {
        /* Enable PWM */
        Cy_TCPWM_PWM_Enable(PWM1_HW, PWM1_NUM);

        #if(CY_IP_MXTCPWM_VERSION > 1)
        {
            /* Start PWM */
            Cy_TCPWM_TriggerStart_Single(PWM1_HW, PWM1_NUM);

        }
        #else
        {
            /* Start PWM */
            Cy_TCPWM_TriggerStart(PWM1_HW, PWM1_MASK);

        }
        #endif

        uint32_t brightness = (led1_data->brightness < LED_MIN_BRIGHTNESS) ? LED_MIN_BRIGHTNESS : led1_data->brightness;

        /* Drive the LED with brightness */
        Cy_TCPWM_PWM_SetCompare0(PWM1_HW, PWM1_NUM, brightness);

        led1_state_cur = LED_ON;
    }
}

void update_led2_state(led_data_t *led2_data)
{
    if ((led2_state_cur == LED_OFF) && (led2_data->state == LED_ON))
    {
        /* Enable PWM */
        Cy_TCPWM_PWM_Enable(PWM2_HW, PWM2_NUM);

        #if(CY_IP_MXTCPWM_VERSION > 1)
        {
            /* Start PWM */
            Cy_TCPWM_TriggerStart_Single(PWM2_HW, PWM2_NUM);
        }
        #else
        {
            /* Start PWM */
            Cy_TCPWM_TriggerStart(PWM2_HW, PWM2_MASK);
        }
        #endif

        led2_state_cur = LED_ON;
        led2_data->brightness = LED_MAX_BRIGHTNESS;
    }
    else if ((led2_state_cur == LED_ON) && (led2_data->state == LED_OFF))
    {
        /* Disable PWM to turn off the LED */
        Cy_TCPWM_PWM_Disable(PWM2_HW, PWM2_NUM);
        led2_state_cur = LED_OFF;
        led2_data->brightness = 0;
    }
    else
    {
    }

    if ((LED_ON == led2_state_cur) || ((LED_OFF == led2_state_cur) && (led2_data->brightness > 0)))
    {
        /* Enable PWM */
        Cy_TCPWM_PWM_Enable(PWM2_HW, PWM2_NUM);

        #if(CY_IP_MXTCPWM_VERSION > 1)
        {
            /* Start PWM */
            Cy_TCPWM_TriggerStart_Single(PWM2_HW, PWM2_NUM);

        }
        #else
        {
            /* Start PWM */
            Cy_TCPWM_TriggerStart(PWM2_HW, PWM2_MASK);

        }
        #endif

        uint32_t brightness = (led2_data->brightness < LED_MIN_BRIGHTNESS) ? LED_MIN_BRIGHTNESS : led2_data->brightness;

        /* Drive the LED with brightness */
        Cy_TCPWM_PWM_SetCompare0(PWM2_HW, PWM2_NUM, brightness);

        led2_state_cur = LED_ON;
    }
}

/*******************************************************************************
* Function Name: initialize_led
********************************************************************************
* Summary:
*  Initializes a PWM resource for driving an LED.
*
* Parameters:
*  none
*
* Return
*  cy_rslt_t rslt - status of operation
*
*******************************************************************************/
void initialize_led(void)
{
    /* Configure the TCPWM for PWM operation */
    Cy_TCPWM_PWM_Init(PWM1_HW, PWM1_NUM, &PWM1_config);
    Cy_TCPWM_PWM_Init(PWM2_HW, PWM2_NUM, &PWM2_config);

    /* Enable PWM */
    Cy_TCPWM_PWM_Enable(PWM1_HW, PWM1_NUM);
    Cy_TCPWM_PWM_Enable(PWM2_HW, PWM2_NUM);

    /* Drive the LED with brightness */
    Cy_TCPWM_PWM_SetCompare0(PWM1_HW, PWM1_NUM, LED_MAX_BRIGHTNESS);
    Cy_TCPWM_PWM_SetCompare0(PWM2_HW, PWM2_NUM, LED_MAX_BRIGHTNESS);

    #if(CY_IP_MXTCPWM_VERSION > 1)
    {
        /* Start PWM */
        Cy_TCPWM_TriggerStart_Single(PWM1_HW, PWM1_NUM);
        Cy_TCPWM_TriggerStart_Single(PWM2_HW, PWM2_NUM);
    }
    #else
    {
        /* Start PWM */
        Cy_TCPWM_TriggerStart(PWM1_HW, PWM1_MASK);
        Cy_TCPWM_TriggerStart(PWM2_HW, PWM2_MASK);

    }
    #endif
}

Toggle Button Control Logic

For this project, I am interested to have the 2 capsense buttons to independently turn ON/OFF the motors or thereby the PWM signals driving them. As we have seen above in the CM0+ for main loop, process_touch() function is called and so the hint was to go there and add what I want to do as a part of processing the touch captured by the button. The flow goes so: 

Get button status -> Get slider status -> Detect new touch on the button {do user defined action} -> Detect new touch on the slider {do user defined action} -> Update states (LED for example)

This block of code is written to toggle the LED status when a touch is detected on the button.

main.c (CM0+)

    /* Detect new touch on Button0 */
    if((0u != button0_status) &&
       (0u == button0_status_prev))
    {
        /* Turn USER LED1 ON/OFF */
    	if(led1_data.state){
        led1_data.state = LED_OFF;
        led1_update_req = true;
    	}
    	else{
            led1_data.state = LED_ON;
            led1_update_req = true;
    	}
    }

    /* Detect new touch on Button1 */
    if((0u != button1_status) &&
       (0u == button1_status_prev))
    {
        /* Turn the USER LED2 ON/OFF */
    	if(led2_data.state){
        led2_data.state = LED_OFF;
        led2_update_req = true;
    	}
    	else{
            led2_data.state = LED_ON;
            led2_update_req = true;
    	}
    }

Sneak Peek

image

image

Further, I am working on integrating the modules developed to run on and the link between two different cores by using semaphores. In the next blog, we'll test this out and then explore the usage of motor driver shields to run two motors separately by the user signal through Capsense. Thanks for reading all the way through and do share your comments or if you think something is interesting. Thank you Slight smile

Did you miss?


(+) AtTheCore: Blog #1 - Intro and what's up with the kit! - Blog - At The Core Design Challenge - element14 Community

(+) AtTheCore: Blog #2 - Interfacing LED Bar with ALS - Blog - At The Core Design Challenge - element14 Community

References

Infineon/mtb-example-psoc6-capsense-buttons-slider: Uses a 5-segment CapSense slider and two CapSense buttons to control an LED. (github.com)
MTB CAT1 Peripheral driver library: EZI2C (SCB) (infineon.github.io)
BLDC-SHIELD_IFX007T - Infineon Technologies

CY8CKIT-062S4 User Guide - Infineon Technologies
  • Sign in to reply
  • navadeepganeshu
    navadeepganeshu over 2 years ago

    image

    Am I making this over complicated Disappointed?

    The shield doesn't fit with compatible pin mapping and thus this big lump of wires jumping and flying...

    • Cancel
    • Vote Up 0 Vote Down
    • Sign in to reply
    • More
    • Cancel
element14 Community

element14 is the first online community specifically for engineers. Connect with your peers and get expert answers to your questions.

  • Members
  • Learn
  • Technologies
  • Challenges & Projects
  • Products
  • Store
  • About Us
  • Feedback & Support
  • FAQs
  • Terms of Use
  • Privacy Policy
  • Legal and Copyright Notices
  • Sitemap
  • Cookies

An Avnet Company © 2025 Premier Farnell Limited. All Rights Reserved.

Premier Farnell Ltd, registered in England and Wales (no 00876412), registered office: Farnell House, Forge Lane, Leeds LS12 2NE.

ICP 备案号 10220084.

Follow element14

  • X
  • Facebook
  • linkedin
  • YouTube