@joergs5 It seemed to me as if it's motor position, because my kinematics is only called once with end position. The GetLinearAxes()
does return AxesBitmap::MakeFromRaw(0)
treating none of the axes as linear (or am I misunderstanding of it?) Otherwise I inherent the ZLeadscrewKinematics, where segmentsPerSecond=100, minSegmentLength=0.2000.
@dc42 I did this:
PAXKinematics::PAXKinematics() noexcept
: ZLeadscrewKinematics(KinematicsType::pax, SegmentationType(true, true, true)) // useSeg, useZSeg, useG0Seg
{
}
and as mentioned above, GetSegmentsPerSecond()
returns 100, and GetMinSegmentLength()
returns 0.2.
What am I missing otherwise? The PAXKinematics::CartesianToMotorSteps()
is called only once with G1 B20
(to keep the example simple).
I went ahead to understand it better what the problem could be, and dived into Gcodes/Gcodes.cpp
function GCodes::DoStraightMove()
: where the amount of segments are calculated, line #2110:
// Apply segmentation if necessary. To speed up simulation on SCARA printers, we don't apply kinematics segmentation when simulating.
// As soon as we set segmentsLeft nonzero, the Move process will assume that the move is ready to take, so this must be the last thing we do.
if (st.useSegmentation && simulationMode != 1 && (moveBuffer.hasPositiveExtrusion || moveBuffer.isCoordinated || st.useG0Segmentation))
{
debugPrintf("calculate segmentation\n");
// This kinematics approximates linear motion by means of segmentation
float moveLengthSquared = fsquare(currentUserPosition[X_AXIS] - initialUserPosition[X_AXIS]) + fsquare(currentUserPosition[Y_AXIS] - initialUserPosition[Y_AXIS]);
if (st.useZSegmentation)
{
moveLengthSquared += fsquare(currentUserPosition[Z_AXIS] - initialUserPosition[Z_AXIS]);
}
const float moveLength = fastSqrtf(moveLengthSquared);
const float moveTime = moveLength/moveBuffer.feedRate; // this is a best-case time, often the move will take longer
moveBuffer.totalSegments = (unsigned int)max<long>(1, lrintf(min<float>(moveLength * kin.GetReciprocalMinSegmentLength(), moveTime * kin.GetSegmentsPerSecond())));
}
it enters that if
block, but the result is
calculate segmentation
moveLength = 0.0000, moveTime = 0.0000, kin.GetReciprocalMinSegmentLength = 5.0000, kin.GetSegmentsPerSecond = 100.0000
mb.totalSegments = 1, mb.isCoordinated = 1, useSegmentation = 1, simulationMode = 0
mb = moveBuffer
Now, I did override moveBuffer.totalSegments = 10
(after the quoted if
block) and now the motor moves exactly as I expected.
At my superficial glance of that particular if
block, the axes A
& B
are disregarded there, so, I added in haste following lines (indicated by ** in front):
if (st.useZSegmentation)
{
moveLengthSquared += fsquare(currentUserPosition[Z_AXIS] - initialUserPosition[Z_AXIS]);
}
**moveLengthSquared += fsquare(currentUserPosition[3] - initialUserPosition[3]);
**moveLengthSquared += fsquare(currentUserPosition[4] - initialUserPosition[4]);
A[axis=3] and B[axis=4] are in degrees, so it's not really "length", but anyway, it produces this debug output:
calculate segmentation
moveLength = 45.0000, moveTime = 0.1350, kin.GetReciprocalMinSegmentLength = 5.0000, kin.GetSegmentsPerSecond = 100.0000
mb.totalSegments = 13, mb.isCoordinated = 1, useSegmentation = 1, simulationMode = 0
and now I have much better mb.totalSegments = 13
.
@dc42 am I missing some settings in my kinematics or is the segmentation computation problem actually higher up at Gcodes/Gcode.cpp
?
With the two axes (A & B) hardcoded into segments calculation the firmware & machine behaves now as I desired https://www.youtube.com/watch?v=TiV0zEc5spw - the nozzle stays in place, A & B are rotating, whereas X, Y & Z compensate properly.