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
diff options
context:
space:
mode:
authorDavid Crocker <dcrocker@eschertech.com>2018-02-28 19:37:07 +0300
committerDavid Crocker <dcrocker@eschertech.com>2018-02-28 19:45:25 +0300
commitfa55cdada75c00cac180e26a31e151ed18093abd (patch)
tree282a59f5bdc524a8e3a8214b64b77cbb440a14b9 /src/PrintMonitor.cpp
parent3b2c5340e1b8a399335c0e2b0dbe68aff55ec168 (diff)
Version 1.21RC3
Upgrade notes: - On Cartesian and CoreXY printers, normal G0 and G1 moves are no longer allowed before the corresponding axes have been homed. In particular, if your homex.g, homey.g and homeall.g files raise Z a little at the start and lower it at the end, you will need to add the S2 parameter to those G1 Z moves. Otherwise the G1 Z move will be refused unless Z has already been homed and the homing macro will be terminated. New features: - On Cartesian and CoreXY printers, normal movement commands are no longer permitted until the corresponding axes have been homed - Illegal movement commands in a print file or macro file cause the file to be terminated and heaters/spindle motors/lasers to be turned off; except that when the printer is in FDM mode, G0 and G1 moves outside the movement limits are just truncated as before - The M39 command reports the SD card cluster size - If GCode attempts to set the temperature of a non-existent bed or chamber heater to zero (to turn it off), the error message that would normally be generated is suppressed - G60 command to set a restore point is implemented - M671 command now supports the F (fudge factor) parameter - The standstill current fraction can now be set on the Duet Maestro build - M118 support added (thanks chrishamm) - When using external stepper drivers the DIR signal is no longer changed before the step pulse has ended - The M452, M453 and M573 commands now support the I1 parameter to invert the laser, spindle or extrusion signal polarity Bug fixes - Duet Ethernet only: fixed bugs in the DHCP client code that could cause the printer to become very slow - G2 and G3 arc moves are terminated if the attempt to exceed the axis limits - When multi-touch Z probe mode is enabled, the recovery time is applied before all probing movements, not just the first one - Z probe mode 9 (for BLTouch) ow works in multi-touch mode - During simulation the status is set to "Simulating" instead of "Printing" - M556 with a zero S parameter no longer messes up the coordinate calculations - When large files were uploaded or copied to the SD card and the cluster size was small, HTTP requests could time out while DWC attempted to get the information for those files - The Duet3D rotating magnet filament monitor is supported again - FTP didn't work reliable in 1.21RC2 - Endstops 5 thru 9 on a DueX2/DueX5 board can now be used for simple filament sensors - When resuming a paused print the first move executed was sometimes incorrect
Diffstat (limited to 'src/PrintMonitor.cpp')
-rw-r--r--src/PrintMonitor.cpp402
1 files changed, 216 insertions, 186 deletions
diff --git a/src/PrintMonitor.cpp b/src/PrintMonitor.cpp
index cb00022a..6e857748 100644
--- a/src/PrintMonitor.cpp
+++ b/src/PrintMonitor.cpp
@@ -345,239 +345,269 @@ bool PrintMonitor::GetFileInfo(const char *directory, const char *fileName, GCod
char* const buf = reinterpret_cast<char*>(buf32);
size_t sizeToRead, sizeToScan; // number of bytes we want to read and scan in this go
- if (parseState == parsingHeader)
+ switch (parseState)
{
- bool headerInfoComplete = true;
-
- // Read a chunk from the header. On the first run only process GCODE_READ_SIZE bytes, but use overlap next times.
- sizeToRead = (size_t)min<FilePosition>(fileBeingParsed->Length() - fileBeingParsed->Position(), GCODE_READ_SIZE);
- if (fileOverlapLength > 0)
- {
- memcpy(buf, fileOverlap, fileOverlapLength);
- sizeToScan = sizeToRead + fileOverlapLength;
- }
- else
+ case parsingHeader:
{
- sizeToScan = sizeToRead;
- }
+ bool headerInfoComplete = true;
- uint32_t startTime = millis();
- const int nbytes = fileBeingParsed->Read(&buf[fileOverlapLength], sizeToRead);
- if (nbytes != (int)sizeToRead)
- {
- platform.MessageF(ErrorMessage, "Failed to read header of G-Code file \"%s\"\n", fileName);
- parseState = notParsing;
- fileBeingParsed->Close();
- info = parsedFileInfo;
- return true;
- }
- buf[sizeToScan] = 0;
+ // Read a chunk from the header. On the first run only process GCODE_READ_SIZE bytes, but use overlap next times.
+ sizeToRead = (size_t)min<FilePosition>(fileBeingParsed->Length() - fileBeingParsed->Position(), GCODE_READ_SIZE);
+ if (fileOverlapLength > 0)
+ {
+ memcpy(buf, fileOverlap, fileOverlapLength);
+ sizeToScan = sizeToRead + fileOverlapLength;
+ }
+ else
+ {
+ sizeToScan = sizeToRead;
+ }
- // Record performance data
- uint32_t now = millis();
- accumulatedReadTime += now - startTime;
- startTime = now;
+ uint32_t startTime = millis();
+ const int nbytes = fileBeingParsed->Read(&buf[fileOverlapLength], sizeToRead);
+ if (nbytes != (int)sizeToRead)
+ {
+ platform.MessageF(ErrorMessage, "Failed to read header of G-Code file \"%s\"\n", fileName);
+ parseState = notParsing;
+ fileBeingParsed->Close();
+ info = parsedFileInfo;
+ return true;
+ }
+ buf[sizeToScan] = 0;
- // Search for filament usage (Cura puts it at the beginning of a G-code file)
- if (parsedFileInfo.numFilaments == 0)
- {
- parsedFileInfo.numFilaments = FindFilamentUsed(buf, sizeToScan, parsedFileInfo.filamentNeeded, DRIVES - reprap.GetGCodes().GetTotalAxes());
- headerInfoComplete &= (parsedFileInfo.numFilaments != 0);
- }
+ // Record performance data
+ uint32_t now = millis();
+ accumulatedReadTime += now - startTime;
+ startTime = now;
- // Look for first layer height
- if (parsedFileInfo.firstLayerHeight == 0.0)
- {
- headerInfoComplete &= FindFirstLayerHeight(buf, sizeToScan, parsedFileInfo.firstLayerHeight);
- }
+ // Search for filament usage (Cura puts it at the beginning of a G-code file)
+ if (parsedFileInfo.numFilaments == 0)
+ {
+ parsedFileInfo.numFilaments = FindFilamentUsed(buf, sizeToScan, parsedFileInfo.filamentNeeded, DRIVES - reprap.GetGCodes().GetTotalAxes());
+ headerInfoComplete &= (parsedFileInfo.numFilaments != 0);
+ }
- // Look for layer height
- if (parsedFileInfo.layerHeight == 0.0)
- {
- headerInfoComplete &= FindLayerHeight(buf, sizeToScan, parsedFileInfo.layerHeight);
- }
+ // Look for first layer height
+ if (parsedFileInfo.firstLayerHeight == 0.0)
+ {
+ headerInfoComplete &= FindFirstLayerHeight(buf, sizeToScan, parsedFileInfo.firstLayerHeight);
+ }
- // Look for slicer program
- if (parsedFileInfo.generatedBy[0] == 0)
- {
- static const char * const GeneratedByStrings[] =
+ // Look for layer height
+ if (parsedFileInfo.layerHeight == 0.0)
{
- "generated by ", // slic3r and S3D
- ";Sliced by ", // ideaMaker
- "; KISSlicer", // KISSlicer
- ";Sliced at: ", // Cura (old)
- ";Generated with " // Cura (new)
- };
-
- size_t index = 0;
- const char* pos;
- do
+ headerInfoComplete &= FindLayerHeight(buf, sizeToScan, parsedFileInfo.layerHeight);
+ }
+
+ // Look for slicer program
+ if (parsedFileInfo.generatedBy[0] == 0)
{
- pos = strstr(buf, GeneratedByStrings[index]);
- if (pos != nullptr)
+ static const char * const GeneratedByStrings[] =
{
- break;
- }
- ++index;
- } while (index < ARRAY_SIZE(GeneratedByStrings));
+ "generated by ", // slic3r and S3D
+ ";Sliced by ", // ideaMaker
+ "; KISSlicer", // KISSlicer
+ ";Sliced at: ", // Cura (old)
+ ";Generated with " // Cura (new)
+ };
+
+ size_t index = 0;
+ const char* pos;
+ do
+ {
+ pos = strstr(buf, GeneratedByStrings[index]);
+ if (pos != nullptr)
+ {
+ break;
+ }
+ ++index;
+ } while (index < ARRAY_SIZE(GeneratedByStrings));
- if (pos != nullptr)
- {
- const char* introString = "";
- switch (index)
+ if (pos != nullptr)
{
- default:
- pos += strlen(GeneratedByStrings[index]);
- break;
+ const char* introString = "";
+ switch (index)
+ {
+ default:
+ pos += strlen(GeneratedByStrings[index]);
+ break;
- case 2: // KISSlicer
- pos += 2;
- break;
+ case 2: // KISSlicer
+ pos += 2;
+ break;
- case 3: // Cura (old)
- introString = "Cura at ";
- pos += strlen(GeneratedByStrings[index]);
- break;
+ case 3: // Cura (old)
+ introString = "Cura at ";
+ pos += strlen(GeneratedByStrings[index]);
+ break;
+ }
+
+ strcpy(parsedFileInfo.generatedBy, introString);
+ size_t i = strlen(introString);
+ while (i < ARRAY_SIZE(parsedFileInfo.generatedBy) - 1 && *pos >= ' ')
+ {
+ parsedFileInfo.generatedBy[i++] = *pos++;
+ }
+ parsedFileInfo.generatedBy[i] = 0;
}
+ }
+ headerInfoComplete &= (parsedFileInfo.generatedBy[0] != 0);
+
+ // Keep track of the time stats
+ accumulatedParseTime += millis() - startTime;
- strcpy(parsedFileInfo.generatedBy, introString);
- size_t i = strlen(introString);
- while (i < ARRAY_SIZE(parsedFileInfo.generatedBy) - 1 && *pos >= ' ')
+ // Can we proceed to the footer? Don't scan more than the first 4KB of the file
+ FilePosition pos = fileBeingParsed->Position();
+ if (headerInfoComplete || pos >= GCODE_HEADER_SIZE || pos == fileBeingParsed->Length())
+ {
+ // Yes - see if we need to output some debug info
+ if (reprap.Debug(modulePrintMonitor))
{
- parsedFileInfo.generatedBy[i++] = *pos++;
+ platform.MessageF(UsbMessage, "Header complete, processed %lu bytes, read time %.3fs, parse time %.3fs\n",
+ fileBeingParsed->Position(), (double)((float)accumulatedReadTime/1000.0), (double)((float)accumulatedParseTime/1000.0));
}
- parsedFileInfo.generatedBy[i] = 0;
+
+ // Go to the last chunk and proceed from there on
+ const FilePosition seekFromEnd = ((fileBeingParsed->Length() - 1) % GCODE_READ_SIZE) + 1;
+ nextSeekPos = fileBeingParsed->Length() - seekFromEnd;
+ accumulatedSeekTime = accumulatedReadTime = accumulatedParseTime = 0;
+ fileOverlapLength = 0;
+ parseState = seeking;
+ }
+ else
+ {
+ // No - copy the last chunk of the buffer for overlapping search
+ fileOverlapLength = min<size_t>(sizeToRead, GCODE_OVERLAP_SIZE);
+ memcpy(fileOverlap, &buf[sizeToRead - fileOverlapLength], fileOverlapLength);
}
}
- headerInfoComplete &= (parsedFileInfo.generatedBy[0] != 0);
-
- // Keep track of the time stats
- accumulatedParseTime += millis() - startTime;
+ break;
- // Can we proceed to the footer? Don't scan more than the first 4KB of the file
- FilePosition pos = fileBeingParsed->Position();
- if (headerInfoComplete || pos >= GCODE_HEADER_SIZE || pos == fileBeingParsed->Length())
+ case seeking:
+ // Seeking into a large file can take a long time using the FAT file system, so do it in stages
{
- // Yes - see if we need to output some debug info
- if (reprap.Debug(modulePrintMonitor))
+ FilePosition currentPos = fileBeingParsed->Position();
+ const uint32_t clsize = fileBeingParsed->ClusterSize();
+ if (currentPos/clsize > nextSeekPos/clsize)
{
- platform.MessageF(UsbMessage, "Header complete, processed %lu bytes, read time %.3fs, parse time %.3fs\n",
- fileBeingParsed->Position(), (double)((float)accumulatedReadTime/1000.0), (double)((float)accumulatedParseTime/1000.0));
+ // Seeking backwards over a cluster boundary, so in practice the seek will start from the start of the file
+ currentPos = 0;
}
- // Go to the last chunk and proceed from there on
- startTime = millis();
- const FilePosition seekFromEnd = ((fileBeingParsed->Length() - 1) % GCODE_READ_SIZE) + 1;
- fileBeingParsed->Seek(fileBeingParsed->Length() - seekFromEnd);
- accumulatedSeekTime = millis() - startTime;
- accumulatedReadTime = accumulatedParseTime = 0;
- fileOverlapLength = 0;
- parseState = parsingFooter;
- }
- else
- {
- // No - copy the last chunk of the buffer for overlapping search
- fileOverlapLength = min<size_t>(sizeToRead, GCODE_OVERLAP_SIZE);
- memcpy(fileOverlap, &buf[sizeToRead - fileOverlapLength], fileOverlapLength);
- }
- }
+ // Seek at most 512 clusters at a time
+ const FilePosition maxSeekDistance = 512 * (FilePosition)clsize;
+ const bool doFullSeek = (nextSeekPos <= currentPos) || (nextSeekPos - currentPos <= maxSeekDistance);
+ const FilePosition thisSeekPos = (doFullSeek) ? nextSeekPos : currentPos + maxSeekDistance;
- if (parseState == parsingFooter)
- {
- // Processing the footer. See how many bytes we need to read and if we can reuse the overlap
- FilePosition pos = fileBeingParsed->Position();
- sizeToRead = (size_t)min<FilePosition>(fileBeingParsed->Length() - pos, GCODE_READ_SIZE);
- if (fileOverlapLength > 0)
- {
- memcpy(&buf[sizeToRead], fileOverlap, fileOverlapLength);
- sizeToScan = sizeToRead + fileOverlapLength;
- }
- else
- {
- sizeToScan = sizeToRead;
+ const uint32_t startTime = millis();
+ if (!fileBeingParsed->Seek(thisSeekPos))
+ {
+ platform.Message(ErrorMessage, "Could not seek from end of file!\n");
+ parseState = notParsing;
+ fileBeingParsed->Close();
+ info = parsedFileInfo;
+ return true;
+ }
+ accumulatedSeekTime += millis() - startTime;
+ if (doFullSeek)
+ {
+ parseState = parsingFooter;
+ }
}
+ break;
- // Read another chunk from the footer
- uint32_t startTime = millis();
- int nbytes = fileBeingParsed->Read(buf, sizeToRead);
- if (nbytes != (int)sizeToRead)
+ case parsingFooter:
{
- platform.MessageF(ErrorMessage, "Failed to read footer from G-Code file \"%s\"\n", fileName);
- parseState = notParsing;
- fileBeingParsed->Close();
- info = parsedFileInfo;
- return true;
- }
- buf[sizeToScan] = 0;
+ // Processing the footer. See how many bytes we need to read and if we can reuse the overlap
+ FilePosition pos = fileBeingParsed->Position();
+ sizeToRead = (size_t)min<FilePosition>(fileBeingParsed->Length() - pos, GCODE_READ_SIZE);
+ if (fileOverlapLength > 0)
+ {
+ memcpy(&buf[sizeToRead], fileOverlap, fileOverlapLength);
+ sizeToScan = sizeToRead + fileOverlapLength;
+ }
+ else
+ {
+ sizeToScan = sizeToRead;
+ }
- // Record performance data
- uint32_t now = millis();
- accumulatedReadTime += now - startTime;
- startTime = now;
+ // Read another chunk from the footer
+ uint32_t startTime = millis();
+ int nbytes = fileBeingParsed->Read(buf, sizeToRead);
+ if (nbytes != (int)sizeToRead)
+ {
+ platform.MessageF(ErrorMessage, "Failed to read footer from G-Code file \"%s\"\n", fileName);
+ parseState = notParsing;
+ fileBeingParsed->Close();
+ info = parsedFileInfo;
+ return true;
+ }
+ buf[sizeToScan] = 0;
- bool footerInfoComplete = true;
+ // Record performance data
+ uint32_t now = millis();
+ accumulatedReadTime += now - startTime;
+ startTime = now;
- // Search for filament used
- if (parsedFileInfo.numFilaments == 0)
- {
- parsedFileInfo.numFilaments = FindFilamentUsed(buf, sizeToScan, parsedFileInfo.filamentNeeded, DRIVES - reprap.GetGCodes().GetTotalAxes());
+ bool footerInfoComplete = true;
+
+ // Search for filament used
if (parsedFileInfo.numFilaments == 0)
{
- footerInfoComplete = false;
+ parsedFileInfo.numFilaments = FindFilamentUsed(buf, sizeToScan, parsedFileInfo.filamentNeeded, DRIVES - reprap.GetGCodes().GetTotalAxes());
+ if (parsedFileInfo.numFilaments == 0)
+ {
+ footerInfoComplete = false;
+ }
}
- }
- // Search for layer height
- if (parsedFileInfo.layerHeight == 0.0)
- {
- if (!FindLayerHeight(buf, sizeToScan, parsedFileInfo.layerHeight))
+ // Search for layer height
+ if (parsedFileInfo.layerHeight == 0.0)
{
- footerInfoComplete = false;
+ if (!FindLayerHeight(buf, sizeToScan, parsedFileInfo.layerHeight))
+ {
+ footerInfoComplete = false;
+ }
}
- }
- // Search for object height
- if (parsedFileInfo.objectHeight == 0.0)
- {
- if (!FindHeight(buf, sizeToScan, parsedFileInfo.objectHeight))
+ // Search for object height
+ if (parsedFileInfo.objectHeight == 0.0)
{
- footerInfoComplete = false;
+ if (!FindHeight(buf, sizeToScan, parsedFileInfo.objectHeight))
+ {
+ footerInfoComplete = false;
+ }
}
- }
- // Keep track of the time stats
- accumulatedParseTime += millis() - startTime;
+ // Keep track of the time stats
+ accumulatedParseTime += millis() - startTime;
- // If we've collected all details, scanned the last 192K of the file or if we cannot go any further, stop here.
- if (footerInfoComplete || pos == 0 || fileBeingParsed->Length() - pos >= GCODE_FOOTER_SIZE)
- {
- if (reprap.Debug(modulePrintMonitor))
+ // If we've collected all details, scanned the last 192K of the file or if we cannot go any further, stop here.
+ if (footerInfoComplete || pos == 0 || fileBeingParsed->Length() - pos >= GCODE_FOOTER_SIZE)
{
- platform.MessageF(UsbMessage, "Footer complete, processed %lu bytes, read time %.3fs, parse time %.3fs, seek time %.3fs\n",
- fileBeingParsed->Length() - fileBeingParsed->Position() + GCODE_READ_SIZE,
- (double)((float)accumulatedReadTime/1000.0), (double)((float)accumulatedParseTime/1000.0), (double)((float)accumulatedSeekTime/1000.0));
+ if (reprap.Debug(modulePrintMonitor))
+ {
+ platform.MessageF(UsbMessage, "Footer complete, processed %lu bytes, read time %.3fs, parse time %.3fs, seek time %.3fs\n",
+ fileBeingParsed->Length() - fileBeingParsed->Position() + GCODE_READ_SIZE,
+ (double)((float)accumulatedReadTime/1000.0), (double)((float)accumulatedParseTime/1000.0), (double)((float)accumulatedSeekTime/1000.0));
+ }
+ parseState = notParsing;
+ fileBeingParsed->Close();
+ info = parsedFileInfo;
+ return true;
}
- parseState = notParsing;
- fileBeingParsed->Close();
- info = parsedFileInfo;
- return true;
- }
- // Else go back further
- startTime = millis();
- size_t seekOffset = (size_t)min<FilePosition>(pos, GCODE_READ_SIZE);
- if (!fileBeingParsed->Seek(pos - seekOffset))
- {
- platform.Message(ErrorMessage, "Could not seek from end of file!\n");
- parseState = notParsing;
- fileBeingParsed->Close();
- info = parsedFileInfo;
- return true;
+ // Else go back further
+ fileOverlapLength = (size_t)min<FilePosition>(sizeToScan, GCODE_OVERLAP_SIZE);
+ memcpy(fileOverlap, buf, fileOverlapLength);
+ nextSeekPos = (pos <= GCODE_READ_SIZE) ? 0 : pos - GCODE_READ_SIZE;
+ parseState = seeking;
}
- accumulatedSeekTime += millis() - startTime;
+ break;
- fileOverlapLength = (size_t)min<FilePosition>(sizeToScan, GCODE_OVERLAP_SIZE);
- memcpy(fileOverlap, buf, fileOverlapLength);
+ default: // should not get here
+ info = parsedFileInfo;
+ return true;
}
} while (!isPrinting && millis() - loopStartTime < MAX_FILEINFO_PROCESS_TIME);
return false;
@@ -1057,7 +1087,7 @@ bool PrintMonitor::FindLayerHeight(const char *buf, size_t len, float& layerHeig
// Scan the buffer for the filament used. The buffer is null-terminated.
// Returns the number of filaments found.
-unsigned int PrintMonitor::FindFilamentUsed(const char* buf, size_t len, float *filamentUsed, unsigned int maxFilaments) const
+unsigned int PrintMonitor::FindFilamentUsed(const char* buf, size_t len, float *filamentUsed, size_t maxFilaments) const
{
unsigned int filamentsFound = 0;
@@ -1159,7 +1189,7 @@ unsigned int PrintMonitor::FindFilamentUsed(const char* buf, size_t len, float *
if (p != nullptr)
{
const float filamentCMM = strtof(p + strlen(filamentVolumeStr), nullptr) * 1000.0;
- filamentUsed[filamentsFound++] = filamentCMM / (PI * (platform.GetFilamentWidth() / 2.0) * (platform.GetFilamentWidth() / 2.0));
+ filamentUsed[filamentsFound++] = filamentCMM / (Pi * fsquare(platform.GetFilamentWidth() / 2.0));
}
}