OpenPnP w. sFOC

I’m not sure what you’re trying to do or my own code ;*( It’s been too long since I wrote it and I don’t have much free time at the moment. Maybe in a couple of weeks or a month I’ll have more free time and can try to help you.

1 Like

Not trying, did it! I managed to get OpenPNP and SFOC talking together. Just using the very basic point to point Gcode driver. Next step is setting up the machine, and see how it behaves. Actually, maybe a homing sequence would be pretty useful.

I guess it should be:

Move to the direction of the sensor slowly.

STOP if hitting the switch!

Do it again very slowly. Bounce.

Cero the position.

Ready…

All commands are prepared and then only put into an outgoing queue. The queued commands are sent to the controller using a separate writer thread.

I mean, should that imply that the commands should just be executed as fast as possible when received?

If above is true, then openPnP times the outgoing commands to form a motion, expecting that the commands will take effect when received ?

Hmm… maybe the solution could be to time the execution of the next command inline, compared to the coasting period. We know when the move we are executing should stop coasting, and we therefore know when to trigger the next move command in the buffer?

Yes, the code you provided should work in the context you’ve described. It checks three conditions before triggering the next command/move from the buffer:

  1. !buffer.isEmpty(): Checks if the buffer is not empty, meaning there’s a command waiting to be executed.
  2. !m400_flag: Ensures that the M400 flag is not raised, which means there’s no need to handle an M400 command.
  3. timeSinceStartingTrajectoryInSeconds >= (Tf_ - Td_ - EventHorizon): This condition checks if the coasting period is almost over. If this condition is met, it triggers the next command/move from the buffer.

This code will only execute the next command if all three conditions are true, ensuring that it fires when the planner is executing, there’s a command in the buffer, and the coasting period is almost over.

if (!buffer.isEmpty() && !m400_flag && timeSinceStartingTrajectoryInSeconds >= (Tf_ - Td_ - EventHorizon)){
                   
                   char* cmd = buffer.pop();
                   doTrapezoidalPlannerCommand(cmd);
            }

So, the next command triggers when time from start of move to now, is more or equal to (Full time of move - time it takes to decelerate - time to transition to new move).

That should work if you don’t have sFOCs LPF settings too high. It can get easily out off sync, when each motor has it’s own PID and LPF settings.
Maybe it’s better to put a copy of the PID model in the openPNP planner to take these delays into account?

Although more knowledge is always better.

I think it will improve the planning a lot, if we, at least, take a look at the next command in the queue.

This is compiling now, but im not using the nextItem yet. Have to find a way to incorporate it.


if (!isTrajectoryExecuting){

if (!buffer.isEmpty()){
// we have a new move to start
buffer.pop(tailItem, nextItem);

                #ifdef __debug
                Serial.println("tailItem: ");
                Serial.println(tailItem);
                Serial.println("nextItem: ");
                Serial.println(nextItem);
                #endif
                
                doTrapezoidalPlannerCommand(tailItem, nextItem);

}
}

I’m seen some deviation from the actual move to the planned move. Think it is best if we integrate the encoder readings into the planner.

Edit: I introduced the motor->shaft_angle and the current velocity, and now it moves to the target position. Actually with a tiny overshoot. This was a move to 20mm, and those values are M114 responses, over a minute or so.

X:20.0018
ok
X:20.0016
ok
X:20.0018
ok
X:20.0016
ok
X:20.0016
ok
X:20.0016
ok
X:20.0018
ok
X:20.0016
GGode command: G0X20.0000

Move to new position (rads): 7.24395
--------------------------------- 
 Calculated trapezoidal Values:   
     Tf: 0.98
     Ta: 0.49
     Tv: 0.00
     Td: 0.49
     --------------------- 
     Ar: 30.00
     Vr: 14.74
     Dr: -30.00
     --------------------- 
     Xf: 7.24
     Xi: 0.00
Starting to move to a new position
Time to complete move (secs):0.98
Velocity for move: 40.00, Acceleration: 30.00

Ok, Update on the planner story!

Now running quite smooth using a S-curve approach suggested by @Karl_Makes_Music, using cos to calculate the ramp and deceleration motion, in velocity mode. The angle mode made some undesirable stuttering, but we can still use it to hold a angle at the end of a move.

Here is the target velocity and actual velocity for a move between 0 and 100mm.

Not using feed_forward, yet…

2 Likes

Ive forked the modified TrapezoidalPlanner and CircularBuffer here.

Feel free to try out and help out!

If someone @Antun_Skuric knows how to use the feed_forward, plz look it through.

CosIPlanner/FirmWare/lib at main · Juanduino/CosIPlanner (github.com)

It responds to eg. G0X20.0000 or M114

O you mean a virtual node with local serial bridge ?

We should be able to calibrate the mass, by homing in on the perfect curve.

This also means we can fine tune a CNC to apply a certain force. We just need to know exactly when to apply that force.