diff options
author | David Crocker <dcrocker@eschertech.com> | 2015-08-22 12:59:56 +0300 |
---|---|---|
committer | David Crocker <dcrocker@eschertech.com> | 2015-08-22 13:01:28 +0300 |
commit | 87980e2966c0312c0f63e44bab9910e21cff1df3 (patch) | |
tree | fa9b25e16e2c808cc3a806dcf93260166a481c78 | |
parent | 9d6603c678109a7f240e940f276c9221034351fd (diff) |
Version 1.09f
Fixed print quality problems that mostly affected delta printers e.g. on
spiral vase cylinder
When reconnecting a browser, cancel any file upload from the same IP
address
M111 now prints the number of each module with debugging enabled or
disabled
In special moves on delta printers, the F parameter is now interpreted
as the speed of the tower that moves the most
M114 now reports stepper positions as well as head position
Default to output in Marlin mode
M104 command defaults to the only tool if there is only one tool and it
is not selected
Trying different code for M999PERASE command to see if we can get it to
unlock flash and reset more reliably
When step errors are logged, report them immediately if Move debugging
is enabled. Also reports the total number of step errors in M122.
Changed interrupt priority to make tick interrupt higher priority than
step interrupt, because we rely on the tick interrupt to check for over
temperature conditions and kick the watchdog
-rw-r--r-- | .settings/org.eclipse.cdt.core.prefs | 4 | ||||
-rw-r--r-- | Configuration.h | 4 | ||||
-rw-r--r-- | DDA.cpp | 73 | ||||
-rw-r--r-- | DDA.h | 5 | ||||
-rw-r--r-- | DeltaParameters.cpp | 4 | ||||
-rw-r--r-- | DriveMovement.cpp | 83 | ||||
-rw-r--r-- | DriveMovement.h | 4 | ||||
-rw-r--r-- | GCodes.cpp | 12 | ||||
-rw-r--r-- | Move.cpp | 31 | ||||
-rw-r--r-- | Move.h | 3 | ||||
-rw-r--r-- | Platform.cpp | 52 | ||||
-rw-r--r-- | Release/RepRapFirmware-1.09f-testing-dc42.bin | bin | 0 -> 228680 bytes | |||
-rw-r--r-- | RepRapFirmware.cpp | 23 | ||||
-rw-r--r-- | RepRapFirmware.h | 1 | ||||
-rw-r--r-- | Reprap.h | 7 | ||||
-rw-r--r-- | SD-image/sys-CoreXY/pause.g | 1 | ||||
-rw-r--r-- | SD-image/sys-CoreXY/resume.g | 1 | ||||
-rw-r--r-- | SD-image/sys-Huxley/pause.g | 1 | ||||
-rw-r--r-- | SD-image/sys-Huxley/resume.g | 1 | ||||
-rw-r--r-- | SD-image/sys-MiniKossel/homedelta.g | 4 | ||||
-rw-r--r-- | SD-image/sys-MiniKossel/pause.g | 1 | ||||
-rw-r--r-- | SD-image/sys-MiniKossel/resume.g | 1 | ||||
-rw-r--r-- | SD-image/sys-Ormerod1/pause.g | 1 | ||||
-rw-r--r-- | SD-image/sys-Ormerod1/resume.g | 1 | ||||
-rw-r--r-- | SD-image/sys-Ormerod2/pause.g | 1 | ||||
-rw-r--r-- | SD-image/sys-Ormerod2/resume.g | 1 | ||||
-rw-r--r-- | Webserver.cpp | 3 |
27 files changed, 243 insertions, 80 deletions
diff --git a/.settings/org.eclipse.cdt.core.prefs b/.settings/org.eclipse.cdt.core.prefs index 6d0b64af..7b5d9178 100644 --- a/.settings/org.eclipse.cdt.core.prefs +++ b/.settings/org.eclipse.cdt.core.prefs @@ -91,7 +91,7 @@ environment/project/it.baeyens.arduino.core.toolChain.release.674980254/A.COMPIL environment/project/it.baeyens.arduino.core.toolChain.release.674980254/A.COMPILER.C.EXTRA_FLAGS/value= environment/project/it.baeyens.arduino.core.toolChain.release.674980254/A.COMPILER.C.FLAGS/delimiter=; environment/project/it.baeyens.arduino.core.toolChain.release.674980254/A.COMPILER.C.FLAGS/operation=replace -environment/project/it.baeyens.arduino.core.toolChain.release.674980254/A.COMPILER.C.FLAGS/value=-c -g -O2 -w -ffunction-sections -fdata-sections -nostdlib --param max-inline-insns-single\=500 -Dprintf\=iprintf +environment/project/it.baeyens.arduino.core.toolChain.release.674980254/A.COMPILER.C.FLAGS/value=-c -g -std\=gnu99 -O2 -ffunction-sections -fdata-sections -nostdlib --param max-inline-insns-single\=500 -Dprintf\=iprintf environment/project/it.baeyens.arduino.core.toolChain.release.674980254/A.COMPILER.CPP.CMD/delimiter=; environment/project/it.baeyens.arduino.core.toolChain.release.674980254/A.COMPILER.CPP.CMD/operation=replace environment/project/it.baeyens.arduino.core.toolChain.release.674980254/A.COMPILER.CPP.CMD/value=arm-none-eabi-g++ @@ -100,7 +100,7 @@ environment/project/it.baeyens.arduino.core.toolChain.release.674980254/A.COMPIL environment/project/it.baeyens.arduino.core.toolChain.release.674980254/A.COMPILER.CPP.EXTRA_FLAGS/value= environment/project/it.baeyens.arduino.core.toolChain.release.674980254/A.COMPILER.CPP.FLAGS/delimiter=; environment/project/it.baeyens.arduino.core.toolChain.release.674980254/A.COMPILER.CPP.FLAGS/operation=replace -environment/project/it.baeyens.arduino.core.toolChain.release.674980254/A.COMPILER.CPP.FLAGS/value=-c -g -O2 -save-temps -w -ffunction-sections -fdata-sections -nostdlib -fno-threadsafe-statics --param max-inline-insns-single\=500 -fno-rtti -fno-exceptions -Dprintf\=iprintf +environment/project/it.baeyens.arduino.core.toolChain.release.674980254/A.COMPILER.CPP.FLAGS/value=-c -g -std\=gnu++11 -O2 -ffunction-sections -fdata-sections -nostdlib -fno-threadsafe-statics --param max-inline-insns-single\=500 -fno-rtti -fno-exceptions -Dprintf\=iprintf environment/project/it.baeyens.arduino.core.toolChain.release.674980254/A.COMPILER.DEFINE/delimiter=; environment/project/it.baeyens.arduino.core.toolChain.release.674980254/A.COMPILER.DEFINE/operation=replace environment/project/it.baeyens.arduino.core.toolChain.release.674980254/A.COMPILER.DEFINE/value=-DARDUINO\= diff --git a/Configuration.h b/Configuration.h index 968c792f..dd0c30fb 100644 --- a/Configuration.h +++ b/Configuration.h @@ -24,8 +24,8 @@ Licence: GPL #define CONFIGURATION_H #define NAME "RepRapFirmware" -#define VERSION "1.09e-dc42" -#define DATE "2015-08-10" +#define VERSION "1.09f-dc42" +#define DATE "2015-08-22" #define AUTHORS "reprappro, dc42, zpl" #define FLASH_SAVE_ENABLED (1) @@ -38,15 +38,21 @@ void DDA::DebugPrint() const debugPrintf("DDA:"); if (endCoordinatesValid) { + float startCoordinates[AXES]; + for (size_t i = 0; i < AXES; ++i) + { + startCoordinates[i] = endCoordinates[i] - (totalDistance * directionVector[i]); + } + DebugPrintVector(" start", startCoordinates, AXES); DebugPrintVector(" end", endCoordinates, AXES); } debugPrintf(" d=%f", totalDistance); DebugPrintVector(" vec", directionVector, 5); - debugPrintf(" a=%f reqv=%f topv=%f startv=%f endv=%f\n" - "daccel=%f ddecel=%f fstep=%u\n", + debugPrintf("\na=%f reqv=%f topv=%f startv=%f endv=%f\n" + "daccel=%f ddecel=%f fstep=%u cks=%u\n", acceleration, requestedSpeed, topSpeed, startSpeed, endSpeed, - accelDistance, decelDistance, firstStepTime); + accelDistance, decelDistance, firstStepTime, clocksNeeded); // reprap.GetPlatform()->GetLine()->Flush(); ddm[0].DebugPrint('x', isDeltaMovement); ddm[1].DebugPrint('y', isDeltaMovement); @@ -197,6 +203,8 @@ bool DDA::Init(const float nextMove[], EndstopChecks ce, bool doMotorMapping, Fi } else { + // The distance to reversal is the solution to a quadratic equation. One root corresponds to the carriages being above the bed, + // the other root corresponds to the carriages being above the bed. const float drev = ((directionVector[Z_AXIS] * sqrt(a2b2D2 - fsquare(A * directionVector[Y_AXIS] - B * directionVector[X_AXIS]))) - aAplusbB)/a2plusb2; if (drev > 0.0 && drev < totalDistance) // if the reversal point is within range @@ -250,7 +258,26 @@ bool DDA::Init(const float nextMove[], EndstopChecks ce, bool doMotorMapping, Fi // Set the speed to the smaller of the requested and maximum speed. // Also enforce a minimum speed of 0.5mm/sec. We need a minimum speed to avoid overflow in the movement calculations. - requestedSpeed = max<float>(0.5, min<float>(nextMove[DRIVES], VectorBoxIntersection(normalisedDirectionVector, reprap.GetPlatform()->MaxFeedrates(), DRIVES))); + float reqSpeed = nextMove[DRIVES]; + if (reprap.GetMove()->IsDeltaMode() && !isDeltaMovement) + { + // Special case of a raw or homing move on a delta printer + // We use the Cartesian motion system to implement these moves, so the feed rate will be interpreted in Cartesian coordinates. + // This is wrong, we want the feed rate to apply to the drive that is moving the farthest. + float maxDistance = 0.0; + for (size_t axis = 0; axis < AXES; ++axis) + { + if (normalisedDirectionVector[axis] > maxDistance) + { + maxDistance = normalisedDirectionVector[axis]; + } + } + if (maxDistance != 0.0) // should always be true + { + reqSpeed /= maxDistance; // because normalisedDirectionVector is unit-normalised + } + } + requestedSpeed = max<float>(0.5, min<float>(reqSpeed, VectorBoxIntersection(normalisedDirectionVector, reprap.GetPlatform()->MaxFeedrates(), DRIVES))); // On a Cartesian printer, it is OK to limit the X and Y speeds and accelerations independently, and in consequence to allow greater values // for diagonal moves. On a delta, this is not OK and any movement in the XY plane should be limited to the X/Y axis values, which we assume to be equal. @@ -622,7 +649,7 @@ void DDA::Prepare() dm.stepsTillRecalc = 1; uint32_t st = (isDeltaMovement && drive < AXES) ? dm.CalcNextStepTimeDelta(*this, drive) - : dm.CalcNextStepTimeCartesian(drive); + : dm.CalcNextStepTimeCartesian(*this, drive); if (st < firstStepTime) { firstStepTime = st; @@ -633,10 +660,7 @@ void DDA::Prepare() if (reprap.Debug(moduleDda) && reprap.Debug(moduleMove)) // temp show the prepared DDA if debug enabled for both modules { DebugPrint(); - reprap.GetPlatform()->GetLine()->Flush(); } -//debugPrintf("Done\n"); -//reprap.GetPlatform()->GetLine()->Flush(); state = frozen; // must do this last so that the ISR doesn't start executing it before we have finished setting it up } @@ -645,6 +669,7 @@ void DDA::Prepare() #pragma GCC optimize ("O3") // Start executing the move, returning true if Step() needs to be called immediately. Must be called with interrupts disabled, to avoid a race condition. +// Returns true if the caller needs to call the step ISR immediately. bool DDA::Start(uint32_t tim) //pre(state == frozen) { @@ -654,8 +679,7 @@ bool DDA::Start(uint32_t tim) if (firstStepTime == DriveMovement::NoStepTime) { // No steps are pending. This should not happen! - state = completed; - return false; + return true; // schedule another interrupt immediately } else { @@ -707,14 +731,9 @@ bool DDA::Start(uint32_t tim) extern uint32_t maxReps; // This is called by the interrupt service routine to execute steps. -// It returns true if it needs to be called again with the DDA of the next move, otherwise false. +// It returns true if it needs to be called again on the DDA of the new current move, otherwise false. bool DDA::Step() { - if (state != executing) - { - return false; - } - bool repeat; uint32_t numReps = 0; do @@ -803,7 +822,7 @@ bool DDA::Step() if (now + minInterruptInterval >= st0) { reprap.GetPlatform()->StepHigh(drive); - uint32_t st1 = (isDeltaMovement && drive < AXES) ? dm.CalcNextStepTimeDelta(*this, drive) : dm.CalcNextStepTimeCartesian(drive); + uint32_t st1 = (isDeltaMovement && drive < AXES) ? dm.CalcNextStepTimeDelta(*this, drive) : dm.CalcNextStepTimeCartesian(*this, drive); if (st1 < nextInterruptTime) { nextInterruptTime = st1; @@ -828,10 +847,10 @@ bool DDA::Step() if (state == completed) { - uint32_t finishTime = Platform::GetInterruptClocks(); + uint32_t finishTime = moveStartTime + clocksNeeded; // calculate how long this move should take Move *move = reprap.GetMove(); - move->CurrentMoveCompleted(); // tell Move that the current move is complete - return move->StartNextMove(finishTime); // schedule the next move + move->CurrentMoveCompleted(); // tell Move that the current move is complete + return move->StartNextMove(finishTime); // schedule the next move } repeat = reprap.GetPlatform()->ScheduleInterrupt(nextInterruptTime + moveStartTime); } while (repeat); @@ -890,21 +909,17 @@ void DDA::ReduceHomingSpeed() } } -void DDA::PrintIfHasStepError() +bool DDA::HasStepError() const { - bool printed = false; for (size_t drive = 0; drive < DRIVES; ++drive) { - if (ddm[drive].stepError) + const DriveMovement& dm = ddm[drive]; + if (dm.moving && dm.stepError) { - if (!printed) - { - DebugPrint(); - printed = true; - } - ddm[drive].stepError = false; + return true; } } + return false; } // Take a unit positive-hyperquadrant vector, and return the factor needed to obtain @@ -37,10 +37,11 @@ public: bool Step(); // Take one step of the DDA, called by timed interrupt. void SetNext(DDA *n) { next = n; } void SetPrevious(DDA *p) { prev = p; } - void Release() { state = empty; } + void Complete() { state = completed; } + void Free() { state = empty; } void Prepare(); // Calculate all the values and freeze this DDA float CalcTime() const; // Calculate the time needed for this move (used for simulation) - void PrintIfHasStepError(); + bool HasStepError() const; bool CanPause() const { return canPause; } DDAState GetState() const { return state; } diff --git a/DeltaParameters.cpp b/DeltaParameters.cpp index 3c62259f..a81c6694 100644 --- a/DeltaParameters.cpp +++ b/DeltaParameters.cpp @@ -203,8 +203,8 @@ void DeltaParameters::Adjust(size_t numFactors, const float v[]) void DeltaParameters::PrintParameters(StringRef& reply) const { - reply.printf("Endstops X%.2f Y%.2f Z%.2f, height %.2f, diagonal %.2f, radius %.2f, xcorr %.2f, ycorr %.2f\n", - endstopAdjustments[A_AXIS], endstopAdjustments[B_AXIS], endstopAdjustments[C_AXIS], homedHeight, diagonal, radius, xCorrection, yCorrection); + reply.printf("Endstops X%.2f Y%.2f Z%.2f, height %.2f, diagonal %.2f, radius %.2f, xcorr %.2f, ycorr %.2f, zcorr %.2f\n", + endstopAdjustments[A_AXIS], endstopAdjustments[B_AXIS], endstopAdjustments[C_AXIS], homedHeight, diagonal, radius, xCorrection, yCorrection, zCorrection); } // End diff --git a/DriveMovement.cpp b/DriveMovement.cpp index 04fc2bf7..bb03ecb7 100644 --- a/DriveMovement.cpp +++ b/DriveMovement.cpp @@ -60,7 +60,7 @@ void DriveMovement::PrepareDeltaAxis(const DDA& dda, const PrepParams& params, s // First check whether there is any deceleration at all, otherwise we may get strange results because of rounding errors if (dda.decelDistance * stepsPerMm < 0.5) { - mp.delta.decelStartDsK = (uint32_t)(dda.totalDistance * stepsPerMm * K2) * 2; // the *2 is to make sure it is definitely high enough + mp.delta.decelStartDsK = 0xFFFFFFFF; topSpeedTimesCdivAPlusDecelStartClocks = 0; twoDistanceToStopTimesCsquaredDivA = 0; } @@ -156,7 +156,7 @@ void DriveMovement::DebugPrint(char c, bool isDeltaMovement) const if (moving || stepError) { debugPrintf("DM%c%s dir=%c steps=%u next=%u interval=%u sstcda=%u " - "acmadtcdts=%d tstcdapdsc=%u tstdca2=%" PRIu64 "\n", + "acmadtcdts=%d tstcdapdsc=%u 2dtstc2diva=%" PRIu64 "\n", c, (stepError) ? " ERR:" : ":", (direction) ? 'F' : 'B', totalSteps, nextStep, stepInterval, startSpeedTimesCdivA, accelClocksMinusAccelDistanceTimesCdivTopSpeed, topSpeedTimesCdivAPlusDecelStartClocks, twoDistanceToStopTimesCsquaredDivA); @@ -188,7 +188,8 @@ void DriveMovement::DebugPrint(char c, bool isDeltaMovement) const #pragma GCC optimize ("O3") // Calculate the time since the start of the move when the next step for the specified DriveMovement is due -uint32_t DriveMovement::CalcNextStepTimeCartesian(size_t drive) +// This is also used for extruders on delta machines +uint32_t DriveMovement::CalcNextStepTimeCartesian(const DDA &dda, size_t drive) { if (nextStep >= totalSteps) { @@ -197,7 +198,7 @@ uint32_t DriveMovement::CalcNextStepTimeCartesian(size_t drive) } ++nextStep; - if (stepsTillRecalc > 1) + if (stepsTillRecalc > 1 && nextStep != totalSteps) { --stepsTillRecalc; nextStepTime += stepInterval; @@ -242,19 +243,42 @@ uint32_t DriveMovement::CalcNextStepTimeCartesian(size_t drive) int32_t interval = (int32_t)nextStepTime - (int32_t)lastStepTime; if (interval < DDA::MinStepInterval) { - stepInterval = (uint32_t)interval; stepError = true; - return NoStepTime; + if (reprap.Debug(moduleMove)) + { + stepInterval = (uint32_t)interval; + return NoStepTime; + } } - - // If the step interval is very short, flag not to recalculate it next time - if (interval < DDA::MinCalcInterval) + else if (interval < DDA::MinCalcInterval) { + // If the step interval is very short, flag not to recalculate it next time stepInterval = (uint32_t)interval; stepsTillRecalc = DDA::MinCalcInterval/stepInterval + 1; } } } + + if (nextStepTime > dda.clocksNeeded) + { + // The calculation makes this step late. + // When the end speed is very low, calculating the time of the last step is very sensitive to rounding error. + // So if this is the last step and it is late, bring it forward to the expected finish time. + if (nextStep == totalSteps) + { + nextStepTime = dda.clocksNeeded; + } + else + { + // We don't expect any step except the last to be late + stepError = true; + if (reprap.Debug(moduleMove)) + { + stepInterval = 10000000 + nextStepTime; // so we can tell what happened in debug + return NoStepTime; + } + } + } return nextStepTime; } @@ -268,7 +292,7 @@ uint32_t DriveMovement::CalcNextStepTimeDelta(const DDA &dda, size_t drive) } ++nextStep; - if (stepsTillRecalc > 1 && nextStep != mp.delta.reverseStartStep) + if (stepsTillRecalc > 1 && nextStep != mp.delta.reverseStartStep && nextStep != totalSteps) { --stepsTillRecalc; nextStepTime += stepInterval; @@ -290,6 +314,7 @@ uint32_t DriveMovement::CalcNextStepTimeDelta(const DDA &dda, size_t drive) { direction = false; reprap.GetPlatform()->SetDirection(drive, false); // going down now + stepsTillRecalc = 1; // we can't trust the interval at the inflexion point } // Calculate d*s*K as an integer, where d = distance the head has travelled, s = steps/mm for this drive, K = a power of 2 to reduce the rounding errors @@ -304,7 +329,9 @@ uint32_t DriveMovement::CalcNextStepTimeDelta(const DDA &dda, size_t drive) const int32_t hmz0scK = (int32_t)(((int64_t)mp.delta.hmz0sK * dda.cKc)/Kc); const int32_t t1 = mp.delta.minusAaPlusBbTimesKs + hmz0scK; - const int32_t t2 = isqrt64(isquare64(t1) + mp.delta.dSquaredMinusAsquaredMinusBsquaredTimesKsquaredSsquared - isquare64(mp.delta.hmz0sK)); + // Due to rounding error we can end up trying to take the square root of a negative number + const int64_t t2a = (int64_t)isquare64(t1) + mp.delta.dSquaredMinusAsquaredMinusBsquaredTimesKsquaredSsquared - (int64_t)isquare64(mp.delta.hmz0sK); + const int32_t t2 = (t2a > 0) ? isqrt64(t2a) : 0; const int32_t dsK = (direction) ? t1 - t2 : t1 + t2; // Now feed dsK into a modified version of the step algorithm for Cartesian motion without elasticity compensation @@ -342,18 +369,42 @@ uint32_t DriveMovement::CalcNextStepTimeDelta(const DDA &dda, size_t drive) if (interval < DDA::MinStepInterval) { stepError = true; - stepInterval = (uint32_t)interval; - return NoStepTime; + if (reprap.Debug(moduleMove)) + { + stepInterval = (uint32_t)interval; + return NoStepTime; + } } - - // If the step interval is very short, flag not to recalculate it next time - if (interval < DDA::MinCalcInterval) + else if (interval < DDA::MinCalcInterval) { + // If the step interval is very short, flag not to recalculate it next time stepInterval = (uint32_t)interval; stepsTillRecalc = DDA::MinCalcInterval/stepInterval + 1; } } } + + if (nextStepTime > dda.clocksNeeded) + { + // The calculation makes this step late. + // When the end speed is very low, calculating the time of the last step is very sensitive to rounding error. + // So if this is the last step and it is late, bring it forward to the expected finish time. + if (nextStep == totalSteps) + { + nextStepTime = dda.clocksNeeded; + } + else + { + // We don't expect any step except the last to be late + stepError = true; + if (reprap.Debug(moduleMove)) + { + stepInterval = 10000000 + nextStepTime; // so we can tell what happened in debug + return NoStepTime; + } + } + } + return nextStepTime; } diff --git a/DriveMovement.h b/DriveMovement.h index e3d8c1a1..05956f36 100644 --- a/DriveMovement.h +++ b/DriveMovement.h @@ -26,7 +26,7 @@ struct PrepParams class DriveMovement { public: - uint32_t CalcNextStepTimeCartesian(size_t drive); + uint32_t CalcNextStepTimeCartesian(const DDA &dda, size_t drive); uint32_t CalcNextStepTimeDelta(const DDA &dda, size_t drive); void PrepareCartesianAxis(const DDA& dda, const PrepParams& params, size_t drive); void PrepareDeltaAxis(const DDA& dda, const PrepParams& params, size_t drive); @@ -91,7 +91,7 @@ public: static const uint32_t NoStepTime = 0xFFFFFFFF; // value to indicate that no further steps are needed when calculating the next step time static const uint32_t K1 = 1024; // a power of 2 used to multiply the value mmPerStepTimesCdivtopSpeed to reduce rounding errors static const uint32_t K2 = 512; // a power of 2 used in delta calculations to reduce rounding errors (but too large makes things worse) - static const int32_t Kc = 4096; // a power of 2 for scaling the Z movement fraction + static const int32_t Kc = 1024 * 1024; // a power of 2 for scaling the Z movement fraction }; #endif /* DRIVEMOVEMENT_H_ */ @@ -1304,6 +1304,13 @@ void GCodes::GetCurrentCoordinates(StringRef& s) const { s.catf("E%u:%.1f ", i - AXES, liveCoordinates[i]); } + + // Print the stepper motor positions as Marlin does, as an aid to debugging + s.cat(" Count"); + for (size_t i = 0; i < DRIVES; ++i) + { + s.catf(" %d", reprap.GetMove()->GetEndPoint(i)); + } } bool GCodes::OpenFileToWrite(const char* directory, const char* fileName, GCodeBuffer *gb) @@ -2785,6 +2792,11 @@ bool GCodes::HandleMcode(GCodeBuffer* gb, StringRef& reply) else { tool = reprap.GetCurrentTool(); + // If no tool is selected, and there is only one tool, set the active temperature for that one + if (tool == nullptr) + { + tool = reprap.GetOnlyTool(); + } } SetToolHeaters(tool, temperature); } @@ -32,7 +32,7 @@ void Move::Init() deltaProbing = false; // Empty the ring - ddaRingGetPointer = ddaRingAddPointer; + ddaRingGetPointer = ddaRingCheckPointer = ddaRingAddPointer; DDA *dda = ddaRingAddPointer; do { @@ -42,6 +42,7 @@ void Move::Init() currentDda = nullptr; addNoMoreMoves = false; + stepErrors = 0; // Clear the transforms SetIdentityTransform(); @@ -53,6 +54,7 @@ void Move::Init() for (size_t i = 0; i < DRIVES; i++) { move[i] = 0.0; + liveEndPoints[i] = 0; // not actually right for a delta, but better than printing random values in response to M114 reprap.GetPlatform()->SetDirection(i, FORWARDS); // DC: I don't see any reason why we do this } SetLiveCoordinates(move); @@ -104,14 +106,25 @@ void Move::Spin() ++idleCount; } + // Check for DDA errors to print if Move debug is enabled + while (ddaRingCheckPointer->GetState() == DDA::completed) + { + if (ddaRingCheckPointer->HasStepError()) + { + if (reprap.Debug(moduleMove)) + { + ddaRingCheckPointer->DebugPrint(); + } + ++stepErrors; + } + ddaRingCheckPointer->Free(); + ddaRingCheckPointer = ddaRingCheckPointer->GetNext(); + } + // See if we can add another move to the ring if (!addNoMoreMoves && ddaRingAddPointer->GetState() == DDA::empty) { DDA *dda = ddaRingAddPointer; - if (reprap.Debug(moduleMove)) - { - dda->PrintIfHasStepError(); - } // In order to react faster to speed and extrusion rate changes, only add more moves if the total duration of // all un-frozen moves is less than 2 seconds, or the total duration of all but the first un-frozen move is @@ -197,7 +210,7 @@ void Move::Spin() DDA *dda = ddaRingGetPointer; simulationTime += dda->CalcTime(); liveCoordinatesValid = dda->FetchEndPosition(const_cast<int32_t*>(liveEndPoints), const_cast<float *>(liveCoordinates)); - dda->Release(); + dda->Complete(); ddaRingGetPointer = ddaRingGetPointer->GetNext(); } } @@ -333,7 +346,7 @@ FilePosition Move::PausePrint(float positions[DRIVES+1]) { fPos = dda->GetFilePosition(); } - dda->Release(); + dda->Complete(); dda = dda->GetNext(); } while (dda != savedDdaRingAddPointer); @@ -356,7 +369,7 @@ extern uint64_t lastNum; void Move::Diagnostics() { reprap.GetPlatform()->AppendMessage(BOTH_MESSAGE, "Move Diagnostics:\n"); - reprap.GetPlatform()->AppendMessage(BOTH_MESSAGE, "MaxReps: %u\n", maxReps); + reprap.GetPlatform()->AppendMessage(BOTH_MESSAGE, "MaxReps: %u, StepErrors: %u\n", maxReps, stepErrors); maxReps = 0; #if 0 @@ -1086,7 +1099,7 @@ void Move::CurrentMoveCompleted() // Save the current motor coordinates, and the machine Cartesian coordinates if known liveCoordinatesValid = currentDda->FetchEndPosition(const_cast<int32_t*>(liveEndPoints), const_cast<float *>(liveCoordinates)); - currentDda->Release(); + currentDda->Complete(); currentDda = nullptr; ddaRingGetPointer = ddaRingGetPointer->GetNext(); } @@ -37,6 +37,7 @@ public: void Spin(); // Called in a tight loop to keep the class going void Exit(); // Shut down void GetCurrentUserPosition(float m[DRIVES + 1], uint8_t moveType) const; // Return the position (after all queued moves have been executed) in transformed coords + int32_t GetEndPoint(size_t drive) const { return liveEndPoints[drive]; } // Get the current position of a motor void LiveCoordinates(float m[DRIVES]); // Gives the last point at the end of the last complete DDA transformed to user coords void Interrupt(); // The hardware's (i.e. platform's) interrupt should call this. void InterruptTime(); // Test function - not used @@ -123,6 +124,7 @@ private: DDA* volatile currentDda; DDA* ddaRingAddPointer; DDA* volatile ddaRingGetPointer; + DDA* ddaRingCheckPointer; bool addNoMoreMoves; // If true, allow no more moves to be added to the look-ahead bool active; // Are we live and running? @@ -156,6 +158,7 @@ private: uint32_t deltaProbingStartTime; bool deltaProbing; int coreXYMode; // 0 = Cartesian, 1 = CoreXY, 2 = CoreXZ, 3 = CoreYZ + unsigned int stepErrors; // count of step errors, for diagnostics }; //****************************************************************************************************** diff --git a/Platform.cpp b/Platform.cpp index 4cf1e732..99e5bde7 100644 --- a/Platform.cpp +++ b/Platform.cpp @@ -568,7 +568,7 @@ bool Platform::MustHomeXYBeforeZ() const void Platform::ResetNvData() { - nvData.compatibility = me; + nvData.compatibility = marlin; // default to Marlin because the common host programs expect the "OK" response to commands ARRAY_INIT(nvData.ipAddress, IP_ADDRESS); ARRAY_INIT(nvData.netMask, NET_MASK); ARRAY_INIT(nvData.gateWay, GATE_WAY); @@ -740,13 +740,49 @@ void Platform::Spin() ClassReport(longWait); } +// Switch into boot mode and reset +#if 1 // trying the Arduino code to see if it is more reliable + +__attribute__ ((long_call, section (".ramfunc"))) +void eraseAndReset() { + cpu_irq_disable(); + + // Set boot flag to run SAM-BA bootloader at restart + const int EEFC_FCMD_CGPB = 0x0C; + const int EEFC_KEY = 0x5A; + while ((EFC0->EEFC_FSR & EEFC_FSR_FRDY) == 0); + EFC0->EEFC_FCR = + EEFC_FCR_FCMD(EEFC_FCMD_CGPB) | + EEFC_FCR_FARG(1) | + EEFC_FCR_FKEY(EEFC_KEY); + while ((EFC0->EEFC_FSR & EEFC_FSR_FRDY) == 0); + + // From here flash memory is no more available. + const int RSTC_KEY = 0xA5; + RSTC->RSTC_CR = + RSTC_CR_KEY(RSTC_KEY) | + RSTC_CR_PROCRST | + RSTC_CR_PERRST; + + while (true); +} + +#else + +void eraseAndReset() +{ + cpu_irq_disable(); + flash_unlock(0x00080000, 0x000FFFFF, nullptr, nullptr); + flash_clear_gpnvm(1); // tell the system to boot from flash next time +} + +#endif + void Platform::SoftwareReset(uint16_t reason) { if (reason == SoftwareResetReason::erase) { - cpu_irq_disable(); - flash_unlock(0x00080000, 0x000FFFFF, nullptr, nullptr); - flash_clear_gpnvm(1); // tell the system to boot from flash next time + eraseAndReset(); } else { @@ -789,6 +825,7 @@ void Platform::SoftwareReset(uint16_t reason) for(;;) {} } + //***************************************************************************************************************** // Interrupts @@ -823,6 +860,9 @@ void FanInterrupt() void Platform::InitialiseInterrupts() { + // Set the tick interrupt to the highest priority. We need to to monitor the heaters and kick the watchdog. + NVIC_SetPriority (SysTick_IRQn, 0); // set priority for tick interrupts + // Timer interrupt for stepper motors // The clock rate we use is a compromise. Too fast and the 64-bit square roots take a long time to execute. Too slow and we lose resolution. // We choose a clock divisor of 32, which gives us 0.38us resolution. The next option is 128 which would give 1.524us resolution. @@ -832,7 +872,7 @@ void Platform::InitialiseInterrupts() TC1 ->TC_CHANNEL[0].TC_IDR = ~(uint32_t)0; // interrupts disabled for now TC_Start(TC1, 0); TC_GetStatus(TC1, 0); // clear any pending interrupt - NVIC_SetPriority(TC3_IRQn, 0); // set highest priority for this IRQ; it's time-critical + NVIC_SetPriority(TC3_IRQn, 2); // set high priority for this IRQ; it's time-critical NVIC_EnableIRQ(TC3_IRQn); // Timer interrupt to keep the networking timers running (called at 16Hz) @@ -844,7 +884,7 @@ void Platform::InitialiseInterrupts() TC_Start(TC1, 1); TC1 ->TC_CHANNEL[1].TC_IER = TC_IER_CPCS; TC1 ->TC_CHANNEL[1].TC_IDR = ~TC_IER_CPCS; - NVIC_SetPriority(TC4_IRQn, 4); // step interrupt is time-critical + NVIC_SetPriority(TC4_IRQn, 4); // step interrupt is more time-critical than this one NVIC_EnableIRQ(TC4_IRQn); // Interrupt for 4-pin PWM fan sense line diff --git a/Release/RepRapFirmware-1.09f-testing-dc42.bin b/Release/RepRapFirmware-1.09f-testing-dc42.bin Binary files differnew file mode 100644 index 00000000..6804cb7e --- /dev/null +++ b/Release/RepRapFirmware-1.09f-testing-dc42.bin diff --git a/RepRapFirmware.cpp b/RepRapFirmware.cpp index c42cd35a..954b7c44 100644 --- a/RepRapFirmware.cpp +++ b/RepRapFirmware.cpp @@ -427,11 +427,19 @@ void RepRap::PrintDebug() if (debug != 0) { platform->Message(BOTH_MESSAGE, "Debugging enabled for modules:"); - for(uint8_t i=0; i<16;i++) + for (unsigned int i = 0; i < numModules; i++) { - if (debug & (1 << i)) + if ((debug & (1 << i)) != 0) { - platform->AppendMessage(BOTH_MESSAGE, " %s", moduleName[i]); + platform->AppendMessage(BOTH_MESSAGE, " %s(%u)", moduleName[i], i); + } + } + platform->Message(BOTH_MESSAGE, "\nDebugging disabled for modules:"); + for (unsigned int i = 0; i < numModules; i++) + { + if ((debug & (1 << i)) == 0) + { + platform->AppendMessage(BOTH_MESSAGE, " %s(%u)", moduleName[i], i); } } platform->AppendMessage(BOTH_MESSAGE, "\n"); @@ -565,7 +573,7 @@ void RepRap::StandbyTool(int toolNumber) platform->Message(BOTH_MESSAGE, "Attempt to standby a non-existent tool: %d.\n", toolNumber); } -Tool* RepRap::GetTool(int toolNumber) +Tool* RepRap::GetTool(int toolNumber) const { Tool* tool = toolList; @@ -580,6 +588,11 @@ Tool* RepRap::GetTool(int toolNumber) return NULL; // Not an error } +Tool* RepRap::GetOnlyTool() const +{ + return (toolList != nullptr && toolList->Next() == nullptr) ? toolList : nullptr; +} + #if 0 // not used Tool* RepRap::GetToolByDrive(int driveNumber) { @@ -1573,7 +1586,7 @@ size_t StringRef::cat(const char* src) // Utilities and storage not part of any class -static char scratchStringBuffer[100]; // this is now used only for short messages +static char scratchStringBuffer[120]; // this is now used only for short messages; needs to be long enough to print delta parameters StringRef scratchString(scratchStringBuffer, ARRAY_SIZE(scratchStringBuffer)); // For debug use diff --git a/RepRapFirmware.h b/RepRapFirmware.h index 897f38da..a332f97d 100644 --- a/RepRapFirmware.h +++ b/RepRapFirmware.h @@ -37,6 +37,7 @@ enum Module moduleHeat = 5, moduleDda = 6, modulePrintMonitor = 7, + numModules = 8, // make this one greater than the last module number noModule = 15 }; @@ -52,8 +52,9 @@ class RepRap void DeleteTool(Tool* t); void SelectTool(int toolNumber); void StandbyTool(int toolNumber); - Tool* GetCurrentTool(); - Tool* GetTool(int toolNumber); + Tool* GetCurrentTool() const; + Tool* GetTool(int toolNumber) const; + Tool* GetOnlyTool() const; //Tool* GetToolByDrive(int driveNumber); void SetToolVariables(int toolNumber, float* standbyTemperatures, float* activeTemperatures); @@ -151,7 +152,7 @@ inline PrintMonitor* RepRap::GetPrintMonitor() const { return printMonitor; } inline bool RepRap::Debug(Module m) const { return debug & (1 << m); } inline Module RepRap::GetSpinningModule() const { return spinningModule; } -inline Tool* RepRap::GetCurrentTool() { return currentTool; } +inline Tool* RepRap::GetCurrentTool() const { return currentTool; } inline uint16_t RepRap::GetExtrudersInUse() const { return activeExtruders; } inline uint16_t RepRap::GetHeatersInUse() const { return activeHeaters; } inline bool RepRap::ColdExtrude() const { return coldExtrude; } diff --git a/SD-image/sys-CoreXY/pause.g b/SD-image/sys-CoreXY/pause.g index b098f19f..67f7cac7 100644 --- a/SD-image/sys-CoreXY/pause.g +++ b/SD-image/sys-CoreXY/pause.g @@ -1,4 +1,5 @@ ; Pause macro file +M83 ; relative extruder moves G1 E-4 F2500 ; retract 4mm G91 ; relative moves G1 Z5 F5000 ; raise nozzle 2mm diff --git a/SD-image/sys-CoreXY/resume.g b/SD-image/sys-CoreXY/resume.g index 49e46853..152f5e80 100644 --- a/SD-image/sys-CoreXY/resume.g +++ b/SD-image/sys-CoreXY/resume.g @@ -1,4 +1,5 @@ ; Resume macro file G1 R1 Z2 F5000 ; move to 2mm above resume point G1 R1 ; lower nozzle to resume point +M83 ; relative extruder moves G1 E4 F2500 ; undo the retraction
\ No newline at end of file diff --git a/SD-image/sys-Huxley/pause.g b/SD-image/sys-Huxley/pause.g index 70c11cb5..b6d3af0d 100644 --- a/SD-image/sys-Huxley/pause.g +++ b/SD-image/sys-Huxley/pause.g @@ -1,4 +1,5 @@ ; Pause macro file +M83 ; relative extruder moves G1 E-4 F2500 ; retract 4mm G91 ; relative moves G1 Z2 F5000 ; raise nozzle 2mm diff --git a/SD-image/sys-Huxley/resume.g b/SD-image/sys-Huxley/resume.g index 49e46853..152f5e80 100644 --- a/SD-image/sys-Huxley/resume.g +++ b/SD-image/sys-Huxley/resume.g @@ -1,4 +1,5 @@ ; Resume macro file G1 R1 Z2 F5000 ; move to 2mm above resume point G1 R1 ; lower nozzle to resume point +M83 ; relative extruder moves G1 E4 F2500 ; undo the retraction
\ No newline at end of file diff --git a/SD-image/sys-MiniKossel/homedelta.g b/SD-image/sys-MiniKossel/homedelta.g index d889e51d..34b294d8 100644 --- a/SD-image/sys-MiniKossel/homedelta.g +++ b/SD-image/sys-MiniKossel/homedelta.g @@ -1,8 +1,8 @@ ; Homing file for RepRapFirmware on Mini Kossel G91 ; use relative positioning -;******* Change F500 in the following line by F5000 when you are finished commissioning +;******* Change F300 in the following line to F3000 when you are finished commissioning ;******* Change 320 in the following to a higher value if your Kossel has taller towers -G1 S1 X320 Y320 Z320 F500 ; move all carriages up 320mm, stopping at the endstops +G1 S1 X320 Y320 Z320 F300 ; move all carriages up 320mm, stopping at the endstops G1 S2 X-3 Y-3 Z-3 ; move all carriages down 3mm G1 S1 X6 Y6 Z6 F250 ; move carriages slowly up 6mm, stopping at the endstops G1 Z-5 F2000 ; down a few mm so that we can centre the head diff --git a/SD-image/sys-MiniKossel/pause.g b/SD-image/sys-MiniKossel/pause.g index 18855ff7..0cb1d1f9 100644 --- a/SD-image/sys-MiniKossel/pause.g +++ b/SD-image/sys-MiniKossel/pause.g @@ -1,4 +1,5 @@ ; Pause macro file +M83 ; relative extruder moves G1 E-4 F2500 ; retract 4mm G91 ; relative moves G1 Z5 F5000 ; raise nozzle 2mm diff --git a/SD-image/sys-MiniKossel/resume.g b/SD-image/sys-MiniKossel/resume.g index 49e46853..152f5e80 100644 --- a/SD-image/sys-MiniKossel/resume.g +++ b/SD-image/sys-MiniKossel/resume.g @@ -1,4 +1,5 @@ ; Resume macro file G1 R1 Z2 F5000 ; move to 2mm above resume point G1 R1 ; lower nozzle to resume point +M83 ; relative extruder moves G1 E4 F2500 ; undo the retraction
\ No newline at end of file diff --git a/SD-image/sys-Ormerod1/pause.g b/SD-image/sys-Ormerod1/pause.g index b098f19f..67f7cac7 100644 --- a/SD-image/sys-Ormerod1/pause.g +++ b/SD-image/sys-Ormerod1/pause.g @@ -1,4 +1,5 @@ ; Pause macro file +M83 ; relative extruder moves G1 E-4 F2500 ; retract 4mm G91 ; relative moves G1 Z5 F5000 ; raise nozzle 2mm diff --git a/SD-image/sys-Ormerod1/resume.g b/SD-image/sys-Ormerod1/resume.g index 49e46853..152f5e80 100644 --- a/SD-image/sys-Ormerod1/resume.g +++ b/SD-image/sys-Ormerod1/resume.g @@ -1,4 +1,5 @@ ; Resume macro file G1 R1 Z2 F5000 ; move to 2mm above resume point G1 R1 ; lower nozzle to resume point +M83 ; relative extruder moves G1 E4 F2500 ; undo the retraction
\ No newline at end of file diff --git a/SD-image/sys-Ormerod2/pause.g b/SD-image/sys-Ormerod2/pause.g index b098f19f..67f7cac7 100644 --- a/SD-image/sys-Ormerod2/pause.g +++ b/SD-image/sys-Ormerod2/pause.g @@ -1,4 +1,5 @@ ; Pause macro file +M83 ; relative extruder moves G1 E-4 F2500 ; retract 4mm G91 ; relative moves G1 Z5 F5000 ; raise nozzle 2mm diff --git a/SD-image/sys-Ormerod2/resume.g b/SD-image/sys-Ormerod2/resume.g index 49e46853..152f5e80 100644 --- a/SD-image/sys-Ormerod2/resume.g +++ b/SD-image/sys-Ormerod2/resume.g @@ -1,4 +1,5 @@ ; Resume macro file G1 R1 Z2 F5000 ; move to 2mm above resume point G1 R1 ; lower nozzle to resume point +M83 ; relative extruder moves G1 E4 F2500 ; undo the retraction
\ No newline at end of file diff --git a/Webserver.cpp b/Webserver.cpp index 45b9a3da..1ed8249f 100644 --- a/Webserver.cpp +++ b/Webserver.cpp @@ -946,6 +946,7 @@ bool Webserver::HttpInterpreter::GetJsonResponse(const char* request, StringRef& { // This is only possible if we have at least one HTTP session left response.copy("{\"err\":0}"); + } else { @@ -958,6 +959,8 @@ bool Webserver::HttpInterpreter::GetJsonResponse(const char* request, StringRef& // Wrong password response.copy("{\"err\":1}"); } + + CancelUpload(); // if a file upload was in progress from this IP address, cancel it } else if (!IsAuthenticated()) { |