diff options
author | David Crocker <dcrocker@eschertech.com> | 2018-02-28 19:37:07 +0300 |
---|---|---|
committer | David Crocker <dcrocker@eschertech.com> | 2018-02-28 19:45:25 +0300 |
commit | fa55cdada75c00cac180e26a31e151ed18093abd (patch) | |
tree | 282a59f5bdc524a8e3a8214b64b77cbb440a14b9 /src/PrintMonitor.cpp | |
parent | 3b2c5340e1b8a399335c0e2b0dbe68aff55ec168 (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.cpp | 402 |
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)); } } |