Position open-loop sequence of positions with minimal delay

Thanks for working on SimpleFOC. I’ve spent some frustrating times with a couple different TI LaunchXL boards. SimpleFOC has been much more straighforward.

I’m having some success using position open-loop with a small gimbal motor.

6.28 is a full turn, etc.

Now I’m trying to make the motor follow a sequence of positions, and do so without additional delay. I still want the motor to fully arrive at each position, but as soon as it does, I want to tell it to go to the next position.

If I reduce this _delay(500) to 100, the motor appears to jump around… like it’s skipping to the next position before it arrives arrives at the current one. I’m doing something wrong, for sure. Is there some library method that would tell me if the motor has arrived at the next position? Or perhaps some example code showing how to move through three positions without delay?

float error = 0;
int index = 0;
const float points[11] = { 0.0, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0 };
float multiplier = 0.10;

void setup() {
  // driver config
  // power supply voltage [V]
  driver.voltage_power_supply = 12;
  driver.init();
  // link the motor and the driver
  motor.linkDriver(&driver);

  motor.useMonitoring(Serial);

  // limiting motor current (provided resistance)
  motor.current_limit = 0.5;   // [Amps]
 
  // open loop control config
  motor.controller = MotionControlType::angle_openloop;
  // choose FOC modulation (optional)
  motor.foc_modulation = FOCModulationType::SpaceVectorPWM;

  //  maximal velocity of the position control
  // default 20
  motor.velocity_limit = 20;

  // init motor hardware
  motor.init();

  // add target command T
  command.add('T', doTarget, "target angle");

  Serial.begin(115200);
  Serial.println("Motor ready!");
  Serial.println("Set target position [rad]");
  _delay(1000);
}


void loop() {
  motor.monitor();
  motor.move(target_position);

  error = abs(target_position - motor.shaft_angle);
  
  if(error < 0.01)
  {
    _delay(500);
    target_position = points[index] * multiplier;
    if (++index > 10) 
    { 
      index = 0; 
      multiplier += 0.1;
    } 
  }
}

Hi,

you have to think about your code structure differently - you can’t use the delay() function in this way.
The call to move() has to be very frequent, at least 1kHz would be good. So you can’t call delay(500) in the code, that would pause for hall a second, during which move would not be called…

You can think about the following kind of structure:

  • create an array of movements, where each element is a struct { float target; int time; }
  • in your main loop, track the variables index (position in your array of movements) and nexttimestamp
  • whenever _micros() >= nexttimestemp, advance to the next movement:
index = index+1; 
nexttimestamp = _micros() + movements[index].time;
motor.target = movements[index].target;
  • something like that

  • no delays in the main loop, just a comparison with the current time, and advancing to the next movement when needed