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

nrf52832 cannot control a PWM(servo motor) via Bluetooth

I am using the Hackable kit which has nrf52832 to control a servo motor and read accelerometer(AXL335) readings through a iOS app. I am a novice when comes to embedded. I got the ios app ready to send an integer value to the kit. Right now i am using the ble_blinky example from SDK 15 to turn on/off some external LED's and a piezo buzzer. But when i try to run the PWM_Library integrated(basically copy pasted with the pin numbers changed) in the same project the servo motor doesn't run and the program crashes at run time. Can anyone help me to accomplish my goal?

The code i use for BLE is as below.

APP_PWM_INSTANCE(PWM1,1);                   // Create the instance "PWM1" using TIMER1.(For Servo Motor)

static volatile bool ready_flag;            // A flag indicating PWM status.(For Servo Motor)

void pwm_ready_callback(uint32_t pwm_id)    // PWM callback function. (For Servo Motor)
{
    ready_flag = true;
}

void servo_config()
{
    ret_code_t err_code;
   app_pwm_config_t pwm1_cfg = APP_PWM_DEFAULT_CONFIG_2CH(5000L, 2, 3);

    /* Switch the polarity of the second channel. */
    pwm1_cfg.pin_polarity[1] = APP_PWM_POLARITY_ACTIVE_HIGH;

    /* Initialize and enable PWM. */
    err_code = app_pwm_init(&PWM1, &pwm1_cfg, pwm_ready_callback);
    APP_ERROR_CHECK(err_code);
    app_pwm_enable(&PWM1);
    nrf_gpio_cfg_output(2);
    nrf_gpio_cfg_output(3);
}

void servo_start()
{

    uint32_t value = 0;
    int a = 0;
    while (true) {
      
      for (uint8_t i = 0; i < 40; ++i) {
        value = (i < 20) ? (i * 5) : (100 - (i - 20) * 5);

        ready_flag = false;
        /* Set the duty cycle - keep trying until PWM is ready... */
        while (app_pwm_channel_duty_set(&PWM1, 0, value) == NRF_ERROR_BUSY)
          ;

        /* ... or wait for callback. */
        while (!ready_flag)
          ;
        APP_ERROR_CHECK(app_pwm_channel_duty_set(&PWM1, 1, value));
        nrf_delay_ms(25);
      }
      a = a + 1;
      if (a == 20) {
        break;
      }
  }
}

void servo_stop()
{
    app_pwm_disable(&PWM1);
    nrf_gpio_pin_clear(2);
    nrf_gpio_pin_clear(3);
} 

/**@brief Function for handling write events to the LED characteristic.
 *
 * @param[in] p_lbs     Instance of LED Button Service to which the write applies.
 * @param[in] led_state Written/desired state of the LED.
 */
static void led_write_handler(uint16_t conn_handle, ble_lbs_t *p_lbs, uint8_t led_state) {
 
  switch (led_state) {
  case 0:
    //bsp_board_led_off(LEDBUTTON_LED);
    NRF_LOG_INFO("Received LED OFF!");
    for (int i = 25; i < 28; i++) {
      nrf_gpio_pin_clear(i);
    }
    break;
  case 1:
    //bsp_board_led_on(LEDBUTTON_LED);
    NRF_LOG_INFO("Received LED ON!");
    for (int i = 25; i < 28; i++) {
      nrf_gpio_pin_set(i);
    }
    break;
  case 2:
    //Buzzer On
    nrf_gpio_pin_set(4);
    break;
  case 3:
    //Buzzer Off
    nrf_gpio_pin_clear(4);
    break;
  case 4:
    //Servo Motor ON
    servo_start();
    break;
  case 5:
    //Servo Off
    servo_stop();
    break;
  default:
    break;
  }
}

int main(void)
{
    // Initialize.
    log_init();
    leds_init();
    timers_init();

    buttons_init();
    power_management_init();
    ble_stack_init();
    gap_params_init();
    gatt_init();
    services_init();
    advertising_init();
    conn_params_init();
    
    //servo_start();
    // Start execution.
    NRF_LOG_INFO("Blinky example started.");
    advertising_start();
    servo_config();
    
//    // Enter main loop.
    for (;;)
    {
        idle_state_handle();
    }
}
it is same as the ble Blinky with this function added. Also there were some sdk_config changes that were made to compile this code like Enabling NRFX_TIMER = 1.

I am using SEGGER to program and compile the code, and push it to the device using ARM GCC GDB. 

Parents
  • Hello,

    When you say that "the program crashes at run time", can you please explain what happens?

    I assume that it is one of the calls for APP_ERROR_CHECK(err_code) that receives an err_code != 0 (NRF_SUCCESS). Have you checked your log? I am not familiar with the hackable kit, but you can either enable the UART logging backend, or the RTT logging backend. I assume that you program the kit via SWDIO pin. This means that you can use the RTT backend, which will send the logging information via this pin. You can view the log in JLINK RTT Viewer.

    You can also enable the UART log backend, and use one of the pins as the UART TX pin. All of these settings are set in sdk_config.h.

     

    Alternatively, you can debug to find out which call that returned the err_code != 0. add the define DEBUG in your preprocessor defines (and you probably need to turn off optimization as well. Set it to -O0). Then set a breakpoint on line 91 in app_error_weak.c. this is where the error is sent to the log, so you can see here what id, the file name and line code where the error occured.

     

    Best regards,

    Edvin

  • Thanks for your time. Sorry if my texts "the program crashes at run time" were misleading. What i meant is, the ble_blinky has a flow that if it is not connected or disconnected from the device(iOS app) the red LED would light up and the BLE would advertise again. But after Running PWM, even if i disconnect from my iOS app the BLE won't advertise and no red LED. Also after the sending the command (case 4 and 5) for the PWM,  the commands for the external LEDs(case 0 and 1) and buzzer(case 2 and 3) doesn't toggles them.I have to reset the kit with the reset button on the kit to start the program from the beginning. 

    But thanks for the debugging tip. I will try them and reply to you.

  • Ok. So it sounds like the application is stopping somewhere. Try out the debugging tip ,or RTT log, because if you are able to program the chip, then it uses the same wires for the RTT log. Just define RTT_LOG_BACKEND_ENABLE 1 and NRF_LOG_ENABLE 1 in SDK config, open JLINK RTT Viewer and run the application.

    The log module in SDK15 should print all relevant debug info.

     

    Best regards,

    Edvin

  • Sorry for the delayed information I don't own a J-Link device. I use Bumpy  to load my code. Also for all the ble examples i have to merge the s132_softdevice.hex and the app.hex files using the nRF5x-command-line-tools mergehex command and then load this merged hex file. The problem is this merged hex file does not contain any debug symbols so i cannot debug it at the runtime and also no log comes to the GDB console. Hence i am stuck in this debugging. So could you please point me if i am missing anything or any alternative.

Reply
  • Sorry for the delayed information I don't own a J-Link device. I use Bumpy  to load my code. Also for all the ble examples i have to merge the s132_softdevice.hex and the app.hex files using the nRF5x-command-line-tools mergehex command and then load this merged hex file. The problem is this merged hex file does not contain any debug symbols so i cannot debug it at the runtime and also no log comes to the GDB console. Hence i am stuck in this debugging. So could you please point me if i am missing anything or any alternative.

Children
  • Ok. I understand. Then I suggest that you try to get some logging information via UART, since RTT is not available, and debugging is not an option.

     

    Actually, this makes it a bit hard to develop software on your device. Do you have access to any of the nRF DKs? Either nRF51DK or nRF52DK? If not, then you have to get the logging information from the UART, but you would need an external UART->USB device. Try to google "uart to usb".

     

    If you don't have any of these, I guess you can try to toggle a led after every before APP_ERROR_CHECK(err_code) if err_code != 0 (NRF_SUCCESS)

    But you would also have to stop your device after these, because an APP_ERROR_CHECK(err_code) with an err_code != 0 will reset the device. So maybe you can go into some infinite loop, instead of APP_ERROR_CHECK().

    You will have to do this once for every APP_ERROR_CHECK() you want to check. Change the code, compile, upload and see.

     

    I am sorry. It is a bit hard to do app development if you can't see what is actually going on in the software.

     

    Best regards,

    Edvin

  • Thanks for your tip buddy. I will try out the UART logging as you suggest. If it isn't working then i have to do it with the leds. I will try it out and let you know. Again thanks a lot. It is a drag to not own a J-Link or any of nordics DK's.

Related