FOC mode to continue spinning without constantly needing to call move?

I am trying to create an accel/decel function for my FOC project. It would be a lot easier if there was an FOC mode where you could set a speed once and it would continue at that speed without having to constantly call motor.move().

Your request is somewhat confusing. Why do you care if you call the move? Could you provide pseudocode of what you are trying to achieve?

Also, if you are building a speed profile, how can you not use the move function?

Cheers,
Valentine

Depending on your hardware, there are different solutions available. If your hardware runs RTOS you can create a separate task to call motor.move() continously. This way, your mail loop would be free for you to implement blocking functions that accel/decel.
Alternatively, you would use a timer to call motor.move().
Without any knowledge on your hardware and an idea of what you are trying to do in software though, it is hard to give concrete advice.

The hardware is a SimpleFOC shield Ver 2.0.3 on an Arduino UNO. The motor is a BGM4108-130T. The sensor is a CUI AMT103-V set to 2048 PPR. The battery is a 4S 2200MAH Lithium Ion.

Software is a Windows 11 PC running Arduino IDE Version 1.8.19.

The goal is to create an accel/decel ramp so I can set a motor speed using motor.move(target_speed). It would then ramp up or down from its current speed to the target_speed. No further action would be required to control speed until a target_speed change is requested. The motor would once again ramp up or down to the new target_speed and maintain that speed.
The only time I would need to call motor.move is when I want to initiate or change the motor speed.

Hope that clarifies what I have and what I am trying to do.

You confused me even more. How can you build a velocity profile without calling move()? I’m sure you have something in mind however it’s difficult for me to understand.

In a closed loop, if you call move() for example every 100 milliseconds instead of every loop, the LoopFOC() will just keep spinning the motor at the last velocity you requested in between the calls. This will massively confuse the closed loop logic. A lot of variables get updated during move().

I believe you need to gain a lot deeper understanding of the library first.

In an open loop, if you do not call move() then there is nothing to send a signal to the PWM pins to spin the magnetic field. The PWM pins will keep oscillating at the last value and effectively stall the magnetic field. Imagine you hitting the gas pedal of your car then taking your foot off and asking the engine to keep running at the last speed you hit the gas pedal but with no fuel mixture entering the cylinders.

move() is the core function that actually rotates the magnetic field. Imagine cutting the branch on the tree you sit on. Defies gravity. If you don’t call move() then literally the motor doesn’t move.

Cheers,
Valentine

First off, I am brand new to FOC, so apologies if I have confused you.

Based on your response Valentine, the answer to my question is, no, there is no FOC mode where you could set a speed once and it would continue at that speed without having to constantly call motor.move().

I noticed while viewing the FOC docs, there seems to be a built-in ramp function in
PIDController(float P, float I, float D, float ramp, float limit). That may be what I am looking for.

Unfortunately, there doesn’t appear to be an example of ramping using PID in the examples folder.

Correct, move() is what ACTUALLY moves the motor so yes, if you want your motor to spin you have to move() it.

This is a closed-loop function. It will slowly ramp-up or ramp-down only in a certain closed loop velocity mode configuration. In other modes it has no meaning. It is super useful when you have implemented a full current sensing velocity closed loop though. Guarantees you won’t rip your motor off the foundation and cut your head off if you decide to hit it with 10000 rpm from dead stop.

You are not the first one to attempt doing this so please check the following threads:

Cheers,
Valentine

The ramp in the PID code is not what you’re after. It’s only a fine tuning parameter, limiting extremely fast changes of acceleration.

What you need is to write another layer of control logic on top of motor.move. Something like

float current_velocity, target_velocity, acceleration;
void UpdateVelocityRamp()
{
  static long oldMicros = _micros();
  long newMicros = _micros();
  float time = ((float)(newMicros - oldMicros)) / 1000000.0f;
  oldMicros = newMicros;

  if (current_velocity < target_velocity)
     current_velocity = fmin(current_velocity + acceleration * time, target_velocity);
  else if (current_velocity > target_velocity)
     current_velocity = fmax(current_velocity - acceleration * time, target_velocity);
  motor.move(current_velocity);
}
1 Like

dekutree64, this seems like a reasonable solution, so I will put something together. I will do it in a way that keeps the timing of calls to move as consistent as possible whether it is ramping or not.

Thank you!