Problems about the high velocity error of motor speed

Hello!
i am doing test to control the motor rotate at some speed. The control code is modified from

When controling the motor,i also plot the desired speed,actual speed and the error in real time.

Here is the plot:

speed at 25 radia/s:

and the plot at 50 radian/s:

  1. red line is the desired speed
  2. green line is the actual speed
  3. blue line is the velocity error

I have check the motor_board.cpp of BLMC_drivers to make sure that the actual speed
is already in rad/s,not krpm.

As you can see that the actual speed seems very noisy.

Here is my question:

  1. The velocity error interval is [-50,25], i think this is bad. does this means there is some problems with my encoder wheel?
  2. Can anyone tell me what the normal velocity error interval is expected?
  3. Does the speed needs some filtering?I try the low pass filter,the result is not good.

When i am doing the test, the error with error code=1 occurs sometimes,so i modified the udriver.
from

#define QEP_MAX_INDEX_ERROR (1./360.) * USER_MOTOR_ENCODER_LINES

to

#define QEP_MAX_INDEX_ERROR (10./360.) * USER_MOTOR_ENCODER_LINES

Does this make the encoder more inaccurate?

Best Regards!

There is a bug in the code of blmc_drives,i will post the details after i finish test.

I haven’t used the velocity_ctrl.py script in a long time, so I can’t comment on it right now. I can look into it in the next days when I’m in the lab again (but will wait for the details on the bug you mentioned).

Just a quick note on the encoder error: With a properly working encoder, you should never get this error, so I recommend double-checking the hardware in this regard. Note that this error does not necessarily mean that something is wrong with the encoder itself, it can also indicate an issue with the wires connecting the encoder to the board (on our robots, we get this from time to time, when a wire breaks inside the insulation, thus creating a loose contact).
Increasing the value of QEP_MAX_INDEX_ERROR will just cause the error to be triggered less quickly but will not help against the actual problem of incorrect encoder measurements.

1 Like

I can’t find out what cause the problem.

Here is the way i do the test:

  1. implement a PID controller modified from velocity_ctrl.py,the PID params i used is not changed,always [5,0.5,0]
  2. Only enable motor1,make it rotate CW,track a desired speed

The blmc driver decode velocity data in the function:

CanBusMotorBoard::loop()
{
.....
        // convert to measurement ------------------------------------------
        double measurement_0 = qbytes_to_float(can_frame.data.begin());
        double measurement_1 = qbytes_to_float((can_frame.data.begin() + 4));
        switch (can_frame.id)
        {
            ......
            case CanframeIDs::SPEED:
                // Convert the speed unit from the blmc card
                // (kilo-rotations-per-minutes) into rad/s.
                measurement_[velocity_0]->append(measurement_0 * 2 * M_PI *
                                                 (1000. / 60.));
                measurement_[velocity_1]->append(measurement_1 * 2 * M_PI *
                                                 (1000. / 60.));
               .......
         }
......
}

Test 1:

If i set desired speed as 9 rad/s,then run the test,i found that i often receive a negative speed.
Here is one of the original can data i record:

can_frame.data={255,255,181,8,0,0,0,0}

i think the actual speed received from board may larger or less a litte bit than desired speed,but should not be negative.

Test 2

I run the velocity_ctrl.py of python_blmc with desired speed = 0.2,found that the speed is always positive.
I check the code of python_blmc,it decode the speed data as below:

# Motor_data.py
def _conv_stamp_2val_q_msg(msg):
    return (StampedValue(q_bytes_to_value(MDL(msg.data)), msg.timestamp),
            StampedValue(q_bytes_to_value(MDH(msg.data)), msg.timestamp))

....
  def set_velocity(self, msg):
        (self.mtr1.velocity, self.mtr2.velocity) = _conv_stamp_2val_q_msg(msg)

It convert the speed from Q24 to KRPM,not rad/s.

so i modify the loop() function of blmc as blow:

            case CanframeIDs::SPEED:
                double cur_vel0 = measurement_0;
                double cur_vel1 = measurement_1 
                measurement_[velocity_0]->append(cur_vel0 );
                measurement_[velocity_1]->append(cur_vel1);

then rebuild blmc,and my test code,and then run it with desired speed 0.9 KRPM and same PID params=(5,0.5,0).

It doesn’t receive negative speed again!!!

That is the problem what i met, i can’t not figure out the reason.

I realised that there might be a misconception: The python_blmc package is a independent pure-Python package that does not use blmc_drivers or any other of our packages. So any changes in blmc_drivers do not affect the velocity_ctrl.py script.

The python_blmc package hasn’t been maintained for some years now (it was mostly made for some prototype testing during development). I just gave it a quick try and migrated it to Python3 (pushed to the master branch now). Further I modified the velocity_ctrl.py script a bit to log data over 15 seconds and then plot it (this is on a separate branch).

When running this with a target velocity of 0.5 krpm (roughly the same as 50 rad/s) and PI gains 5, 2, I get the following behaviour (red is desired, blue actual velocity):
plot_velocity1
It’s still not perfect but looks reasonable good.

It also works as expected for negative velocities, although I had to remove the “emergency break” safety feature for this, as it couldn’t handle negative velocities.

Can you try running the script from my branch (linked above) to see if that works for you?
Also, can you share your modified script? This would make it easier for me to understand, what exactly you are doing.

1 Like
  1. Your plot looks very good ,the velocity direction doesn’t frequent change its direction,the velocity error is very small,almost 0.1 KRPM = 10.4 rad/s
  2. The python_blmc package works for me,it is ok.
  3. I know that the python_blmc is independent of the blmc_drivers.
  4. The problem i met is that when i use blmc_drivers in c++ with deisred speed 25 rad /s or 50 rad /s,i often recevie positive speed and negative speed in a short time.You know,if using PID controller to control the motor using those different direction velocity data ,the motor would shock.

The blmc_drivers convert velocity from KRPM to rad/s,this is different from python_blmc.If I modify the blmc_drivers,make it just convert velocity to KRPM,not rad/s,then the blmc_drivers doesn’t recevie positive speed and negative speed in a short time again.Using the same control code with desired speed=1.5 KRPM=25 rad/s,nothing changed,the velocity plot is :


red line is the desired speed,green line is the actual speed,blue line is the velocity error.

I post original plot with blmc_drivers converting velocity to KRPM here again As a comparison:


Here is my velocity control code.

  1. I use QT to create an control panel,so that i can change the PID parameters and desired velocity by hand when running. The code about UI is very simple,so i don’t post here
  2. PyPID is almost same as pid.py in python_blmc packages.
  3. The DesiredSpeedController inherit from IControllerInterface,and the IControllerInterface will auto start a child thread to run DesiredSpeedController::RoutineEntry()

If needed,i can post the whole project to github later,i need some time to remove the unused code to make the project clean.

Thanks for the clarification and sharing the code!
Just to make sure, I understand correctly:

  • When using blmc_drivers as is (i.e. reporting velocity in rad/s), you get the bad behaviour but if you remove the code for converting it (so velocity is just forwarded in krpm, as reported by the board), then it is good?
  • In the bad case: Does the motor actually move back and forth as the reported velocity suggests?

One thing I noticed: You said “speed=1.5 KRPM=25 rad/s”. However, 1.5 krpm corresponds to 157 rad/s (however, it is 25 revolutions per second). So the two cases may not be fully comparable if the target velocity is very different.

  • When using blmc_drivers as is (i.e. reporting velocity in rad/s), you get the bad behaviour but if you remove the code for converting it (so velocity is just forwarded in krpm, as reported by the board), then it is good?

Yes.

  • In the bad case: Does the motor actually move back and forth as the reported velocity suggests?

No.The motor shock hard,and move forward slowly.

One thing I noticed: You said “speed=1.5 KRPM=25 rad/s”. However, 1.5 krpm corresponds to 157 rad/s (however, it is 25 revolutions per second). So the two cases may not be fully comparable if the target velocity is very different.

You are right,i think i make a mistake,i will fix this bug and test it later.

@felixwidmaier
I notice that in your plot,the velocity error is almost 0.1 KRPM=10.4 rad/s.
Does the velocity error vary with velocity?