Skip to content

Motor stops due to direction change - voltages NaN #192

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
runger1101001 opened this issue Jun 17, 2022 · 9 comments
Closed

Motor stops due to direction change - voltages NaN #192

runger1101001 opened this issue Jun 17, 2022 · 9 comments

Comments

@runger1101001
Copy link
Member

This is a simplified template, feel free to change it if it does not fit your case.

Describe the bug
The motor stops sometimes when it changes direction. The calculated voltages are NaN - causing this behaviour.
See: https://community.simplefoc.com/t/inrush-current-problem-with-our-bldc-driver-board/2052/25

Describe the hardware setup
For us it is very important to know what is the hardware setup you're using in order to be able to help more directly

  • Which motor
  • Self made driver, see forum post
  • STM32G0
  • Hall Sensors
  • No

IDE you are using

  • Arduino IDE

Tried the Getting started guide? - if applicable
See forum post - we've been trying to get the motor driver running, and have run into this problem.

@askuric
Copy link
Member

askuric commented Jun 18, 2022

Could this be realted to this issue #177 ?

@runger1101001
Copy link
Member Author

Doesn't seem so - it's STM32 rather than ESP32, and Adharsh doesn't have the phase resistance set.
An interesting difference in his setup is that he has pre-aligned the sensor to the motor, and so he initialises initFOC() with a value of 0.0f - that's probably a fairly unique feature of his setup. But otherwise he's just doing velocity control, no current limiting.

@markovica
Copy link

I did some debugging, and void BLDCMotor::setPhaseVoltage(float Uq, float Ud, float angle_el) is being fed NaN for Uq, which seems to be coming from the PID of loopFoc.
Normalized angle was reading correct values, even when the motor was stalled.

@kadharsh
Copy link

Yes @markovica, the value Uq is being fed NaN,
I did some testing and my findings are updated in the forum thread.
https://community.simplefoc.com/t/inrush-current-problem-with-our-bldc-driver-board/2052/38?u=adharsh_k

The problem is coming from Sensor::getVelocity() returning INF one time while running and this screws up all other functions which rely on this value. And in the end the Uq is fed NaN and the motor stops.
The function getVelocity() continues to work.

sens_vel: -3.26 lpf_velo: -3.26 retVal: -3.15
sens_vel: -3.26 lpf_velo: -3.26 retVal: -3.19
sens_vel: 0.00 lpf_velo: 0.00 retVal: -2.00
sens_vel: -3.09 lpf_velo: -3.09 retVal: -2.40
sens_vel: inf lpf_velo: inf retVal: inf <- This is where the problem happens ie: Sensor::getVelocity() returning INF
sens_vel: 0.00 lpf_velo: nan retVal: inf
sens_vel: 0.00 lpf_velo: nan retVal: inf
sens_vel: 0.00 lpf_velo: nan retVal: inf
sens_vel: 0.00 lpf_velo: nan retVal: inf

where sens_vel is the value returned by Sensor::getVelocity()
lpf_velo is the value after low pass filter,
retVal is the value returned by the function FOCMotor::shaftVelocity()

@kadharsh
Copy link

kadharsh commented Jun 21, 2022

For a quick fix you can modify the function FOCMotor::shaftVelocity() like this:

float FOCMotor::shaftVelocity() {
  // if no sensor linked return previous value ( for open loop )
  if(!sensor) return shaft_velocity;
  
  float vel = sensor->getVelocity();
  if(vel < -1000 || vel > 1000)    vel = 0;   //if velocity is out of range then make it zero
  return sensor_direction*LPF_velocity(vel);
}

@markovica
Copy link

Thank you @kadharsh

I moved your fix to HallSensor::getVelocity() as it makes more sense to me since this seems to be a hall sensor issue and it seems it's working perfectly.

float HallSensor::getVelocity(){
  if (pulse_diff == 0 || ((long)(_micros() - pulse_timestamp) > pulse_diff) ) { // last velocity isn't accurate if too old
    return 0;
  } else {
    // quick fix https://github.com/simplefoc/Arduino-FOC/issues/192
    float vel = direction * (_2PI / (float)cpr) / (pulse_diff / 1000000.0f);
    if(vel < -1000 || vel > 1000)    vel = 0;   //if velocity is out of range then make it zero
    //return direction * (_2PI / (float)cpr) / (pulse_diff / 1000000.0f);
    return vel;
  }

@kadharsh
Copy link

as it makes more sense to me since this seems to be a hall sensor issue and it seems it's working perfectly.

Yes, you are right, I just put it there just in case.

@Khanmmk
Copy link

Khanmmk commented Jun 22, 2022

That's nice work and you guys are able to solve the issue, but I was looking at the source code, and over there vel is not declared. Kindly you can highlight where you declared the vel value. Thanks

@kadharsh
Copy link

That's nice work and you guys are able to solve the issue, but I was looking at the source code, and over there vel is not declared. Kindly you can highlight where you declared the vel value. Thanks
The actual HallSensor::getVelocity() code in src/sensors/HallSensor.cpp is

float HallSensor::getVelocity(){
  if (pulse_diff == 0 || ((long)(_micros() - pulse_timestamp) > pulse_diff) ) { // last velocity isn't accurate if too old
    return 0;
  } else {
    return direction * (_2PI / (float)cpr) / (pulse_diff / 1000000.0f);
  }

}

just replace it with this:

Thank you @kadharsh

I moved your fix to HallSensor::getVelocity() as it makes more sense to me since this seems to be a hall sensor issue and it seems it's working perfectly.

float HallSensor::getVelocity(){
  if (pulse_diff == 0 || ((long)(_micros() - pulse_timestamp) > pulse_diff) ) { // last velocity isn't accurate if too old
    return 0;
  } else {
    // quick fix https://github.com/simplefoc/Arduino-FOC/issues/192
    float vel = direction * (_2PI / (float)cpr) / (pulse_diff / 1000000.0f);
    if(vel < -1000 || vel > 1000)    vel = 0;   //if velocity is out of range then make it zero
    //return direction * (_2PI / (float)cpr) / (pulse_diff / 1000000.0f);
    return vel;
  }

And it should work!

Happy hacking : )

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

5 participants