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

The PWM pluse width flutter on NRF52

    I want to drive a servo by the PWM on nrf52832. The pwm cycle is 20ms and the duty is 1.5ms. But i have a problem that the duty is not precise when the BLE is working. I need a precise PWM with 1500us duty, but the duty will flutter randomly among 1500us-1520us when the BLE is working. This problem will make the servo flutter synchronously. 

    I have make a lot of experiment as below:

    1. I combine two projects in the SDK to generate the PWM when the BLE is working. One is examples\ble_peripheral\ble_app_template and the other is examples\peripheral\pwm_driver. The PWM is generated by the PWM modulation.  The problem can be captured easily by the oscilloscope.

    2. I try another way to generate the PWM in which pwm is generate by TIMER+PPI+GPIOE. I combine examples\peripheral\pwm_library to examples\ble_peripheral\ble_app_template. And the problem is the same. 

    3. I try SDK11 and SDK15. The problem is the same.

    4. If I the BLE is not working, the pwm is very precisely without any flutter. 

    5. If I using the RADIO to receive 2.4G data(not using the BLE), the pwm is very precisely without any flutter.

    6. I have modify different pins to output the PWM. Each pins have the same problem.

    6. I have tested the problem on two NRF52-DK pca10040 evaluation board and 10 boards I designed. The pwm will flutter on all of them, BUT the amplitude of the flutter is different. On the NRF52-DK boards the amplitude is about 10us. On the boards I designed the amplitude is different, some is about 10us, some is about 15us, and the worst is about 20us.

    7. I have tried to write a uart programme to send a data which will make a waveform near the pwm i want. I find that the waveform will flutter a little the same as PWM.

    So I think the problem is not only in the PWM. I guess the problem is related to the clk of the chip, it seems that the chip miss a little clk randomly when BLE is working so that the duty of the PWM will longer than I set.

    How can I get a precise PWM when the BLE is working?

     

I using the PWM code as below, after I init the PWM I never the duty of the PWM.

#define PIN_PWM_SERVO				3
#define SERVO_PERIOD				(1000000 / 50)
static nrf_drv_pwm_t m_pwm0 = NRF_DRV_PWM_INSTANCE(0);
nrf_pwm_values_individual_t m_demo1_seq_values;
uint16_t ServoValue = 1500;
static uint8_t m_used = 0;
#define USED_PWM(idx) (1UL << idx)
static nrf_pwm_sequence_t const    m_demo1_seq =
{
    .values.p_individual = &m_demo1_seq_values,
    .length              = 1, 
    .repeats             = 0,
    .end_delay           = 0
};

void PwmInit()
{
	nrf_drv_pwm_config_t const config0 =
    {
        .output_pins =
        {
            PIN_PWM_SERVO,//BSP_LED_0 | NRF_DRV_PWM_PIN_INVERTED, // channel 0
            NRF_DRV_PWM_PIN_NOT_USED, //BSP_LED_1 | NRF_DRV_PWM_PIN_INVERTED, // channel 1
            NRF_DRV_PWM_PIN_NOT_USED, //BSP_LED_3 | NRF_DRV_PWM_PIN_INVERTED, // channel 2
            NRF_DRV_PWM_PIN_NOT_USED, //BSP_LED_2 | NRF_DRV_PWM_PIN_INVERTED  // channel 3
        },
        .irq_priority = APP_IRQ_PRIORITY_LOWEST,
        .base_clock   = NRF_PWM_CLK_1MHz,
        .count_mode   = NRF_PWM_MODE_UP,
        .top_value    = SERVO_PERIOD,
        .load_mode    = NRF_PWM_LOAD_COMMON,
        .step_mode    = NRF_PWM_STEP_AUTO
    };
    APP_ERROR_CHECK(nrf_drv_pwm_init(&m_pwm0, &config0, NULL));
    m_used |= USED_PWM(0);

    m_demo1_seq_values.channel_0 = 0;
    m_demo1_seq_values.channel_1 = 0;
    m_demo1_seq_values.channel_2 = 0;
    m_demo1_seq_values.channel_3 = 0;

    (void)nrf_drv_pwm_simple_playback(&m_pwm0, &m_demo1_seq, 1,
                                      NRF_DRV_PWM_FLAG_LOOP);
		
	m_demo1_seq_values.channel_0 = SERVO_PERIOD - ServoValue;
}

Related