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

PWM Duty Cycle Does Not Change

Hello,

I'm working on nRF52811, SDK16.0, Softdevice 7.0.1.

Using the pwm_driver example in the SDK, I'm trying to run a simple PWM for an RGB LED. Following is my simplified code. I can see the PWM at output but changing duty cycle (by seq_values->channel_0 = value; ) does not effect the output (no color change). I have tried the demo app on an nRF52840 board and that works fine. But I have to do it on my custom made nRF52811 board. Please help. 

#include <stdio.h>
#include <string.h>
#include "nrf_drv_pwm.h"
#include "app_util_platform.h"
#include "app_error.h"
#include "boards.h"
//#include "bsp.h"
#include "nrf_drv_clock.h"
#include "nrf_delay.h"
#include "nrf_log.h"


#define OUTPUT_PIN_1 30
#define OUTPUT_PIN_2 28
#define OUTPUT_PIN_3 25

static nrf_drv_pwm_t m_pwm0 = NRF_DRV_PWM_INSTANCE(0);

// Declare variables holding PWM sequence values. In this example only one channel is used 
nrf_pwm_values_individual_t seq_values[] = {0, 0, 0, 0};
nrf_pwm_sequence_t const seq =
{
    .values.p_individual = seq_values,
    .length          = NRF_PWM_VALUES_LENGTH(seq_values),
    .repeats         = 0,
    .end_delay       = 0
};


static void pwm_init(void)
{
    nrf_drv_pwm_config_t const config0 =
    {
        .output_pins =
        {
            OUTPUT_PIN_1,               // channel 0
            OUTPUT_PIN_2,               // channel 1
            OUTPUT_PIN_3,               // channel 2
            NRF_DRV_PWM_PIN_NOT_USED,                              // channel 3
        },
        .irq_priority = APP_IRQ_PRIORITY_LOWEST,
        .base_clock   = NRF_PWM_CLK_1MHz,
        .count_mode   = NRF_PWM_MODE_UP,
        .top_value    = 100,
        .load_mode    = NRF_PWM_LOAD_INDIVIDUAL,
        .step_mode    = NRF_PWM_STEP_AUTO
    };
    // Init PWM without error handler
    APP_ERROR_CHECK(nrf_drv_pwm_init(&m_pwm0, &config0, NULL));
    
}


void rgb_outputs_init(void)
{
//    // Start clock for accurate frequencies
//    NRF_CLOCK->TASKS_HFCLKSTART = 1; 
//    // Wait for clock to start
//    while(NRF_CLOCK->EVENTS_HFCLKSTARTED == 0);
    
    pwm_init();

    seq_values->channel_0 = 0;
    seq_values->channel_1 = 50;
    seq_values->channel_2 = 0;
    nrf_drv_pwm_simple_playback(&m_pwm0, &seq, 1, NRF_DRV_PWM_FLAG_LOOP);

    NRF_LOG_INFO("PWM Initialized...");
}

Parents
  • Hello,

    Just so I understand you correctly, the change you are expecting is between the sec_values 0 and 50?

    If I read your code correctly, you set one channel to 0, the second channel to 50 (50%) and the last one to 0, and then you start the pwm, so I would expect this to not change any cycles.

    Channel 0 will be continuously off (or on, depending on the polarity), channel 1 will be at 50%, and channel 2 will be the same as channel 0. 

    Are you saying that channel 1 is not at 50%? 

    I see that you commented out NRF_CLOCK->TASKS_HFCLKSTART = 1. Do you start the HFCLK from somewhere else, or may the problem be that the clock is not running? Because if so, the PWM will not work.

    Best regards,

    Edvin

  • Hello, thanks for reply.

    If I set seq_values->channel_X = 0, it completely turns off the LED which is expected.

    If I set seq_values->channel_X = 100, it turns on the LED to fullest which is also expected. 

    But any value in between does not effect the intensity of LED. I have tried several values from 10, 20, ...90. Every time the intensity is maximum except for 0.

    I tried both commenting and un-commentating NRF_CLOCK->TASKS_HFCLKSTART = 1, with same result.

    Thanks.

Reply
  • Hello, thanks for reply.

    If I set seq_values->channel_X = 0, it completely turns off the LED which is expected.

    If I set seq_values->channel_X = 100, it turns on the LED to fullest which is also expected. 

    But any value in between does not effect the intensity of LED. I have tried several values from 10, 20, ...90. Every time the intensity is maximum except for 0.

    I tried both commenting and un-commentating NRF_CLOCK->TASKS_HFCLKSTART = 1, with same result.

    Thanks.

Children
  • Does the unmodified pwm_driver example work on your board? Is there any way for me to reproduce what you are seeing? Do you have an nRF52832, nRF52833, or nRF52840 DK to test on? Have you tried to debug to check the return value for nrf_drv_pwm_simple_playback()? What does it return?

    What happens if you try to run e.g. demo5() from the pwm_driver example. Does it behave properly? You can reduce the number of channels used by one if you only want to test with only 3.

    BR,
    Edvin

  • Finally this code worked:

    #include <stdio.h>
    #include <string.h>
    #include "nrf_drv_pwm.h"
    #include "app_util_platform.h"
    #include "app_error.h"
    #include "boards.h"
    //#include "bsp.h"
    #include "nrf_drv_clock.h"
    #include "nrf_delay.h"
    #include "nrf_log.h"
    
    
    #define OUTPUT_PIN_1 30
    #define OUTPUT_PIN_2 28
    #define OUTPUT_PIN_3 25
    
    
    
    uint8_t RGB_val_R=50;
    uint8_t RGB_val_G=50;
    uint8_t RGB_val_B=1;
    
    
    static nrf_drv_pwm_t m_pwm0 = NRF_DRV_PWM_INSTANCE(0);
    
    // Declare variables holding PWM sequence values. In this example only one channel is used 
    nrf_pwm_values_individual_t seq_values[] = {0, 0, 0, 0};
    nrf_pwm_sequence_t const seq =
    {
        .values.p_individual = seq_values,
        .length          = NRF_PWM_VALUES_LENGTH(seq_values),
        .repeats         = 0,
        .end_delay       = 0
    };
    
    
    static void pwm_init(void)
    {
        nrf_drv_pwm_config_t const config0 =
        {
            .output_pins =
            {
                OUTPUT_PIN_1 | NRF_DRV_PWM_PIN_INVERTED,               // channel 0
                //NRF_DRV_PWM_PIN_NOT_USED,
                OUTPUT_PIN_2 | NRF_DRV_PWM_PIN_INVERTED,               // channel 1
                //NRF_DRV_PWM_PIN_NOT_USED,
                OUTPUT_PIN_3 | NRF_DRV_PWM_PIN_INVERTED,               // channel 2
                NRF_DRV_PWM_PIN_NOT_USED,                              // channel 3
            },
            .irq_priority = APP_IRQ_PRIORITY_LOWEST,
            .base_clock   = NRF_PWM_CLK_1MHz,
            .count_mode   = NRF_PWM_MODE_UP,
            .top_value    = 100,
            .load_mode    = NRF_PWM_LOAD_INDIVIDUAL,
            .step_mode    = NRF_PWM_STEP_AUTO
        };
        // Init PWM without error handler
        APP_ERROR_CHECK(nrf_drv_pwm_init(&m_pwm0, &config0, NULL));
        
    }
    
    
    void rgb_outputs_init(void)
    {
        // Start clock for accurate frequencies
        NRF_CLOCK->TASKS_HFCLKSTART = 1; 
        // Wait for clock to start
        while(NRF_CLOCK->EVENTS_HFCLKSTARTED == 0);
        
        pwm_init();
        rgb_outputs_set(255, 0, 0);
        NRF_LOG_INFO("PWM Initialized...");
    }
    
    void rgb_outputs_set(uint16_t R, uint16_t G, uint16_t B){
    
        seq_values->channel_0 = 100 - (R*100)/255;
        seq_values->channel_1 = 100 - (G*100)/255;
        seq_values->channel_2 = 100 - (B*100)/255;
        nrf_drv_pwm_simple_playback(&m_pwm0, &seq, 1, NRF_DRV_PWM_FLAG_LOOP);
    }

Related