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

Flicker LEDs to indicate full brightness

I am working on a project and have successfully implemented single channel PWM to dim leds (using a transistor FET). The pwm init code is below:

uint32_t err_code;
nrf_drv_pwm_config_t const config0 =
{
    .output_pins =
    {
        outputLED, // channel 0
        NRF_DRV_PWM_PIN_NOT_USED, // channel 1
        NRF_DRV_PWM_PIN_NOT_USED, // channel 2
        NRF_DRV_PWM_PIN_NOT_USED  // channel 3
    },
    .irq_priority = APP_IRQ_PRIORITY_LOW,
    .base_clock   = NRF_PWM_CLK_1MHz,
    .count_mode   = NRF_PWM_MODE_UP,
    .top_value    = mode8,
    .load_mode    = NRF_PWM_LOAD_COMMON,
    .step_mode    = NRF_PWM_STEP_AUTO
};
err_code = nrf_drv_pwm_init(&m_pwm0, &config0, NULL);
APP_ERROR_CHECK(err_code);

I then increment the PWM value when a button is pressed (up or down depending on the button). That function [ void update_pwm(int16_t duty_cycle) ] is below:

m_seq_values = duty_cycle;
pwmValue = duty_cycle;
nrf_drv_pwm_simple_playback(&m_pwm0, &m_seq, 1, 0);

I would like to flicker the lights (go from full brightness down to a dimmer setting back and forth with a delay between the different PWM settings) for a second or 2 when they are full brightness as a form of feedback to let the user know that the lights will not brighten any more. I did it successfully with the following code:

for (int k = 1; k <= 10; k = k + 1) 
{
	m_seq_values = mode6;
	nrf_drv_pwm_simple_playback(&m_pwm0, &m_seq, 1, 0);
	nrf_delay_ms(25);
	m_seq_values = mode8;
	nrf_drv_pwm_simple_playback(&m_pwm0, &m_seq, 1, 0);
	nrf_delay_ms(25);		
}
  update_pwm(pwmValue);

The problem is, I am using a timer that is driving a 2 digit 7 segment display. During the delay functions, the display stops on 1 digit because of the delay. Is there a better way to easily make these lights flicker without using a delay?

  • Is the problem is that the timer interrupt is not able to interrupt the flicker code? Then one solution is to run the flicker code in a context with lower priority, or increase the priority of the timer interrupt. But if the timer interrupt is able to interrupt the flicker code it could affect the delay between the playbacks. Another solution would be to use a hardware timer instead of nrf_delay_ms(), then the timer interrupt could be handled inbetween.

  • For completeness, I ended up using a timer to call the flicker code below.

    if (myData.powerState == 1)
    {
    	if (flickerNumber <= 11 && flickerNumber !=0)
    		{
    		if (pwmValue[myData.pwmIndex] >= 50)
    			{
    			if (flickerNumber % 2)
    				{
    				app_pwm_channel_duty_set(&PWM1, 0, pwmValue[(sizeof pwmValue / sizeof *pwmValue - 1)]);
    				}
    			else
    				{
    				app_pwm_channel_duty_set(&PWM1, 0, 35);
    				}
    			++flickerNumber;
    			}
    		if (pwmValue[myData.pwmIndex] < 50)
    			{
    			if (flickerNumber % 2)
    				{
    				app_pwm_channel_duty_set(&PWM1, 0, 0);
    				}
    			else
    				{
    				app_pwm_channel_duty_set(&PWM1, 0, pwmValue[myData.pwmIndex]);
    				}
    			++flickerNumber;
    			}
    
    		}
    	if (flickerNumber >= 12)
    	{
    		flickerNumber = 0;
    		if (outputLedState == false)
    		{
    			switchLedsOff();
    		}
    		else if (outputLedState == true)
    		{
    			switchLedsOn();
    		}
    	}
    }
    
Related