1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
|
/****************************************************************************************************
RepRapFirmware - PrintMonitor
This class provides methods to obtain print end-time estimations and file information from generated
G-Code files, which may be reported to auxiliary devices and to the web interface using status responses.
-----------------------------------------------------------------------------------------------------
Version 0.1
Created on: Feb 24, 2015
Christian Hammacher
Licence: GPL
****************************************************************************************************/
#ifndef PRINTMONITOR_H
#define PRINTMONITOR_H
const FilePosition GCODE_HEADER_SIZE = 8192uL; // How many bytes to read from the header
const FilePosition GCODE_FOOTER_SIZE = 400000uL; // How many bytes to read from the footer
#ifdef DUET_NG
const size_t GCODE_READ_SIZE = 4096; // How many bytes to read in one go in GetFileInfo() (should be a multiple of 512 for read efficiency)
#else
const size_t GCODE_READ_SIZE = 1024; // How many bytes to read in one go in GetFileInfo() (should be a multiple of 512 for read efficiency)
#endif
const size_t GCODE_OVERLAP_SIZE = 100; // Size of the overlapping buffer for searching (should be a multiple of 4)
const float LAYER_HEIGHT_TOLERANCE = 0.015; // Tolerance for comparing two Z heights (in mm)
const size_t MAX_LAYER_SAMPLES = 5; // Number of layer samples for end-time estimation (except for first layer)
const float ESTIMATION_MIN_FILAMENT_USAGE = 0.01; // Minimum per cent of filament to be printed before the filament-based estimation returns values
const float ESTIMATION_MIN_FILE_USAGE = 0.001; // Minium per cent of the file to be processed before any file-based estimations are made
const float FIRST_LAYER_SPEED_FACTOR = 0.25; // First layer speed factor compared to other layers (only for layer-based estimation)
const uint32_t PRINTMONITOR_UPDATE_INTERVAL = 200; // Update interval in milliseconds
const uint32_t MAX_FILEINFO_PROCESS_TIME = 200; // Maximum time to spend polling for file info in each call
enum PrintEstimationMethod
{
filamentBased,
fileBased,
layerBased
};
// Struct to hold Gcode file information
struct GCodeFileInfo
{
bool isValid;
FilePosition fileSize;
float firstLayerHeight;
float objectHeight;
float filamentNeeded[DRIVES - MIN_AXES];
unsigned int numFilaments;
float layerHeight;
char generatedBy[50];
};
enum FileParseState
{
notParsing,
parsingHeader,
parsingFooter
};
class PrintMonitor
{
public:
PrintMonitor(Platform *p, GCodes *gc);
void Spin();
void Init();
bool IsPrinting() const; // Is a file being printed?
void StartingPrint(const char *filename); // Called to indicate a file will be printed (see M23)
void StartedPrint(); // Called whenever a new live print starts (see M24)
void StoppedPrint(); // Called whenever a file print has stopped
// The following two methods need to be called until they return true - this may take a few runs
bool GetFileInfo(const char *directory, const char *fileName, GCodeFileInfo& info);
bool GetFileInfoResponse(const char *filename, OutputBuffer *&response);
void StopParsing(const char *filename);
// Return an estimate in seconds based on a specific estimation method
float EstimateTimeLeft(PrintEstimationMethod method) const;
// Provide some information about the file being printed
unsigned int GetCurrentLayer() const;
float GetCurrentLayerTime() const;
float GetPrintDuration() const;
float GetWarmUpDuration() const;
float GetFirstLayerDuration() const;
float GetFirstLayerHeight() const;
private:
Platform *platform;
GCodes *gCodes;
float longWait;
uint32_t lastUpdateTime;
// Information/Events concerning the file being printed
void WarmUpComplete();
void FirstLayerComplete();
void LayerComplete();
bool isPrinting;
float printStartTime;
float pauseStartTime, totalPauseTime;
bool heatingUp;
unsigned int currentLayer;
float warmUpDuration, firstLayerDuration;
float firstLayerFilament, firstLayerProgress;
float lastLayerChangeTime, lastLayerFilament, lastLayerZ;
unsigned int numLayerSamples;
float layerDurations[MAX_LAYER_SAMPLES];
float filamentUsagePerLayer[MAX_LAYER_SAMPLES];
float fileProgressPerLayer[MAX_LAYER_SAMPLES];
float layerEstimatedTimeLeft;
// We parse G-Code files in multiple stages. These variables hold the required information
volatile FileParseState parseState;
char filenameBeingParsed[FILENAME_LENGTH];
FileStore *fileBeingParsed;
GCodeFileInfo parsedFileInfo;
char fileOverlap[GCODE_OVERLAP_SIZE];
size_t fileOverlapLength;
bool printingFileParsed;
GCodeFileInfo printingFileInfo;
char filenameBeingPrinted[FILENAME_LENGTH];
// G-Code parser methods
bool FindHeight(const char* buf, size_t len, float& height) const;
bool FindFirstLayerHeight(const char* buf, size_t len, float& layerHeight) const;
bool FindLayerHeight(const char* buf, size_t len, float& layerHeight) const;
unsigned int FindFilamentUsed(const char* buf, size_t len, float *filamentUsed, unsigned int maxFilaments) const;
uint32_t accumulatedParseTime, accumulatedReadTime, accumulatedSeekTime;
};
inline bool PrintMonitor::IsPrinting() const { return isPrinting; }
inline unsigned int PrintMonitor::GetCurrentLayer() const { return currentLayer; }
inline float PrintMonitor::GetCurrentLayerTime() const { return (lastLayerChangeTime > 0.0) ? (GetPrintDuration() - lastLayerChangeTime) : 0.0; }
inline float PrintMonitor::GetFirstLayerDuration() const { return (firstLayerDuration > 0.0) ? firstLayerDuration : ((currentLayer > 0) ? GetPrintDuration() - warmUpDuration : 0.0); }
inline float PrintMonitor::GetFirstLayerHeight() const { return printingFileParsed ? printingFileInfo.firstLayerHeight : 0.0; }
#endif /* PRINTMONITOR_H */
// vim: ts=4:sw=4
|