NRF delay is running before it was call

Hi,

I'm trying to use a nrf delay to make a delay for a motor. The idea is to make the motor oscillated by putting it forward and then reverse via a delay. (you can find this logic at the line 124, the function "oscillate").

But when I want to run the code, I got an issue, the delay is running before the motor is going forward (line 128 with the 1st pwm active). I don't understand why...
The delay is defined via math's formula at the line 77. I tried to put it as a constant and here's the troubleshoot :

  • With the delay as 3000 ms, we clearly see the delay before the motor starts spinning forward.
  • With the delay as 100ms, we don't see it, but it's probably there but the human eye can not see it

So what I want to resolve in my code is that this angluation_delay is running before my motor starts spinning when I want first the motor to spin forward, and then the delay to active.

#define SAMPLES_IN_BUFFER               1                                       //Number of SAADC samples in RAM before returning a SAADC event. For low power SAADC set this constant to 1. Otherwise the EasyDMA will be enabled for an extended time which consumes high current.

#define MOTOR_FORWARD                   34
#define MOTOR_REVERSE                   35

#define MOTOR_MAX_RPM                   50000

static nrf_saadc_value_t m_buffer[SAMPLES_IN_BUFFER];
bool test;
uint16_t motor_angluar_max_speed = MOTOR_MAX_RPM*2*M_PI/60;
uint8_t pourcent_speed;
static nrf_drv_pwm_t m_pwm0 = NRF_DRV_PWM_INSTANCE(0);
int gLEDG = MOTOR_FORWARD;
static uint16_t const m_top  = 255;
static nrf_pwm_values_individual_t  seq_values;
static nrf_pwm_sequence_t const seq =
{
    .values.p_individual = &seq_values,
    .length              = NRF_PWM_VALUES_LENGTH(seq_values),
    .repeats             = 0,
    .end_delay           = 0
};
uint16_t speed;
uint8_t angulation = 90;
uint32_t angulation_delay;

void update_pwm(uint16_t duty_forward, uint16_t duty_reverse)
{
    seq_values.channel_0 = m_top-duty_forward;
    seq_values.channel_1 = m_top-duty_reverse;

    nrf_drv_pwm_simple_playback(&m_pwm0, &seq, 1,  NRF_DRV_PWM_FLAG_LOOP);
}

static void idle_state_handle(void)
{
    if (NRF_LOG_PROCESS() == false)
    {
        nrf_pwr_mgmt_run();
    }
}

uint32_t get_rtc_counter(void)
{
    return NRF_RTC2->COUNTER;
}

/**@brief Function for initializing the nrf log module.
 */
static void log_init(void)
{
    ret_code_t err_code = NRF_LOG_INIT(get_rtc_counter);
    APP_ERROR_CHECK(err_code);

    NRF_LOG_DEFAULT_BACKENDS_INIT();
}

void saadc_callback(nrf_drv_saadc_evt_t const * p_event)
{
    if (p_event->type == NRF_DRV_SAADC_EVT_DONE)
    {
        ret_code_t err_code;

        err_code = nrf_drv_saadc_buffer_convert(p_event->data.done.p_buffer, SAMPLES_IN_BUFFER);
        APP_ERROR_CHECK(err_code);
        
        if (p_event->data.done.p_buffer[0] <= 0){
          speed = 0;
        } else{
          speed = p_event->data.done.p_buffer[0];
        }
        //NRF_LOG_INFO("SPEED %d\r\n", speed);
        pourcent_speed = floor(speed*100/255);       
        //NRF_LOG_INFO("POURCENT %d", pourcent_speed);
        float angulation_rad = angulation * (M_PI / 180.0);
        float number = (angulation_rad/(motor_angluar_max_speed*pourcent_speed/100))*100000;
        angulation_delay = (uint32_t) floor(number);
        //NRF_LOG_INFO("DELAY %d\r\n", angulation_delay);
    }
}

void saadc_init(void)
{
    ret_code_t err_code;
    nrf_saadc_channel_config_t channel_config = NRF_DRV_SAADC_DEFAULT_CHANNEL_CONFIG_SE(NRF_SAADC_INPUT_AIN5);
    
    ////Configure SAADC
    nrf_drv_saadc_config_t saadc_config;                                                  
    saadc_config.resolution = NRF_SAADC_RESOLUTION_8BIT;  

    err_code = nrf_drv_saadc_init(&saadc_config, saadc_callback);
    APP_ERROR_CHECK(err_code);

    err_code = nrf_drv_saadc_channel_init(0, &channel_config);
    APP_ERROR_CHECK(err_code);

    err_code = nrf_drv_saadc_buffer_convert(m_buffer, SAMPLES_IN_BUFFER);
    APP_ERROR_CHECK(err_code);
}

static void pwm_init(void)
{
    uint32_t err_code;
    nrf_drv_pwm_config_t const config0 =
    {
        .output_pins =
        {
            MOTOR_FORWARD,            // channel 0
            MOTOR_REVERSE,            // channel 1
            NRF_DRV_PWM_PIN_NOT_USED, // channel 2
            NRF_DRV_PWM_PIN_NOT_USED  // channel 3
        },
        .irq_priority = APP_IRQ_PRIORITY_LOWEST,
        .base_clock   = NRF_PWM_CLK_16MHz,
        .count_mode   = NRF_PWM_MODE_UP,
        .top_value    = m_top,
        .load_mode    = NRF_PWM_LOAD_INDIVIDUAL,
        .step_mode    = NRF_PWM_STEP_AUTO
    };
    err_code = nrf_drv_pwm_init(&m_pwm0, &config0, NULL);
    APP_ERROR_CHECK(err_code);
}

static void oscillate(void)
{      
    if (pourcent_speed > 5)
    {
        update_pwm(speed, 0);
        nrf_delay_ms(angulation_delay);
        update_pwm(0, speed);
        nrf_delay_ms(angulation_delay);
    } else
    {
        update_pwm(0, 0);
    }
}

/**@brief Function for application main entry.
 */
int main(void)
{
    bool erase_bonds;
    ret_code_t err_code;

    // Initialize.
    log_init();
    saadc_init();
    pwm_init();
    NRF_LOG_INFO("START");
    
    for (;;)
    {   
        nrf_drv_saadc_sample();
        oscillate();
        idle_state_handle();
    }
}


/**
 * @}
 */

Thanks for your answers,

Chris

Parents
  • Hello Chris,

    'angulation_delay' should be defined as volatile since it's being updated from your interrupt callback. It will work fine if you build without code optimization, but with optimization enabled you may experience that the delay gets set to '0' at line 129 and 131 instead of the expected value computed in the SAADC callback.  Could this be the problem, or are you testing the code without code optimization?

    Best regards,

    Vidar

Reply
  • Hello Chris,

    'angulation_delay' should be defined as volatile since it's being updated from your interrupt callback. It will work fine if you build without code optimization, but with optimization enabled you may experience that the delay gets set to '0' at line 129 and 131 instead of the expected value computed in the SAADC callback.  Could this be the problem, or are you testing the code without code optimization?

    Best regards,

    Vidar

Children
Related