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.

Parents
  • Update: This issue is fixed since SDK 10.

    This is fresh copy from our development repository: (This is obsolete. See the newest driver attached below) pwm.7z This fix is going to be presented in the nearest release. There are also some functions added to give the possibility to set PWM duty in cycles - it was something I needed for testing and probably it would be left in official API.

    The error is really subtle and quite hard to find - the order of some operations gives a possibility to break the synchronisation if interrupt occurs between them. This version was simulated whole night with simulated interrupting in random places and in the morning today no errors was found.

    Beside of that this is a real masterpiece of code and as I have told - the error was really subtle.


    Ok - it was a really crazy work. Yesterday I have detected that it is changing channel 1 that breaks channel 2, and additionally it was only after second change from 0 of 100% duty to another value. I mean - first change from 0 to 1... or from 100 to 99 and then second change to any value that is not 0 nor 100% and BAM - because of some event to interrupt race sometimes phase was switched.

    So god news everyone: hardware looks ok. Updated software preview here: pwm_20150708.7z

  • Yes, the 110 Softdevice. The connection interval is between 20 and 75 ms. My use case is a bit different possibly... I connect to a iOS device and stay connected for awhile. Then it might not connect for days, all the while the PWM is constantly changing. I am updating the duty now every 4ms, nearly constantly. My period is 64us, or 15.625kHz. I was having almost constant inversions if I would change the duty value by only one clock tick. I changed the code so that it would only update if it the new duty value was 2 ticks away and that is working fine, no issues that I have seen. I am using the updated PWM library included above, with one additional function that lets me set the duty from 0-512 because I need the resolution. I want to set it from 0-1024, but at my frequency I would need to set it at 1 clock tick intervals, and that isn't working. Hope that helps.

Reply
  • Yes, the 110 Softdevice. The connection interval is between 20 and 75 ms. My use case is a bit different possibly... I connect to a iOS device and stay connected for awhile. Then it might not connect for days, all the while the PWM is constantly changing. I am updating the duty now every 4ms, nearly constantly. My period is 64us, or 15.625kHz. I was having almost constant inversions if I would change the duty value by only one clock tick. I changed the code so that it would only update if it the new duty value was 2 ticks away and that is working fine, no issues that I have seen. I am using the updated PWM library included above, with one additional function that lets me set the duty from 0-512 because I need the resolution. I want to set it from 0-1024, but at my frequency I would need to set it at 1 clock tick intervals, and that isn't working. Hope that helps.

Children
No Data
Related