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.

  • Hi,

    The pin should be set low when you configure it to "active high".

    When I set the pin to active high, I need not change anything as the driver (active high) will have the LED connected turned OFF. 

    Do you get a shorter pulse if you remove the 850 us delay? 

    There isn't any difference in the pulse when I remove the delay or have it as the pulse is quite random. On few occasions, I won't even see the pulse/spike. 

    Is there any startup time for the Mesh? Because, when we tried it with the 15.2.0 SDK, we can't see that initial spike while rebooting.

    Thank you. 

  • Hi,

    So it seems like the spike is not caused by the PWM implementation then. The example do toggle LEDs to indicate various states. Have you checked if one of the LED_x definitions in your board file is assigned to the same pin as LIGHT_FIXTURE?

  • Have you checked if one of the LED_x definitions in your board file is assigned to the same pin as LIGHT_FIXTURE?

    No, there isn't any definition in the board file that matches with the same pin as LIGHT_FIXTURE.

    Here is what we did, I implemented the start_PWM() function before the initialize() and start(). This doesn't result in any spike. 

    Is there any startup time for the Mesh?

    It looks like this spike is a result of the startup/setup time for Mesh.

  • What pin number do you use for "LIGHT_FIXTURE"? 

  • 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.

Reply Children
Related