Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/Duet3D/RepRapFirmware.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorDavid Crocker <dcrocker@eschertech.com>2016-11-19 12:58:13 +0300
committerDavid Crocker <dcrocker@eschertech.com>2016-11-19 12:58:45 +0300
commit59dd1b2dc56ebd35c936e4722cdc76e03fc301f2 (patch)
treea9126c6ad4878667beddd022b6ab3cdc2ff2acf3 /src
parent4669a36386a0c8530a0d39e3bfa7601afacc3fdd (diff)
Version 1.17dev4
Added support for M557 grid definition and G29 grid probing (not complete yet) Workaround for DWC sending volume ID in new name when renaming a file across directories G1 moves with S2 modifier no longer ad the tool offset
Diffstat (limited to 'src')
-rw-r--r--src/Configuration.h21
-rw-r--r--src/GCodes/GCodeBuffer.h12
-rw-r--r--src/GCodes/GCodeMachineState.h6
-rw-r--r--src/GCodes/GCodes.cpp333
-rw-r--r--src/GCodes/GCodes.h5
-rw-r--r--src/Movement/Grid.cpp216
-rw-r--r--src/Movement/Grid.h66
-rw-r--r--src/Movement/Move.cpp59
-rw-r--r--src/Movement/Move.h23
-rw-r--r--src/Platform.cpp14
-rw-r--r--src/Platform.h1
-rw-r--r--src/Storage/MassStorage.cpp7
12 files changed, 699 insertions, 64 deletions
diff --git a/src/Configuration.h b/src/Configuration.h
index f3947989..40d2b9e5 100644
--- a/src/Configuration.h
+++ b/src/Configuration.h
@@ -28,11 +28,11 @@ Licence: GPL
// Firmware name is now defined in the Pins file
#ifndef VERSION
-# define VERSION "1.17dev4"
+# define VERSION "1.17dev5"
#endif
#ifndef DATE
-# define DATE "2016-11-17"
+# define DATE "2016-11-19"
#endif
#define AUTHORS "reprappro, dc42, zpl, t3p3, dnewman"
@@ -124,16 +124,23 @@ const unsigned int DefaultPinWritePwmFreq = 500; // default PWM frequency for M4
// The maximum number of probe points is constrained by RAM usage:
// - Each probe point uses 12 bytes of static RAM. So 16 points use 192 bytes
-// - The delta probe points use the same static ram, but when auto-calibrating we temporarily need another 44 bytes per probe point to hold the matrices etc.
+// - The delta calibration points use the same static ram, but when auto-calibrating we temporarily need another 44 bytes per calibration point to hold the matrices etc.
// So 16 points need 704 bytes of stack space.
#ifdef DUET_NG
-const size_t MAX_PROBE_POINTS = 64; // Maximum number of probe points
-const size_t MAX_DELTA_PROBE_POINTS = 64; // Must be <= MaxProbePoints, may be smaller to reduce matrix storage requirements. Preferably a power of 2.
+const size_t MaxGridProbePoints = 441; // 441 allows us to probe e.g. 400x400 at 20mm intervals
+const size_t MaxProbePoints = 64; // Maximum number of probe points
+const size_t MaxDeltaCalibrationPoints = 64; // Should a power of 2 for speed
#else
-const size_t MAX_PROBE_POINTS = 32; // Maximum number of probe points
-const size_t MAX_DELTA_PROBE_POINTS = 32; // Must be <= MaxProbePoints, may be smaller to reduce matrix storage requirements. Preferably a power of 2.
+const size_t MaxGridProbePoints = 121; // 121 allows us to probe 200x200 at 20mm intervals
+const size_t MaxProbePoints = 32; // Maximum number of probe points
+const size_t MaxDeltaCalibrationPoints = 32; // Should a power of 2 for speed
#endif
+const float DefaultGridSpacing = 20.0; // Default bed probing grid spacing in mm
+
+static_assert(MaxProbePoints <= MaxGridProbePoints, "MaxProbePoints must be <= MaxGridProbePoints");
+static_assert(MaxDeltaCalibrationPoints <= MaxProbePoints, "MaxDeltaCalibrationPoints must be <= MaxProbePoints");
+
const float DEFAULT_Z_DIVE = 5.0; // Millimetres
const float DEFAULT_PROBE_SPEED = 2.0; // Default Z probing speed mm/sec
const float DEFAULT_TRAVEL_SPEED = 100.0; // Default speed for travel to probe points
diff --git a/src/GCodes/GCodeBuffer.h b/src/GCodes/GCodeBuffer.h
index 0032c081..aa8723c9 100644
--- a/src/GCodes/GCodeBuffer.h
+++ b/src/GCodes/GCodeBuffer.h
@@ -46,6 +46,8 @@ public:
bool PushState(); // Push state returning true if successful (i.e. stack not overflowed)
bool PopState(); // Pop state returning true if successful (i.e. no stack underrun)
bool IsDoingFileMacro() const; // Return true if this source is executing a file macro
+ GCodeState GetState() const;
+ void SetState(GCodeState newState);
private:
@@ -106,4 +108,14 @@ inline void GCodeBuffer::SetWritingFileDirectory(const char* wfd)
writingFileDirectory = wfd;
}
+inline GCodeState GCodeBuffer::GetState() const
+{
+ return machineState->state;
+}
+
+inline void GCodeBuffer::SetState(GCodeState newState)
+{
+ machineState->state = newState;
+}
+
#endif /* GCODEBUFFER_H_ */
diff --git a/src/GCodes/GCodeMachineState.h b/src/GCodes/GCodeMachineState.h
index 3e60f661..8424738a 100644
--- a/src/GCodes/GCodeMachineState.h
+++ b/src/GCodes/GCodeMachineState.h
@@ -32,7 +32,11 @@ enum class GCodeState : uint8_t
flashing1,
flashing2,
stopping,
- sleeping
+ sleeping,
+ gridProbing1,
+ gridProbing2,
+ gridProbing3,
+ gridProbing4
};
// Class to hold the state of gcode execution for some input source
diff --git a/src/GCodes/GCodes.cpp b/src/GCodes/GCodes.cpp
index 79ca3dda..eb732666 100644
--- a/src/GCodes/GCodes.cpp
+++ b/src/GCodes/GCodes.cpp
@@ -202,7 +202,7 @@ void GCodes::Spin()
StringRef reply(replyBuffer, ARRAY_SIZE(replyBuffer));
reply.Clear();
- if (gb.MachineState().state == GCodeState::normal)
+ if (gb.GetState() == GCodeState::normal)
{
StartNextGCode(gb, reply);
}
@@ -211,19 +211,19 @@ void GCodes::Spin()
// Perform the next operation of the state machine for this gcode source
bool error = false;
- switch (gb.MachineState().state)
+ switch (gb.GetState())
{
case GCodeState::waitingForMoveToComplete:
if (AllMovesAreFinishedAndMoveBufferIsLoaded())
{
- gb.MachineState().state = GCodeState::normal;
+ gb.SetState(GCodeState::normal);
}
break;
case GCodeState::homing:
if (toBeHomed == 0)
{
- gb.MachineState().state = GCodeState::normal;
+ gb.SetState(GCodeState::normal);
}
else
{
@@ -243,7 +243,7 @@ void GCodes::Spin()
case GCodeState::setBed1:
reprap.GetMove()->SetIdentityTransform();
probeCount = 0;
- gb.MachineState().state = GCodeState::setBed2;
+ gb.SetState(GCodeState::setBed2);
// no break
case GCodeState::setBed2:
@@ -256,7 +256,7 @@ void GCodes::Spin()
{
zProbesSet = true;
reprap.GetMove()->FinishedBedProbing(0, reply);
- gb.MachineState().state = GCodeState::normal;
+ gb.SetState(GCodeState::normal);
}
}
}
@@ -270,7 +270,7 @@ void GCodes::Spin()
reprap.StandbyTool(oldTool->Number());
}
}
- gb.MachineState().state = GCodeState::toolChange2;
+ gb.SetState(GCodeState::toolChange2);
if (reprap.GetTool(newToolNumber) != nullptr && AllAxesAreHomed())
{
scratchString.printf("tpre%d.g", newToolNumber);
@@ -280,7 +280,7 @@ void GCodes::Spin()
case GCodeState::toolChange2: // Select the new tool (even if it doesn't exist - that just deselects all tools)
reprap.SelectTool(newToolNumber);
- gb.MachineState().state = GCodeState::toolChange3;
+ gb.SetState(GCodeState::toolChange3);
if (reprap.GetTool(newToolNumber) != nullptr && AllAxesAreHomed())
{
scratchString.printf("tpost%d.g", newToolNumber);
@@ -289,13 +289,13 @@ void GCodes::Spin()
break;
case GCodeState::toolChange3:
- gb.MachineState().state = GCodeState::normal;
+ gb.SetState(GCodeState::normal);
break;
case GCodeState::pausing1:
if (AllMovesAreFinishedAndMoveBufferIsLoaded())
{
- gb.MachineState().state = GCodeState::pausing2;
+ gb.SetState(GCodeState::pausing2);
DoFileMacro(gb, PAUSE_G);
}
break;
@@ -324,16 +324,16 @@ void GCodes::Spin()
moveBuffer.endStopsToCheck = 0;
moveBuffer.usePressureAdvance = false;
moveBuffer.filePos = noFilePosition;
- if (gb.MachineState().state == GCodeState::resuming1 && currentZ > pauseRestorePoint.moveCoords[Z_AXIS])
+ if (gb.GetState() == GCodeState::resuming1 && currentZ > pauseRestorePoint.moveCoords[Z_AXIS])
{
// First move the head to the correct XY point, then move it down in a separate move
moveBuffer.coords[Z_AXIS] = currentZ;
- gb.MachineState().state = GCodeState::resuming2;
+ gb.SetState(GCodeState::resuming2);
}
else
{
// Just move to the saved position in one go
- gb.MachineState().state = GCodeState::resuming3;
+ gb.SetState(GCodeState::resuming3);
}
moveAvailable = true;
}
@@ -353,7 +353,7 @@ void GCodes::Spin()
feedRate = pauseRestorePoint.feedRate;
isPaused = false;
reply.copy("Printing resumed");
- gb.MachineState().state = GCodeState::normal;
+ gb.SetState(GCodeState::normal);
}
break;
@@ -375,11 +375,11 @@ void GCodes::Spin()
}
if (!updating)
{
- gb.MachineState().state = GCodeState::flashing2;
+ gb.SetState(GCodeState::flashing2);
}
}
#else
- gb.MachineState().state = GCodeState::flashing2;
+ gb.SetState(GCodeState::flashing2;
#endif
break;
@@ -392,7 +392,7 @@ void GCodes::Spin()
// The above call does not return unless an error occurred
}
isFlashing = false;
- gb.MachineState().state = GCodeState::normal;
+ gb.SetState(GCodeState::normal);
break;
case GCodeState::stopping: // MO after executing stop.g if present
@@ -410,7 +410,7 @@ void GCodes::Spin()
// chrishamm 2014-18-10: Although RRP says M0 is supposed to turn off all drives and heaters,
// I think M1 is sufficient for this purpose. Leave M0 for a normal reset.
- if (gb.MachineState().state == GCodeState::sleeping)
+ if (gb.GetState() == GCodeState::sleeping)
{
DisableDrives();
}
@@ -418,14 +418,147 @@ void GCodes::Spin()
{
platform->SetDriversIdle();
}
- gb.MachineState().state = GCodeState::normal;
+ gb.SetState(GCodeState::normal);
+ break;
+
+ case GCodeState::gridProbing1: // ready to move to next grid probe point
+ {
+ // Move to the current probe point
+ const GridDefinition grid = reprap.GetMove()->GetBedProbeGrid();
+ const float x = grid.GetXCoordinate(gridXindex);
+ const float y = grid.GetYCoordinate(gridYindex);
+ if (grid.IsInRadius(x, y) && platform->IsAccessibleProbePoint(x, y))
+ {
+ moveBuffer.moveType = 0;
+ moveBuffer.endStopsToCheck = 0;
+ moveBuffer.usePressureAdvance = false;
+ moveBuffer.filePos = noFilePosition;
+ moveBuffer.coords[X_AXIS] = x - platform->GetZProbeParameters().xOffset;
+ moveBuffer.coords[Y_AXIS] = y - platform->GetZProbeParameters().yOffset;
+ moveBuffer.coords[Z_AXIS] = platform->GetZProbeDiveHeight();
+ moveBuffer.feedRate = platform->GetZProbeTravelSpeed();
+ moveAvailable = true;
+ gb.SetState(GCodeState::gridProbing2);
+ }
+ else
+ {
+ gb.SetState(GCodeState::gridProbing4);
+ }
+ }
+ break;
+
+ case GCodeState::gridProbing2: // ready to probe the current grid probe point
+ if (AllMovesAreFinishedAndMoveBufferIsLoaded())
+ {
+ // Probe the bed at the current XY coordinates
+ // Check for probe already triggered at start
+ if (reprap.GetPlatform()->GetZProbeResult() == EndStopHit::lowHit)
+ {
+ reply.copy("Z probe already triggered before probing move started");
+ error = true;
+ gb.SetState(GCodeState::normal);
+ break;
+ }
+
+ zProbeTriggered = false;
+ moveBuffer.moveType = 0;
+ moveBuffer.endStopsToCheck = ZProbeActive;
+ moveBuffer.usePressureAdvance = false;
+ moveBuffer.filePos = noFilePosition;
+ moveBuffer.coords[Z_AXIS] = -platform->GetZProbeDiveHeight();
+ moveBuffer.feedRate = platform->GetZProbeParameters().probeSpeed;
+ moveAvailable = true;
+ gb.SetState(GCodeState::gridProbing3);
+ }
+ break;
+
+ case GCodeState::gridProbing3: // ready to lift the probe after probing the current grid probe point
+ if (AllMovesAreFinishedAndMoveBufferIsLoaded())
+ {
+ if (!zProbeTriggered)
+ {
+ reply.copy("Z probe was not triggered during probing move");
+ error = true;
+ gb.SetState(GCodeState::normal);
+ break;
+ }
+
+ const float heightError = moveBuffer.coords[Z_AXIS] - platform->ZProbeStopHeight();
+ reprap.GetMove()->SetGridHeight(gridXindex, gridYindex, heightError);
+ ++numPointsProbed;
+ heightSum += (double)heightError;
+ heightSquaredSum += (double)heightError * (double)heightError;
+
+ // Move back up to the dive height
+ moveBuffer.moveType = 0;
+ moveBuffer.endStopsToCheck = 0;
+ moveBuffer.usePressureAdvance = false;
+ moveBuffer.filePos = noFilePosition;
+ moveBuffer.coords[Z_AXIS] = platform->GetZProbeDiveHeight();
+ moveBuffer.feedRate = platform->GetZProbeTravelSpeed();
+ moveAvailable = true;
+ gb.SetState(GCodeState::gridProbing4);
+ }
+ break;
+
+ case GCodeState::gridProbing4: // ready to compute the next probe point
+ if (AllMovesAreFinishedAndMoveBufferIsLoaded())
+ {
+ const GridDefinition grid = reprap.GetMove()->GetBedProbeGrid();
+ if (gridYindex & 1)
+ {
+ // Odd row, so decreasing X
+ if (gridXindex == 0)
+ {
+ ++gridYindex;
+ }
+ else
+ {
+ --gridXindex;
+ }
+ }
+ else
+ {
+ // Even row, so increasing X
+ if (gridXindex + 1 == grid.NumXpoints())
+ {
+ ++gridYindex;
+ }
+ else
+ {
+ ++gridXindex;
+ }
+ }
+ if (gridYindex == grid.NumYpoints())
+ {
+ if (numPointsProbed >= 4)
+ {
+ reprap.GetMove()->UseHeightMap();
+ const double mean = heightSum/numPointsProbed;
+ const double deviation = sqrt(((heightSquaredSum * numPointsProbed) - (heightSum * heightSum)))/numPointsProbed;
+ reply.printf("%u points probed, mean error %.2f, deviation %.2f", numPointsProbed, mean, deviation);
+ }
+ else
+ {
+ reply.copy("Too few points probed");
+ error = true;
+ }
+ gb.SetState(GCodeState::normal);
+ }
+ else
+ {
+ gb.SetState(GCodeState::gridProbing1);
+ }
+ }
break;
default: // should not happen
+ platform->Message(GENERIC_MESSAGE, "Error: undefined GCodeState\n");
+ gb.SetState(GCodeState::normal);
break;
}
- if (gb.MachineState().state == GCodeState::normal)
+ if (gb.GetState() == GCodeState::normal)
{
// We completed a command, so unlock resources and tell the host about it
UnlockAll(gb);
@@ -588,7 +721,7 @@ void GCodes::DoFilePrint(GCodeBuffer& gb, StringRef& reply)
// Finished a macro
Pop(gb);
gb.Init();
- if (gb.MachineState().state == GCodeState::normal)
+ if (gb.GetState() == GCodeState::normal)
{
UnlockAll(gb);
HandleReply(gb, false, "");
@@ -719,7 +852,7 @@ void GCodes::DoPause(bool externalToFile)
{
pausedFanValues[i] = platform->GetFanValue(i);
}
- fileGCode->MachineState().state = GCodeState::pausing1;
+ fileGCode->SetState(GCodeState::pausing1);
isPaused = true;
}
@@ -889,7 +1022,7 @@ bool GCodes::LoadMoveBufferFromGCode(GCodeBuffer& gb, int moveType)
{
moveArg += moveBuffer.coords[axis];
}
- else if (currentTool != nullptr)
+ else if (currentTool != nullptr && moveType == 0)
{
moveArg -= currentTool->GetOffset()[axis]; // adjust requested position to compensate for tool offset
}
@@ -950,7 +1083,6 @@ bool GCodes::LoadMoveBufferFromGCode(GCodeBuffer& gb, int moveType)
// If the Move class can't receive the move (i.e. things have to wait), return 0.
// If we have queued the move and the caller doesn't need to wait for it to complete, return 1.
// If we need to wait for the move to complete before doing another one (e.g. because endstops are checked in this move), return 2.
-
int GCodes::SetUpMove(GCodeBuffer& gb, StringRef& reply)
{
// Last one gone yet?
@@ -1089,7 +1221,7 @@ bool GCodes::DoFileMacro(GCodeBuffer& gb, const char* fileName, bool reportMissi
}
gb.MachineState().fileState.Set(f);
gb.MachineState().doingFileMacro = true;
- gb.MachineState().state = GCodeState::normal;
+ gb.SetState(GCodeState::normal);
gb.Init();
return true;
}
@@ -1314,7 +1446,7 @@ bool GCodes::DoHome(GCodeBuffer& gb, StringRef& reply, bool& error)
}
else
{
- gb.MachineState().state = GCodeState::homing;
+ gb.SetState(GCodeState::homing);
}
}
return true;
@@ -1522,7 +1654,7 @@ bool GCodes::SetSingleZProbeAtAPosition(GCodeBuffer& gb, StringRef& reply)
}
int probePointIndex = gb.GetIValue();
- if (probePointIndex < 0 || (unsigned int)probePointIndex >= MAX_PROBE_POINTS)
+ if (probePointIndex < 0 || (unsigned int)probePointIndex >= MaxProbePoints)
{
reprap.GetPlatform()->Message(GENERIC_MESSAGE, "Z probe point index out of range.\n");
return true;
@@ -1632,6 +1764,106 @@ bool GCodes::SetPrintZProbe(GCodeBuffer& gb, StringRef& reply)
return true;
}
+// Define the probing grid, returning true if error
+// Called when we see an M557 command with no P parameter
+bool GCodes::DefineGrid(GCodeBuffer& gb, StringRef &reply)
+{
+ bool seenX = false, seenY = false, seenR = false, seenS = false;
+ float xValues[2];
+ float yValues[2];
+
+ if (gb.Seen('X'))
+ {
+ size_t count = 2;
+ gb.GetFloatArray(xValues, count, false);
+ if (count == 2)
+ {
+ seenX = true;
+ }
+ else
+ {
+ reply.copy("ERROR: Wrong number of X values in M577, need 2");
+ return true;
+ }
+ }
+ if (gb.Seen('Y'))
+ {
+ size_t count = 2;
+ gb.GetFloatArray(yValues, count, false);
+ if (count == 2)
+ {
+ seenY = true;
+ }
+ else
+ {
+ reply.copy("ERROR: Wrong number of Y values in M577, need 2");
+ return true;
+ }
+ }
+
+ float radius = -1.0;
+ gb.TryGetFValue('R', radius, seenR);
+ float spacing = DefaultGridSpacing;
+ gb.TryGetFValue('S', spacing, seenS);
+
+ if (!seenX && !seenY && !seenR && !seenS)
+ {
+ // Just print the existing grid parameters
+ const GridDefinition& grid = reprap.GetMove()->GetBedProbeGrid();
+ if (grid.IsValid())
+ {
+ reply.copy("Grid: ");
+ grid.PrintParameters(reply);
+ }
+ else
+ {
+ reply.copy("Grid is not defined");
+ }
+ return false;
+ }
+
+ if (seenX != seenY)
+ {
+ reply.copy("ERROR: specify both or neither of X and Y in M577");
+ return true;
+ }
+
+ if (!seenX && !seenR)
+ {
+ // Must have given just the S parameter
+ reply.copy("ERROR: specify at least radius or X,Y ranges in M577");
+ return true;
+
+ }
+
+ if (!seenX)
+ {
+ if (radius > 0)
+ {
+ const float effectiveRadius = floor((radius - 0.1)/spacing) * spacing;
+ xValues[0] = yValues[0] = -effectiveRadius;
+ xValues[1] = yValues[1] = effectiveRadius + 0.1;
+ }
+ else
+ {
+ reply.copy("ERROR: M577 radius must be positive unless X and Y are specified");
+ return true;
+ }
+ }
+ GridDefinition newGrid(xValues, yValues, radius, spacing); // create a new grid
+ if (newGrid.IsValid())
+ {
+ reprap.GetMove()->SetBedProbeGrid(newGrid);
+ return false;
+ }
+ else
+ {
+ reply.copy("ERROR: bad grid definition: ");
+ newGrid.PrintError(reply);
+ return true;
+ }
+}
+
// Return the current coordinates as a printable string.
// Coordinates are updated at the end of each movement, so this won't tell you where you are mid-movement.
void GCodes::GetCurrentCoordinates(StringRef& s) const
@@ -2647,7 +2879,7 @@ bool GCodes::HandleGcode(GCodeBuffer& gb, StringRef& reply)
int res = SetUpMove(gb, reply);
if (res == 2)
{
- gb.MachineState().state = GCodeState::waitingForMoveToComplete;
+ gb.SetState(GCodeState::waitingForMoveToComplete);
}
result = (res != 0);
}
@@ -2696,6 +2928,30 @@ bool GCodes::HandleGcode(GCodeBuffer& gb, StringRef& reply)
result = DoHome(gb, reply, error);
break;
+ case 29: // Grid-based bed probing
+ LockMovementAndWaitForStandstill(gb); // do this first to make sure that a new grid isn't being defined
+
+ if (!reprap.GetMove()->GetBedProbeGrid().IsValid())
+ {
+ reply.copy("No valid grid defined for G29 bed probing");
+ error = true;
+ }
+ else if (!AllAxesAreHomed())
+ {
+ reply.copy("Must home printer before G29 bed probing");
+ error = true;
+ }
+ else
+ {
+ gridXindex = gridYindex = 0;
+ numPointsProbed = 0;
+ heightSum = heightSquaredSum = 0.0;
+
+ reprap.GetMove()->ClearGridHeights();
+ gb.SetState(GCodeState::gridProbing1);
+ }
+ break;
+
case 30: // Z probe/manually set at a position and set that as point P
if (!LockMovementAndWaitForStandstill(gb))
{
@@ -2732,7 +2988,7 @@ bool GCodes::HandleGcode(GCodeBuffer& gb, StringRef& reply)
// If we get here then we are not on a delta printer and there is no bed.g file
if (GetAxisIsHomed(X_AXIS) && GetAxisIsHomed(Y_AXIS))
{
- gb.MachineState().state = GCodeState::setBed1; // no bed.g file, so use the coordinates specified by M557
+ gb.SetState(GCodeState::setBed1); // no bed.g file, so use the coordinates specified by M557
}
else
{
@@ -2760,7 +3016,7 @@ bool GCodes::HandleGcode(GCodeBuffer& gb, StringRef& reply)
reply.printf("invalid G Code: %s", gb.Buffer());
}
- if (result && gb.MachineState().state == GCodeState::normal)
+ if (result && gb.GetState() == GCodeState::normal)
{
UnlockAll(gb);
HandleReply(gb, error, reply.Pointer());
@@ -2804,7 +3060,7 @@ bool GCodes::HandleMcode(GCodeBuffer& gb, StringRef& reply)
}
}
- gb.MachineState().state = (code == 0) ? GCodeState::stopping : GCodeState::sleeping;
+ gb.SetState((code == 0) ? GCodeState::stopping : GCodeState::sleeping);
DoFileMacro(gb, (code == 0) ? STOP_G : SLEEP_G, false);
break;
@@ -3019,7 +3275,7 @@ bool GCodes::HandleMcode(GCodeBuffer& gb, StringRef& reply)
if (isPaused)
{
- gb.MachineState().state = GCodeState::resuming1;
+ gb.SetState(GCodeState::resuming1);
DoFileMacro(gb, RESUME_G);
}
else if (!fileToPrint.IsLive())
@@ -4748,7 +5004,7 @@ bool GCodes::HandleMcode(GCodeBuffer& gb, StringRef& reply)
if (gb.Seen('P'))
{
int point = gb.GetIValue();
- if (point < 0 || (unsigned int)point >= MAX_PROBE_POINTS)
+ if (point < 0 || (unsigned int)point >= MaxProbePoints)
{
reprap.GetPlatform()->Message(GENERIC_MESSAGE, "Z probe point index out of range.\n");
}
@@ -4772,6 +5028,11 @@ bool GCodes::HandleMcode(GCodeBuffer& gb, StringRef& reply)
}
}
}
+ else
+ {
+ LockMovement(gb); // to ensure that probing is not already in progress
+ error = DefineGrid(gb, reply);
+ }
break;
case 558: // Set or report Z probe type and for which axes it is used
@@ -5911,7 +6172,7 @@ bool GCodes::HandleMcode(GCodeBuffer& gb, StringRef& reply)
return false;
}
- gb.MachineState().state = GCodeState::flashing1;
+ gb.SetState(GCodeState::flashing1);
break;
case 998:
@@ -5944,7 +6205,7 @@ bool GCodes::HandleMcode(GCodeBuffer& gb, StringRef& reply)
reply.printf("unsupported command: %s", gb.Buffer());
}
- if (result && gb.MachineState().state == GCodeState::normal)
+ if (result && gb.GetState() == GCodeState::normal)
{
UnlockAll(gb);
HandleReply(gb, error, reply.Pointer());
@@ -5975,7 +6236,7 @@ bool GCodes::HandleTcode(GCodeBuffer& gb, StringRef& reply)
// If old and new are the same we no longer follow the sequence. User can deselect and then reselect the tool if he wants the macros run.
if (oldTool->Number() != newToolNumber)
{
- gb.MachineState().state = GCodeState::toolChange1;
+ gb.SetState(GCodeState::toolChange1);
if (oldTool != nullptr && AllAxesAreHomed())
{
scratchString.printf("tfree%d.g", oldTool->Number());
diff --git a/src/GCodes/GCodes.h b/src/GCodes/GCodes.h
index 140569f3..c1513714 100644
--- a/src/GCodes/GCodes.h
+++ b/src/GCodes/GCodes.h
@@ -206,6 +206,8 @@ private:
void DoPause(bool externalToFile); // Pause the print
void SetMappedFanSpeed(); // Set the speeds of fans mapped for the current tool
+ bool DefineGrid(GCodeBuffer& gb, StringRef &reply); // Define the probing grid, returning true if error
+
Platform* platform; // The RepRap machine
Webserver* webserver; // The webserver class
@@ -265,6 +267,9 @@ private:
float lastProbedZ; // the last height at which the Z probe stopped
bool zProbesSet; // True if all Z probing is done and we can set the bed equation
volatile bool zProbeTriggered; // Set by the step ISR when a move is aborted because the Z probe is triggered
+ size_t gridXindex, gridYindex; // Which grid probe point is next
+ size_t numPointsProbed;
+ double heightSum, heightSquaredSum;
float simulationTime; // Accumulated simulation time
uint8_t simulationMode; // 0 = not simulating, 1 = simulating, >1 are simulation modes for debugging
diff --git a/src/Movement/Grid.cpp b/src/Movement/Grid.cpp
new file mode 100644
index 00000000..d338ceb7
--- /dev/null
+++ b/src/Movement/Grid.cpp
@@ -0,0 +1,216 @@
+/*
+ * Grid.cpp
+ *
+ * Created on: 18 Nov 2016
+ * Author: David
+ */
+
+#include "Grid.h"
+#include "Configuration.h"
+#include <cmath>
+
+// Initialise the grid to be invalid
+GridDefinition::GridDefinition()
+ : xMin(0.0), xMax(-1.0), yMin(0.0), yMax(-1.0), radius(-1.0), spacing(DefaultGridSpacing), gridHeights(nullptr),
+ numX(0), numY(0), recipSpacing(1.0/spacing), isValid(false)
+{
+}
+
+GridDefinition::GridDefinition(const float xRange[2], const float yRange[2], float pRadius, float pSpacing)
+ : xMin(xRange[0]), xMax(xRange[1]), yMin(yRange[0]), yMax(yRange[1]), radius(pRadius), spacing(pSpacing)
+{
+ numX = (xMax - xMin >= MinRange && spacing >= MinSpacing) ? (uint32_t)((xMax - xMin)/spacing) + 1 : 0;
+ numY = (yMax - yMin >= MinRange && spacing >= MinSpacing) ? (uint32_t)((xMax - xMin)/spacing) + 1 : 0;
+ isValid = NumPoints() != 0 && NumPoints() <= MaxGridProbePoints && (radius < 0.0 || radius >= 1.0);
+}
+
+void GridDefinition::SetStorage(const float *heightStorage, const uint32_t *heightSetStorage)
+{
+ gridHeights = heightStorage;
+ gridHeightSet = heightSetStorage;
+}
+
+float GridDefinition::GetXCoordinate(unsigned int xIndex) const
+{
+ return xMin + (xIndex * spacing);
+}
+
+float GridDefinition::GetYCoordinate(unsigned int yIndex) const
+{
+ return yMin + (yIndex * spacing);
+}
+
+bool GridDefinition::IsInRadius(float x, float y) const
+{
+ return radius < 0.0 || x * x + y * y < radius * radius;
+}
+
+// Append the grid parameters to the end of a string
+void GridDefinition::PrintParameters(StringRef& r) const
+{
+ r.catf("X%.1f:%.1f, Y%.1f:%.1f, radius %.1f, spacing %.1f, %d points", xMin, xMax, yMin, yMax, radius, spacing, NumPoints());
+}
+
+// Print what is wrong with the grid
+void GridDefinition::PrintError(StringRef& r) const
+{
+ if (spacing < MinSpacing)
+ {
+ r.cat("Spacing too small");
+ }
+ else if (NumXpoints() == 0)
+ {
+ r.cat("X range too small");
+ }
+ else if (NumYpoints() == 0)
+ {
+ r.cat("Y range too small");
+ }
+ else if (NumPoints() > MaxGridProbePoints)
+ {
+ r.catf("Too many grid points (maximum %d, needed %d)", MaxGridProbePoints, NumPoints());
+ }
+ else
+ {
+ // The only thing left is a bad radius
+ r.cat("Bad radius");
+ }
+}
+
+// Compute the height error at the specified point
+float GridDefinition::ComputeHeightError(float x, float y) const
+{
+ const float xf = (x - xMin) * recipSpacing;
+ const float xFloor = floor(xf);
+ const int32_t xIndex = (int32_t)xFloor;
+ const float yf = (y - yMin) * recipSpacing;
+ const float yFloor = floor(yf);
+ const int32_t yIndex = (int32_t)yFloor;
+
+ if (xIndex < 0)
+ {
+ if (yIndex < 0)
+ {
+ // We are off the bottom left corner of the grid
+ return GetHeightError(0, 0);
+ }
+ else if (yIndex >= (int)NumYpoints())
+ {
+ return GetHeightError(0, NumYpoints());
+ }
+ else
+ {
+ return InterpolateY(0, yIndex, yf - yFloor);
+ }
+ }
+ else if (xIndex >= (int)NumXpoints())
+ {
+ if (yIndex < 0)
+ {
+ // We are off the bottom left corner of the grid
+ return GetHeightError(NumXpoints(), 0);
+ }
+ else if (yIndex >= (int)NumYpoints())
+ {
+ return GetHeightError(NumXpoints(), NumYpoints());
+ }
+ else
+ {
+ return InterpolateY(NumXpoints(), yIndex, yf - yFloor);
+ }
+ }
+ else
+ {
+ if (yIndex < 0)
+ {
+ // We are off the bottom left corner of the grid
+ return InterpolateX(xIndex, 0, xf - xFloor);
+ }
+ else if (yIndex >= (int)NumYpoints())
+ {
+ return InterpolateX(xIndex, NumYpoints(), xf - xFloor);
+ }
+ else
+ {
+ return InterpolateXY(xIndex, yIndex, xf - xFloor, yf - yFloor);
+ }
+ }
+}
+
+float GridDefinition::GetHeightError(uint32_t xIndex, uint32_t yIndex) const
+{
+ const uint32_t index = GetMapIndex(xIndex, yIndex);
+ return (IsHeightSet(index)) ? gridHeights[index] : 0.0;
+}
+
+float GridDefinition::InterpolateX(uint32_t xIndex, uint32_t yIndex, float xFrac) const
+{
+ const uint32_t index1 = GetMapIndex(xIndex, yIndex);
+ return Interpolate2(index1, index1 + 1, xFrac);
+}
+
+float GridDefinition::InterpolateY(uint32_t xIndex, uint32_t yIndex, float yFrac) const
+{
+ const uint32_t index1 = GetMapIndex(xIndex, yIndex);
+ return Interpolate2(index1, index1 + numX, yFrac);
+}
+
+float GridDefinition::Interpolate2(uint32_t index1, uint32_t index2, float frac) const
+{
+ const bool b1 = IsHeightSet(index1);
+ const bool b2 = IsHeightSet(index2);
+ return (b1 && b2) ? (frac * gridHeights[index1]) + ((1.0 - frac) * gridHeights[index2])
+ : (b1) ? gridHeights[index1]
+ : (b2) ? gridHeights[index2]
+ : 0.0;
+}
+
+float GridDefinition::InterpolateXY(uint32_t xIndex, uint32_t yIndex, float xFrac, float yFrac) const
+{
+ const uint32_t indexX0Y0 = GetMapIndex(xIndex, yIndex); // (X0,Y0)
+ const uint32_t indexX1Y0 = indexX0Y0 + 1; // (X1,Y0)
+ const uint32_t indexX0Y1 = indexX0Y0 + numX; // (X0 Y1)
+ const uint32_t indexX1Y1 = indexX0Y1 + 1; // (X1,Y1)
+ const unsigned int cc = ((unsigned int)IsHeightSet(indexX0Y0) << 0)
+ + ((unsigned int)IsHeightSet(indexX1Y0) << 1)
+ + ((unsigned int)IsHeightSet(indexX0Y1) << 2)
+ + ((unsigned int)IsHeightSet(indexX1Y1) << 3);
+ switch(cc)
+ {
+ case 0: // no points defined
+ default:
+ return 0.0;
+ case 1: // (X0,Y0) defined
+ return gridHeights[indexX0Y0];
+ case 2: // (X1,Y0) defined
+ return gridHeights[indexX1Y0];
+ case 3: // (X0,Y0) and (X1,Y0) defined
+ return Interpolate2(indexX0Y0, indexX1Y0, xFrac);
+ case 4: // (X0,Y1) defined
+ return gridHeights[indexX0Y1];
+ case 5: // (X0,Y0) and (X0,Y1) defined
+ return Interpolate2(indexX0Y0, indexX0Y1, yFrac);
+ case 6: // (X1,Y0) and (X0,Y1) defined - diagonal interpolation
+ return DiagonalInterpolate(indexX1Y0, indexX0Y1, 1.0 - xFrac, yFrac);
+ case 7: // (X0,Y0), (X1,Y0) and (X0,Y1) defined - 3-way interpolation
+ return Interpolate3(indexX0Y0, indexX1Y0, indexX0Y1, xFrac, yFrac);
+ case 8: // (X1,Y1) defined
+ return gridHeights[indexX1Y1];
+ case 9: // (X0,Y0) and (X1,Y1) defined - diagonal interpolation
+ return DiagonalInterpolate(indexX0Y0, indexX1Y1, xFrac, yFrac);
+ case 10: // (X1,Y0) and (X1,Y1) defined
+ return Interpolate2(indexX1Y0, indexX1Y1, yFrac);
+ case 11: // (X0,Y0), (X1,Y0) and (X1,Y1) defined - 3-way interpolation
+ return Interpolate3(indexX1Y0, indexX0Y0, indexX1Y1, xFrac, yFrac);
+ case 12: // (X0,Y1) and (X1,Y1) defined
+ return Interpolate2(indexX0Y1, indexX1Y1, yFrac);
+ case 13: // (X0,Y0), (X0,Y1) and (X1,Y1) defined - 3-way interpolation
+ return Interpolate3(indexX0Y1, indexX1Y1, indexX0Y0, xFrac, 1.0 - yFrac);
+ case 14: // (X1,Y0), (X0,Y1) and (X1,Y1) defined - 3-way interpolation
+ return Interpolate3(indexX1Y1, indexX0Y1, indexX1Y0, 1.0 - xFrac, 1.0 - yFrac);
+ case 15: // All points defined
+ return Interpolate4(indexX0Y0, indexX1Y0, indexX0Y1, indexX1Y1, xFrac, yFrac);
+ }
+}
+
+// End
diff --git a/src/Movement/Grid.h b/src/Movement/Grid.h
new file mode 100644
index 00000000..f03ec4e5
--- /dev/null
+++ b/src/Movement/Grid.h
@@ -0,0 +1,66 @@
+/*
+ * Grid.h
+ *
+ * Created on: 18 Nov 2016
+ * Author: David
+ */
+
+#ifndef SRC_MOVEMENT_GRID_H_
+#define SRC_MOVEMENT_GRID_H_
+
+#include <cstdint>
+#include "ecv.h"
+#include "Libraries/General/StringRef.h"
+
+// This class defines the bed probing grid
+class GridDefinition
+{
+public:
+ GridDefinition();
+ GridDefinition(const float xRange[2], const float yRange[2], float pRadius, float pSpacing);
+ void SetStorage(const float *heightStorage, const uint32_t *heightSetStorage);
+
+ uint32_t NumXpoints() const { return numX; }
+ uint32_t NumYpoints() const { return numY; }
+ uint32_t NumPoints() const { return numX * numY; }
+ float GetXCoordinate(unsigned int xIndex) const;
+ float GetYCoordinate(unsigned int yIndex) const;
+ bool IsInRadius(float x, float y) const;
+ bool IsValid() const { return isValid; }
+
+ void PrintParameters(StringRef& r) const;
+ void PrintError(StringRef& r) const
+ pre(!IsValid());
+
+ float ComputeHeightError(float x, float y) const // Compute the height error at the specified point
+ pre(IsValid(); gridHeights != nullptr; gridHeights.upb >= NumPoints());
+
+private:
+ static constexpr float MinSpacing = 0.1; // The minimum point spacing allowed
+ static constexpr float MinRange = 1.0; // The minimum X and Y range allowed
+
+ // Primary parameters
+ float xMin, xMax, yMin, yMax; // The edges of the grid for G29 probing
+ float radius; // The grid radius to probe
+ float spacing; // The spacing of the grid probe points
+ const float *gridHeights; // The map of grid heights
+ const uint32_t *gridHeightSet; // Bitmap of which heights are set
+
+ // Derived parameters
+ uint32_t numX, numY;
+ float recipSpacing;
+ bool isValid;
+
+ uint32_t GetMapIndex(uint32_t xIndex, uint32_t yIndex) const { return (yIndex * numX) + xIndex; }
+ bool IsHeightSet(uint32_t index) const { return (gridHeightSet[index/32] & (1 << (index & 31))) != 0; }
+ float GetHeightError(uint32_t xIndex, uint32_t yIndex) const;
+ float InterpolateX(uint32_t xIndex, uint32_t yIndex, float xFrac) const;
+ float InterpolateY(uint32_t xIndex, uint32_t yIndex, float yFrac) const;
+ float InterpolateXY(uint32_t xIndex, uint32_t yIndex, float xFrac, float yFrac) const;
+ float Interpolate2(uint32_t index1, uint32_t index2, float frac) const;
+ float DiagonalInterpolate(uint32_t index1, uint32_t index2, float xFrac, float yFrac) const;
+ float Interpolate3(uint32_t cornerIndex, uint32_t indexX, uint32_t indexY, float xFrac, float yFrac) const;
+ float Interpolate4(uint32_t index1, uint32_t index2, uint32_t index3, uint32_t index4, float xFrac, float yFrac) const;
+};
+
+#endif /* SRC_MOVEMENT_GRID_H_ */
diff --git a/src/Movement/Move.cpp b/src/Movement/Move.cpp
index b1235bba..9d630f34 100644
--- a/src/Movement/Move.cpp
+++ b/src/Movement/Move.cpp
@@ -66,7 +66,7 @@ void Move::Init()
SetPositions(move);
// Set up default bed probe points. This is only a guess, because we don't know the bed size yet.
- for (size_t point = 0; point < MAX_PROBE_POINTS; point++)
+ for (size_t point = 0; point < MaxProbePoints; point++)
{
if (point < 4)
{
@@ -89,6 +89,7 @@ void Move::Init()
simulationTime = 0.0;
longestGcodeWaitInterval = 0;
waitingForMove = false;
+ useGridHeights = false;
active = true;
}
@@ -865,7 +866,7 @@ void Move::FinishedBedProbing(int sParam, StringRef& reply)
// Clear out the Z heights so that we don't re-use old points.
// This allows us to use different numbers of probe point on different occasions.
- for (size_t i = 0; i < MAX_PROBE_POINTS; ++i)
+ for (size_t i = 0; i < MaxProbePoints; ++i)
{
probePointSet[i] &= ~zSet;
}
@@ -996,8 +997,8 @@ void Move::DoDeltaCalibration(size_t numFactors, StringRef& reply)
//uint32_t startTime = reprap.GetPlatform()->GetInterruptClocks();
// Transform the probing points to motor endpoints and store them in a matrix, so that we can do multiple iterations using the same data
- FixedMatrix<floatc_t, MAX_DELTA_PROBE_POINTS, DELTA_AXES> probeMotorPositions;
- floatc_t corrections[MAX_DELTA_PROBE_POINTS];
+ FixedMatrix<floatc_t, MaxDeltaCalibrationPoints, DELTA_AXES> probeMotorPositions;
+ floatc_t corrections[MaxDeltaCalibrationPoints];
float_t initialSumOfSquares = 0.0;
for (size_t i = 0; i < numPoints; ++i)
{
@@ -1028,7 +1029,7 @@ void Move::DoDeltaCalibration(size_t numFactors, StringRef& reply)
for (;;)
{
// Build a Nx9 matrix of derivatives with respect to xa, xb, yc, za, zb, zc, diagonal.
- FixedMatrix<floatc_t, MAX_DELTA_PROBE_POINTS, NumDeltaFactors> derivativeMatrix;
+ FixedMatrix<floatc_t, MaxDeltaCalibrationPoints, NumDeltaFactors> derivativeMatrix;
for (size_t i = 0; i < numPoints; ++i)
{
for (size_t j = 0; j < numFactors; ++j)
@@ -1079,7 +1080,7 @@ void Move::DoDeltaCalibration(size_t numFactors, StringRef& reply)
PrintVector("Solution", solution, numFactors);
// Calculate and display the residuals
- floatc_t residuals[MAX_DELTA_PROBE_POINTS];
+ floatc_t residuals[MaxDeltaCalibrationPoints];
for (size_t i = 0; i < numPoints; ++i)
{
residuals[i] = zBedProbePoints[i];
@@ -1096,7 +1097,7 @@ void Move::DoDeltaCalibration(size_t numFactors, StringRef& reply)
// Calculate the expected probe heights using the new parameters
{
- floatc_t expectedResiduals[MAX_DELTA_PROBE_POINTS];
+ floatc_t expectedResiduals[MaxDeltaCalibrationPoints];
floatc_t sumOfSquares = 0.0;
for (size_t i = 0; i < numPoints; ++i)
{
@@ -1383,7 +1384,7 @@ void Move::ResetExtruderPositions()
void Move::SetXBedProbePoint(size_t index, float x)
{
- if (index >= MAX_PROBE_POINTS)
+ if (index >= MaxProbePoints)
{
reprap.GetPlatform()->Message(GENERIC_MESSAGE, "Z probe point X index out of range.\n");
return;
@@ -1394,7 +1395,7 @@ void Move::SetXBedProbePoint(size_t index, float x)
void Move::SetYBedProbePoint(size_t index, float y)
{
- if (index >= MAX_PROBE_POINTS)
+ if (index >= MaxProbePoints)
{
reprap.GetPlatform()->Message(GENERIC_MESSAGE, "Z probe point Y index out of range.\n");
return;
@@ -1405,12 +1406,13 @@ void Move::SetYBedProbePoint(size_t index, float y)
void Move::SetZBedProbePoint(size_t index, float z, bool wasXyCorrected, bool wasError)
{
- if (index >= MAX_PROBE_POINTS)
+ if (index >= MaxProbePoints)
{
reprap.GetPlatform()->Message(GENERIC_MESSAGE, "Z probe point Z index out of range.\n");
}
else
{
+ useGridHeights = false;
zBedProbePoints[index] = z;
probePointSet[index] |= zSet;
if (wasXyCorrected)
@@ -1459,26 +1461,55 @@ bool Move::XYProbeCoordinatesSet(int index) const
size_t Move::NumberOfProbePoints() const
{
- for(size_t i = 0; i < MAX_PROBE_POINTS; i++)
+ for(size_t i = 0; i < MaxProbePoints; i++)
{
if(!AllProbeCoordinatesSet(i))
{
return i;
}
}
- return MAX_PROBE_POINTS;
+ return MaxProbePoints;
}
size_t Move::NumberOfXYProbePoints() const
{
- for(size_t i = 0; i < MAX_PROBE_POINTS; i++)
+ for(size_t i = 0; i < MaxProbePoints; i++)
{
if(!XYProbeCoordinatesSet(i))
{
return i;
}
}
- return MAX_PROBE_POINTS;
+ return MaxProbePoints;
+}
+
+// Set a new grid
+void Move::SetBedProbeGrid(const GridDefinition& newGrid)
+{
+ useGridHeights = false;
+ grid = newGrid;
+ grid.SetStorage(zBedProbePoints, gridHeightSet);
+}
+
+void Move::ClearGridHeights()
+{
+ useGridHeights = false;
+ SetIdentityTransform();
+ for (size_t i = 0; i < ARRAY_SIZE(gridHeightSet); ++i)
+ {
+ gridHeightSet[i] = 0;
+ }
+}
+
+// Set the height of a grid point
+void Move::SetGridHeight(size_t xIndex, size_t yIndex, float height)
+{
+ size_t index = yIndex * grid.NumXpoints() + xIndex;
+ if (index < MaxGridProbePoints)
+ {
+ zBedProbePoints[index] = height;
+ gridHeightSet[index/32] |= 1u << (index & 31u);
+ }
}
// Enter or leave simulation mode
diff --git a/src/Movement/Move.h b/src/Movement/Move.h
index b7614349..efd6f73e 100644
--- a/src/Movement/Move.h
+++ b/src/Movement/Move.h
@@ -22,6 +22,7 @@ typedef float floatc_t; // type of matrix element used for delta calibratio
#include "DeltaParameters.h"
#include "DeltaProbe.h"
+#include "Grid.h"
enum PointCoordinateSet
{
@@ -112,6 +113,15 @@ public:
bool IsExtruding() const; // Is filament being extruded?
+ const GridDefinition& GetBedProbeGrid() const { return grid; } // Access the bed probing grid
+
+ void SetBedProbeGrid(const GridDefinition& newGrid) // Set a new grid
+ pre(newGrid.IsValid());
+
+ void ClearGridHeights(); // Clear all grid height corrections
+ void SetGridHeight(size_t xIndex, size_t yIndex, float height); // Set the height of a grid point
+ void UseHeightMap() { useGridHeights = true; } // Start using the height map
+
private:
enum class IdleState : uint8_t { idle, busy, timing };
@@ -158,18 +168,23 @@ private:
volatile bool liveCoordinatesValid; // True if the XYZ live coordinates are reliable (the extruder ones always are)
volatile int32_t liveEndPoints[DRIVES]; // The XYZ endpoints of the last completed move in motor coordinates
- float xBedProbePoints[MAX_PROBE_POINTS]; // The X coordinates of the points on the bed at which to probe
- float yBedProbePoints[MAX_PROBE_POINTS]; // The Y coordinates of the points on the bed at which to probe
- float zBedProbePoints[MAX_PROBE_POINTS]; // The Z coordinates of the points on the bed at which to probe
+ // Variable for G32 bed probing, for bed compensation and delta calibration
+ float xBedProbePoints[MaxProbePoints]; // The X coordinates of the points on the bed at which to probe
+ float yBedProbePoints[MaxProbePoints]; // The Y coordinates of the points on the bed at which to probe
+ float zBedProbePoints[MaxGridProbePoints]; // The Z coordinates of the points on the bed that were probed
float baryXBedProbePoints[5]; // The X coordinates of the triangle corner points
float baryYBedProbePoints[5]; // The Y coordinates of the triangle corner points
float baryZBedProbePoints[5]; // The Z coordinates of the triangle corner points
- uint8_t probePointSet[MAX_PROBE_POINTS]; // Has the XY of this point been set? Has the Z been probed?
+ uint8_t probePointSet[MaxProbePoints]; // Has the XY of this point been set? Has the Z been probed?
float aX, aY, aC; // Bed plane explicit equation z' = z + aX*x + aY*y + aC
float tanXY, tanYZ, tanXZ; // Axis compensation - 90 degrees + angle gives angle between axes
int numBedCompensationPoints; // The number of points we are actually using for bed compensation, 0 means identity bed transform
float xRectangle, yRectangle; // The side lengths of the rectangle used for second-degree bed compensation
+ GridDefinition grid; // Grid definition for G29 bed probing. The probe heights are stored in zBedProbePoints, see above.
+ uint32_t gridHeightSet[MaxGridProbePoints/32]; // Bitmap of which points have been probed
+ bool useGridHeights; // True if the zBedProbePoints came from valid bed probing and relate to the current grid
+
float idleTimeout; // How long we wait with no activity before we reduce motor currents to idle
float lastMoveTime; // The approximate time at which the last move was completed, or 0
float longWait; // A long time for things that need to be done occasionally
diff --git a/src/Platform.cpp b/src/Platform.cpp
index 391b7331..72ddd3f4 100644
--- a/src/Platform.cpp
+++ b/src/Platform.cpp
@@ -652,7 +652,7 @@ const ZProbeParameters& Platform::GetZProbeParameters() const
}
}
-void Platform::SetZProbeParameters(const struct ZProbeParameters& params)
+void Platform::SetZProbeParameters(const ZProbeParameters& params)
{
if (GetZProbeParameters() != params)
{
@@ -683,6 +683,16 @@ void Platform::SetZProbeParameters(const struct ZProbeParameters& params)
}
}
+// Return true if the specified point is accessible to the Z probe
+bool Platform::IsAccessibleProbePoint(float x, float y) const
+{
+ x -= GetZProbeParameters().xOffset;
+ y -= GetZProbeParameters().yOffset;
+ return (reprap.GetMove()->IsDeltaMode())
+ ? x * x + y * y < reprap.GetMove()->GetDeltaParams().GetPrintRadiusSquared()
+ : x >= axisMinima[X_AXIS] && y >= axisMinima[Y_AXIS] && x <= axisMaxima[X_AXIS] && y <= axisMaxima[Y_AXIS];
+}
+
// Return true if we must home X and Y before we home Z (i.e. we are using a bed probe)
bool Platform::MustHomeXYBeforeZ() const
{
@@ -1379,7 +1389,7 @@ void Platform::Diagnostics(MessageType mtype)
// Show the current probe position heights
Message(mtype, "Bed probe heights:");
- for (size_t i = 0; i < MAX_PROBE_POINTS; ++i)
+ for (size_t i = 0; i < MaxProbePoints; ++i)
{
MessageF(mtype, " %.3f", reprap.GetMove()->ZBedProbePoint(i));
}
diff --git a/src/Platform.h b/src/Platform.h
index 958f5557..036084f9 100644
--- a/src/Platform.h
+++ b/src/Platform.h
@@ -524,6 +524,7 @@ public:
float AxisMinimum(size_t axis) const;
void SetAxisMinimum(size_t axis, float value);
float AxisTotalLength(size_t axis) const;
+ bool IsAccessibleProbePoint(float x, float y) const;
float GetPressureAdvance(size_t drive) const;
void SetPressureAdvance(size_t extruder, float factor);
void SetEndStopConfiguration(size_t axis, EndStopType endstopType, bool logicLevel);
diff --git a/src/Storage/MassStorage.cpp b/src/Storage/MassStorage.cpp
index 945045c9..06b38627 100644
--- a/src/Storage/MassStorage.cpp
+++ b/src/Storage/MassStorage.cpp
@@ -242,6 +242,13 @@ bool MassStorage::MakeDirectory(const char *directory)
// Rename a file or directory
bool MassStorage::Rename(const char *oldFilename, const char *newFilename)
{
+ if (newFilename[0] >= '0' && newFilename[0] <= '9' && newFilename[1] == ':')
+ {
+ // Workaround for DWC 1.13 which send a volume specification at the start of the new path.
+ // f_rename can't handle this, so skip past the volume specification.
+ // We are assuming that the user isn't really trying to rename across volumes. This is a safe assumption when the client is DWC.
+ newFilename += 2;
+ }
if (f_rename(oldFilename, newFilename) != FR_OK)
{
platform->MessageF(GENERIC_MESSAGE, "Can't rename file or directory %s to %s\n", oldFilename, newFilename);