PWM sleep

Hi, I've noticed much higher than expected power usage and I've narrowed it down to PWM. I need to be able to turn off the PWMs when they're not needed.

I use all 4 PWMs (PWM0, PWM1, PWM2, PWM3)

I use this code to turn them off.

void nrf_pwm_stop()
{
   	NRF_PWM0->TASKS_STOP = 1 << PWM_TASKS_STOP_TASKS_STOP_Pos;
    NRF_PWM1->TASKS_STOP = 1 << PWM_TASKS_STOP_TASKS_STOP_Pos;
    NRF_PWM2->TASKS_STOP = 1 << PWM_TASKS_STOP_TASKS_STOP_Pos;
    NRF_PWM3->TASKS_STOP = 1 << PWM_TASKS_STOP_TASKS_STOP_Pos;

	do
    {

    } while (
        (!NRF_PWM0->EVENTS_STOPPED) ||
        (!NRF_PWM1->EVENTS_STOPPED) ||
        (!NRF_PWM2->EVENTS_STOPPED) ||
        (!NRF_PWM3->EVENTS_STOPPED));


    NRF_PWM0->PSEL.OUT[0]=(PWM_PSEL_OUT_CONNECT_Disconnected<<PWM_PSEL_OUT_CONNECT_Pos);
	NRF_PWM0->PSEL.OUT[1]=(PWM_PSEL_OUT_CONNECT_Disconnected<<PWM_PSEL_OUT_CONNECT_Pos);
	NRF_PWM0->PSEL.OUT[2]=(PWM_PSEL_OUT_CONNECT_Disconnected<<PWM_PSEL_OUT_CONNECT_Pos);
	NRF_PWM0->PSEL.OUT[3]=(PWM_PSEL_OUT_CONNECT_Disconnected<<PWM_PSEL_OUT_CONNECT_Pos);
	NRF_PWM0->ENABLE = (PWM_ENABLE_ENABLE_Disabled << PWM_ENABLE_ENABLE_Pos);

    NRF_PWM1->PSEL.OUT[0]=(PWM_PSEL_OUT_CONNECT_Disconnected<<PWM_PSEL_OUT_CONNECT_Pos);
	NRF_PWM1->PSEL.OUT[1]=(PWM_PSEL_OUT_CONNECT_Disconnected<<PWM_PSEL_OUT_CONNECT_Pos);
	NRF_PWM1->PSEL.OUT[2]=(PWM_PSEL_OUT_CONNECT_Disconnected<<PWM_PSEL_OUT_CONNECT_Pos);
	NRF_PWM1->PSEL.OUT[3]=(PWM_PSEL_OUT_CONNECT_Disconnected<<PWM_PSEL_OUT_CONNECT_Pos);
	NRF_PWM1->ENABLE = (PWM_ENABLE_ENABLE_Disabled << PWM_ENABLE_ENABLE_Pos);

    NRF_PWM2->PSEL.OUT[0]=(PWM_PSEL_OUT_CONNECT_Disconnected<<PWM_PSEL_OUT_CONNECT_Pos);
    NRF_PWM2->PSEL.OUT[1]=(PWM_PSEL_OUT_CONNECT_Disconnected<<PWM_PSEL_OUT_CONNECT_Pos);
    NRF_PWM2->PSEL.OUT[2]=(PWM_PSEL_OUT_CONNECT_Disconnected<<PWM_PSEL_OUT_CONNECT_Pos);
    NRF_PWM2->PSEL.OUT[3]=(PWM_PSEL_OUT_CONNECT_Disconnected<<PWM_PSEL_OUT_CONNECT_Pos);
    NRF_PWM2->ENABLE = (PWM_ENABLE_ENABLE_Disabled << PWM_ENABLE_ENABLE_Pos);

    NRF_PWM3->PSEL.OUT[0]=(PWM_PSEL_OUT_CONNECT_Disconnected<<PWM_PSEL_OUT_CONNECT_Pos);
    NRF_PWM3->PSEL.OUT[1]=(PWM_PSEL_OUT_CONNECT_Disconnected<<PWM_PSEL_OUT_CONNECT_Pos);
    NRF_PWM3->PSEL.OUT[2]=(PWM_PSEL_OUT_CONNECT_Disconnected<<PWM_PSEL_OUT_CONNECT_Pos);
    NRF_PWM3->PSEL.OUT[3]=(PWM_PSEL_OUT_CONNECT_Disconnected<<PWM_PSEL_OUT_CONNECT_Pos);
    NRF_PWM3->ENABLE = (PWM_ENABLE_ENABLE_Disabled << PWM_ENABLE_ENABLE_Pos);


}

Here is my test main loop

void main()
{
	int ret;

	if (!device_is_ready(button0.port))					return false;
	if (!device_is_ready(button1.port))					return false;
	if (!device_is_ready(button2.port))					return false;
	if (!device_is_ready(button3.port))					return false;

	ret = gpio_pin_configure_dt(&button0, GPIO_INPUT);
	ret = gpio_pin_configure_dt(&button1, GPIO_INPUT);
	ret = gpio_pin_configure_dt(&button2, GPIO_INPUT);
	ret = gpio_pin_configure_dt(&button3, GPIO_INPUT);

	do
	{
		k_msleep(10000);
		nrf_pwm_start();
		nrf_pwm_stop();

	} 
	while (true);

}

I've noticed an unexpected power draw 2 seconds after turning PWM off. My guess is that this is caused by the sequences ending because each takes 1 second.

Here is the power profiler output. As you can see I get 4uA current during k_msleep and then 2 seconds after nrf_pwm_stop() I see 3mA current draw. So it seems that my code to stop the PWM is wrong somehow.

Any help is greatly appreciated because I don't know what might be wrong with this.

Parents
  • Ok, I am not sure what I changed, but this is now working as expected! Very strange.

    I changed my pwm_init to use 

        NRF_PWM0->ENABLE = (PWM_ENABLE_ENABLE_Disabled << PWM_ENABLE_ENABLE_Pos);
        NRF_PWM1->ENABLE = (PWM_ENABLE_ENABLE_Disabled << PWM_ENABLE_ENABLE_Pos);
        NRF_PWM2->ENABLE = (PWM_ENABLE_ENABLE_Disabled << PWM_ENABLE_ENABLE_Pos);
        NRF_PWM3->ENABLE = (PWM_ENABLE_ENABLE_Disabled << PWM_ENABLE_ENABLE_Pos);
    prior to setting up PWM0, PWM1, PWM2 and PWM3.
    and then after they're set up, I use this code to start them.
        NRF_PWM0->ENABLE = (PWM_ENABLE_ENABLE_Enabled << PWM_ENABLE_ENABLE_Pos);
        NRF_PWM1->ENABLE = (PWM_ENABLE_ENABLE_Enabled << PWM_ENABLE_ENABLE_Pos);
        NRF_PWM2->ENABLE = (PWM_ENABLE_ENABLE_Enabled << PWM_ENABLE_ENABLE_Pos);
        NRF_PWM3->ENABLE = (PWM_ENABLE_ENABLE_Enabled << PWM_ENABLE_ENABLE_Pos);
    
    
        NRF_PWM0->TASKS_SEQSTART[0] = PWM_TASKS_SEQSTART_TASKS_SEQSTART_Trigger << PWM_TASKS_SEQSTART_TASKS_SEQSTART_Pos;
        NRF_PWM1->TASKS_SEQSTART[0] = PWM_TASKS_SEQSTART_TASKS_SEQSTART_Trigger << PWM_TASKS_SEQSTART_TASKS_SEQSTART_Pos;
        NRF_PWM2->TASKS_SEQSTART[0] = PWM_TASKS_SEQSTART_TASKS_SEQSTART_Trigger << PWM_TASKS_SEQSTART_TASKS_SEQSTART_Pos;
        NRF_PWM3->TASKS_SEQSTART[0] = PWM_TASKS_SEQSTART_TASKS_SEQSTART_Trigger << PWM_TASKS_SEQSTART_TASKS_SEQSTART_Pos;
    
    I then use the code I posted earlier to stop them again, and I get back to 3uA sleep current. 
    I've had intermittent problems flashing boards in NCS, it appears to upload the new firmware, but then the changes aren't present.
    And if I run it with the debugger then it fixes it. I'm not sure why there would be a difference. Maybe a different flash procedure.
    I also find that if I use the debugger then sometimes later I can't reset my board. The only way to continue is to use the debugger, or use "recover board" to get it back.

    Maybe this happened earlier. I'm not sure.

    But anyway, RIGHT NOW, it's working Slight smile

    Glaedlig Jul!

Reply
  • Ok, I am not sure what I changed, but this is now working as expected! Very strange.

    I changed my pwm_init to use 

        NRF_PWM0->ENABLE = (PWM_ENABLE_ENABLE_Disabled << PWM_ENABLE_ENABLE_Pos);
        NRF_PWM1->ENABLE = (PWM_ENABLE_ENABLE_Disabled << PWM_ENABLE_ENABLE_Pos);
        NRF_PWM2->ENABLE = (PWM_ENABLE_ENABLE_Disabled << PWM_ENABLE_ENABLE_Pos);
        NRF_PWM3->ENABLE = (PWM_ENABLE_ENABLE_Disabled << PWM_ENABLE_ENABLE_Pos);
    prior to setting up PWM0, PWM1, PWM2 and PWM3.
    and then after they're set up, I use this code to start them.
        NRF_PWM0->ENABLE = (PWM_ENABLE_ENABLE_Enabled << PWM_ENABLE_ENABLE_Pos);
        NRF_PWM1->ENABLE = (PWM_ENABLE_ENABLE_Enabled << PWM_ENABLE_ENABLE_Pos);
        NRF_PWM2->ENABLE = (PWM_ENABLE_ENABLE_Enabled << PWM_ENABLE_ENABLE_Pos);
        NRF_PWM3->ENABLE = (PWM_ENABLE_ENABLE_Enabled << PWM_ENABLE_ENABLE_Pos);
    
    
        NRF_PWM0->TASKS_SEQSTART[0] = PWM_TASKS_SEQSTART_TASKS_SEQSTART_Trigger << PWM_TASKS_SEQSTART_TASKS_SEQSTART_Pos;
        NRF_PWM1->TASKS_SEQSTART[0] = PWM_TASKS_SEQSTART_TASKS_SEQSTART_Trigger << PWM_TASKS_SEQSTART_TASKS_SEQSTART_Pos;
        NRF_PWM2->TASKS_SEQSTART[0] = PWM_TASKS_SEQSTART_TASKS_SEQSTART_Trigger << PWM_TASKS_SEQSTART_TASKS_SEQSTART_Pos;
        NRF_PWM3->TASKS_SEQSTART[0] = PWM_TASKS_SEQSTART_TASKS_SEQSTART_Trigger << PWM_TASKS_SEQSTART_TASKS_SEQSTART_Pos;
    
    I then use the code I posted earlier to stop them again, and I get back to 3uA sleep current. 
    I've had intermittent problems flashing boards in NCS, it appears to upload the new firmware, but then the changes aren't present.
    And if I run it with the debugger then it fixes it. I'm not sure why there would be a difference. Maybe a different flash procedure.
    I also find that if I use the debugger then sometimes later I can't reset my board. The only way to continue is to use the debugger, or use "recover board" to get it back.

    Maybe this happened earlier. I'm not sure.

    But anyway, RIGHT NOW, it's working Slight smile

    Glaedlig Jul!

Children
No Data
Related