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

Precise angle control of Servo motor using PWM

I have included PWM library in BLE uart example to control the servo motor. I am able to import the library successfully and able to control the servo. Below is my init_pwm function

void init_pwm(void)
{
		ret_code_t err_code;
    app_pwm_config_t pwm1_cfg = APP_PWM_DEFAULT_CONFIG_1CH(20000L, SERVO);

    pwm1_cfg.pin_polarity[0] = APP_PWM_POLARITY_ACTIVE_HIGH;

    /* Initialize and enable PWM. */
    err_code = app_pwm_init(&PWM1,&pwm1_cfg,NULL);
    APP_ERROR_CHECK(err_code);
    app_pwm_enable(&PWM1);
	
		
		while (app_pwm_channel_duty_set(&PWM1, 0, 7) == NRF_ERROR_BUSY);
		nrf_delay_ms(100);
		app_pwm_disable(&PWM1);
}

Total period for a PWM to control a servo motor should be 20ms. This is have set in the init_pwm function above. Now the problem is to control the angle of the motor the Pulse width should be from 1ms to 2 ms max which converts to duty cycle 5% to 10% and the function  app_pwm_channel_duty_set get input in uint16_t. So I only have the option to set the duty cycle to 5,6,7,8,9 & 10.  Each value corresponds to 36 degree movement for servo motor. This is no where near to Precise angle controlling of servo motor. I have tested different values in this function and figured out that it works with value from 3 to 13. 

Is there any way I can control the angle of the motor precisely in 1 degree step size? 

Hardware information: Custom board with NRF52832. 

Parents
  • Hi

    I wouldn't recommend using the app_pwm driver unless you are targetting the nRF51 series. The nRF51 lacked a proper PWM controller, and the app_pwm library was developed to mitigate this. 

    On the nRF52 series I recommend using the nrf_drv_pwm driver instead, which uses the PWM module in the device rather than relying on timers. 

    I made a small example some while back showing how to use the nrf_drv_pwm driver to set 4 outputs in a loop:

    6644.pwm_driver_simple.zip

    The resolution of the PWM in your case depends primarily on the clock speed, which is set to 1MHz in the example but can be configured up to 16MHz if needed. 

    If you keep the frequency at 1MHz and set the countertop value to 20000 you should have a total PWM interval of 20ms, and a total of 1000 values to choose from when adjusting the PWM length between 1ms and 2ms. 

    Best regards
    Torbjørn

  • Thanks for the code. With some modification the example you have given is working. However when I am trying to implement it in "ble_app_uart" example I am getting the following error. 

    ..\..\..\main.c(96): error:  #20: identifier "NRFX_PWM0_INST_IDX" is undefined

    I have enabled the following in the sdk_config.h

    here NRFX_PWM0_INST_IDX is disabled, however I have enabled it in the sdk_config.h (as shown in the picture above.)

    I am unable to figure out what is the problem. 

Reply
  • Thanks for the code. With some modification the example you have given is working. However when I am trying to implement it in "ble_app_uart" example I am getting the following error. 

    ..\..\..\main.c(96): error:  #20: identifier "NRFX_PWM0_INST_IDX" is undefined

    I have enabled the following in the sdk_config.h

    here NRFX_PWM0_INST_IDX is disabled, however I have enabled it in the sdk_config.h (as shown in the picture above.)

    I am unable to figure out what is the problem. 

Children
Related