Trying to use nrfx_pwm_simple_playback to run an RGB Led continuously for different modes.

Hello, 

With respect to my previous post, I am trying to use the nrfx_pwm_simple_playback function to run sequences continuously for an RGB led. 
Initially I did not fully understand the nrfx_pwm library. 

Objective is to run the RGB led for specific durations. [Due to project requirements, I cannot use/implement the timer based method using sw_pwm, and so I need to use the nrfx_pwm method]

Prior Post:
Trying to use nrfx simple playback command to run RGB LED for specific duration on nrf5340 board

Based on my understanding of the header file, I have made some further changes to the code. 

#include <hal/nrf_gpio.h>
LOG_MODULE_REGISTER(LED_PWM, LOG_LEVEL_DBG); // Register a module for your logs

// Definitions for the LED PINS
#define GREEN_LED_PIN   (NRF_GPIO_PIN_MAP(1, 13)) // This is the pin number for the green LED
#define BLUE_LED_PIN   (NRF_GPIO_PIN_MAP(1, 14))
#define RED_LED_PIN    (NRF_GPIO_PIN_MAP(1, 15))

#include "nrfx_pwm.h"

#define TIME_DELAY_50MS          9 
#define TIME_DELAY_100MS        20
#define TIME_DELAY_150MS        30
#define TIME_DELAY_1950MS      400

#define PWM_TOP_5MS             5000
#define PWM_TOP_2_5MS           2500


#define DUTY_CYCLE_100          0x8000
#define DUTY_CYCLE_YELLOW       0x200
#define DUTY_CYCLE_0            0x00

#define PWM_STEP                4000
#define PWM_COMMON              0x02
#define USED_PWM(idx) (1UL << idx)
static uint8_t m_used = 0;

#define MAX_LED_NUMBER 1

uint8_t previousLEDState = PWM_COMMON;

// Definition for a single pwm driver instance using a Macro for creating a PWM driver instance.
static nrfx_pwm_t m_pwm0 = NRFX_PWM_INSTANCE(0);

static uint16_t const              m_pwm_top      = PWM_TOP_5MS;
static uint16_t const              m_pwm_top_idle = PWM_TOP_2_5MS;
static uint16_t const              m_pwm_step     = PWM_STEP;
static uint8_t                     m_pwm_phase;

static nrf_pwm_values_individual_t m_pwm_seq_values;
static nrf_pwm_sequence_t const    m_pwm_seq =
{
    .values.p_individual = &m_pwm_seq_values,
    .length              = NRF_PWM_VALUES_LENGTH(m_pwm_seq_values),
    .repeats             = 0,
    .end_delay           = 0
};

//Configuration for the idle mode. 
nrfx_pwm_config_t config_pwm_idle =
{
    .output_pins =
        {
            GREEN_LED_PIN, RED_LED_PIN, NRF_PWM_PIN_NOT_CONNECTED
        },
    .irq_priority = NRFX_PWM_DEFAULT_CONFIG_IRQ_PRIORITY,
    .base_clock   = NRF_PWM_CLK_1MHz,
    .count_mode   = NRF_PWM_MODE_UP,
    .top_value    = m_pwm_top_idle, //2500 ticks. 
    .load_mode    = NRF_PWM_LOAD_INDIVIDUAL,
    .step_mode    = NRF_PWM_STEP_AUTO
};

//Function for uninitializing the pwm driver. 
void UninitPWM( void )
{
    if (m_used & USED_PWM(0))
    {
        nrfx_pwm_uninit(&m_pwm0);
    }
    m_used = 0;
}

uint8_t channel    = 0;
uint16_t * p_channels = (uint16_t *)&m_pwm_seq_values;

// Handler Function for the idle mode 
static void ledPwm_handler_idle(nrfx_pwm_evt_type_t event_type)
{
    if (event_type == NRFX_PWM_EVT_FINISHED)
    {
        uint8_t channel    = m_pwm_phase >> 1;
        bool    down       = m_pwm_phase & 1;
        bool    next_phase = false;
		static  uint16_t timer;

        uint16_t * p_channels = (uint16_t *)&m_pwm_seq_values;
        uint16_t value = p_channels[channel];
        if (down)
        {
            value -= m_pwm_step;
            if (value == 0)
            {
                next_phase = true;
            }
        }
        else
        {
            value += m_pwm_step;
            if (value >= m_pwm_top_idle)
            {
                next_phase = true;
            }
        }
       if(timer > 10)
        {

            p_channels[0] = 0;
            if(timer > 4000)
            {
                timer = 0;
            }
        }
        else
        {
            p_channels[0] = DUTY_CYCLE_100;
            
        }
        timer++;
        //p_channels[1]= 0;
        if (next_phase)
        {
            if (++m_pwm_phase >= 2 * NRF_PWM_CHANNEL_COUNT)
            {
                m_pwm_phase = 0;
            }
        }
    }
}

int32_t start_pwm()
{
    // UninitPWM();
    m_pwm_seq_values.channel_0 = 0;
    m_pwm_seq_values.channel_1 = 0;
    m_pwm_seq_values.channel_2 = 0;
    m_pwm_seq_values.channel_3 = 0;
    m_pwm_phase                = 0;
    nrfx_pwm_init(&m_pwm0, &config_pwm_idle, ledPwm_handler_idle, NULL);
	// Tried to increase the playback count below, but the sequence repeats only once. 
	// Tried to put the below statement in a loop but still the sequence executes only once. 
	// NRFX_PWM_FLAG_LOOP i understand that this means after a single sequence is played, it should repeat again but I dont see it. 
	// In the above configuration for idle mode, I have tried to use repeats field but still dont observe the sequence being played again
    nrfx_pwm_simple_playback(&m_pwm0, &m_pwm_seq, 2, NRFX_PWM_FLAG_LOOP);
    LOG_DBG("PWM playback completed");
}


Can you please provide some inputs on how I can achieve my objective? In case there is more detailed documentation +  examples for individual mode using nrfx_pwm, can you please share the link?

Thanks

Parents Reply Children
Related