Version 1.17c
New features: The layer height comment in gcode files produced by Matter Control is now recognised M101 and M103 (firmware retraction commands generated by Simplify3D) are now recognised G20 bed probing now prints the mean height error and RMS deviation to 3 decimal places Bug fixes: G30 with no parameters now sets the machine position to the Z probe trigger height instead of the user position. This means that running G28 (home) and G29 (bed probe) alternately no longer causes the bed height map to creep up or down in average height when Z homing uses the Z probe. However, it means that the Z height displayed after a G30 command is no longer always the same as the Z probe trigger height. In firmware 1.17 the speed change command by the M220 command got delayed until the next G1 or G0 command with an F parameter was read. In firmware 1.16 and 1.17 the acceleration used in G11 un-retraction commands was sometimes incorrectly reduced if pressure advance was configured on a different extruder. In firmware 1.16 and 1.17 when pressure advance was configured, the extruder acceleration limit implied by pressure advance used the pressure advance value for the wrong extruder. Firmware retraction did not work if additional axes had been configured e.g. for an IDEX printer. G29 commands using the P parameter with an upper case M in the filename were recognised as M commands instead
This commit is contained in:
parent
15114700f0
commit
efcb1e5ce6
14 changed files with 185 additions and 132 deletions
Binary file not shown.
BIN
Release/Duet-0.6-0.8.5/Stable/RepRapFirmware-1.17c.bin
Normal file
BIN
Release/Duet-0.6-0.8.5/Stable/RepRapFirmware-1.17c.bin
Normal file
Binary file not shown.
Binary file not shown.
Before Width: | Height: | Size: 3 MiB After Width: | Height: | Size: 3 MiB |
BIN
Release/Duet-WiFi/Stable/DuetWiFiFirmware-1.17c.bin
Normal file
BIN
Release/Duet-WiFi/Stable/DuetWiFiFirmware-1.17c.bin
Normal file
Binary file not shown.
|
@ -170,7 +170,6 @@ bool GCodeBuffer::IsEmpty() const
|
|||
|
||||
// Is 'c' in the G Code string?
|
||||
// Leave the pointer there for a subsequent read.
|
||||
|
||||
bool GCodeBuffer::Seen(char c)
|
||||
{
|
||||
readPointer = 0;
|
||||
|
@ -185,6 +184,24 @@ bool GCodeBuffer::Seen(char c)
|
|||
return false;
|
||||
}
|
||||
|
||||
// Return the first G, M or T command letter. Needed so that we don't pick up a spurious command letter form inside a string parameter.
|
||||
char GCodeBuffer::GetCommandLetter()
|
||||
{
|
||||
readPointer = 0;
|
||||
for (;;)
|
||||
{
|
||||
const char b = gcodeBuffer[readPointer];
|
||||
if (b == 0 || b == ';') break;
|
||||
if (b == 'G' || b == 'M' || b == 'T')
|
||||
{
|
||||
return b;
|
||||
}
|
||||
++readPointer;
|
||||
}
|
||||
readPointer = -1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Get a float after a G Code letter found by a call to Seen()
|
||||
float GCodeBuffer::GetFValue()
|
||||
{
|
||||
|
|
|
@ -23,6 +23,7 @@ public:
|
|||
bool Put(const char *str, size_t len); // Add an entire string
|
||||
bool IsEmpty() const; // Does this buffer contain any code?
|
||||
bool Seen(char c); // Is a character present?
|
||||
char GetCommandLetter(); // Find the first G, M or T command
|
||||
float GetFValue(); // Get a float after a key letter
|
||||
int32_t GetIValue(); // Get an integer after a key letter
|
||||
void TryGetFValue(char c, float& val, bool& seen);
|
||||
|
|
|
@ -589,7 +589,7 @@ void GCodes::Spin()
|
|||
const uint32_t numPointsProbed = reprap.GetMove()->AccessBedProbeGrid().GetStatistics(mean, deviation);
|
||||
if (numPointsProbed >= 4)
|
||||
{
|
||||
reply.printf("%u points probed, mean error %.2f, deviation %.2f\n", numPointsProbed, mean, deviation);
|
||||
reply.printf("%u points probed, mean error %.3f, deviation %.3f\n", numPointsProbed, mean, deviation);
|
||||
error = SaveHeightMap(gb, reply);
|
||||
reprap.GetMove()->AccessBedProbeGrid().UseHeightMap(true);
|
||||
}
|
||||
|
@ -1747,8 +1747,9 @@ bool GCodes::DoSingleZProbe(GCodeBuffer& gb, StringRef& reply, bool reportOnly,
|
|||
else
|
||||
{
|
||||
moveBuffer.coords[Z_AXIS] = platform->ZProbeStopHeight() + heightAdjust;
|
||||
SetPositions(moveBuffer.coords);
|
||||
SetPositions(moveBuffer.coords, false); // set positions WITHOUT (very important) applying bed compensation
|
||||
SetAxisIsHomed(Z_AXIS);
|
||||
reprap.GetMove()->GetCurrentUserPosition(moveBuffer.coords, 0, reprap.GetCurrentXAxes()); // update the user position
|
||||
lastProbedZ = 0.0;
|
||||
}
|
||||
return true;
|
||||
|
@ -3049,10 +3050,10 @@ bool GCodes::RetractFilament(GCodeBuffer& gb, bool retract)
|
|||
{
|
||||
if (retract != isRetracted && (retractLength != 0.0 || retractHop != 0.0 || (!retract && retractExtra != 0.0)))
|
||||
{
|
||||
const Tool *tool = reprap.GetCurrentTool();
|
||||
const Tool * const tool = reprap.GetCurrentTool();
|
||||
if (tool != nullptr)
|
||||
{
|
||||
size_t nDrives = tool->DriveCount();
|
||||
const size_t nDrives = tool->DriveCount();
|
||||
if (nDrives != 0)
|
||||
{
|
||||
if (segmentsLeft != 0)
|
||||
|
@ -3060,28 +3061,30 @@ bool GCodes::RetractFilament(GCodeBuffer& gb, bool retract)
|
|||
return false;
|
||||
}
|
||||
|
||||
reprap.GetMove()->GetCurrentUserPosition(moveBuffer.coords, 0, reprap.GetCurrentXAxes());
|
||||
const uint32_t xAxes = reprap.GetCurrentXAxes();
|
||||
reprap.GetMove()->GetCurrentUserPosition(moveBuffer.coords, 0, xAxes);
|
||||
for (size_t i = numAxes; i < DRIVES; ++i)
|
||||
{
|
||||
moveBuffer.coords[i] = 0.0;
|
||||
}
|
||||
// Set the feed rate. If there is any Z hop then we need to pass the Z speed, else we pass the extrusion speed.
|
||||
const float speedToUse = (retract) ? retractSpeed : unRetractSpeed;
|
||||
moveBuffer.feedRate = (retractHop == 0.0)
|
||||
moveBuffer.feedRate = (retractHop == 0.0 || retractLength == 0.0)
|
||||
? speedToUse
|
||||
: speedToUse * retractHop/retractLength;
|
||||
moveBuffer.coords[Z_AXIS] += (retract) ? retractHop : -retractHop;
|
||||
const float lengthToUse = (retract) ? -retractLength : retractLength + retractExtra;
|
||||
for (size_t i = 0; i < nDrives; ++i)
|
||||
{
|
||||
moveBuffer.coords[E0_AXIS + tool->Drive(i)] = lengthToUse;
|
||||
moveBuffer.coords[numAxes + tool->Drive(i)] = lengthToUse;
|
||||
}
|
||||
|
||||
moveBuffer.moveType = 0;
|
||||
moveBuffer.isFirmwareRetraction = true;
|
||||
moveBuffer.usePressureAdvance = false;
|
||||
moveBuffer.filePos = (&gb == fileGCode) ? gb.MachineState().fileState.GetPosition() : noFilePosition;
|
||||
moveBuffer.canPauseAfter = !retract; // don't pause after a retraction because that could cause too much retraction
|
||||
moveBuffer.xAxes = reprap.GetCurrentXAxes();
|
||||
moveBuffer.xAxes = xAxes;
|
||||
segmentsLeft = 1;
|
||||
}
|
||||
}
|
||||
|
@ -3134,14 +3137,14 @@ bool GCodes::ToolHeatersAtSetTemperatures(const Tool *tool, bool waitWhenCooling
|
|||
return true;
|
||||
}
|
||||
|
||||
// Set the current position
|
||||
void GCodes::SetPositions(float positionNow[DRIVES])
|
||||
// Set the current position, optionally applying bed and axis compensation
|
||||
void GCodes::SetPositions(const float positionNow[DRIVES], bool doBedCompensation)
|
||||
{
|
||||
// Transform the position so that e.g. if the user does G92 Z0,
|
||||
// the position we report (which gets inverse-transformed) really is Z=0 afterwards
|
||||
reprap.GetMove()->Transform(positionNow, reprap.GetCurrentXAxes());
|
||||
reprap.GetMove()->SetLiveCoordinates(positionNow);
|
||||
reprap.GetMove()->SetPositions(positionNow);
|
||||
float newPos[DRIVES];
|
||||
memcpy(newPos, positionNow, sizeof(newPos)); // copy to local storage because Transform modifies it
|
||||
reprap.GetMove()->Transform(newPos, reprap.GetCurrentXAxes(), doBedCompensation);
|
||||
reprap.GetMove()->SetLiveCoordinates(newPos);
|
||||
reprap.GetMove()->SetPositions(newPos);
|
||||
}
|
||||
|
||||
bool GCodes::IsPaused() const
|
||||
|
|
|
@ -199,7 +199,7 @@ private:
|
|||
bool ToolHeatersAtSetTemperatures(const Tool *tool, bool waitWhenCooling) const; // Wait for the heaters associated with the specified tool to reach their set temperatures
|
||||
|
||||
void SetAllAxesNotHomed(); // Flag all axes as not homed
|
||||
void SetPositions(float positionNow[DRIVES]); // Set the current position to be this
|
||||
void SetPositions(const float positionNow[DRIVES], bool doBedCompensation = true); // Set the current position to be this
|
||||
const char *TranslateEndStopResult(EndStopHit es); // Translate end stop result to text
|
||||
bool RetractFilament(GCodeBuffer& gb, bool retract); // Retract or un-retract filaments
|
||||
bool ChangeMicrostepping(size_t drive, int microsteps, int mode) const; // Change microstepping on the specified drive
|
||||
|
|
|
@ -45,27 +45,21 @@ bool GCodes::ActOnCode(GCodeBuffer& gb, StringRef& reply)
|
|||
return true;
|
||||
}
|
||||
|
||||
// M-code parameters might contain letters T and G, e.g. in filenames.
|
||||
// dc42 assumes that G-and T-code parameters never contain the letter M.
|
||||
// Therefore we must check for an M-code first.
|
||||
if (gb.Seen('M'))
|
||||
{
|
||||
return HandleMcode(gb, reply);
|
||||
}
|
||||
// dc42 doesn't think a G-code parameter ever contains letter T, or a T-code ever contains letter G.
|
||||
// So it doesn't matter in which order we look for them.
|
||||
if (gb.Seen('G'))
|
||||
// G29 string parameters may contain the letter M, and various M-code string parameter may contain the letter G.
|
||||
// So we now look for the first G, M or T in the command.
|
||||
switch (gb.GetCommandLetter())
|
||||
{
|
||||
case 'G':
|
||||
return HandleGcode(gb, reply);
|
||||
}
|
||||
if (gb.Seen('T'))
|
||||
{
|
||||
case 'M':
|
||||
return HandleMcode(gb, reply);
|
||||
case 'T':
|
||||
return HandleTcode(gb, reply);
|
||||
default:
|
||||
// An invalid command gets discarded
|
||||
HandleReply(gb, false, "");
|
||||
return true;
|
||||
}
|
||||
|
||||
// An invalid or queued buffer gets discarded
|
||||
HandleReply(gb, false, "");
|
||||
return true;
|
||||
}
|
||||
|
||||
bool GCodes::HandleGcode(GCodeBuffer& gb, StringRef& reply)
|
||||
|
@ -73,7 +67,7 @@ bool GCodes::HandleGcode(GCodeBuffer& gb, StringRef& reply)
|
|||
bool result = true;
|
||||
bool error = false;
|
||||
|
||||
int code = gb.GetIValue();
|
||||
const int code = gb.GetIValue();
|
||||
if (simulationMode != 0 && code != 0 && code != 1 && code != 4 && code != 10 && code != 20 && code != 21 && code != 90 && code != 91 && code != 92)
|
||||
{
|
||||
return true; // we only simulate some gcodes
|
||||
|
@ -885,6 +879,22 @@ bool GCodes::HandleMcode(GCodeBuffer& gb, StringRef& reply)
|
|||
FileMacroCyclesReturn(gb);
|
||||
break;
|
||||
|
||||
case 101: // Un-retract
|
||||
if (!LockMovement(gb))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
result = RetractFilament(gb, false);
|
||||
break;
|
||||
|
||||
case 103: // Retract
|
||||
if (!LockMovement(gb))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
result = RetractFilament(gb, true);
|
||||
break;
|
||||
|
||||
case 104: // Deprecated. This sets the active temperature of every heater of the active tool
|
||||
if (gb.Seen('S'))
|
||||
{
|
||||
|
@ -1676,11 +1686,21 @@ bool GCodes::HandleMcode(GCodeBuffer& gb, StringRef& reply)
|
|||
float newSpeedFactor = (gb.GetFValue() * 0.01) * secondsToMinutes; // include the conversion from mm/minute to mm/second
|
||||
if (newSpeedFactor > 0.0)
|
||||
{
|
||||
gb.MachineState().feedrate *= newSpeedFactor / speedFactor;
|
||||
// Update the feed rate for ALL input sources, and all feed rates on the stack
|
||||
const float speedFactorRatio = newSpeedFactor / speedFactor;
|
||||
for (size_t i = 0; i < ARRAY_SIZE(gcodeSources); ++i)
|
||||
{
|
||||
GCodeMachineState *ms = &gcodeSources[i]->MachineState();
|
||||
while (ms != nullptr)
|
||||
{
|
||||
ms->feedrate *= speedFactorRatio;
|
||||
ms = ms->previous;
|
||||
}
|
||||
}
|
||||
// If the last move hasn't gone yet, update its feed rate too if it is not a firmware retraction
|
||||
if (segmentsLeft != 0 && !moveBuffer.isFirmwareRetraction)
|
||||
{
|
||||
// The last move has not gone yet, so we can update it
|
||||
moveBuffer.feedRate *= newSpeedFactor / speedFactor;
|
||||
moveBuffer.feedRate *= speedFactorRatio;
|
||||
}
|
||||
speedFactor = newSpeedFactor;
|
||||
}
|
||||
|
|
|
@ -178,7 +178,7 @@ bool DDA::Init(const GCodes::RawMove &nextMove, bool doMotorMapping)
|
|||
}
|
||||
|
||||
isPrintingMove = false;
|
||||
bool realMove = false, xyMoving = false;
|
||||
bool realMove = false, xyMoving = false, xyzMoving = false;
|
||||
const bool isSpecialDeltaMove = (move->IsDeltaMode() && !doMotorMapping);
|
||||
float accelerations[DRIVES];
|
||||
const float * const normalAccelerations = reprap.GetPlatform()->Accelerations();
|
||||
|
@ -197,7 +197,16 @@ bool DDA::Init(const GCodes::RawMove &nextMove, bool doMotorMapping)
|
|||
DriveMovement& dm = ddm[drive];
|
||||
if (drive < numAxes && !isSpecialDeltaMove)
|
||||
{
|
||||
directionVector[drive] = nextMove.coords[drive] - prev->GetEndCoordinate(drive, false);
|
||||
const float positionDelta = nextMove.coords[drive] - prev->GetEndCoordinate(drive, false);
|
||||
directionVector[drive] = positionDelta;
|
||||
if (positionDelta != 0)
|
||||
{
|
||||
xyzMoving = true;
|
||||
if (drive != Z_AXIS)
|
||||
{
|
||||
xyMoving = true;
|
||||
}
|
||||
}
|
||||
dm.state = (isDeltaMovement || delta != 0)
|
||||
? DMState::moving // on a delta printer, if one tower moves then we assume they all do
|
||||
: DMState::idle;
|
||||
|
@ -214,22 +223,20 @@ bool DDA::Init(const GCodes::RawMove &nextMove, bool doMotorMapping)
|
|||
dm.direction = (delta >= 0); // for now this is the direction of net movement, but gets adjusted later if it is a delta movement
|
||||
realMove = true;
|
||||
|
||||
if (drive < numAxes && drive != Z_AXIS)
|
||||
{
|
||||
xyMoving = true;
|
||||
}
|
||||
|
||||
if (drive >= numAxes && xyMoving)
|
||||
{
|
||||
if (delta > 0)
|
||||
{
|
||||
isPrintingMove = true; // we have both movement and extrusion
|
||||
}
|
||||
const float compensationTime = reprap.GetPlatform()->GetPressureAdvance(drive);
|
||||
if (compensationTime > 0.0)
|
||||
if (nextMove.usePressureAdvance)
|
||||
{
|
||||
// Compensation causes instant velocity changes equal to acceleration * k, so we may need to limit the acceleration
|
||||
accelerations[drive] = min<float>(accelerations[drive], reprap.GetPlatform()->ConfiguredInstantDv(drive)/compensationTime);
|
||||
const float compensationTime = reprap.GetPlatform()->GetPressureAdvance(drive - numAxes);
|
||||
if (compensationTime > 0.0)
|
||||
{
|
||||
// Compensation causes instant velocity changes equal to acceleration * k, so we may need to limit the acceleration
|
||||
accelerations[drive] = min<float>(accelerations[drive], reprap.GetPlatform()->ConfiguredInstantDv(drive)/compensationTime);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -252,10 +259,11 @@ bool DDA::Init(const GCodes::RawMove &nextMove, bool doMotorMapping)
|
|||
endCoordinatesValid = (endStopsToCheck == 0) && (doMotorMapping || !move->IsDeltaMode());
|
||||
|
||||
// 4. Normalise the direction vector and compute the amount of motion.
|
||||
// If there is any XYZ movement, then we normalise it so that the total XYZ movement has unit length.
|
||||
// This means that the user gets the feed rate that he asked for. It also makes the delta calculations simpler.
|
||||
if (xyMoving || ddm[Z_AXIS].state == DMState::moving)
|
||||
if (xyzMoving)
|
||||
{
|
||||
// There is some XYZ movement, so normalise the direction vector so that the total XYZ movement has unit length and 'totalDistance' is the XYZ distance moved.
|
||||
// This means that the user gets the feed rate that he asked for. It also makes the delta calculations simpler.
|
||||
// First do the bed tilt compensation for deltas.
|
||||
if (isDeltaMovement)
|
||||
{
|
||||
// Add on the Z movement needed to compensate for bed tilt
|
||||
|
@ -299,7 +307,7 @@ bool DDA::Init(const GCodes::RawMove &nextMove, bool doMotorMapping)
|
|||
}
|
||||
else
|
||||
{
|
||||
// The distance to reversal is the solution to a quadratic equation. One root corresponds to the carriages being above the bed,
|
||||
// The distance to reversal is the solution to a quadratic equation. One root corresponds to the carriages being below the bed,
|
||||
// the other root corresponds to the carriages being above the bed.
|
||||
const float drev = ((directionVector[Z_AXIS] * sqrt(a2b2D2 - fsquare(A * directionVector[Y_AXIS] - B * directionVector[X_AXIS])))
|
||||
- aAplusbB)/a2plusb2;
|
||||
|
@ -342,16 +350,22 @@ bool DDA::Init(const GCodes::RawMove &nextMove, bool doMotorMapping)
|
|||
}
|
||||
else
|
||||
{
|
||||
// Extruder-only movement.
|
||||
// Currently we normalise vector sum of all extruder movement to unit length.
|
||||
// Alternatives would be:
|
||||
// 1. Normalise the largest one to unit length. This means that when retracting multiple filaments, they all get the requested retract speed.
|
||||
// 2. Normalise the sum to unit length. This means that when we use mixing, we get the requested extrusion rate at the nozzle.
|
||||
// 3. Normalise the sum to the sum of the mixing coefficients (which we would have to include in the move details).
|
||||
totalDistance = Normalise(directionVector, DRIVES, DRIVES);
|
||||
}
|
||||
|
||||
// 5. Compute the maximum acceleration available and maximum top speed
|
||||
// 5. Compute the maximum acceleration available
|
||||
float normalisedDirectionVector[DRIVES]; // Used to hold a unit-length vector in the direction of motion
|
||||
memcpy(normalisedDirectionVector, directionVector, sizeof(normalisedDirectionVector));
|
||||
Absolute(normalisedDirectionVector, DRIVES);
|
||||
acceleration = VectorBoxIntersection(normalisedDirectionVector, accelerations, DRIVES);
|
||||
|
||||
// Set the speed to the smaller of the requested and maximum speed.
|
||||
// 6. Set the speed to the smaller of the requested and maximum speed.
|
||||
// Also enforce a minimum speed of 0.5mm/sec. We need a minimum speed to avoid overflow in the movement calculations.
|
||||
float reqSpeed = nextMove.feedRate;
|
||||
if (isSpecialDeltaMove)
|
||||
|
@ -372,13 +386,13 @@ bool DDA::Init(const GCodes::RawMove &nextMove, bool doMotorMapping)
|
|||
reqSpeed /= maxDistance; // because normalisedDirectionVector is unit-normalised
|
||||
}
|
||||
}
|
||||
requestedSpeed = max<float>(0.5, min<float>(reqSpeed, VectorBoxIntersection(normalisedDirectionVector, reprap.GetPlatform()->MaxFeedrates(), DRIVES)));
|
||||
requestedSpeed = constrain<float>(reqSpeed, 0.5, VectorBoxIntersection(normalisedDirectionVector, reprap.GetPlatform()->MaxFeedrates(), DRIVES));
|
||||
|
||||
// On a Cartesian or CoreXY printer, it is OK to limit the X and Y speeds and accelerations independently, and in consequence to allow greater values
|
||||
// for diagonal moves. On a delta, this is not OK and any movement in the XY plane should be limited to the X/Y axis values, which we assume to be equal.
|
||||
if (isDeltaMovement)
|
||||
{
|
||||
const float xyFactor = sqrt(fsquare(normalisedDirectionVector[X_AXIS]) + fsquare(normalisedDirectionVector[X_AXIS]));
|
||||
const float xyFactor = sqrtf(fsquare(normalisedDirectionVector[X_AXIS]) + fsquare(normalisedDirectionVector[X_AXIS]));
|
||||
const float maxSpeed = reprap.GetPlatform()->MaxFeedrates()[X_AXIS];
|
||||
if (requestedSpeed * xyFactor > maxSpeed)
|
||||
{
|
||||
|
@ -392,7 +406,7 @@ bool DDA::Init(const GCodes::RawMove &nextMove, bool doMotorMapping)
|
|||
}
|
||||
}
|
||||
|
||||
// 6. Calculate the provisional accelerate and decelerate distances and the top speed
|
||||
// 7. Calculate the provisional accelerate and decelerate distances and the top speed
|
||||
endSpeed = 0.0; // until the next move asks us to adjust it
|
||||
|
||||
if (prev->state != provisional)
|
||||
|
@ -827,13 +841,13 @@ void DDA::Prepare()
|
|||
float DDA::VectorBoxIntersection(const float v[], const float box[], size_t dimensions)
|
||||
{
|
||||
// Generate a vector length that is guaranteed to exceed the size of the box
|
||||
float biggerThanBoxDiagonal = 2.0*Magnitude(box, dimensions);
|
||||
const float biggerThanBoxDiagonal = 2.0*Magnitude(box, dimensions);
|
||||
float magnitude = biggerThanBoxDiagonal;
|
||||
for (size_t d = 0; d < dimensions; d++)
|
||||
{
|
||||
if (biggerThanBoxDiagonal*v[d] > box[d])
|
||||
{
|
||||
float a = box[d]/v[d];
|
||||
const float a = box[d]/v[d];
|
||||
if (a < magnitude)
|
||||
{
|
||||
magnitude = a;
|
||||
|
@ -863,8 +877,7 @@ float DDA::Magnitude(const float v[], size_t dimensions)
|
|||
{
|
||||
magnitude += v[d]*v[d];
|
||||
}
|
||||
magnitude = sqrtf(magnitude);
|
||||
return magnitude;
|
||||
return sqrtf(magnitude);
|
||||
}
|
||||
|
||||
// Multiply a vector by a scalar
|
||||
|
|
|
@ -185,10 +185,10 @@ void Move::Spin()
|
|||
if (simulationMode < 2) // in simulation mode 2 and higher, we don't process incoming moves beyond this point
|
||||
{
|
||||
|
||||
bool doMotorMapping = (nextMove.moveType == 0) || (nextMove.moveType == 1 && !IsDeltaMode());
|
||||
const bool doMotorMapping = (nextMove.moveType == 0) || (nextMove.moveType == 1 && !IsDeltaMode());
|
||||
if (doMotorMapping)
|
||||
{
|
||||
Transform(nextMove.coords, nextMove.xAxes);
|
||||
Transform(nextMove.coords, nextMove.xAxes, true);
|
||||
}
|
||||
if (ddaRingAddPointer->Init(nextMove, doMotorMapping))
|
||||
{
|
||||
|
@ -481,7 +481,7 @@ int32_t Move::MotorEndPointToMachine(size_t drive, float coord)
|
|||
// This is computationally expensive on a delta, so only call it when necessary, and never from the step ISR.
|
||||
void Move::MachineToEndPoint(const int32_t motorPos[], float machinePos[], size_t numDrives) const
|
||||
{
|
||||
const float *stepsPerUnit = reprap.GetPlatform()->GetDriveStepsPerUnit();
|
||||
const float * const stepsPerUnit = reprap.GetPlatform()->GetDriveStepsPerUnit();
|
||||
|
||||
// Convert the axes
|
||||
if (IsDeltaMode())
|
||||
|
@ -629,10 +629,13 @@ void Move::InverseAxisTransform(float xyzPoint[MAX_AXES]) const
|
|||
xyzPoint[X_AXIS] -= (tanXY*xyzPoint[Y_AXIS] + tanXZ*xyzPoint[Z_AXIS]);
|
||||
}
|
||||
|
||||
void Move::Transform(float xyzPoint[MAX_AXES], uint32_t xAxes) const
|
||||
void Move::Transform(float xyzPoint[MAX_AXES], uint32_t xAxes, bool useBedCompensation) const
|
||||
{
|
||||
AxisTransform(xyzPoint);
|
||||
BedTransform(xyzPoint, xAxes);
|
||||
if (useBedCompensation)
|
||||
{
|
||||
BedTransform(xyzPoint, xAxes);
|
||||
}
|
||||
}
|
||||
|
||||
void Move::InverseTransform(float xyzPoint[MAX_AXES], uint32_t xAxes) const
|
||||
|
@ -804,13 +807,13 @@ void Move::SetAxisCompensation(int8_t axis, float tangent)
|
|||
|
||||
void Move::BarycentricCoordinates(size_t p1, size_t p2, size_t p3, float x, float y, float& l1, float& l2, float& l3) const
|
||||
{
|
||||
float y23 = baryYBedProbePoints[p2] - baryYBedProbePoints[p3];
|
||||
float x3 = x - baryXBedProbePoints[p3];
|
||||
float x32 = baryXBedProbePoints[p3] - baryXBedProbePoints[p2];
|
||||
float y3 = y - baryYBedProbePoints[p3];
|
||||
float x13 = baryXBedProbePoints[p1] - baryXBedProbePoints[p3];
|
||||
float y13 = baryYBedProbePoints[p1] - baryYBedProbePoints[p3];
|
||||
float iDet = 1.0 / (y23 * x13 + x32 * y13);
|
||||
const float y23 = baryYBedProbePoints[p2] - baryYBedProbePoints[p3];
|
||||
const float x3 = x - baryXBedProbePoints[p3];
|
||||
const float x32 = baryXBedProbePoints[p3] - baryXBedProbePoints[p2];
|
||||
const float y3 = y - baryYBedProbePoints[p3];
|
||||
const float x13 = baryXBedProbePoints[p1] - baryXBedProbePoints[p3];
|
||||
const float y13 = baryYBedProbePoints[p1] - baryYBedProbePoints[p3];
|
||||
const float iDet = 1.0 / (y23 * x13 + x32 * y13);
|
||||
l1 = (y23 * x3 + x32 * y3) * iDet;
|
||||
l2 = (-y13 * x3 + x13 * y3) * iDet;
|
||||
l3 = 1.0 - l1 - l2;
|
||||
|
@ -831,7 +834,7 @@ float Move::TriangleZ(float x, float y) const
|
|||
{
|
||||
for (size_t i = 0; i < 4; i++)
|
||||
{
|
||||
size_t j = (i + 1) % 4;
|
||||
const size_t j = (i + 1) % 4;
|
||||
float l1, l2, l3;
|
||||
BarycentricCoordinates(i, j, 4, x, y, l1, l2, l3);
|
||||
if (l1 > TRIANGLE_ZERO && l2 > TRIANGLE_ZERO && l3 > TRIANGLE_ZERO)
|
||||
|
@ -1173,7 +1176,10 @@ void Move::DoDeltaCalibration(size_t numFactors, StringRef& reply)
|
|||
// Decide whether to do another iteration. Two is slightly better than one, but three doesn't improve things.
|
||||
// Alternatively, we could stop when the expected RMS error is only slightly worse than the RMS of the residuals.
|
||||
++iteration;
|
||||
if (iteration == 2) break;
|
||||
if (iteration == 2)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Print out the calculation time
|
||||
|
@ -1235,7 +1241,7 @@ void Move::DeltaProbeInterrupt()
|
|||
deltaProbe.Trigger();
|
||||
}
|
||||
|
||||
bool dir = deltaProbe.GetDirection();
|
||||
const bool dir = deltaProbe.GetDirection();
|
||||
Platform * const platform = reprap.GetPlatform();
|
||||
platform->SetDirection(X_AXIS, dir);
|
||||
platform->SetDirection(Y_AXIS, dir);
|
||||
|
@ -1245,7 +1251,7 @@ void Move::DeltaProbeInterrupt()
|
|||
Platform::StepDriversHigh(steppersMoving);
|
||||
ShortDelay();
|
||||
Platform::StepDriversLow();
|
||||
uint32_t tim = deltaProbe.CalcNextStepTime();
|
||||
const uint32_t tim = deltaProbe.CalcNextStepTime();
|
||||
again = (tim != 0xFFFFFFFF && platform->ScheduleInterrupt(tim + deltaProbingStartTime));
|
||||
} while (again);
|
||||
}
|
||||
|
@ -1295,11 +1301,9 @@ void Move::HitHighStop(size_t axis, DDA* hitDDA)
|
|||
{
|
||||
if (axis < reprap.GetGCodes()->GetNumAxes()) // should always be true
|
||||
{
|
||||
float hitPoint = (IsDeltaMode())
|
||||
? deltaParams.GetHomedCarriageHeight(axis)
|
||||
// this is a delta printer, so the motor is at the homed carriage height for this drive
|
||||
: reprap.GetPlatform()->AxisMaximum(axis);
|
||||
// this is a Cartesian printer, so we're at the maximum for this axis
|
||||
const float hitPoint = (IsDeltaMode())
|
||||
? deltaParams.GetHomedCarriageHeight(axis) // this is a delta printer, so the motor is at the homed carriage height for this drive
|
||||
: reprap.GetPlatform()->AxisMaximum(axis); // this is a Cartesian printer, so we're at the maximum for this axis
|
||||
JustHomed(axis, hitPoint, hitDDA);
|
||||
}
|
||||
}
|
||||
|
@ -1335,7 +1339,7 @@ void Move::ZProbeTriggered(DDA* hitDDA)
|
|||
// Return the untransformed machine coordinates
|
||||
void Move::GetCurrentMachinePosition(float m[DRIVES], bool disableMotorMapping) const
|
||||
{
|
||||
DDA *lastQueuedMove = ddaRingAddPointer->GetPrevious();
|
||||
DDA * const lastQueuedMove = ddaRingAddPointer->GetPrevious();
|
||||
const size_t numAxes = reprap.GetGCodes()->GetNumAxes();
|
||||
for (size_t i = 0; i < DRIVES; i++)
|
||||
{
|
||||
|
@ -1359,7 +1363,7 @@ void Move::GetCurrentMachinePosition(float m[DRIVES], bool disableMotorMapping)
|
|||
bool Move::IsExtruding() const
|
||||
{
|
||||
cpu_irq_disable();
|
||||
bool rslt = currentDda != nullptr && currentDda->IsPrintingMove();
|
||||
const bool rslt = currentDda != nullptr && currentDda->IsPrintingMove();
|
||||
cpu_irq_enable();
|
||||
return rslt;
|
||||
}
|
||||
|
|
|
@ -77,7 +77,7 @@ public:
|
|||
void SetAxisCompensation(int8_t axis, float tangent); // Set an axis-pair compensation angle
|
||||
float AxisCompensation(int8_t axis) const; // The tangent value
|
||||
void SetIdentityTransform(); // Cancel the bed equation; does not reset axis angle compensation
|
||||
void Transform(float move[], uint32_t xAxes) const; // Take a position and apply the bed and the axis-angle compensations
|
||||
void Transform(float move[], uint32_t xAxes, bool useBedCompensation) const; // Take a position and apply the bed and the axis-angle compensations
|
||||
void InverseTransform(float move[], uint32_t xAxes) const; // Go from a transformed point back to user coordinates
|
||||
float GetTaperHeight() const { return (useTaper) ? taperHeight : 0.0; }
|
||||
void SetTaperHeight(float h);
|
||||
|
|
|
@ -362,7 +362,7 @@ bool PrintMonitor::GetFileInfo(const char *directory, const char *fileName, GCod
|
|||
}
|
||||
|
||||
uint32_t startTime = millis();
|
||||
int nbytes = fileBeingParsed->Read(&buf[fileOverlapLength], sizeToRead);
|
||||
const int nbytes = fileBeingParsed->Read(&buf[fileOverlapLength], sizeToRead);
|
||||
if (nbytes != (int)sizeToRead)
|
||||
{
|
||||
platform->MessageF(HOST_MESSAGE, "Error: Failed to read header of G-Code file \"%s\"\n", fileName);
|
||||
|
@ -1010,52 +1010,47 @@ bool PrintMonitor::FindHeight(const char* buf, size_t len, float& height) const
|
|||
// Scan the buffer for the layer height. The buffer is null-terminated.
|
||||
bool PrintMonitor::FindLayerHeight(const char *buf, size_t len, float& layerHeight) const
|
||||
{
|
||||
// Look for layer_height as generated by Slic3r
|
||||
const char* layerHeightStringSlic3r = "; layer_height ";
|
||||
const char *pos = strstr(buf, layerHeightStringSlic3r);
|
||||
if (pos != nullptr)
|
||||
static const char* const layerHeightStrings[] =
|
||||
{
|
||||
pos += strlen(layerHeightStringSlic3r);
|
||||
while (strchr(" \t=:", *pos))
|
||||
"layer_height", // slic3r
|
||||
"Layer height", // Cura
|
||||
"layerHeight", // S3D
|
||||
"layer_thickness_mm", // Kisslicer
|
||||
"layerThickness" // Matter Control
|
||||
};
|
||||
|
||||
if (*buf != 0)
|
||||
{
|
||||
++buf; // make sure we can look back 1 character after we find a match
|
||||
for (size_t i = 0; i < ARRAY_SIZE(layerHeightStrings); ++i) // search for each string in turn
|
||||
{
|
||||
++pos;
|
||||
const char *pos = buf;
|
||||
for(;;) // loop until success or strstr returns null
|
||||
{
|
||||
pos = strstr(pos, layerHeightStrings[i]);
|
||||
if (pos == nullptr)
|
||||
{
|
||||
break; // didn't find this string in the buffer, so try the next string
|
||||
}
|
||||
|
||||
const char c = pos[-1]; // fetch the previous character
|
||||
pos += strlen(layerHeightStrings[i]); // skip the string we matched
|
||||
if (c == ' ' || c == ';' || c == '\t') // check we are not in the middle of a word
|
||||
{
|
||||
while (strchr(" \t=:,", *pos) != nullptr) // skip the possible separators
|
||||
{
|
||||
++pos;
|
||||
}
|
||||
char *tailPtr;
|
||||
const float val = strtod(pos, &tailPtr);
|
||||
if (tailPtr != pos) // if we found and converted a number
|
||||
{
|
||||
layerHeight = val;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
layerHeight = strtod(pos, nullptr);
|
||||
return true;
|
||||
}
|
||||
|
||||
// Look for layer height as generated by Cura
|
||||
const char* layerHeightStringCura = "Layer height: ";
|
||||
pos = strstr(buf, layerHeightStringCura);
|
||||
if (pos != nullptr)
|
||||
{
|
||||
pos += strlen(layerHeightStringCura);
|
||||
while (strchr(" \t=:", *pos))
|
||||
{
|
||||
++pos;
|
||||
}
|
||||
layerHeight = strtod(pos, nullptr);
|
||||
return true;
|
||||
}
|
||||
|
||||
// Look for layer height as generated by S3D
|
||||
const char* layerHeightStringS3D = "layerHeight,";
|
||||
pos = strstr(buf, layerHeightStringS3D);
|
||||
if (pos != nullptr)
|
||||
{
|
||||
pos += strlen(layerHeightStringS3D);
|
||||
layerHeight = strtod(pos, nullptr);
|
||||
return true;
|
||||
}
|
||||
|
||||
// Look for layer height as generated by KISSlicer
|
||||
const char* layerHeightStringKisslicer = "layer_thickness_mm = ";
|
||||
pos = strstr(buf, layerHeightStringKisslicer);
|
||||
if (pos != nullptr)
|
||||
{
|
||||
pos += strlen(layerHeightStringKisslicer);
|
||||
layerHeight = strtod(pos, nullptr);
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
|
|
|
@ -9,11 +9,11 @@
|
|||
#define SRC_VERSION_H_
|
||||
|
||||
#ifndef VERSION
|
||||
# define VERSION "1.17b"
|
||||
# define VERSION "1.17c"
|
||||
#endif
|
||||
|
||||
#ifndef DATE
|
||||
# define DATE "2017-01-07"
|
||||
# define DATE "2017-01-14"
|
||||
#endif
|
||||
|
||||
#define AUTHORS "reprappro, dc42, chrishamm, t3p3, dnewman"
|
||||
|
|
Reference in a new issue