This post is older than 2 years and might not be relevant anymore
More Info: Consider searching for newer posts

Initial spike with PWM implementation

Hi,

I am using a PWM to control the output of an LED driver and I am implementing a soft_on function when powering ON the driver, so we have a start_PWM function that looks like this:

static void start_PWM(void)
{
// PWM stuff
    app_pwm_config_t m_pwm0_config = APP_PWM_DEFAULT_CONFIG_1CH(1000, LIGHT_FIXTURE);
    m_pwm0_config.pin_polarity[0] = APP_PWM_POLARITY_ACTIVE_HIGH;

    uint32_t status = app_pwm_init(&PWM0, &m_pwm0_config, NULL);
    APP_ERROR_CHECK(status);
    m_pwm0_max = app_pwm_cycle_ticks_get(&PWM0);
    __LOG(LOG_SRC_APP, LOG_LEVEL_INFO, "PWM max ticks: %d\n", m_pwm0_max);

    app_pwm_enable(&PWM0);
    nrf_delay_us(850);
//this is the soft on: for(uint16_t i = 0; i < 300; i++) { //(void) app_pwm_channel_duty_ticks_set(&PWM0, 0, i); while (app_pwm_channel_duty_ticks_set(&PWM0, 0, i) == NRF_ERROR_BUSY); nrf_delay_ms(1); __LOG(LOG_SRC_APP, LOG_LEVEL_ERROR, "Current dimming: %d\n", i); } __LOG(LOG_SRC_APP, LOG_LEVEL_INFO, "Soft ON\n"); }

Now, the issue is that there is an initial pulse when powering ON and before the soft on happens. we also tried just simply to set to 0 with:

static void start_PWM(void)
{
// PWM stuff
    app_pwm_config_t m_pwm0_config = APP_PWM_DEFAULT_CONFIG_1CH(1000, LIGHT_FIXTURE);
    m_pwm0_config.pin_polarity[0] = APP_PWM_POLARITY_ACTIVE_HIGH;

    uint32_t status = app_pwm_init(&PWM0, &m_pwm0_config, NULL);
    APP_ERROR_CHECK(status);
    m_pwm0_max = app_pwm_cycle_ticks_get(&PWM0);
    __LOG(LOG_SRC_APP, LOG_LEVEL_INFO, "PWM max ticks: %d\n", m_pwm0_max);

    app_pwm_enable(&PWM0);
    nrf_delay_us(850);
    (void) app_pwm_channel_duty_ticks_set(&PWM0, 0, 0);

}

But still, there is that initial pulse. We had a similar issue few weeks ago with this thread: https://devzone.nordicsemi.com/f/nordic-q-a/41616/initial-pulse-while-starting-a-pwm-application we thought that we solved but now we have it again...

and just to clarify, if we don't set anything after the enable function then there is no pulse:

static void start_PWM(void)
{
// PWM stuff
    app_pwm_config_t m_pwm0_config = APP_PWM_DEFAULT_CONFIG_1CH(1000, LIGHT_FIXTURE);
    m_pwm0_config.pin_polarity[0] = APP_PWM_POLARITY_ACTIVE_HIGH;

    uint32_t status = app_pwm_init(&PWM0, &m_pwm0_config, NULL);
    APP_ERROR_CHECK(status);
    m_pwm0_max = app_pwm_cycle_ticks_get(&PWM0);
    __LOG(LOG_SRC_APP, LOG_LEVEL_INFO, "PWM max ticks: %d\n", m_pwm0_max);

    app_pwm_enable(&PWM0);
}

is there any reason to have that pulse when setting the PWM output?

I am using 15.2.0 SDK and 3.0.0 Mesh SDK.

Parents
  • I see multiple bugs in the PWM libraries, not sure whether that would help. A fix worth trying is to use ms-bit inverted, if you haven't tried already.  The startup pulse is different for Low-High PWM (value) vs. High-Low PWM (0x8000|value). I use differential PWM signals so see both simultaneously; maybe try doing this for your LED drive to see if one signal in your case looks preferable. I also control pin initialisation seperately from the library, but can get a 4uSec unwanted pulse on Low-High but not on High-Low startup.

    So the bugs: From the user manual

    // 6.17.5.15 PSEL.OUT[n] (n=0..3)
    //  Address offset: 0x560 + (n × 0x4)
    //  Output pin select for PWM channel n
    //  Bit number 31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
    //          ID                                                                         C B A A A A A
    // Reset 0xFFFFFFFF                  1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
    //  ID RW Field Value ID Value Description
    //  A RW PIN [0..31] Pin number
    //  B RW PORT [0..1] Port number
    //  C RW CONNECT Connection   Disconnected 1 Connected 0

    From the library for PWM nrfx_pwm.h and nrfx_pwm.c in SDK 15.2.0:

    /**
     * @brief This value can be added to a pin number to inverse its polarity
     *        (set idle state = 1).
     */
    #define NRFX_PWM_PIN_INVERTED    0x80
    
    static void configure_pins(nrfx_pwm_t const * const p_instance,
                               nrfx_pwm_config_t const * p_config)
    {
        uint32_t out_pins[NRF_PWM_CHANNEL_COUNT];
        uint8_t i;
    
        for (i = 0; i < NRF_PWM_CHANNEL_COUNT; ++i)
        {
            uint8_t output_pin = p_config->output_pins[i];
            if (output_pin != NRFX_PWM_PIN_NOT_USED)
            {
                bool inverted = output_pin &  NRFX_PWM_PIN_INVERTED;
                out_pins[i]   = output_pin & ~NRFX_PWM_PIN_INVERTED;
    
                if (inverted)
                {
                    nrf_gpio_pin_set(out_pins[i]);
                }
                else
                {
                    nrf_gpio_pin_clear(out_pins[i]);
                }
    
                nrf_gpio_cfg_output(out_pins[i]);
            }
            else
            {
                out_pins[i] = NRF_PWM_PIN_NOT_CONNECTED;
            }
        }
    
        nrf_pwm_pins_set(p_instance->p_registers, out_pins);
    }
    

    There is no inverted bit in the manual; this affects port output initialisation and the use of Port 1.x for PWM.

  • I did try inverting the polarity of the PWM pin which is similar to what you are suggesting.
    That also has a similar spike when powering ON the driver.

  • We are using pin 11 for "LIGHT_FIXTURE".  There is a pin definition as SER_CONN_CHIP_RESET_PIN defined as 11 but that never affected our development till date. We were able to implement PWM and UART communication successfully on pin 11.

  • UART Tx? You should not have both PWM output and UART enabled on the same pin at the same time. Do you see the spike if you don't initialize UART?

  • Sorry, you got me wrong. They were separate applications. We were able to implement UART Tx on pin 11 in a different application and PWM on pin 11 in a different application. 

    We never faced any error in prior cases as we never had the soft-on PWM functionality on reset. 

  • Sorry, misread that. Our Mesh examples do not use Pin 11 as far as I can see. Please try the following: comment out the PWM initialization then read out the pin configuration register after the app has been initialized to determine whether the pin has its default configuration or not (input - disconnect). 

    EDIT: you mentioned testing this with SDK 15.2.0, but have you tried the same with other Mesh examples? 

  • have you tried the same with other Mesh examples? 

    Yes I did try. 

    I implemented the start_PWM() function before the initialize() and start(). This doesn't result in any spike. 

    This one solved the issue because the pin is initially configured active LOW because of which there is the spike when I reboot and the initialize() function takes few ms to implement. Now, as I am initializing the PWM initially, there isn't the spike.

Reply Children
No Data
Related