diff options
author | David Crocker <dcrocker@eschertech.com> | 2018-03-11 14:16:57 +0300 |
---|---|---|
committer | David Crocker <dcrocker@eschertech.com> | 2018-03-11 14:16:57 +0300 |
commit | b1369644379aa9c6a1dd8f84d20210f32ded6dd5 (patch) | |
tree | 0d5e376cc33d1344e6d007540127b2746f1803be /src/PrintMonitor.cpp | |
parent | afd7e327ec71865a2ecf0243265ef6f84387becb (diff) |
Version 1.21RC4(11b1)
New features:
- On CoreXZ machines we no longer require Z to be homed before bed
probing with G30
- M589 now checks that the password is either empty or 8 characters
minimum
- G10 L2 is supported as an alternative way to set tool offsets
- G10 L20 is supported as an alternative way to set workspace
coordinates
- Heater fault detection is suppressed when heaters are suspended during
bed probing
- DuetWiFiServer/bin uses a new SDK version, which seems to resolve some
issues
- On boards with a W5500 Ethernet interface, the Ethernet PHY is now
programmed to auto negotiate
- Added M564 H0 command to allow axis movement before homing on
Cartesian/CoreXY printers
- The filament length comment proposed to be generated by the next
version of Cura when using more than one filament is supported
Bug fixes:
- I parameter on M452, M453 and M573 didn't work
- If a homing file contained an illegal movement command then homing was
not cancelled
- Corrected Z probe input pin in RADDS build
- Possible fix to Duet 06/085 failure to start when using DHCP
Diffstat (limited to 'src/PrintMonitor.cpp')
-rw-r--r-- | src/PrintMonitor.cpp | 210 |
1 files changed, 108 insertions, 102 deletions
diff --git a/src/PrintMonitor.cpp b/src/PrintMonitor.cpp index 6e857748..216f27ed 100644 --- a/src/PrintMonitor.cpp +++ b/src/PrintMonitor.cpp @@ -45,7 +45,7 @@ void PrintMonitor::Spin() // File information about the file being printed must be available before layer estimations can be made if (filenameBeingPrinted[0] != 0 && !printingFileParsed) { - printingFileParsed = GetFileInfo(platform.GetGCodeDir(), filenameBeingPrinted, printingFileInfo); + printingFileParsed = GetFileInfo(platform.GetGCodeDir(), filenameBeingPrinted.c_str(), printingFileInfo); if (!printingFileParsed) { platform.ClassReport(longWait); @@ -111,24 +111,22 @@ void PrintMonitor::Spin() currentLayer = 1; } } - // Print is in progress and filament is being extruded else if (!gCodes.DoingFileMacro() && reprap.GetMove().IsExtruding()) { + // Print is in progress and filament is being extruded float liveCoordinates[DRIVES]; reprap.GetMove().LiveCoordinates(liveCoordinates, reprap.GetCurrentXAxes(), reprap.GetCurrentYAxes()); - // See if we need to determine the first layer height (usually smaller than the nozzle diameter) - if (printingFileInfo.firstLayerHeight == 0.0) + if (currentLayer == 1) { - if (liveCoordinates[Z_AXIS] < platform.GetNozzleDiameter() * 1.5) + // See if we need to determine the first layer height (usually smaller than the nozzle diameter) + if (printingFileInfo.firstLayerHeight == 0.0 && liveCoordinates[Z_AXIS] < platform.GetNozzleDiameter() * 1.5) { // This shouldn't be needed because we parse the first layer height anyway, but it won't harm printingFileInfo.firstLayerHeight = liveCoordinates[Z_AXIS]; } - } - // Check if we've finished the first layer - else if (currentLayer == 1) - { + + // Check if we've finished the first layer if (liveCoordinates[Z_AXIS] > printingFileInfo.firstLayerHeight + LAYER_HEIGHT_TOLERANCE) { FirstLayerComplete(); @@ -169,7 +167,7 @@ float PrintMonitor::GetWarmUpDuration() const void PrintMonitor::StartingPrint(const char* filename) { printingFileParsed = GetFileInfo(platform.GetGCodeDir(), filename, printingFileInfo); - SafeStrncpy(filenameBeingPrinted, filename, ARRAY_SIZE(filenameBeingPrinted)); + filenameBeingPrinted.copy(filename); } // Tell this class that the file set for printing is now actually processed @@ -195,9 +193,9 @@ void PrintMonitor::FirstLayerComplete() // Update layer-based estimation time (if the object and layer heights are known) // This won't be very accurate, but at least something can be sent the web interface and to PanelDue - if (printingFileInfo.objectHeight > 0.0 && printingFileInfo.layerHeight > 0.0) + if (printingFileInfo.layerHeight > 0.0 && printingFileInfo.objectHeight > printingFileInfo.layerHeight) { - unsigned int layersToPrint = round((printingFileInfo.objectHeight - printingFileInfo.firstLayerHeight) / printingFileInfo.layerHeight) + 1; + unsigned int layersToPrint = lrintf((printingFileInfo.objectHeight - printingFileInfo.firstLayerHeight) / printingFileInfo.layerHeight) + 1; layerEstimatedTimeLeft = firstLayerDuration * FIRST_LAYER_SPEED_FACTOR * (layersToPrint - 1); } } @@ -238,7 +236,7 @@ void PrintMonitor::LayerComplete() lastLayerFilament = extrRawTotal; // Update layer-based estimation time (if the object and layer heights are known) - if (printingFileInfo.objectHeight > 0.0 && printingFileInfo.layerHeight > 0.0) + if (printingFileInfo.layerHeight > 0.0 && printingFileInfo.objectHeight > printingFileInfo.layerHeight) { // Calculate the average layer time and include the first layer if possible float avgLayerTime = (numLayerSamples < MAX_LAYER_SAMPLES) @@ -251,8 +249,7 @@ void PrintMonitor::LayerComplete() avgLayerTime /= (numLayerSamples < MAX_LAYER_SAMPLES) ? numLayerSamples + 1 : numLayerSamples; // Estimate the layer-based time left - unsigned int totalLayers; - totalLayers = round((printingFileInfo.objectHeight - printingFileInfo.firstLayerHeight) / printingFileInfo.layerHeight) + 1; + const unsigned int totalLayers = lrintf((printingFileInfo.objectHeight - printingFileInfo.firstLayerHeight) / printingFileInfo.layerHeight) + 1; if (currentLayer < totalLayers) { // Current layer is within reasonable boundaries, so an estimation can be made @@ -278,6 +275,19 @@ void PrintMonitor::StoppedPrint() bool PrintMonitor::GetFileInfo(const char *directory, const char *fileName, GCodeFileInfo& info) { + if (parseState != notParsing && !StringEquals(fileName, filenameBeingParsed.c_str())) + { + // We are already parsing a different file + if (millis() - lastFileParseTime < MaxFileParseInterval) + { + return false; // try again later + } + + // Time this client out because it has probably disconnected + fileBeingParsed->Close(); + parseState = notParsing; + } + if (parseState == notParsing) { // See if we can access the file @@ -297,7 +307,7 @@ bool PrintMonitor::GetFileInfo(const char *directory, const char *fileName, GCod } // File has been opened, let's start now - SafeStrncpy(filenameBeingParsed, fileName, ARRAY_SIZE(filenameBeingParsed)); + filenameBeingParsed.copy(fileName); fileOverlapLength = 0; // Set up the info struct @@ -331,11 +341,6 @@ bool PrintMonitor::GetFileInfo(const char *directory, const char *fileName, GCod } parseState = parsingHeader; } - else if (!StringEquals(fileName, filenameBeingParsed)) - { - // We are already parsing a different file. Try again later. - return false; - } // Getting file information take a few runs. Speed it up when we are not printing by calling it several times. const uint32_t loopStartTime = millis(); @@ -400,58 +405,10 @@ bool PrintMonitor::GetFileInfo(const char *directory, const char *fileName, GCod } // Look for slicer program - if (parsedFileInfo.generatedBy[0] == 0) + if (parsedFileInfo.generatedBy.IsEmpty()) { - static const char * const 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) - { - default: - pos += strlen(GeneratedByStrings[index]); - break; - - case 2: // KISSlicer - pos += 2; - 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 &= FindSlicerInfo(buf, sizeToScan, parsedFileInfo.generatedBy.GetRef()); } - headerInfoComplete &= (parsedFileInfo.generatedBy[0] != 0); // Keep track of the time stats accumulatedParseTime += millis() - startTime; @@ -496,7 +453,7 @@ bool PrintMonitor::GetFileInfo(const char *directory, const char *fileName, GCod // Seek at most 512 clusters at a time const FilePosition maxSeekDistance = 512 * (FilePosition)clsize; - const bool doFullSeek = (nextSeekPos <= currentPos) || (nextSeekPos - currentPos <= maxSeekDistance); + const bool doFullSeek = (nextSeekPos <= currentPos + maxSeekDistance); const FilePosition thisSeekPos = (doFullSeek) ? nextSeekPos : currentPos + maxSeekDistance; const uint32_t startTime = millis(); @@ -519,8 +476,7 @@ bool PrintMonitor::GetFileInfo(const char *directory, const char *fileName, GCod case 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); + sizeToRead = (size_t)min<FilePosition>(fileBeingParsed->Length() - nextSeekPos, GCODE_READ_SIZE); if (fileOverlapLength > 0) { memcpy(&buf[sizeToRead], fileOverlap, fileOverlapLength); @@ -583,7 +539,7 @@ bool PrintMonitor::GetFileInfo(const char *directory, const char *fileName, GCod 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 (footerInfoComplete || nextSeekPos == 0 || fileBeingParsed->Length() - nextSeekPos >= GCODE_FOOTER_SIZE) { if (reprap.Debug(modulePrintMonitor)) { @@ -600,7 +556,7 @@ bool PrintMonitor::GetFileInfo(const char *directory, const char *fileName, GCod // 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; + nextSeekPos = (nextSeekPos <= GCODE_READ_SIZE) ? 0 : nextSeekPos - GCODE_READ_SIZE; parseState = seeking; } break; @@ -609,7 +565,8 @@ bool PrintMonitor::GetFileInfo(const char *directory, const char *fileName, GCod info = parsedFileInfo; return true; } - } while (!isPrinting && millis() - loopStartTime < MAX_FILEINFO_PROCESS_TIME); + lastFileParseTime = millis(); + } while (!isPrinting && lastFileParseTime - loopStartTime < MAX_FILEINFO_PROCESS_TIME); return false; } @@ -659,7 +616,7 @@ bool PrintMonitor::GetFileInfoResponse(const char *filename, OutputBuffer *&resp } } response->cat("],\"generatedBy\":"); - response->EncodeString(info.generatedBy, ARRAY_SIZE(info.generatedBy), false); + response->EncodeString(info.generatedBy.c_str(), info.generatedBy.MaxLength(), false); response->cat("}"); } else @@ -699,9 +656,9 @@ bool PrintMonitor::GetFileInfoResponse(const char *filename, OutputBuffer *&resp } } response->cat("],\"generatedBy\":"); - response->EncodeString(printingFileInfo.generatedBy, ARRAY_SIZE(printingFileInfo.generatedBy), false); + response->EncodeString(printingFileInfo.generatedBy.GetRef(), false); response->catf(",\"printDuration\":%d,\"fileName\":", (int)GetPrintDuration()); - response->EncodeString(filenameBeingPrinted, ARRAY_SIZE(filenameBeingPrinted), false); + response->EncodeString(filenameBeingPrinted.GetRef(), false); response->cat('}'); } else @@ -717,22 +674,6 @@ bool PrintMonitor::GetFileInfoResponse(const char *filename, OutputBuffer *&resp return true; } -// May be called from ISR -void PrintMonitor::StopParsing(const char *filename) -{ - if (parseState != notParsing && StringEquals(filenameBeingParsed, filename)) - { - if (filenameBeingPrinted[0] != 0 && !printingFileParsed) - { - // If this is the file we're parsing for internal purposes, don't bother with this request - return; - } - - parseState = notParsing; - fileBeingParsed->Close(); - } -} - // Estimate the print time left in seconds on a preset estimation method float PrintMonitor::EstimateTimeLeft(PrintEstimationMethod method) const { @@ -1085,6 +1026,58 @@ bool PrintMonitor::FindLayerHeight(const char *buf, size_t len, float& layerHeig return false; } +bool PrintMonitor::FindSlicerInfo(const char* buf, size_t len, const StringRef& generatedBy) const +{ + static const char * const 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) + { + default: + pos += strlen(GeneratedByStrings[index]); + break; + + case 2: // KISSlicer + pos += 2; + break; + + case 3: // Cura (old) + introString = "Cura at "; + pos += strlen(GeneratedByStrings[index]); + break; + } + + generatedBy.copy(introString); + while (*pos >= ' ') + { + generatedBy.cat(*pos++); + } + return true; + } + return false; +} + // 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, size_t maxFilaments) const @@ -1092,7 +1085,7 @@ unsigned int PrintMonitor::FindFilamentUsed(const char* buf, size_t len, float * unsigned int filamentsFound = 0; // Look for filament usage as generated by Slic3r and Cura - const char* filamentUsedStr1 = "ilament used"; // comment string used by slic3r and Cura, followed by filament used and "mm" + const char* const filamentUsedStr1 = "ilament used"; // comment string used by slic3r and Cura, followed by filament used and "mm" const char* p = buf; while (filamentsFound < maxFilaments && (p = strstr(p, filamentUsedStr1)) != nullptr) { @@ -1101,20 +1094,33 @@ unsigned int PrintMonitor::FindFilamentUsed(const char* buf, size_t len, float * { ++p; // this allows for " = " from default slic3r comment and ": " from default Cura comment } - if (isDigit(*p)) + while (isDigit(*p)) { char* q; filamentUsed[filamentsFound] = strtod(p, &q); - if (*q == 'm' && *(q + 1) != 'm') + p = q; + if (*p == 'm') { - filamentUsed[filamentsFound] *= 1000.0; // Cura outputs filament used in metres not mm + ++p; + if (*p == 'm') + { + ++p; + } + else + { + filamentUsed[filamentsFound] *= 1000.0; // Cura outputs filament used in metres not mm + } } ++filamentsFound; + while (strchr(", \t", *p) != nullptr) + { + ++p; + } } } // Look for filament usage string generated by Ideamaker - const char* filamentUsedStr2 = ";Material#"; // comment string used by Ideamaker, e.g. ";Material#1 Used: 868.0" + const char* const filamentUsedStr2 = ";Material#"; // comment string used by Ideamaker, e.g. ";Material#1 Used: 868.0" p = buf; while (filamentsFound < maxFilaments && (p = strstr(p, filamentUsedStr2)) != nullptr) { @@ -1146,7 +1152,7 @@ unsigned int PrintMonitor::FindFilamentUsed(const char* buf, size_t len, float * p += strlen(filamentLengthStr); while(strchr(" :=\t", *p) != nullptr) { - ++p; // this allows for " = " from default slic3r comment and ": " from default Cura comment + ++p; } if (isDigit(*p)) { |