// Configure the temperature sensor GCodeResult Thermistor::Configure(unsigned int mCode, unsigned int heater, GCodeBuffer& gb, const StringRef& reply) { bool seen = false; if (mCode == 305) { gb.TryGetFValue('R', seriesR, seen); if (!isPT1000) { gb.TryGetFValue('B', beta, seen); if (seen) { shC = 0.0; // if user changes B and doesn't define C, assume C=0 } gb.TryGetFValue('C', shC, seen); gb.TryGetFValue('T', r25, seen); if (seen) { CalcDerivedParameters(); } } #if !HAS_VREF_MONITOR if (gb.Seen('L')) { adcLowOffset = (int8_t)constrain<int>(gb.GetIValue(), -120, 120); seen = true; } if (gb.Seen('H')) { adcHighOffset = (int8_t)constrain<int>(gb.GetIValue(), -120, 120); seen = true; } #endif TryConfigureHeaterName(gb, seen); if (!seen && !gb.Seen('X')) { CopyBasicHeaterDetails(heater, reply); if (isPT1000) { // For a PT1000 sensor, only the series resistor is configurable reply.catf(", R:%.1f", (double)seriesR); } else { reply.catf(", T:%.1f B:%.1f C:%.2e R:%.1f", (double)r25, (double)beta, (double)shC, (double)seriesR); } #if !HAS_VREF_MONITOR reply.catf(" L:%d H:%d", adcLowOffset, adcHighOffset); #endif } } return GCodeResult::ok; }
// Print what is wrong with the grid, appending it to the existing string void GridDefinition::PrintError(float originalXrange, float originalYrange, StringRef& r) const { if (spacing < MinSpacing) { r.cat("Spacing too small"); } else if (numX == 0) { r.cat("X range too small"); } else if (numY == 0) { r.cat("Y range too small"); } else if ( numX > MaxXGridPoints || numX > MaxGridProbePoints || numY > MaxGridProbePoints // check X and Y individually in case X*Y overflows || NumPoints() > MaxGridProbePoints ) { const float totalRange = originalXrange + originalYrange; const float area = originalXrange * originalYrange; const float minSpacing = (totalRange + sqrtf(fsquare(totalRange) + 4.0 * (MaxGridProbePoints - 1) * area))/(2.0 * (MaxGridProbePoints - 1)); const float minXspacing = originalXrange/(MaxXGridPoints - 1); r.catf("Too many grid points; suggest increase spacing to %.1fmm", max<float>(minSpacing, minXspacing)); } else { // The only thing left is a bad radius r.cat("Bad radius"); } }
void Tool::Print(StringRef& reply) { reply.printf("Tool %d - drives:", myNumber); char sep = ' '; for (size_t drive = 0; drive < driveCount; drive++) { reply.catf("%c%d", sep, drives[drive]); sep = ','; } reply.cat("; heaters (active/standby temps):"); sep = ' '; for (size_t heater = 0; heater < heaterCount; heater++) { reply.catf("%c%d (%.1f/%.1f)", sep, heaters[heater], activeTemperatures[heater], standbyTemperatures[heater]); sep = ','; } reply.cat("; xmap:"); sep = ' '; for (size_t xi = 0; xi < MAX_AXES; ++xi) { if ((xMapping & (1u << xi)) != 0) { reply.catf("%c%c", sep, GCodes::axisLetters[xi]); sep = ','; } } reply.cat("; fans:"); sep = ' '; for (size_t fi = 0; fi < NUM_FANS; ++fi) { if ((fanMapping & (1u << fi)) != 0) { reply.catf("%c%u", sep, fi); sep = ','; } } reply.catf("; status: %s", active ? "selected" : "standby"); }
// Unmount the specified SD card, returning true if done, false if needs to be called again. // If an error occurs, return true with the error message in 'reply'. GCodeResult MassStorage::Unmount(size_t card, const StringRef& reply) { if (card >= NumSdCards) { reply.copy("SD card number out of range"); return GCodeResult::error; } reply.printf("SD card %u may now be removed", card); const unsigned int numFilesClosed = InternalUnmount(card, true); if (numFilesClosed != 0) { reply.catf(" (%u file(s) were closed)", numFilesClosed); } return GCodeResult::ok; }
// Append the grid parameters to the end of a string void GridDefinition::PrintParameters(StringRef& s) const { s.catf("X%.1f:%.1f, Y%.1f:%.1f, radius %.1f, spacing %.1f, %d points", xMin, xMax, yMin, yMax, radius, spacing, NumPoints()); }
// Load the grid from file, returning true if an error occurred with the error reason appended to the buffer bool HeightMap::LoadFromFile(FileStore *f, StringRef& r) { const size_t MaxLineLength = (MaxXGridPoints * 8) + 2; // maximum length of a line in the height map file, need 8 characters per grid point const char* const readFailureText = "failed to read line from file"; char buffer[MaxLineLength + 1]; StringRef s(buffer, ARRAY_SIZE(buffer)); ClearGridHeights(); GridDefinition newGrid; if (f->ReadLine(buffer, sizeof(buffer)) <= 0) { r.cat(readFailureText); } else if (!StringStartsWith(buffer, HeightMapComment)) // check the version line is as expected { r.cat("bad header line or wrong version header"); } else if (f->ReadLine(buffer, sizeof(buffer)) <= 0) { r.cat(readFailureText); } else if (!GridDefinition::CheckHeading(s)) // check the label line is as expected { r.cat("bad label line"); } else if (f->ReadLine(buffer, sizeof(buffer)) <= 0) // read the height map parameters { r.cat(readFailureText); } else if (!newGrid.ReadParameters(s)) { r.cat("failed to parse grid parameters"); } else if (!newGrid.IsValid()) { r.cat("invalid grid"); } else { SetGrid(newGrid); for (uint32_t row = 0; row < def.numY; ++row) // read the grid a row at a time { if (f->ReadLine(buffer, sizeof(buffer)) <= 0) { r.cat(readFailureText); return true; // failed to read a line } const char *p = buffer; for (uint32_t col = 0; col < def.numX; ++col) { if (*p == '0' && (p[1] == ',' || p[1] == 0)) { // Values of 0 with no decimal places in un-probed values, so leave the point set as not valid ++p; } else { char* np = nullptr; const float f = strtod(p, &np); if (np == p) { r.catf("number expected at line %u column %d", row + 3, (p - buffer) + 1); return true; // failed to read a number } SetGridHeight(col, row, f); p = np; } if (*p == ',') { ++p; } } } ExtrapolateMissing(); return false; // success! } return true; // an error occurred }