Version 0.78d-dc42

M116 now accepts a P parameter so that you can wait just for the heaters
associated with a particular tool
M220 and M221 commands report the current override factor if no S
parameter is provided
Multiple "Filament used" values from gcode files are reported to the web
interface
Active and standby temperatures for all heaters are reported to the web
interface
Bug fix: defining a tool with no drives or no extruders would cause it
to use a collection of drives or extruders depending on the values of
un-initialised array elements
Bug fix: running a macro file would reset the extruder position to a
value depending on what extrusion (if any) was requested by the last
movement command in the macro file
This commit is contained in:
David Crocker 2014-07-17 00:28:26 +01:00
parent 8f1dd9c315
commit 8bab7ab035
6 changed files with 155 additions and 45 deletions

View file

@ -48,6 +48,18 @@ Additional functionality in 0.78a-dc42 release compared to RRP 0.78:
* M0 and M1 commands now turn all heaters off instead of setting them to their standby temperatures
* When using a Z probe, Z homing and bed probing are done in two stages (a fast stage followed by a slow stage) for better accuracy.
* M116 takes an optional P parameter to specify which tool to wait for. If no P parameter is given, it waits for all tools and the bed as before. The main purpose of this is that on a tool change, you can wait for the new tool to heat up to operating temperature but not wait for the old tool to cool down to standby temperature.
* When fetching file info, if the gcode file contains more than one 'filament used' comment, the filament lengths in all of them are returned to the web interface
* The active and standby temperatures of all heaters are included in the status poll response
* The default initial Z homing and bed probing speed has been increased. This is possible because Z homing and bed probing slow down when the probe reading is approaching the target value.
* The M220 and M221 commands now return the override factors if no S parameter is provided
* FTP server supported (thanks zombiepantslol)
* Telnet server supported (thanks zombiepantslol)
@ -64,6 +76,10 @@ Additional functionality in 0.78a-dc42 release compared to RRP 0.78:
* Bug fix: if bed compensation or axis compensation was in use, then a G1 S1 command to home an axis could be prematurely terminated if the head was already at the endstop position for a different axis.
* Bug fix: if a tool was defined as using zero drives or zero extruders, it would be treated as assuming a collection of drives or extruders according to the vales in an uninitialised array
* Bug fix: the cumulative extruder positions were getting reset (typically to zero) on a tool change or other macro file execution
Additional functionality in web interface 0.95 compared to RRP 0.65:

View file

@ -24,8 +24,8 @@ Licence: GPL
#define CONFIGURATION_H
#define NAME "RepRapFirmware"
#define VERSION "0.78c-dc42"
#define DATE "2014-07-15"
#define VERSION "0.78d-dc42"
#define DATE "2014-07-16"
#define LAST_AUTHOR "reprappro, dc42. zpl"
// Other firmware that we might switch to be compatible with.

View file

@ -305,15 +305,16 @@ bool GCodes::Pop()
axesRelative = axesRelativeStack[stackPointer];
fileBeingPrinted.MoveFrom(fileStack[stackPointer]);
platform->PopMessageIndent();
// Remember for next time if we have just been switched
// to absolute drive moves
// Remember for next time if we have just been switched to absolute drive moves
// DC 2014-07-16: the following code is wrong, it messes up the absolute extruder position (typically it resets it to zero) and does nothing useful as far as I can see.
// So I am commenting it out.
//for(int8_t i = AXES; i < DRIVES; i++)
//{
// lastPos[i - AXES] = moveBuffer[i];
//}
for(int8_t i = AXES; i < DRIVES; i++)
{
lastPos[i - AXES] = moveBuffer[i];
}
// Do a null move to set the correct feedrate
// Set the correct feedrate
moveBuffer[DRIVES] = feedrateStack[stackPointer];
@ -644,7 +645,9 @@ bool GCodes::OffsetAxes(GCodeBuffer* gb)
{
//LoadMoveBufferFromArray(record);
for (int drive = 0; drive <= DRIVES; drive++)
{
moveBuffer[drive] = record[drive];
}
reprap.GetMove()->SetLiveCoordinates(record); // This doesn't transform record
reprap.GetMove()->SetPositions(record); // This does
offSetSet = false;
@ -1258,6 +1261,10 @@ void GCodes::AddNewTool(GCodeBuffer *gb)
{
gb->GetLongArray(drives, dCount);
}
else
{
dCount = 0;
}
long heaters[HEATERS];
int hCount = HEATERS;
@ -1265,6 +1272,10 @@ void GCodes::AddNewTool(GCodeBuffer *gb)
{
gb->GetLongArray(heaters, hCount);
}
else
{
hCount = 0;
}
Tool* tool = new Tool(toolNumber, drives, dCount, heaters, hCount);
reprap.AddTool(tool);
@ -1870,7 +1881,7 @@ bool GCodes::HandleMcode(GCodeBuffer* gb)
platform->SetAtxPower(code == 80);
break;
case 82:
case 82: // Use absolute extruder positioning
for (int8_t extruder = AXES; extruder < DRIVES; extruder++)
{
lastPos[extruder - AXES] = 0.0;
@ -1878,12 +1889,15 @@ bool GCodes::HandleMcode(GCodeBuffer* gb)
drivesRelative = false;
break;
case 83:
for (int8_t extruder = AXES; extruder < DRIVES; extruder++)
case 83: // Use relative extruder positioning
if (!drivesRelative) // don't reset the absolute extruder position if it was already relative
{
lastPos[extruder - AXES] = 0.0;
for (int8_t extruder = AXES; extruder < DRIVES; extruder++)
{
lastPos[extruder - AXES] = 0.0;
}
drivesRelative = true;
}
drivesRelative = true;
break;
case 84: // Motors off - deprecated, use M18
@ -2060,7 +2074,28 @@ bool GCodes::HandleMcode(GCodeBuffer* gb)
{
return false;
}
result = reprap.GetHeat()->AllHeatersAtSetTemperatures(true);
if (gb->Seen('P'))
{
// Wait for the heaters associated with the specified tool to be ready
int toolNumber = gb->GetIValue();
Tool* tool = reprap.GetTool(toolNumber);
if (tool != NULL)
{
for (int i = 0; i < tool->HeaterCount(); ++i)
{
if (!reprap.GetHeat()->HeaterAtSetTemperature(tool->Heater(i)))
{
return false;
}
}
}
result = true;
}
else
{
// Wait for all heaters to be ready
result = reprap.GetHeat()->AllHeatersAtSetTemperatures(true);
}
break;
//TODO M119
@ -2306,19 +2341,21 @@ bool GCodes::HandleMcode(GCodeBuffer* gb)
case 220: // set speed factor override percentage
if (gb->Seen('S'))
{
float newSpeedFactor = gb->GetFValue()/(60 * 100.0); // include the conversion from mm/minute to mm/second
float newSpeedFactor = gb->GetFValue()/(60.0 * 100.0); // include the conversion from mm/minute to mm/second
if (newSpeedFactor > 0)
{
speedFactorChange *= newSpeedFactor/speedFactor;
speedFactor = newSpeedFactor;
}
}
else
{
snprintf(reply, STRING_LENGTH, "Speed factor override: %.1f%%\n", speedFactor * (60.0 * 100.0));
}
break;
case 221: // set extrusion factor override percentage
if (gb->Seen('S')) // S parameter sets the override percentage
{
float extrusionFactor = gb->GetFValue()/100.0;
int drive;
if (gb->Seen('D')) // D parameter (if present) selects the extruder drive number
{
@ -2328,9 +2365,19 @@ bool GCodes::HandleMcode(GCodeBuffer* gb)
{
drive = 0; // default to drive 0 if not specified
}
if (drive >= 0 && drive < DRIVES - AXES && extrusionFactor >= 0)
if (gb->Seen('S')) // S parameter sets the override percentage
{
extrusionFactors[drive] = extrusionFactor;
float extrusionFactor = gb->GetFValue()/100.0;
if (drive >= 0 && drive < DRIVES - AXES && extrusionFactor >= 0)
{
extrusionFactors[drive] = extrusionFactor;
}
}
else
{
snprintf(reply, STRING_LENGTH, "Extrusion factor override for drive %d: %.1f%%\n", drive, extrusionFactors[drive] * 100.0);
}
}
break;

View file

@ -150,9 +150,9 @@ const unsigned int numZProbeReadingsAveraged = 8; // we average this number of r
// AXES
#define AXIS_MAXIMA {220, 200, 200} // mm
#define AXIS_MINIMA {0, 0, 0} // mm
#define HOME_FEEDRATES {50.0, 50.0, 1.0} // mm/sec
#define AXIS_MAXIMA {220, 200, 200} // mm
#define AXIS_MINIMA {0, 0, 0} // mm
#define HOME_FEEDRATES {50.0, 50.0, 100.0/60.0} // mm/sec (increased Z because we slow down z-homing when approaching the target height)
#define HEAD_OFFSETS {0.0, 0.0, 0.0} // mm
#define X_AXIS 0 // The index of the X axis in the arrays

View file

@ -888,14 +888,29 @@ bool Webserver::HttpInterpreter::GetJsonResponse(const char* request, const char
else if (StringEquals(request, "fileinfo") && StringEquals(key, "name"))
{
unsigned long length;
float height, filament, layerHeight;
float height, filament[DRIVES - AXES], layerHeight;
unsigned int numFilaments = DRIVES - AXES;
char generatedBy[50];
bool found = webserver->GetFileInfo(value, length, height, filament, layerHeight, generatedBy, ARRAY_SIZE(generatedBy));
bool found = webserver->GetFileInfo(value, length, height, filament, numFilaments, layerHeight, generatedBy, ARRAY_SIZE(generatedBy));
if (found)
{
snprintf(jsonResponse, ARRAY_UPB(jsonResponse),
"{\"err\":0,\"size\":%lu,\"height\":%.2f,\"filament\":%.1f,\"layerHeight\":%.2f,\"generatedBy\":\"%s\"}",
length, height, filament, layerHeight, generatedBy);
"{\"err\":0,\"size\":%lu,\"height\":%.2f,\"layerHeight\":%.2f,\"filament\":",
length, height, layerHeight);
char ch = '[';
if (numFilaments == 0)
{
sncatf(jsonResponse, ARRAY_UPB(jsonResponse), "%c", ch);
}
else
{
for (unsigned int i = 0; i < numFilaments; ++i)
{
sncatf(jsonResponse, ARRAY_UPB(jsonResponse), "%c%.1f", ch, filament[i]);
ch = ',';
}
}
sncatf(jsonResponse, ARRAY_UPB(jsonResponse), "],\"generatedBy\":\"%s\"}", generatedBy);
}
else
{
@ -968,7 +983,7 @@ void Webserver::HttpInterpreter::GetStatusResponse(uint8_t type)
char ch = (reprap.IsStopped()) ? 'S' : (gc->PrintingAFile()) ? 'P' : 'I';
snprintf(jsonResponse, ARRAY_UPB(jsonResponse), "{\"status\":\"%c\",\"heaters\":", ch);
// Send the heater temperatures
// Send the heater actual temperatures
ch = '[';
for (int8_t heater = 0; heater < reprap.GetHeatersInUse(); heater++)
{
@ -976,7 +991,25 @@ void Webserver::HttpInterpreter::GetStatusResponse(uint8_t type)
ch = ',';
}
// Send XYZ and extruder positions
// Send the heater active temperatures
strncat(jsonResponse, "],\"active\":", ARRAY_UPB(jsonResponse));
ch = '[';
for (int8_t heater = 0; heater < reprap.GetHeatersInUse(); heater++)
{
sncatf(jsonResponse, ARRAY_UPB(jsonResponse), "%c\%.1f", ch, reprap.GetHeat()->GetActiveTemperature(heater));
ch = ',';
}
// Send the heater standby temperatures
strncat(jsonResponse, "],\"standby\":", ARRAY_UPB(jsonResponse));
ch = '[';
for (int8_t heater = 0; heater < reprap.GetHeatersInUse(); heater++)
{
sncatf(jsonResponse, ARRAY_UPB(jsonResponse), "%c\%.1f", ch, reprap.GetHeat()->GetStandbyTemperature(heater));
ch = ',';
}
// Send XYZ positions
float liveCoordinates[DRIVES + 1];
reprap.GetMove()->LiveCoordinates(liveCoordinates);
strncat(jsonResponse, "],\"pos\":", ARRAY_UPB(jsonResponse)); // announce the XYZ position
@ -986,6 +1019,8 @@ void Webserver::HttpInterpreter::GetStatusResponse(uint8_t type)
sncatf(jsonResponse, ARRAY_UPB(jsonResponse), "%c%.2f", ch, liveCoordinates[drive]);
ch = ',';
}
// Send extruder total extrusion since power up or last G92
sncatf(jsonResponse, ARRAY_UPB(jsonResponse), "],\"extr\":"); // announce the extruder positions
ch = '[';
for (int8_t drive = 0; drive < reprap.GetExtrudersInUse(); drive++) // loop through extruders
@ -2339,8 +2374,8 @@ void Webserver::TelnetInterpreter::HandleGcodeReply(const char *reply)
//
//********************************************************************************************
// Get information for a file on the SD card
bool Webserver::GetFileInfo(const char *fileName, unsigned long& length, float& height, float& filamentUsed, float& layerHeight, char* generatedBy, size_t generatedByLength)
// Get information for a file on the SD card.
bool Webserver::GetFileInfo(const char *fileName, unsigned long& length, float& height, float *filamentUsed, unsigned int& numFilaments, float& layerHeight, char* generatedBy, size_t generatedByLength)
{
FileStore *f = platform->GetFileStore("0:/", fileName, false);
if (f != NULL)
@ -2348,7 +2383,6 @@ bool Webserver::GetFileInfo(const char *fileName, unsigned long& length, float&
// Try to find the object height by looking for the last G1 Zxxx command in the file
length = f->Length();
height = 0.0;
filamentUsed = 0.0;
layerHeight = 0.0;
generatedBy[0] = 0;
@ -2424,7 +2458,7 @@ bool Webserver::GetFileInfo(const char *fileName, unsigned long& length, float&
}
unsigned long seekPos = length - sizeToRead; // read on a 512b boundary
size_t sizeToScan = sizeToRead;
bool foundFilamentUsed = false;
unsigned int filamentsFound = 0;
for (;;)
{
if (!f->Seek(seekPos))
@ -2437,10 +2471,20 @@ bool Webserver::GetFileInfo(const char *fileName, unsigned long& length, float&
break; // read failed so give up
}
buf[sizeToScan] = 0; // add a null terminator
if (!foundFilamentUsed)
// Search for filament used
float filaments[DRIVES - AXES];
unsigned int nFilaments = FindFilamentUsed(buf, sizeToScan, filaments, DRIVES - AXES);
if (nFilaments != 0 && nFilaments >= filamentsFound)
{
foundFilamentUsed = FindFilamentUsed(buf, sizeToScan, filamentUsed);
filamentsFound = min<unsigned int>(nFilaments, numFilaments);
for (unsigned int i = 0; i < filamentsFound; ++i)
{
filamentUsed[i] = filaments[i];
}
}
// Search for object height
if (FindHeight(buf, sizeToScan, height))
{
break; // quit if found height
@ -2454,6 +2498,7 @@ bool Webserver::GetFileInfo(const char *fileName, unsigned long& length, float&
sizeToScan = readSize + overlap;
memcpy(buf + sizeToRead, buf, overlap);
}
numFilaments = filamentsFound;
}
}
f->Close();
@ -2505,11 +2550,13 @@ bool Webserver::FindHeight(const char* buf, size_t len, float& height)
}
// Scan the buffer for the filament used. The buffer is null-terminated.
bool Webserver::FindFilamentUsed(const char* buf, size_t len, float& filamentUsed)
// Returns the number of filaments found.
unsigned int Webserver::FindFilamentUsed(const char* buf, size_t len, float *filamentUsed, unsigned int maxFilaments)
{
const char* filamentUsedStr = "ilament used"; // comment string used by slic3r, followed by filament used and "mm"
const char* p = strstr(buf, filamentUsedStr);
if (p != NULL)
unsigned int filamentsFound = 0;
const char* p = buf;
while (filamentsFound < maxFilaments && (p = strstr(p, filamentUsedStr)) != NULL)
{
p += strlen(filamentUsedStr);
while(strchr(" :=\t", *p) != NULL)
@ -2519,15 +2566,15 @@ bool Webserver::FindFilamentUsed(const char* buf, size_t len, float& filamentUse
if (isDigit(*p))
{
char* q;
filamentUsed = strtod(p, &q);
filamentUsed[filamentsFound] = strtod(p, &q);
if (*q == 'm' && *(q + 1) != 'm')
{
filamentUsed *= 1000.0; // Cura outputs filament used in metres not mm
filamentUsed[filamentsFound] *= 1000.0; // Cura outputs filament used in metres not mm
}
return true;
++filamentsFound;
}
}
return false;
return filamentsFound;
}

View file

@ -292,9 +292,9 @@ class Webserver
void StoreGcodeData(const char* data, size_t len);
// File info methods
bool GetFileInfo(const char *fileName, unsigned long& length, float& height, float& filamentUsed, float& layerHeight, char* generatedBy, size_t generatedByLength);
bool GetFileInfo(const char *fileName, unsigned long& length, float& height, float *filamentUsed, unsigned int& numFilaments, float& layerHeight, char* generatedBy, size_t generatedByLength);
static bool FindHeight(const char* buf, size_t len, float& height);
static bool FindFilamentUsed(const char* buf, size_t len, float& filamentUsed);
static unsigned int FindFilamentUsed(const char* buf, size_t len, float *filamentUsed, unsigned int maxFilaments);
static void CopyParameterText(const char* src, char *dst, size_t length);
// Buffer to hold gcode that is ready for processing