0

I'm writing a code to manage the velocity of a motor that is remotly controlled. For security reasons I want to stop the motor after 1 seconds it receives a command if it doesn't receive another.

I have a "motor" struct:

motor mt = {
    .m_pwm_pin=M_PWM,
    .timeout=1000,
    .freq=50.0,
    .cycle_time=0.000000008,
    .divider=256.0,
    .forward_period=2.0,
    .neutral_period=1.5,
    .backward_period=1.0,
    .motor_kv=2150 
};

The code I wrote looks like that:

int64_t cb_stop_motor(long id, void *mot){
    motor *m = mot;
    stop_motor(m);
    return 0;
}

int stop_motor(motor *m)
{
    gpio_put(16, 1);
    pwm_set_chan_level(m->slice, PWM_CHAN_B, getDuty(m->neutral_period));
    return 0;
}

int move_motor(motor *m, int rpm)
{
    double period_per_rpm;
    double m_period;

    if(rpm == 0){
        stop_motor(m);
    }
    else if(rpm < 0){
        period_per_rpm = (m->neutral_period - m->backward_period) / ((double) m->motor_kv);
        m_period = m->neutral_period - (period_per_rpm * (double) rpm * -1.0);
    }
    else if(rpm > 0){
        period_per_rpm = (m->forward_period - m->neutral_period) / ((double) m->motor_kv);
        m_period = m->neutral_period + (period_per_rpm * (double) rpm);
    }

    pwm_set_chan_level(m->slice, PWM_CHAN_B, getDuty(m_period));
    
    cancel_alarm(m->alarm_id);

    m->alarm_id = add_alarm_in_ms(m->timeout, cb_stop_motor, m, true);
}

The problem is that immidiatly after the "move_motor" command the alarm is fired. I know that becouse I checked with an oscilloscope, the period gets to 1.72ms for an instant and then gets back to 1.5ms.

What could be the problem here? Any help is higly appreciated.

lasb3tas
  • 75
  • 1
  • 9
  • 1
    "The code I wrote looks like that:" Better show a [mre] of your code than something which is similar. I miss some context of what gets called when and how often. – Yunnosch Aug 15 '22 at 14:17
  • You're passing true to the `fire_if_past` arg. This means that it _will_ fire immediately if the time for the alarm has already passed. So, your calculations are off. You probably want to ensure the firing time is in the future – Craig Estey Aug 15 '22 at 17:57
  • Can you prove/show that `m->timeout` is 1000 when the call is made? Try a hard-coded value of 1000 to see – Craig Estey Aug 15 '22 at 18:06
  • You have UB. If `rpm` is 0, then `m_period` will be unitialized/random – Craig Estey Aug 15 '22 at 18:10

1 Answers1

0

Seems like the time in milliseconds should be specified with an added zero, by setting timeout=10000 i get a 1s timeout as wanted.

lasb3tas
  • 75
  • 1
  • 9
  • As it’s currently written, your answer is unclear. Please [edit] to add additional details that will help others understand how this addresses the question asked. You can find more information on how to write good answers [in the help center](/help/how-to-answer). – Community Aug 20 '22 at 00:00