Version 1.17c+1

Implemented G2 and G3
Fixed bug: couldn't update WiFi server or DWC on Duet WiFi after sending
M997 S3
Disable the uart used to update the WiFi module during normal WiFi
operation
This commit is contained in:
David Crocker 2017-01-19 20:11:04 +00:00
parent d5e7dfba41
commit 120987ff63
12 changed files with 275 additions and 79 deletions

View file

@ -165,6 +165,8 @@ const float DefaultFeedrate = 3000.0; // The initial requested feed rate afte
const float DefaultRetractSpeed = 1000.0; // The default firmware retraction and un-retraction speed, in mm
const float DefaultRetractLength = 1.0;
const float DefaultArcSegmentLength = 0.2; // G2 and G3 arc movement commands get split into segments this long
const float DEFAULT_IDLE_TIMEOUT = 30.0; // Seconds
const float DEFAULT_IDLE_CURRENT_FACTOR = 0.3; // Proportion of normal motor current that we use for idle hold

View file

@ -114,7 +114,7 @@ const Pin COOLING_FAN_RPM_PIN = 23; // Pin PA15
const size_t NumSdCards = 2;
const Pin SdCardDetectPins[NumSdCards] = {13, NoPin};
const Pin SdWriteProtectPins[NumSdCards] = {NoPin, NoPin};
const Pin SdSpiCSPins[1] = {67}; // Note: this clashes with inkjet support
const Pin SdSpiCSPins[1] = {67}; // Pin PB16 Note: this clashes with inkjet support
#if SUPPORT_INKJET
// Inkjet control pins

View file

@ -55,7 +55,7 @@ Network::Network(Platform* p) : platform(p), responseCode(0), responseBody(nullp
void Network::Init()
{
// Make sure the ESP8266 is held in the reset state
pinMode(EspResetPin, OUTPUT_LOW);
ResetWiFi();
uploader = new WifiFirmwareUploader(Serial1);
}
@ -118,7 +118,7 @@ void Network::Start()
// GPIO0 has to be held high for sufficient time:
// - 10ms is not enough
// - 18ms after reset is released, an oscillating signal appears on GPIO0 for 55ms
// - so 18ms is probably long enough. Use 25ms for safety.
// - so 18ms is probably long enough. Use 50ms for safety.
delay(50);
// Relinquish control of our CS pin so that the ESP can take it over
@ -1120,16 +1120,18 @@ void Network::SpiInterrupt()
// Reset the ESP8266 and leave held in reset
void Network::ResetWiFi()
{
pinMode(EspResetPin, OUTPUT_LOW);
pinMode(EspResetPin, OUTPUT_LOW); // assert ESP8266 /RESET
pinMode(APIN_UART1_TXD, INPUT_PULLUP); // just enable pullups on TxD and RxD pins for now to avoid floating pins
pinMode(APIN_UART1_RXD, INPUT_PULLUP);
}
// Reset the ESP8266 to take commands from the UART. The caller must wait for the reset to complete after calling this.
// Reset the ESP8266 to take commands from the UART or from external input. The caller must wait for the reset to complete after calling this.
// ESP8266 boot modes:
// GPIO0 GPIO2 GPIO15
// 0 1 0 Firmware download from UART
// 1 1 0 Normal boot from flash memory
// 0 0 1 SD card boot (not used in on Duet)
void Network::ResetWiFiForUpload()
void Network::ResetWiFiForUpload(bool external)
{
// Make sure the ESP8266 is in the reset state
pinMode(EspResetPin, OUTPUT_LOW);
@ -1152,17 +1154,18 @@ void Network::ResetWiFiForUpload()
// Make sure it has time to reset - no idea how long it needs, but 50ms should be plenty
delay(50);
if (external)
{
pinMode(APIN_UART1_TXD, INPUT_PULLUP); // just enable pullups on TxD and RxD pins
pinMode(APIN_UART1_RXD, INPUT_PULLUP);
}
else
{
ConfigurePin(g_APinDescription[APINS_UART1]); // connect the pins to UART1
}
// Release the reset on the ESP8266
digitalWrite(EspResetPin, HIGH);
}
// Reset the ESP8266 to take commands from an external input. The caller must wait for the reset to complete after calling this.
void Network::ResetWiFiForExternalUpload()
{
ResetWiFiForUpload();
// Set our TxD pin low to make things easier for the FTDI chip to drive the ESP RxD input
pinMode(APIN_UART1_TXD, OUTPUT_LOW);
}
// End

View file

@ -76,8 +76,7 @@ public:
WifiFirmwareUploader *GetWifiUploader() { return uploader; }
static void ResetWiFi();
static void ResetWiFiForUpload();
static void ResetWiFiForExternalUpload();
static void ResetWiFiForUpload(bool external);
const char *GetWiFiServerVersion() const { return wiFiServerVersion; }

View file

@ -586,7 +586,7 @@ void WifiFirmwareUploader::Spin()
}
uploadPort.begin(baud);
uploadPort.setInterruptPriority(1); // we are going to move data at seriously high speeds
Network::ResetWiFiForUpload();
Network::ResetWiFiForUpload(false);
lastAttemptTime = lastResetTime = millis();
state = UploadState::connecting;
}

View file

@ -62,7 +62,7 @@ namespace FirmwareUpdater
switch(module)
{
case WifiExternalFirmwareModule:
Network::ResetWiFiForExternalUpload();
Network::ResetWiFiForUpload(true);
break;
case WifiFirmwareModule:

View file

@ -12,7 +12,7 @@ unsigned int GCodeMachineState::numAllocated = 0;
// Create a default initialised GCodeMachineState
GCodeMachineState::GCodeMachineState()
: previous(nullptr), feedrate(DefaultFeedrate * secondsToMinutes), fileState(), lockedResources(0), state(GCodeState::normal),
: previous(nullptr), feedrate(DefaultFeedrate * SecondsToMinutes), fileState(), lockedResources(0), state(GCodeState::normal),
drivesRelative(false), axesRelative(false), doingFileMacro(false), runningM502(false)
{
}

View file

@ -55,7 +55,7 @@ void GCodes::RestorePoint::Init()
{
moveCoords[i] = 0.0;
}
feedRate = DefaultFeedrate * secondsToMinutes;
feedRate = DefaultFeedrate * SecondsToMinutes;
}
GCodes::GCodes(Platform* p, Webserver* w) :
@ -82,6 +82,7 @@ void GCodes::Init()
numAxes = MIN_AXES;
numExtruders = MaxExtruders;
distanceScale = 1.0;
arcSegmentLength = DefaultArcSegmentLength;
rawExtruderTotal = 0.0;
for (size_t extruder = 0; extruder < MaxExtruders; extruder++)
{
@ -111,7 +112,7 @@ void GCodes::Init()
retractLength = retractExtra = DefaultRetractLength;
retractHop = 0.0;
retractSpeed = unRetractSpeed = DefaultRetractSpeed * secondsToMinutes;
retractSpeed = unRetractSpeed = DefaultRetractSpeed * SecondsToMinutes;
isRetracted = false;
}
@ -134,7 +135,7 @@ void GCodes::Reset()
probeCount = 0;
cannedCycleMoveCount = 0;
cannedCycleMoveQueued = false;
speedFactor = secondsToMinutes; // default is just to convert from mm/minute to mm/second
speedFactor = SecondsToMinutes; // default is just to convert from mm/minute to mm/second
for (size_t i = 0; i < MaxExtruders; ++i)
{
extrusionFactors[i] = 1.0;
@ -362,7 +363,7 @@ void GCodes::Spin()
{
moveBuffer.coords[drive] = 0.0;
}
moveBuffer.feedRate = DefaultFeedrate * secondsToMinutes; // ask for a good feed rate, we may have paused during a slow move
moveBuffer.feedRate = DefaultFeedrate * SecondsToMinutes; // ask for a good feed rate, we may have paused during a slow move
moveBuffer.moveType = 0;
moveBuffer.endStopsToCheck = 0;
moveBuffer.usePressureAdvance = false;
@ -980,11 +981,10 @@ void GCodes::Pop(GCodeBuffer& gb)
}
}
// Move expects all axis movements to be absolute, and all extruder drive moves to be relative. This function serves that.
// 'moveType' is the S parameter in the G0 or G1 command, or -1 if we are doing G92.
// For regular (type 0) moves, we apply limits and do X axis mapping.
// Returns the number of segments if we have a legal move, 1 if we are doing G92, or zero if this gcode should be discarded
unsigned int GCodes::LoadMoveBufferFromGCode(GCodeBuffer& gb, int moveType)
// Set up the extrusion and feed rate of a move for the Move class
// 'moveType' is the S parameter in the G0 or G1 command, or zero for a G2 or G3 command
// Returns true if this gcode is valid so far, false if it should be discarded
bool GCodes::LoadExtrusionAndFeedrateFromGCode(GCodeBuffer& gb, int moveType)
{
// Zero every extruder drive as some drives may not be changed
for (size_t drive = numAxes; drive < DRIVES; drive++)
@ -998,7 +998,7 @@ unsigned int GCodes::LoadMoveBufferFromGCode(GCodeBuffer& gb, int moveType)
const float rate = gb.GetFValue() * distanceScale;
gb.MachineState().feedrate = (moveType == 0)
? rate * speedFactor
: rate * secondsToMinutes; // don't apply the speed factor to homing and other special moves
: rate * SecondsToMinutes; // don't apply the speed factor to homing and other special moves
}
moveBuffer.feedRate = gb.MachineState().feedrate;
@ -1009,7 +1009,7 @@ unsigned int GCodes::LoadMoveBufferFromGCode(GCodeBuffer& gb, int moveType)
if (tool == nullptr)
{
platform->Message(GENERIC_MESSAGE, "Attempting to extrude with no tool selected.\n");
return 0;
return false;
}
const size_t eMoveCount = tool->DriveCount();
if (eMoveCount > 0)
@ -1073,8 +1073,16 @@ unsigned int GCodes::LoadMoveBufferFromGCode(GCodeBuffer& gb, int moveType)
}
}
}
return true;
}
// Now the movement axes
// Set up the axis coordinates of a move for the Move class
// Move expects all axis movements to be absolute, and all extruder drive moves to be relative. This function serves that.
// 'moveType' is the S parameter in the G0 or G1 command, or -1 if we are doing G92.
// For regular (type 0) moves, we apply limits and do X axis mapping.
// Returns the number of segments if we have a legal move, 1 if we are doing G92, or zero if this gcode should be discarded
unsigned int GCodes::LoadMoveBufferFromGCode(GCodeBuffer& gb, int moveType)
{
const Tool * const currentTool = reprap.GetCurrentTool();
unsigned int numSegments = 1;
for (size_t axis = 0; axis < numAxes; axis++)
@ -1216,6 +1224,7 @@ int GCodes::SetUpMove(GCodeBuffer& gb, StringRef& reply)
// Check to see if the move is a 'homing' move that endstops are checked on.
moveBuffer.endStopsToCheck = 0;
moveBuffer.moveType = 0;
doingArcMove = false;
moveBuffer.xAxes = reprap.GetCurrentXAxes();
if (gb.Seen('S'))
{
@ -1279,31 +1288,157 @@ int GCodes::SetUpMove(GCodeBuffer& gb, StringRef& reply)
// Load the move buffer with either the absolute movement required or the relative movement required
memcpy(moveBuffer.initialCoords, moveBuffer.coords, numAxes * sizeof(moveBuffer.initialCoords[0]));
segmentsLeft = LoadMoveBufferFromGCode(gb, moveBuffer.moveType);
if (segmentsLeft != 0)
if (LoadExtrusionAndFeedrateFromGCode(gb, moveBuffer.moveType))
{
// Flag whether we should use pressure advance, if there is any extrusion in this move.
// We assume it is a normal printing move needing pressure advance if there is forward extrusion and XYU.. movement.
// The movement code will only apply pressure advance if there is forward extrusion, so we only need to check for XYU.. movement here.
moveBuffer.usePressureAdvance = false;
for (size_t axis = 0; axis < numAxes; ++axis)
segmentsLeft = LoadMoveBufferFromGCode(gb, moveBuffer.moveType);
if (segmentsLeft != 0)
{
if (axis != Z_AXIS && moveBuffer.coords[axis] != moveBuffer.initialCoords[axis])
// Flag whether we should use pressure advance, if there is any extrusion in this move.
// We assume it is a normal printing move needing pressure advance if there is forward extrusion and XYU.. movement.
// The movement code will only apply pressure advance if there is forward extrusion, so we only need to check for XYU.. movement here.
moveBuffer.usePressureAdvance = false;
for (size_t axis = 0; axis < numAxes; ++axis)
{
moveBuffer.usePressureAdvance = true;
break;
if (axis != Z_AXIS && moveBuffer.coords[axis] != moveBuffer.initialCoords[axis])
{
moveBuffer.usePressureAdvance = true;
break;
}
}
moveBuffer.filePos = (&gb == fileGCode) ? gb.MachineState().fileState.GetPosition() : noFilePosition;
moveBuffer.canPauseAfter = (moveBuffer.endStopsToCheck == 0);
//debugPrintf("Queue move pos %u\n", moveFilePos);
}
moveBuffer.filePos = (&gb == fileGCode) ? gb.MachineState().fileState.GetPosition() : noFilePosition;
moveBuffer.canPauseAfter = (moveBuffer.endStopsToCheck == 0);
//debugPrintf("Queue move pos %u\n", moveFilePos);
}
return (moveBuffer.moveType != 0 || moveBuffer.endStopsToCheck != 0) ? 2 : 1;
}
// The Move class calls this function to find what to do next.
// Execute an arc move returning true if it was badly-formed
// We already have the movement lock and the last move has gone
bool GCodes::DoArcMove(GCodeBuffer& gb, bool clockwise)
{
memcpy(moveBuffer.initialCoords, moveBuffer.coords, numAxes * sizeof(moveBuffer.initialCoords[0]));
// Get the axis parameters. X Y I J are compulsory, Z is optional.
if (!gb.Seen('X')) return true;
const float xParam = gb.GetFValue();
if (!gb.Seen('Y')) return true;
const float yParam = gb.GetFValue();
if (!gb.Seen('I')) return true;
const float iParam = gb.GetFValue();
if (!gb.Seen('J')) return true;
const float jParam = gb.GetFValue();
// Adjust them for relative/absolute coordinates, tool offset, and X axis mapping. Also get the optional Z parameter
const Tool * const currentTool = reprap.GetCurrentTool();
const bool axesRelative = gb.MachineState().axesRelative;
if (gb.Seen('Z'))
{
const float zParam = gb.GetFValue();
if (axesRelative)
{
moveBuffer.coords[Z_AXIS] += zParam;
}
else
{
moveBuffer.coords[Z_AXIS] = zParam;
if (currentTool != nullptr)
{
moveBuffer.coords[Z_AXIS] -= currentTool->GetOffset()[Z_AXIS];
}
}
}
float initialDx = 0.0;
if (currentTool != nullptr)
{
// Record which axes behave like an X axis
arcAxesMoving = currentTool->GetXAxisMap() & ~((1 << Y_AXIS) | (1 << Z_AXIS));
// Sort out the Y axis
if (axesRelative)
{
moveBuffer.coords[Y_AXIS] += yParam;
arcCentre[Y_AXIS] = moveBuffer.initialCoords[Y_AXIS] + jParam;
}
else
{
moveBuffer.coords[Y_AXIS] = yParam - currentTool->GetOffset()[Y_AXIS];
arcCentre[Y_AXIS] = jParam - currentTool->GetOffset()[Y_AXIS];
}
// Deal with the X axes
for (size_t axis = 0; axis < numAxes; ++axis)
{
if ((arcAxesMoving & (1 << axis)) != 0)
{
if (axesRelative)
{
moveBuffer.coords[axis] += xParam;
arcCentre[axis] = moveBuffer.initialCoords[axis] + iParam;
initialDx = -iParam;
}
else
{
moveBuffer.coords[axis] = xParam - currentTool->GetOffset()[axis];
arcCentre[axis] = iParam + currentTool->GetOffset()[axis];
initialDx = moveBuffer.initialCoords[axis] - arcCentre[axis];
}
}
}
}
else
{
arcAxesMoving = (1 << X_AXIS);
if (axesRelative)
{
moveBuffer.coords[X_AXIS] += xParam;
arcCentre[X_AXIS] = moveBuffer.initialCoords[X_AXIS] + iParam;
moveBuffer.coords[Y_AXIS] += yParam;
arcCentre[Y_AXIS] = moveBuffer.initialCoords[Y_AXIS] + jParam;;
initialDx = -iParam;
}
else
{
moveBuffer.coords[X_AXIS] = xParam;
arcCentre[X_AXIS] = iParam;
moveBuffer.coords[Y_AXIS] = yParam;
arcCentre[Y_AXIS] = jParam;
initialDx = moveBuffer.initialCoords[X_AXIS] - arcCentre[X_AXIS];
}
}
moveBuffer.endStopsToCheck = 0;
moveBuffer.moveType = 0;
moveBuffer.xAxes = reprap.GetCurrentXAxes();
if (LoadExtrusionAndFeedrateFromGCode(gb, moveBuffer.moveType)) // this reports an error if necessary, so no need to return true if it fails
{
const float initialDy = moveBuffer.initialCoords[Y_AXIS] - arcCentre[Y_AXIS];
arcRadius = sqrtf(initialDx * initialDx + initialDy * initialDy);
arcCurrentAngle = atan2(initialDy, initialDx);
const float finalTheta = atan2(yParam - jParam, xParam - iParam);
// Calculate the total angle moved, which depends on which way round we are going
float totalArc = (clockwise) ? arcCurrentAngle - finalTheta : finalTheta - arcCurrentAngle;
if (totalArc < 0)
{
totalArc += 2 * PI;
}
segmentsLeft = max<unsigned int>((unsigned int)((arcRadius * totalArc)/arcSegmentLength + 0.8), 1);
arcAngleIncrement = totalArc/segmentsLeft;
if (clockwise)
{
arcAngleIncrement = -arcAngleIncrement;
}
doingArcMove = true;
moveBuffer.usePressureAdvance = true;
// debugPrintf("Radius %.2f, initial angle %.1f, increment %.1f, segments %u\n",
// arcRadius, arcCurrentAngle * RadiansToDegrees, arcAngleIncrement * RadiansToDegrees, segmentsLeft);
}
return false;
}
// The Move class calls this function to find what to do next.
bool GCodes::ReadMove(RawMove& m)
{
if (segmentsLeft == 0)
@ -1314,6 +1449,7 @@ bool GCodes::ReadMove(RawMove& m)
m = moveBuffer;
if (segmentsLeft == 1)
{
// If there is just 1 segment left, it doesn't matter if it is an arc move or not, just move to the end position
ClearMove();
}
else
@ -1322,10 +1458,30 @@ bool GCodes::ReadMove(RawMove& m)
m.canPauseAfter = false;
// Do the axes
if (doingArcMove)
{
arcCurrentAngle += arcAngleIncrement;
}
for (size_t drive = 0; drive < numAxes; ++drive)
{
const float movementToDo = (moveBuffer.coords[drive] - moveBuffer.initialCoords[drive])/segmentsLeft;
moveBuffer.initialCoords[drive] += movementToDo;
if (doingArcMove && drive != Z_AXIS)
{
if (drive == Y_AXIS)
{
moveBuffer.initialCoords[drive] = arcCentre[drive] + arcRadius * sinf(arcCurrentAngle);
}
else if ((arcAxesMoving & (1 << drive)) != 0)
{
// X axis or a substitute X axis
moveBuffer.initialCoords[drive] = arcCentre[drive] + arcRadius * cosf(arcCurrentAngle);
}
}
else
{
const float movementToDo = (moveBuffer.coords[drive] - moveBuffer.initialCoords[drive])/segmentsLeft;
moveBuffer.initialCoords[drive] += movementToDo;
}
m.coords[drive] = moveBuffer.initialCoords[drive];
}
@ -1336,6 +1492,7 @@ bool GCodes::ReadMove(RawMove& m)
m.coords[drive] = extrusionToDo;
moveBuffer.coords[drive] -= extrusionToDo;
}
--segmentsLeft;
}
return true;
@ -1344,6 +1501,7 @@ bool GCodes::ReadMove(RawMove& m)
void GCodes::ClearMove()
{
segmentsLeft = 0;
doingArcMove = false;
moveBuffer.endStopsToCheck = 0;
moveBuffer.moveType = 0;
moveBuffer.isFirmwareRetraction = false;
@ -1528,7 +1686,7 @@ bool GCodes::OffsetAxes(GCodeBuffer& gb)
if (gb.Seen(feedrateLetter)) // Has the user specified a feedrate?
{
cannedFeedRate = gb.GetFValue() * distanceScale * secondsToMinutes;
cannedFeedRate = gb.GetFValue() * distanceScale * SecondsToMinutes;
}
else
{

View file

@ -101,7 +101,7 @@ public:
void SetAxisNotHomed(unsigned int axis) // Tell us that the axis is not homed
{ axesHomed &= ~(1 << axis); }
float GetSpeedFactor() const { return speedFactor * minutesToSeconds; } // Return the current speed factor
float GetSpeedFactor() const { return speedFactor * MinutesToSeconds; } // Return the current speed factor
float GetExtrusionFactor(size_t extruder) { return extrusionFactors[extruder]; } // Return the current extrusion factors
float GetRawExtruderPosition(size_t drive) const; // Get the actual extruder position, after adjusting the extrusion factor
float GetRawExtruderTotalByDrive(size_t extruder) const; // Get the total extrusion since start of print, for one drive
@ -158,8 +158,8 @@ private:
void StartNextGCode(GCodeBuffer& gb, StringRef& reply); // Fetch a new or old GCode and process it
void DoFilePrint(GCodeBuffer& gb, StringRef& reply); // Get G Codes from a file and print them
bool DoFileMacro(GCodeBuffer& gb, const char* fileName, bool reportMissing, bool runningM502 = false);
// Run a GCode macro file, optionally report error if not found
bool DoFileMacro(GCodeBuffer& gb, const char* fileName, bool reportMissing, bool runningM502 = false);
// Run a GCode macro file, optionally report error if not found
bool DoCannedCycleMove(GCodeBuffer& gb, EndstopChecks ce); // Do a move from an internally programmed canned cycle
void FileMacroCyclesReturn(GCodeBuffer& gb); // End a macro
bool ActOnCode(GCodeBuffer& gb, StringRef& reply); // Do a G, M or T Code
@ -177,9 +177,13 @@ private:
void SetBedEquationWithProbe(int sParam, StringRef& reply); // Probes a series of points and sets the bed equation
bool SetPrintZProbe(GCodeBuffer& gb, StringRef& reply); // Either return the probe value, or set its threshold
bool SetOrReportOffsets(GCodeBuffer& gb, StringRef& reply); // Deal with a G10
bool SetPositions(GCodeBuffer& gb); // Deal with a G92
unsigned int LoadMoveBufferFromGCode(GCodeBuffer& gb, int moveType); // Set up a move for the Move class
bool NoHome() const; // Are we homing and not finished?
bool LoadExtrusionAndFeedrateFromGCode(GCodeBuffer& gb, int moveType); // Set up the extrusion and feed rate of a move for the Move class
unsigned int LoadMoveBufferFromGCode(GCodeBuffer& gb, int moveType); // Set up the axis coordinates of a move for the Move class
bool DoArcMove(GCodeBuffer& gb, bool clockwise) // Execute an arc move returning true if it was badly-formed
pre(segmentsLeft == 0; resourceOwners[MoveResource] == &gb);
bool Push(GCodeBuffer& gb); // Push feedrate etc on the stack
void Pop(GCodeBuffer& gb); // Pop feedrate etc
void DisableDrives(); // Turn the motors off
@ -223,8 +227,8 @@ private:
static uint32_t LongArrayToBitMap(const long *arr, size_t numEntries); // Convert an array of longs to a bit map
Platform* platform; // The RepRap machine
Webserver* webserver; // The web server class
Platform* const platform; // The RepRap machine
Webserver* const webserver; // The web server class
GCodeBuffer* gcodeSources[6]; // The various sources of gcodes
@ -244,9 +248,18 @@ private:
bool runningConfigFile; // We are running config.g during the startup process
bool doingToolChange; // We are running tool change macros
unsigned int segmentsLeft; // The number of segments left to do in the current move, or 0 if no move available
float dwellTime; // How long a pause for a dwell (seconds)?
// The following contain the details of moves that the Move module fetches
RawMove moveBuffer; // Move details to pass to Move class
unsigned int segmentsLeft; // The number of segments left to do in the current move, or 0 if no move available
float arcCentre[MAX_AXES];
float arcRadius;
float arcCurrentAngle;
float arcAngleIncrement;
uint32_t arcAxesMoving;
bool doingArcMove;
RestorePoint simulationRestorePoint; // The position and feed rate when we started a simulation
RestorePoint pauseRestorePoint; // The position and feed rate when we paused the print
RestorePoint toolChangeRestorePoint; // The position and feed rate when we freed a tool
@ -262,6 +275,7 @@ private:
CannedMoveType cannedMoveType[DRIVES]; // Is this drive involved in a canned cycle move?
bool offSetSet; // Are any axis offsets non-zero?
float distanceScale; // MM or inches
float arcSegmentLength; // Length of segments that we split arc moves into
FileData fileToPrint;
FileStore* fileBeingWritten; // A file to write G Codes (or sometimes HTML) to
uint16_t toBeHomed; // Bitmap of axes still to be homed

View file

@ -108,7 +108,7 @@ bool GCodes::HandleGcode(GCodeBuffer& gb, StringRef& reply)
{
moveBuffer.coords[drive] = 0.0;
}
moveBuffer.feedRate = (gb.Seen(feedrateLetter)) ? gb.GetFValue() * secondsToMinutes : gb.MachineState().feedrate;
moveBuffer.feedRate = (gb.Seen(feedrateLetter)) ? gb.GetFValue() * SecondsToMinutes : gb.MachineState().feedrate;
moveBuffer.filePos = noFilePosition;
moveBuffer.usePressureAdvance = false;
segmentsLeft = 1;
@ -125,6 +125,24 @@ bool GCodes::HandleGcode(GCodeBuffer& gb, StringRef& reply)
}
break;
case 2: // Clockwise arc
case 3: // Anti clockwise arc
// We only support X and Y axes in these, but you can map them to other axes in the tool definitions
if (!LockMovement(gb))
{
return false;
}
if (segmentsLeft != 0)
{
return false;
}
if (DoArcMove(gb, code == 2))
{
reply.copy("Invalid G2 or G3 command");
error = true;
}
break;
case 4: // Dwell
result = DoDwell(gb);
break;
@ -1566,7 +1584,7 @@ bool GCodes::HandleMcode(GCodeBuffer& gb, StringRef& reply)
{
if (gb.Seen(axisLetters[axis]))
{
platform->SetMaxFeedrate(axis, gb.GetFValue() * distanceScale * secondsToMinutes); // G Code feedrates are in mm/minute; we need mm/sec
platform->SetMaxFeedrate(axis, gb.GetFValue() * distanceScale * SecondsToMinutes); // G Code feedrates are in mm/minute; we need mm/sec
seen = true;
}
}
@ -1579,7 +1597,7 @@ bool GCodes::HandleMcode(GCodeBuffer& gb, StringRef& reply)
gb.GetFloatArray(eVals, eCount, true);
for (size_t e = 0; e < eCount; e++)
{
platform->SetMaxFeedrate(numAxes + e, eVals[e] * distanceScale * secondsToMinutes);
platform->SetMaxFeedrate(numAxes + e, eVals[e] * distanceScale * SecondsToMinutes);
}
}
@ -1588,13 +1606,13 @@ bool GCodes::HandleMcode(GCodeBuffer& gb, StringRef& reply)
reply.copy("Maximum feedrates: ");
for (size_t axis = 0; axis < numAxes; ++axis)
{
reply.catf("%c: %.1f, ", axisLetters[axis], platform->MaxFeedrate(axis) / (distanceScale * secondsToMinutes));
reply.catf("%c: %.1f, ", axisLetters[axis], platform->MaxFeedrate(axis) / (distanceScale * SecondsToMinutes));
}
reply.cat("E:");
char sep = ' ';
for (size_t extruder = 0; extruder < numExtruders; extruder++)
{
reply.catf("%c%.1f", sep, platform->MaxFeedrate(extruder + numAxes) / (distanceScale * secondsToMinutes));
reply.catf("%c%.1f", sep, platform->MaxFeedrate(extruder + numAxes) / (distanceScale * SecondsToMinutes));
sep = ':';
}
}
@ -1620,12 +1638,12 @@ bool GCodes::HandleMcode(GCodeBuffer& gb, StringRef& reply)
}
if (gb.Seen('F'))
{
unRetractSpeed = retractSpeed = max<float>(gb.GetFValue(), 60.0) * secondsToMinutes;
unRetractSpeed = retractSpeed = max<float>(gb.GetFValue(), 60.0) * SecondsToMinutes;
seen = true;
}
if (gb.Seen('T')) // must do this one after 'F'
{
unRetractSpeed = max<float>(gb.GetFValue(), 60.0) * secondsToMinutes;
unRetractSpeed = max<float>(gb.GetFValue(), 60.0) * SecondsToMinutes;
seen = true;
}
if (gb.Seen('Z'))
@ -1636,7 +1654,7 @@ bool GCodes::HandleMcode(GCodeBuffer& gb, StringRef& reply)
if (!seen)
{
reply.printf("Retraction/un-retraction settings: length %.2f/%.2fmm, speed %d/%dmm/min, Z hop %.2fmm",
retractLength, retractLength + retractExtra, (int)(retractSpeed * minutesToSeconds), (int)(unRetractSpeed * minutesToSeconds), retractHop);
retractLength, retractLength + retractExtra, (int)(retractSpeed * MinutesToSeconds), (int)(unRetractSpeed * MinutesToSeconds), retractHop);
}
}
break;
@ -1683,7 +1701,7 @@ bool GCodes::HandleMcode(GCodeBuffer& gb, StringRef& reply)
case 220: // Set/report speed factor override percentage
if (gb.Seen('S'))
{
float newSpeedFactor = (gb.GetFValue() * 0.01) * secondsToMinutes; // include the conversion from mm/minute to mm/second
float newSpeedFactor = (gb.GetFValue() * 0.01) * SecondsToMinutes; // include the conversion from mm/minute to mm/second
if (newSpeedFactor > 0.0)
{
// Update the feed rate for ALL input sources, and all feed rates on the stack
@ -1712,7 +1730,7 @@ bool GCodes::HandleMcode(GCodeBuffer& gb, StringRef& reply)
}
else
{
reply.printf("Speed factor override: %.1f%%", speedFactor * minutesToSeconds * 100.0);
reply.printf("Speed factor override: %.1f%%", speedFactor * MinutesToSeconds * 100.0);
}
break;
@ -2366,13 +2384,13 @@ bool GCodes::HandleMcode(GCodeBuffer& gb, StringRef& reply)
if (gb.Seen('F')) // feed rate i.e. probing speed
{
params.probeSpeed = gb.GetFValue() * secondsToMinutes;
params.probeSpeed = gb.GetFValue() * SecondsToMinutes;
seenParam = true;
}
if (gb.Seen('T')) // travel speed to probe point
{
params.travelSpeed = gb.GetFValue() * secondsToMinutes;
params.travelSpeed = gb.GetFValue() * SecondsToMinutes;
seenParam = true;
}
@ -2394,7 +2412,7 @@ bool GCodes::HandleMcode(GCodeBuffer& gb, StringRef& reply)
{
reply.printf("Z Probe type %d, invert %s, dive height %.1fmm, probe speed %dmm/min, travel speed %dmm/min, recovery time %.2f sec",
platform->GetZProbeType(), (params.invertReading) ? "yes" : "no", params.diveHeight,
(int)(params.probeSpeed * minutesToSeconds), (int)(params.travelSpeed * minutesToSeconds), params.recoveryTime);
(int)(params.probeSpeed * MinutesToSeconds), (int)(params.travelSpeed * MinutesToSeconds), params.recoveryTime);
if (platform->GetZProbeType() == ZProbeTypeDelta)
{
reply.catf(", extra parameter %.2f", params.extraParam);
@ -2485,7 +2503,7 @@ bool GCodes::HandleMcode(GCodeBuffer& gb, StringRef& reply)
{
if (gb.Seen(axisLetters[axis]))
{
platform->SetInstantDv(axis, gb.GetFValue() * distanceScale * secondsToMinutes); // G Code feedrates are in mm/minute; we need mm/sec
platform->SetInstantDv(axis, gb.GetFValue() * distanceScale * SecondsToMinutes); // G Code feedrates are in mm/minute; we need mm/sec
seen = true;
}
}
@ -2498,7 +2516,7 @@ bool GCodes::HandleMcode(GCodeBuffer& gb, StringRef& reply)
gb.GetFloatArray(eVals, eCount, true);
for (size_t e = 0; e < eCount; e++)
{
platform->SetInstantDv(numAxes + e, eVals[e] * distanceScale * secondsToMinutes);
platform->SetInstantDv(numAxes + e, eVals[e] * distanceScale * SecondsToMinutes);
}
}
else if (!seen)
@ -2506,13 +2524,13 @@ bool GCodes::HandleMcode(GCodeBuffer& gb, StringRef& reply)
reply.copy("Maximum jerk rates: ");
for (size_t axis = 0; axis < numAxes; ++axis)
{
reply.catf("%c: %.1f, ", axisLetters[axis], platform->ConfiguredInstantDv(axis) / (distanceScale * secondsToMinutes));
reply.catf("%c: %.1f, ", axisLetters[axis], platform->ConfiguredInstantDv(axis) / (distanceScale * SecondsToMinutes));
}
reply.cat("E:");
char sep = ' ';
for (size_t extruder = 0; extruder < numExtruders; extruder++)
{
reply.catf("%c%.1f", sep, platform->ConfiguredInstantDv(extruder + numAxes) / (distanceScale * secondsToMinutes));
reply.catf("%c%.1f", sep, platform->ConfiguredInstantDv(extruder + numAxes) / (distanceScale * SecondsToMinutes));
sep = ':';
}
}

View file

@ -89,11 +89,13 @@ const size_t CART_AXES = 3; // The number of Cartesian axes
const size_t X_AXIS = 0, Y_AXIS = 1, Z_AXIS = 2, E0_AXIS = 3; // The indices of the Cartesian axes in drive arrays
// Common conversion factors
const float minutesToSeconds = 60.0;
const float secondsToMinutes = 1.0/minutesToSeconds;
const float MinutesToSeconds = 60.0;
const float SecondsToMinutes = 1.0/MinutesToSeconds;
const float SecondsToMillis = 1000.0;
const float MillisToSeconds = 0.001;
const float InchToMm = 25.4;
const float DegreesToRadians = PI/180.0;
const float RadiansToDegrees = 180.0/PI;
// Type of an offset in a file
typedef uint32_t FilePosition;

View file

@ -9,11 +9,11 @@
#define SRC_VERSION_H_
#ifndef VERSION
# define VERSION "1.17c"
# define VERSION "1.17c+1"
#endif
#ifndef DATE
# define DATE "2017-01-14"
# define DATE "2017-01-19"
#endif
#define AUTHORS "reprappro, dc42, chrishamm, t3p3, dnewman"