From 120987ff6314c3ff0a01d14735794f0b39bdea14 Mon Sep 17 00:00:00 2001 From: David Crocker Date: Thu, 19 Jan 2017 20:11:04 +0000 Subject: 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 --- src/Configuration.h | 2 + src/Duet/Pins_Duet.h | 2 +- src/DuetNG/DuetWiFi/Network.cpp | 31 ++-- src/DuetNG/DuetWiFi/Network.h | 3 +- src/DuetNG/DuetWiFi/WifiFirmwareUploader.cpp | 2 +- src/DuetNG/FirmwareUpdater.cpp | 2 +- src/GCodes/GCodeMachineState.cpp | 2 +- src/GCodes/GCodes.cpp | 216 +++++++++++++++++++++++---- src/GCodes/GCodes.h | 30 +++- src/GCodes/GCodes2.cpp | 52 ++++--- src/RepRapFirmware.h | 6 +- src/Version.h | 4 +- 12 files changed, 274 insertions(+), 78 deletions(-) (limited to 'src') diff --git a/src/Configuration.h b/src/Configuration.h index 14ecfe0d..4c844ed4 100644 --- a/src/Configuration.h +++ b/src/Configuration.h @@ -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 diff --git a/src/Duet/Pins_Duet.h b/src/Duet/Pins_Duet.h index 4234a869..18096b6d 100644 --- a/src/Duet/Pins_Duet.h +++ b/src/Duet/Pins_Duet.h @@ -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 diff --git a/src/DuetNG/DuetWiFi/Network.cpp b/src/DuetNG/DuetWiFi/Network.cpp index 63720451..316461c4 100644 --- a/src/DuetNG/DuetWiFi/Network.cpp +++ b/src/DuetNG/DuetWiFi/Network.cpp @@ -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 diff --git a/src/DuetNG/DuetWiFi/Network.h b/src/DuetNG/DuetWiFi/Network.h index 66963776..4b13f34e 100644 --- a/src/DuetNG/DuetWiFi/Network.h +++ b/src/DuetNG/DuetWiFi/Network.h @@ -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; } diff --git a/src/DuetNG/DuetWiFi/WifiFirmwareUploader.cpp b/src/DuetNG/DuetWiFi/WifiFirmwareUploader.cpp index cfe108d3..a94518c5 100644 --- a/src/DuetNG/DuetWiFi/WifiFirmwareUploader.cpp +++ b/src/DuetNG/DuetWiFi/WifiFirmwareUploader.cpp @@ -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; } diff --git a/src/DuetNG/FirmwareUpdater.cpp b/src/DuetNG/FirmwareUpdater.cpp index 3fd43179..87a9dcaa 100644 --- a/src/DuetNG/FirmwareUpdater.cpp +++ b/src/DuetNG/FirmwareUpdater.cpp @@ -62,7 +62,7 @@ namespace FirmwareUpdater switch(module) { case WifiExternalFirmwareModule: - Network::ResetWiFiForExternalUpload(); + Network::ResetWiFiForUpload(true); break; case WifiFirmwareModule: diff --git a/src/GCodes/GCodeMachineState.cpp b/src/GCodes/GCodeMachineState.cpp index e21cddfb..420b2c5b 100644 --- a/src/GCodes/GCodeMachineState.cpp +++ b/src/GCodes/GCodeMachineState.cpp @@ -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) { } diff --git a/src/GCodes/GCodes.cpp b/src/GCodes/GCodes.cpp index 97bebd8e..cb83c7d1 100644 --- a/src/GCodes/GCodes.cpp +++ b/src/GCodes/GCodes.cpp @@ -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 (LoadExtrusionAndFeedrateFromGCode(gb, moveBuffer.moveType)) + { + segmentsLeft = LoadMoveBufferFromGCode(gb, moveBuffer.moveType); + if (segmentsLeft != 0) + { + // 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) + { + 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); + } + } + return (moveBuffer.moveType != 0 || moveBuffer.endStopsToCheck != 0) ? 2 : 1; +} + +// 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])); - if (segmentsLeft != 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')) { - // 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; + 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 (axis != Z_AXIS && moveBuffer.coords[axis] != moveBuffer.initialCoords[axis]) + if ((arcAxesMoving & (1 << axis)) != 0) { - moveBuffer.usePressureAdvance = true; - break; + 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]; + } } } - 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; + 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)((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 { diff --git a/src/GCodes/GCodes.h b/src/GCodes/GCodes.h index 017d98dc..6a32aa87 100644 --- a/src/GCodes/GCodes.h +++ b/src/GCodes/GCodes.h @@ -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 diff --git a/src/GCodes/GCodes2.cpp b/src/GCodes/GCodes2.cpp index 0308fcf9..86690abf 100644 --- a/src/GCodes/GCodes2.cpp +++ b/src/GCodes/GCodes2.cpp @@ -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(gb.GetFValue(), 60.0) * secondsToMinutes; + unRetractSpeed = retractSpeed = max(gb.GetFValue(), 60.0) * SecondsToMinutes; seen = true; } if (gb.Seen('T')) // must do this one after 'F' { - unRetractSpeed = max(gb.GetFValue(), 60.0) * secondsToMinutes; + unRetractSpeed = max(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 = ':'; } } diff --git a/src/RepRapFirmware.h b/src/RepRapFirmware.h index 1b866008..6e596092 100644 --- a/src/RepRapFirmware.h +++ b/src/RepRapFirmware.h @@ -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; diff --git a/src/Version.h b/src/Version.h index 6bf69967..d3cf2f3b 100644 --- a/src/Version.h +++ b/src/Version.h @@ -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" -- cgit v1.2.3