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

sometimes PWM signal is reversed .

Hi Nordics!

I am using app_pwm.c file in SDK 8.1, and when I use it with softdevice(advertising or data transfer event), sometimes pwm signal is reversed.

I guess, reversed signal's reason is the BLE interrupt. Because this problem is not occurred, when I don't use softdevice ( advertising or data transfer event)

And I need your advice for overcome this problem.

These are my development environment.


SDK 8.1

SD 8.0

nRF51822 AA G0

custom board

Timer1- 2channels

Timer2-1 channel.

3 PWM channels - Red led, Green led, Blue led.


first, I used app_pwm library. (100Hz )

/* */

static void pwm_init(void)

{

    ret_code_t err_code;
    
    /* 2-channel PWM, 100Hz, output on LED pins. */
    app_pwm_config_t pwm1_cfg = APP_PWM_DEFAULT_CONFIG_2CH(10000L, GPIO_LED_RED, GPIO_LED_GREEN);
    app_pwm_config_t pwm2_cfg = APP_PWM_DEFAULT_CONFIG_1CH(10000L, GPIO_LED_BLUE);
    
    /* Set the polarity of the channel. */
    pwm1_cfg.pin_polarity[0] = APP_PWM_POLARITY_ACTIVE_HIGH;
    pwm1_cfg.pin_polarity[1] = APP_PWM_POLARITY_ACTIVE_HIGH;
    pwm2_cfg.pin_polarity[0] = APP_PWM_POLARITY_ACTIVE_HIGH;
        
    /* Initialize and enable PWM. */
    err_code = app_pwm_init(&PWM1,&pwm1_cfg,pwm_1_ready_callback);
    APP_ERROR_CHECK(err_code);
    err_code = app_pwm_init(&PWM2,&pwm2_cfg,pwm_2_ready_callback);
    APP_ERROR_CHECK(err_code);
    
    app_pwm_enable(&PWM1);
    app_pwm_enable(&PWM2);
}



void pwm_1_ready_callback(uint32_t pwm_id)   

{
    pwm_1_ready_flag = true;
}

void pwm_2_ready_callback(uint32_t pwm_id)   
{
    pwm_2_ready_flag = true;
}





second, I set the pwm chanel duty by using below code. 

(in this function, I didn't wait callback. I just keep trying until PWM is ready)

static void color_setting(uint8_t red, uint8_t green, uint8_t blue)
{
    
    color_red=red;
    color_green=green;
    color_blue=blue;
    
    pwm_1_ready_flag = false;
    pwm_2_ready_flag = false;
    
    /* Set the duty cycle - keep trying until PWM is ready... */    
    while (app_pwm_channel_duty_set(&PWM1, 0, (uint32_t)(sin_table[color_red]/2.55)) == NRF_ERROR_BUSY);
    while (app_pwm_channel_duty_set(&PWM1, 1, (uint32_t)(sin_table[color_green]/2.55)) == NRF_ERROR_BUSY);
    while (app_pwm_channel_duty_set(&PWM2, 0, (uint32_t)(sin_table[color_blue]/2.55)) == NRF_ERROR_BUSY);

    /* ... or wait for callback. */
   //    while(!pwm_1_ready_flag);


}

sin_table's value is from 0 to 255. so I divided it by 2.55

And this color_setting function is called in app_timer call_back function.

my app timer's interval is 40ms.

In other words, PWM values is changed in every 40ms, and it repeat 0~100 value.

This "PWM signal reversed" issue is not appeared, when I don't use softDevice.

Is there any idea for avoiding this problem??

This problem is critical issue on my project.

Please help me.

Thanks.

  • @plskeggs For SDK 7 + S110 7, there is also the PWM library on Nordic's Github, the nrf_pwm.c. I believe it has proven itself to be fairly reliable since the update in November 2014.

    Limitations: Maximum 4 PWM with softdevice. Maximum 62.5 KHz PWM frequency. Maximum duty cycle update frequency is somewhat lower, perhaps a few kHz, so it is really not suitable for motor control, but should be fine for LEDs. Some more info on this thread and this thread.

  • @stefanbirnir, I did not have good success with the nrf_pwm library, that's why I went this direction. The nrf_pwm library was stable for low frequencies (e.g., 480Hz), but had terrible inversion problems at 16KHz. I have been partially successful at merging the drv_timer + drv_ppi + drv_gpiote with SDK 6.1 and have gotten 2 channels working using the app_pwm library. However, it is quite PPI-hungry, and so I have been unable to get it to work with the SD110 v7 active (which uses 8 of the 16 PPIs) while using more than 2 channels.

  • @plseggs Thank you for your feedback on the pwm_libarary. I assume that you evaluated the pwm_library after the november 2014 update? Are you using the second revision nRF51 hardware or the third revision? When you tried the 16kHz pwm frequency, what was the frequency of the pwm duty cycle updates?

  • @stefanbirnir, yes, I kept up with changes to nrf_pwm. I've tested with both the second and third revisions, though I should probably retest 16KHz on the third just in case I missed that. We use the PWM for motor control with a PID feedback loop; we measure the back-EMF voltage of the motor at 100 Hz by switching off PWM for 2 ms then reading the motor voltage using the ADC. We then switch PWM back on and potentially change the duty cycle based on the PID calculations. I understand this is a rather demanding use case for the PWM library, but running this same code on an Atmel ATMEGA328p never had this issue.

  • @plskeggs Ok, this sounds a bit demanding task for the CPU of the nRF51. nRF51 third revision + SDK 7 + S110 7 is no better than nRF51 second revision unless you unblock the CPU. It is blocked by default in SDK 7. The guide to unblock it is here. With the CPU unblocked, the CPU stands a better chance of performing your task.

    My advise for future products is to migrate to nRF52, with Cortex M4 CPU (~5x CPU power) and dedicated PWM hardware.

Related