diff options
author | David Crocker <dcrocker@eschertech.com> | 2017-01-14 21:51:55 +0300 |
---|---|---|
committer | David Crocker <dcrocker@eschertech.com> | 2017-01-14 21:52:12 +0300 |
commit | efcb1e5ce650788d3a82727880e258c2e44ec324 (patch) | |
tree | 66655befe44b65bca262312a3da7cf100a776a49 | |
parent | 15114700f05b82d168703290be55b2fa6dc74dda (diff) |
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
-rw-r--r-- | Release/Duet-0.6-0.8.5/Stable/DuetWebControl-1.14a.zip (renamed from Release/Duet-0.6-0.8.5/Stable/DuetWebControl-1.14.zip) | bin | 477735 -> 478936 bytes | |||
-rw-r--r-- | Release/Duet-0.6-0.8.5/Stable/RepRapFirmware-1.17c.bin | bin | 0 -> 320276 bytes | |||
-rw-r--r-- | Release/Duet-WiFi/Stable/DuetWebControl-1.14a.bin (renamed from Release/Duet-WiFi/Stable/DuetWebControl-1.14.bin) | bin | 3125248 -> 3125248 bytes | |||
-rw-r--r-- | Release/Duet-WiFi/Stable/DuetWiFiFirmware-1.17c.bin | bin | 0 -> 269788 bytes | |||
-rw-r--r-- | src/GCodes/GCodeBuffer.cpp | 19 | ||||
-rw-r--r-- | src/GCodes/GCodeBuffer.h | 1 | ||||
-rw-r--r-- | src/GCodes/GCodes.cpp | 33 | ||||
-rw-r--r-- | src/GCodes/GCodes.h | 2 | ||||
-rw-r--r-- | src/GCodes/GCodes2.cpp | 62 | ||||
-rw-r--r-- | src/Movement/DDA.cpp | 61 | ||||
-rw-r--r-- | src/Movement/Move.cpp | 50 | ||||
-rw-r--r-- | src/Movement/Move.h | 2 | ||||
-rw-r--r-- | src/PrintMonitor.cpp | 81 | ||||
-rw-r--r-- | src/Version.h | 4 |
14 files changed, 184 insertions, 131 deletions
diff --git a/Release/Duet-0.6-0.8.5/Stable/DuetWebControl-1.14.zip b/Release/Duet-0.6-0.8.5/Stable/DuetWebControl-1.14a.zip Binary files differindex c89f82b5..18e5ba2c 100644 --- a/Release/Duet-0.6-0.8.5/Stable/DuetWebControl-1.14.zip +++ b/Release/Duet-0.6-0.8.5/Stable/DuetWebControl-1.14a.zip diff --git a/Release/Duet-0.6-0.8.5/Stable/RepRapFirmware-1.17c.bin b/Release/Duet-0.6-0.8.5/Stable/RepRapFirmware-1.17c.bin Binary files differnew file mode 100644 index 00000000..02acb7e9 --- /dev/null +++ b/Release/Duet-0.6-0.8.5/Stable/RepRapFirmware-1.17c.bin diff --git a/Release/Duet-WiFi/Stable/DuetWebControl-1.14.bin b/Release/Duet-WiFi/Stable/DuetWebControl-1.14a.bin Binary files differindex 5866d339..b79a3a2c 100644 --- a/Release/Duet-WiFi/Stable/DuetWebControl-1.14.bin +++ b/Release/Duet-WiFi/Stable/DuetWebControl-1.14a.bin diff --git a/Release/Duet-WiFi/Stable/DuetWiFiFirmware-1.17c.bin b/Release/Duet-WiFi/Stable/DuetWiFiFirmware-1.17c.bin Binary files differnew file mode 100644 index 00000000..3f45a8de --- /dev/null +++ b/Release/Duet-WiFi/Stable/DuetWiFiFirmware-1.17c.bin diff --git a/src/GCodes/GCodeBuffer.cpp b/src/GCodes/GCodeBuffer.cpp index 1db905bb..ee852627 100644 --- a/src/GCodes/GCodeBuffer.cpp +++ b/src/GCodes/GCodeBuffer.cpp @@ -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() { diff --git a/src/GCodes/GCodeBuffer.h b/src/GCodes/GCodeBuffer.h index 198512d1..79c79d36 100644 --- a/src/GCodes/GCodeBuffer.h +++ b/src/GCodes/GCodeBuffer.h @@ -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); diff --git a/src/GCodes/GCodes.cpp b/src/GCodes/GCodes.cpp index 2b8b2dd7..97bebd8e 100644 --- a/src/GCodes/GCodes.cpp +++ b/src/GCodes/GCodes.cpp @@ -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 diff --git a/src/GCodes/GCodes.h b/src/GCodes/GCodes.h index 58967284..017d98dc 100644 --- a/src/GCodes/GCodes.h +++ b/src/GCodes/GCodes.h @@ -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 diff --git a/src/GCodes/GCodes2.cpp b/src/GCodes/GCodes2.cpp index 51df0408..0308fcf9 100644 --- a/src/GCodes/GCodes2.cpp +++ b/src/GCodes/GCodes2.cpp @@ -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; } diff --git a/src/Movement/DDA.cpp b/src/Movement/DDA.cpp index 52333877..3b63be51 100644 --- a/src/Movement/DDA.cpp +++ b/src/Movement/DDA.cpp @@ -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 diff --git a/src/Movement/Move.cpp b/src/Movement/Move.cpp index a63ab16d..ab419fdd 100644 --- a/src/Movement/Move.cpp +++ b/src/Movement/Move.cpp @@ -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; } diff --git a/src/Movement/Move.h b/src/Movement/Move.h index 74747c12..d23090ca 100644 --- a/src/Movement/Move.h +++ b/src/Movement/Move.h @@ -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); diff --git a/src/PrintMonitor.cpp b/src/PrintMonitor.cpp index 83fdd3da..e2d2a84c 100644 --- a/src/PrintMonitor.cpp +++ b/src/PrintMonitor.cpp @@ -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)) - { - ++pos; - } - 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) + "layer_height", // slic3r + "Layer height", // Cura + "layerHeight", // S3D + "layer_thickness_mm", // Kisslicer + "layerThickness" // Matter Control + }; + + if (*buf != 0) { - pos += strlen(layerHeightStringCura); - while (strchr(" \t=:", *pos)) + ++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; - } - 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; - } + 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 + } - // 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; + 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; + } + } + } + } } return false; diff --git a/src/Version.h b/src/Version.h index 376762a8..6bf69967 100644 --- a/src/Version.h +++ b/src/Version.h @@ -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" |