Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/Duet3D/RepRapFirmware.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorDavid Crocker <dcrocker@eschertech.com>2016-12-09 17:01:40 +0300
committerDavid Crocker <dcrocker@eschertech.com>2016-12-09 17:02:18 +0300
commita7ea87d1e38117823c13dc3eae4810afb73420ab (patch)
treeee608001013df3879923f41301285b3954a9b869 /src
parent9799ffce733ce08f4110d81d6476c8fc174ccabb (diff)
Version 1.17dev8
Fixed bugs related to grid bed compensation and M571 in 1.17dev7 version Software reset code storage/retrieval now works on Duet WiFi Removed max average printing acceleration parameter M571 now accepts F parameter to set the PWM frequency M106 now shows if fan is disabled
Diffstat (limited to 'src')
-rw-r--r--src/Configuration.h6
-rw-r--r--src/Fan.cpp10
-rw-r--r--src/Fan.h2
-rw-r--r--src/GCodes/GCodes.cpp (renamed from src/GCodes/GCodes1.cpp)103
-rw-r--r--src/GCodes/GCodes.h6
-rw-r--r--src/GCodes/GCodes2.cpp218
-rw-r--r--src/Movement/DDA.cpp44
-rw-r--r--src/Movement/DDA.h4
-rw-r--r--src/Movement/Move.cpp23
-rw-r--r--src/Movement/Move.h3
-rw-r--r--src/Platform.cpp128
-rw-r--r--src/Platform.h58
-rw-r--r--src/Tool.cpp11
13 files changed, 349 insertions, 267 deletions
diff --git a/src/Configuration.h b/src/Configuration.h
index 924e1634..728a1156 100644
--- a/src/Configuration.h
+++ b/src/Configuration.h
@@ -28,11 +28,11 @@ Licence: GPL
// Firmware name is now defined in the Pins file
#ifndef VERSION
-# define VERSION "1.17dev7"
+# define VERSION "1.17dev8"
#endif
#ifndef DATE
-# define DATE "2016-12-07"
+# define DATE "2016-12-09"
#endif
#define AUTHORS "reprappro, dc42, zpl, t3p3, dnewman"
@@ -118,7 +118,7 @@ const unsigned int FirstRtdChannel = 200; // Temperature sensor channels 200..
const unsigned int SlowHeaterPwmFreq = 10; // slow PWM frequency for bed and chamber heaters, compatible with DC/AC SSRs
const unsigned int NormalHeaterPwmFreq = 250; // normal PWM frequency used for hot ends
const unsigned int DefaultFanPwmFreq = 250; // increase to 25kHz using M106 command to meet Intel 4-wire PWM fan specification
-const unsigned int DefaultPinWritePwmFreq = 500; // default PWM frequency for M42 pin writes
+const unsigned int DefaultPinWritePwmFreq = 500; // default PWM frequency for M42 pin writes and extrusion ancilliary PWM
// Default Z probe values
diff --git a/src/Fan.cpp b/src/Fan.cpp
index 89e2f972..83c56e45 100644
--- a/src/Fan.cpp
+++ b/src/Fan.cpp
@@ -132,4 +132,14 @@ void Fan::Check()
}
}
+void Fan::Disable()
+{
+ if (pin != NoPin)
+ {
+ inverted = false;
+ SetHardwarePwm(0.0);
+ }
+ pin = NoPin;
+}
+
// End
diff --git a/src/Fan.h b/src/Fan.h
index 9e31feb4..1c277bf4 100644
--- a/src/Fan.h
+++ b/src/Fan.h
@@ -48,7 +48,7 @@ public:
void SetTriggerTemperature(float t) { triggerTemperature = t; }
void SetHeatersMonitored(uint16_t h);
void Check();
- void Disable() { pin = NoPin; }
+ void Disable();
};
#endif /* SRC_FAN_H_ */
diff --git a/src/GCodes/GCodes1.cpp b/src/GCodes/GCodes.cpp
index e5622453..3fb29110 100644
--- a/src/GCodes/GCodes1.cpp
+++ b/src/GCodes/GCodes.cpp
@@ -148,7 +148,7 @@ void GCodes::Reset()
simulationMode = 0;
simulationTime = 0.0;
isPaused = false;
- filePos = moveBuffer.filePos = noFilePosition;
+ moveBuffer.filePos = noFilePosition;
lastEndstopStates = platform->GetAllEndstopStates();
firmwareUpdateModuleMap = 0;
@@ -699,11 +699,6 @@ void GCodes::DoFilePrint(GCodeBuffer& gb, StringRef& reply)
char b;
if (fd.Read(b))
{
- if (gb.StartingNewCode() && &gb == fileGCode && gb.MachineState().previous == nullptr)
- {
- filePos = fd.GetPosition() - 1;
- //debugPrintf("Set file pos %u\n", filePos);
- }
if (gb.Put(b))
{
gb.SetFinished(ActOnCode(gb, reply));
@@ -732,6 +727,7 @@ void GCodes::DoFilePrint(GCodeBuffer& gb, StringRef& reply)
if (gb.MachineState().previous == nullptr)
{
// Finished printing SD card file
+ UnlockAll(gb);
reprap.GetPrintMonitor()->StoppedPrint();
if (platform->Emulating() == marlin)
{
@@ -947,7 +943,7 @@ void GCodes::Pop(GCodeBuffer& gb)
// Move expects all axis movements to be absolute, and all extruder drive moves to be relative. This function serves that.
// 'moveType' is the S parameter in the G0 or G1 command, or -1 if we are doing G92.
// For regular (type 0) moves, we apply limits and do X axis mapping.
-// Returns the number of segments if we have a legal move (or 1 if we are doing G92), or zero if this gcode should be discarded
+// Returns the number of segments if we have a legal move, 1 if we are doing G92, or zero if this gcode should be discarded
unsigned int GCodes::LoadMoveBufferFromGCode(GCodeBuffer& gb, int moveType)
{
// Zero every extruder drive as some drives may not be changed
@@ -1214,7 +1210,7 @@ int GCodes::SetUpMove(GCodeBuffer& gb, StringRef& reply)
}
}
- // Load the last position and feed rate into moveBuffer
+ // Load the last position into moveBuffer
#if SUPPORT_ROLAND
if (reprap.GetRoland()->Active())
{
@@ -1227,24 +1223,25 @@ int GCodes::SetUpMove(GCodeBuffer& gb, StringRef& reply)
}
// Load the move buffer with either the absolute movement required or the relative movement required
- float oldCoords[MAX_AXES];
- memcpy(oldCoords, moveBuffer.coords, sizeof(oldCoords));
+ memcpy(moveBuffer.initialCoords, moveBuffer.coords, numAxes * sizeof(moveBuffer.initialCoords[0]));
segmentsLeft = LoadMoveBufferFromGCode(gb, moveBuffer.moveType);
+
if (segmentsLeft != 0)
{
// Flag whether we should use pressure advance, if there is any extrusion in this move.
- // We assume it is a normal printing move needing pressure advance if there is forward extrusion and XY movement.
- // The movement code will only apply pressure advance if there is forward extrusion, so we only need to check for XY movement here.
+ // We assume it is a normal printing move needing pressure advance if there is forward extrusion and XYU.. movement.
+ // The movement code will only apply pressure advance if there is forward extrusion, so we only need to check for XYU.. movement here.
moveBuffer.usePressureAdvance = false;
for (size_t axis = 0; axis < numAxes; ++axis)
{
- if (axis != Z_AXIS && moveBuffer.coords[axis] != oldCoords[axis])
+ if (axis != Z_AXIS && moveBuffer.coords[axis] != moveBuffer.initialCoords[axis])
{
moveBuffer.usePressureAdvance = true;
break;
}
}
- moveBuffer.filePos = (&gb == fileGCode) ? filePos : noFilePosition;
+ moveBuffer.filePos = (&gb == fileGCode) ? gb.MachineState().fileState.GetPosition() : noFilePosition;
+ moveBuffer.canPauseAfter = (moveBuffer.endStopsToCheck == 0);
//debugPrintf("Queue move pos %u\n", moveFilePos);
}
return (moveBuffer.moveType != 0 || moveBuffer.endStopsToCheck != 0) ? 2 : 1;
@@ -1266,7 +1263,9 @@ bool GCodes::ReadMove(RawMove& m)
}
else
{
- // This move needs to be divided into 2 or more segments
+ // This move needs to be divided into 2 or more segments. We can only pause after the final segment.
+ m.canPauseAfter = false;
+
// Do the axes
for (size_t drive = 0; drive < numAxes; ++drive)
{
@@ -1375,52 +1374,65 @@ bool GCodes::DoCannedCycleMove(GCodeBuffer& gb, EndstopChecks ce)
return false;
}
-// This handles G92
+// This handles G92. Return true if completed, false if it needs to be called again.
bool GCodes::SetPositions(GCodeBuffer& gb)
{
- // Don't pause the machine if only extruder drives are being reset (DC, 2015-09-06).
- // This avoids blobs and seams when the gcode uses absolute E coordinates and periodically includes G92 E0.
- bool includingAxes = false;
- for (size_t drive = 0; drive < numAxes; ++drive)
+ if (gb.Seen('R') && gb.GetIValue() == 1)
{
- if (gb.Seen(axisLetters[drive]))
+ // Babystepping command. All coordinates except Z are ignored.
+ if (gb.Seen('Z'))
{
- includingAxes = true;
- break;
+ const float babystepAmount = gb.GetFValue() * distanceScale;
+ if (fabs(babystepAmount) <= 1.0) // limit babystepping to 1mm
+ {
+ reprap.GetMove()->Babystep(babystepAmount);
+ }
}
}
-
- if (includingAxes)
+ else
{
- if (!LockMovementAndWaitForStandstill(gb))
+ // Don't pause the machine if only extruder drives are being reset (DC, 2015-09-06).
+ // This avoids blobs and seams when the gcode uses absolute E coordinates and periodically includes G92 E0.
+ bool includingAxes = false;
+ for (size_t drive = 0; drive < numAxes; ++drive)
+ {
+ if (gb.Seen(axisLetters[drive]))
+ {
+ includingAxes = true;
+ break;
+ }
+ }
+
+ if (includingAxes)
+ {
+ if (!LockMovementAndWaitForStandstill(gb)) // lock movement and get current coordinates
+ {
+ return false;
+ }
+ }
+ else if (segmentsLeft != 0) // wait for previous move to be taken so that GetCurrentUserPosition returns the correct value
{
return false;
}
- }
- else if (segmentsLeft != 0) // wait for previous move to be taken so that GetCurrentUserPosition returns the correct value
- {
- return false;
- }
- reprap.GetMove()->GetCurrentUserPosition(moveBuffer.coords, 0, reprap.GetCurrentXAxes()); // make sure move buffer is up to date
- bool ok = LoadMoveBufferFromGCode(gb, -1);
- if (ok && includingAxes)
- {
-#if SUPPORT_ROLAND
- if (reprap.GetRoland()->Active())
+ const bool ok = LoadMoveBufferFromGCode(gb, -1);
+ if (ok && includingAxes)
{
- for(size_t axis = 0; axis < AXES; axis++)
+#if SUPPORT_ROLAND
+ if (reprap.GetRoland()->Active())
{
- if (!reprap.GetRoland()->ProcessG92(moveBuffer[axis], axis))
+ for(size_t axis = 0; axis < AXES; axis++)
{
- return false;
+ if (!reprap.GetRoland()->ProcessG92(moveBuffer[axis], axis))
+ {
+ return false;
+ }
}
}
- }
#endif
- SetPositions(moveBuffer.coords);
+ SetPositions(moveBuffer.coords);
+ }
}
-
return true;
}
@@ -2974,7 +2986,7 @@ void GCodes::StartToolChange(GCodeBuffer& gb, bool inM109)
}
// Retract or un-retract filament, returning true if movement has been queued, false if this needs to be called again
-bool GCodes::RetractFilament(bool retract)
+bool GCodes::RetractFilament(GCodeBuffer& gb, bool retract)
{
if (retractLength != 0.0 || retractHop != 0.0 || (!retract && retractExtra != 0.0))
{
@@ -3008,7 +3020,8 @@ bool GCodes::RetractFilament(bool retract)
moveBuffer.isFirmwareRetraction = true;
moveBuffer.usePressureAdvance = false;
- moveBuffer.filePos = filePos;
+ moveBuffer.filePos = (&gb == fileGCode) ? gb.MachineState().fileState.GetPosition() : noFilePosition;
+ moveBuffer.canPauseAfter = !retract; // don't pause after a retraction because that could cause too much retraction
moveBuffer.xAxes = reprap.GetCurrentXAxes();
segmentsLeft = 1;
}
diff --git a/src/GCodes/GCodes.h b/src/GCodes/GCodes.h
index eee3cd72..4c677382 100644
--- a/src/GCodes/GCodes.h
+++ b/src/GCodes/GCodes.h
@@ -65,12 +65,13 @@ public:
float coords[DRIVES]; // new positions for the axes, amount of movement for the extruders
float initialCoords[MAX_AXES]; // the initial positions of the axes
float feedRate; // feed rate of this move
- FilePosition filePos; // offset in the file being printed that this move was read from
+ FilePosition filePos; // offset in the file being printed at the end of reading this move
uint32_t xAxes; // axes that X is mapped to
EndstopChecks endStopsToCheck; // endstops to check
uint8_t moveType; // the S parameter from the G0 or G1 command, 0 for a normal move
bool isFirmwareRetraction; // true if this is a firmware retraction/un-retraction move
bool usePressureAdvance; // true if we want to us extruder pressure advance, if there is any extrusion
+ bool canPauseAfter; // true if we can pause just after this move and successfully restart
};
GCodes(Platform* p, Webserver* w);
@@ -197,7 +198,7 @@ private:
void SetAllAxesNotHomed(); // Flag all axes as not homed
void SetPositions(float positionNow[DRIVES]); // Set the current position to be this
const char *TranslateEndStopResult(EndStopHit es); // Translate end stop result to text
- bool RetractFilament(bool retract); // Retract or un-retract filaments
+ bool RetractFilament(GCodeBuffer& gb, bool retract); // Retract or un-retract filaments
bool ChangeMicrostepping(size_t drive, int microsteps, int mode) const; // Change microstepping on the specified drive
void ListTriggers(StringRef reply, TriggerMask mask); // Append a list of trigger endstops to a message
void CheckTriggers(); // Check for and execute triggers
@@ -280,7 +281,6 @@ private:
float simulationTime; // Accumulated simulation time
uint8_t simulationMode; // 0 = not simulating, 1 = simulating, >1 are simulation modes for debugging
- FilePosition filePos; // The position we got up to in the file being printed
// Firmware retraction settings
float retractLength, retractExtra; // retraction length and extra length to un-retract
diff --git a/src/GCodes/GCodes2.cpp b/src/GCodes/GCodes2.cpp
index 5c7ef148..3dd0c2d4 100644
--- a/src/GCodes/GCodes2.cpp
+++ b/src/GCodes/GCodes2.cpp
@@ -133,7 +133,7 @@ bool GCodes::HandleGcode(GCodeBuffer& gb, StringRef& reply)
{
return false;
}
- result = RetractFilament(true);
+ result = RetractFilament(gb, true);
}
break;
@@ -142,7 +142,7 @@ bool GCodes::HandleGcode(GCodeBuffer& gb, StringRef& reply)
{
return false;
}
- result = RetractFilament(false);
+ result = RetractFilament(gb, false);
break;
case 20: // Inches (which century are we living in, here?)
@@ -913,121 +913,127 @@ bool GCodes::HandleMcode(GCodeBuffer& gb, StringRef& reply)
}
else
{
- bool seen = false;
Fan& fan = platform->GetFan(fanNum);
-
- if (gb.Seen('I')) // Invert cooling
+ if (!fan.IsEnabled())
+ {
+ reply.printf("Fan number %d is disabled", fanNum);
+ }
+ else
{
- const int invert = gb.GetIValue();
- if (invert < 0)
+ bool seen = false;
+ if (gb.Seen('I')) // Invert cooling
{
- fan.Disable();
+ const int invert = gb.GetIValue();
+ if (invert < 0)
+ {
+ fan.Disable();
+ }
+ else
+ {
+ fan.SetInverted(invert > 0);
+ }
+ seen = true;
}
- else
+
+ if (gb.Seen('F')) // Set PWM frequency
{
- fan.SetInverted(invert > 0);
+ fan.SetPwmFrequency(gb.GetFValue());
+ seen = true;
}
- seen = true;
- }
-
- if (gb.Seen('F')) // Set PWM frequency
- {
- fan.SetPwmFrequency(gb.GetFValue());
- seen = true;
- }
-
- if (gb.Seen('T')) // Set thermostatic trigger temperature
- {
- seen = true;
- fan.SetTriggerTemperature(gb.GetFValue());
- }
- if (gb.Seen('B')) // Set blip time
- {
- seen = true;
- fan.SetBlipTime(gb.GetFValue());
- }
-
- if (gb.Seen('L')) // Set minimum speed
- {
- seen = true;
- fan.SetMinValue(gb.GetFValue());
- }
+ if (gb.Seen('T')) // Set thermostatic trigger temperature
+ {
+ seen = true;
+ fan.SetTriggerTemperature(gb.GetFValue());
+ }
- if (gb.Seen('H')) // Set thermostatically-controller heaters
- {
- seen = true;
- long heaters[HEATERS];
- size_t numH = HEATERS;
- gb.GetLongArray(heaters, numH);
- // Note that M106 H-1 disables thermostatic mode. The following code implements that automatically.
- uint16_t hh = 0;
- for (size_t h = 0; h < numH; ++h)
- {
- const int hnum = heaters[h];
- if (hnum >= 0 && hnum < HEATERS)
- {
- hh |= (1u << (unsigned int)hnum);
- }
+ if (gb.Seen('B')) // Set blip time
+ {
+ seen = true;
+ fan.SetBlipTime(gb.GetFValue());
}
- if (hh != 0)
+
+ if (gb.Seen('L')) // Set minimum speed
{
- platform->SetFanValue(fanNum, 1.0); // default the fan speed to full for safety
+ seen = true;
+ fan.SetMinValue(gb.GetFValue());
}
- fan.SetHeatersMonitored(hh);
- }
- if (gb.Seen('S')) // Set new fan value - process this after processing 'H' or it may not be acted on
- {
- const float f = constrain<float>(gb.GetFValue(), 0.0, 255.0);
- if (seen || seenFanNum)
+ if (gb.Seen('H')) // Set thermostatically-controller heaters
{
- platform->SetFanValue(fanNum, f);
+ seen = true;
+ long heaters[HEATERS];
+ size_t numH = HEATERS;
+ gb.GetLongArray(heaters, numH);
+ // Note that M106 H-1 disables thermostatic mode. The following code implements that automatically.
+ uint16_t hh = 0;
+ for (size_t h = 0; h < numH; ++h)
+ {
+ const int hnum = heaters[h];
+ if (hnum >= 0 && hnum < HEATERS)
+ {
+ hh |= (1u << (unsigned int)hnum);
+ }
+ }
+ if (hh != 0)
+ {
+ platform->SetFanValue(fanNum, 1.0); // default the fan speed to full for safety
+ }
+ fan.SetHeatersMonitored(hh);
}
- else
+
+ if (gb.Seen('S')) // Set new fan value - process this after processing 'H' or it may not be acted on
{
- // We are processing an M106 S### command with no other recognised parameters and we have a tool selected.
- // Apply the fan speed setting to the fans in the fan mapping for the current tool.
- lastDefaultFanSpeed = f;
- SetMappedFanSpeed();
+ const float f = constrain<float>(gb.GetFValue(), 0.0, 255.0);
+ if (seen || seenFanNum)
+ {
+ platform->SetFanValue(fanNum, f);
+ }
+ else
+ {
+ // We are processing an M106 S### command with no other recognised parameters and we have a tool selected.
+ // Apply the fan speed setting to the fans in the fan mapping for the current tool.
+ lastDefaultFanSpeed = f;
+ SetMappedFanSpeed();
+ }
}
- }
- else if (gb.Seen('R'))
- {
- const int i = gb.GetIValue();
- switch(i)
+ else if (gb.Seen('R'))
{
- case 0:
- case 1:
- // Restore fan speed to value when print was paused
- platform->SetFanValue(fanNum, pausedFanValues[fanNum]);
- break;
- case 2:
- // Set the speeds of mapped fans to the last known value. Fan number is ignored.
- SetMappedFanSpeed();
- break;
- default:
- break;
+ const int i = gb.GetIValue();
+ switch(i)
+ {
+ case 0:
+ case 1:
+ // Restore fan speed to value when print was paused
+ platform->SetFanValue(fanNum, pausedFanValues[fanNum]);
+ break;
+ case 2:
+ // Set the speeds of mapped fans to the last known value. Fan number is ignored.
+ SetMappedFanSpeed();
+ break;
+ default:
+ break;
+ }
}
- }
- else if (!seen)
- {
- reply.printf("Fan%i frequency: %dHz, speed: %d%%, min: %d%%, blip: %.2f, inverted: %s",
- fanNum,
- (int)(fan.GetPwmFrequency()),
- (int)(fan.GetValue() * 100.0),
- (int)(fan.GetMinValue() * 100.0),
- fan.GetBlipTime(),
- (fan.GetInverted()) ? "yes" : "no");
- uint16_t hh = fan.GetHeatersMonitored();
- if (hh != 0)
- {
- reply.catf(", trigger: %dC, heaters:", (int)fan.GetTriggerTemperature());
- for (unsigned int i = 0; i < HEATERS; ++i)
+ else if (!seen)
+ {
+ reply.printf("Fan%i frequency: %dHz, speed: %d%%, min: %d%%, blip: %.2f, inverted: %s",
+ fanNum,
+ (int)(fan.GetPwmFrequency()),
+ (int)(fan.GetValue() * 100.0),
+ (int)(fan.GetMinValue() * 100.0),
+ fan.GetBlipTime(),
+ (fan.GetInverted()) ? "yes" : "no");
+ uint16_t hh = fan.GetHeatersMonitored();
+ if (hh != 0)
{
- if ((hh & (1u << i)) != 0)
+ reply.catf(", trigger: %dC, heaters:", (int)fan.GetTriggerTemperature());
+ for (unsigned int i = 0; i < HEATERS; ++i)
{
- reply.catf(" %u", i);
+ if ((hh & (1u << i)) != 0)
+ {
+ reply.catf(" %u", i);
+ }
}
}
}
@@ -1491,13 +1497,6 @@ bool GCodes::HandleMcode(GCodeBuffer& gb, StringRef& reply)
}
}
- if (gb.Seen('P'))
- {
- // Set max average printing acceleration
- platform->SetMaxAverageAcceleration(gb.GetFValue() * distanceScale);
- seen = true;
- }
-
if (!seen)
{
reply.printf("Accelerations: ");
@@ -1512,7 +1511,6 @@ bool GCodes::HandleMcode(GCodeBuffer& gb, StringRef& reply)
reply.catf("%c%.1f", sep, platform->Acceleration(extruder + numAxes) / distanceScale);
sep = ':';
}
- reply.catf(", avg. printing: %.1f", platform->GetMaxAverageAcceleration());
}
}
break;
@@ -2591,6 +2589,10 @@ bool GCodes::HandleMcode(GCodeBuffer& gb, StringRef& reply)
}
seen = true;
}
+ if (gb.Seen('F'))
+ {
+ platform->SetExtrusionAncilliaryPwmFrequency(gb.GetFValue());
+ }
if (gb.Seen('S'))
{
platform->SetExtrusionAncilliaryPwmValue(gb.GetFValue());
@@ -2598,8 +2600,10 @@ bool GCodes::HandleMcode(GCodeBuffer& gb, StringRef& reply)
}
if (!seen)
{
- reply.printf("Extrusion ancillary PWM %.3f on pin %u",
- platform->GetExtrusionAncilliaryPwmValue(), platform->GetExtrusionAncilliaryPwmPin());
+ reply.printf("Extrusion ancillary PWM %.3f at %.1fHz on pin %u",
+ platform->GetExtrusionAncilliaryPwmValue(),
+ platform->GetExtrusionAncilliaryPwmFrequency(),
+ platform->GetExtrusionAncilliaryPwmPin());
}
}
break;
diff --git a/src/Movement/DDA.cpp b/src/Movement/DDA.cpp
index a42ac642..6456d6e2 100644
--- a/src/Movement/DDA.cpp
+++ b/src/Movement/DDA.cpp
@@ -240,6 +240,7 @@ bool DDA::Init(const GCodes::RawMove &nextMove, bool doMotorMapping)
// 3. Store some values
endStopsToCheck = nextMove.endStopsToCheck;
+ canPauseAfter = nextMove.canPauseAfter;
filePos = nextMove.filePos;
usePressureAdvance = nextMove.usePressureAdvance;
hadLookaheadUnderrun = false;
@@ -564,15 +565,14 @@ void DDA::RecalculateMove()
topSpeed = requestedSpeed;
}
- canPause = (endStopsToCheck == 0);
- if (canPause && endSpeed != 0.0)
+ if (canPauseAfter && endSpeed != 0.0)
{
const Platform * const p = reprap.GetPlatform();
for (size_t drive = 0; drive < DRIVES; ++drive)
{
if (ddm[drive].state == DMState::moving && endSpeed * fabsf(directionVector[drive]) > p->ActualInstantDv(drive))
{
- canPause = false;
+ canPauseAfter = false;
break;
}
}
@@ -724,44 +724,6 @@ void DDA::Prepare()
float decelStartTime = accelStopTime + (params.decelStartDistance - accelDistance)/topSpeed;
float totalTime = decelStartTime + (topSpeed - endSpeed)/acceleration;
- // Enforce the maximum average acceleration
- if (isPrintingMove && topSpeed > startSpeed && topSpeed > endSpeed)
- {
- const float maxAverageAcceleration = reprap.GetPlatform()->GetMaxAverageAcceleration();
- if (2 * topSpeed - startSpeed - endSpeed > totalTime * maxAverageAcceleration)
- {
- // Reduce the top speed to comply with the maximum average acceleration
- const float a2 = fsquare(acceleration);
- const float am2 = fsquare(maxAverageAcceleration);
- const float aam = acceleration * maxAverageAcceleration;
- const float discriminant = (a2 + (2 * aam) - am2) * (fsquare(startSpeed) + fsquare(endSpeed))
- + (2 * a2 + 2 * am2 - 4 * aam) * startSpeed * endSpeed
- + (8 * a2 * maxAverageAcceleration - 4 * acceleration * am2) * totalDistance;
- const float oldTopSpeed = topSpeed;
- if (discriminant < 0.0)
- {
- topSpeed = max<float>(startSpeed, endSpeed);
- }
- else
- {
- const float temp = (sqrtf(discriminant) + (acceleration - maxAverageAcceleration) * (startSpeed + endSpeed))
- /(4 * acceleration - 2 * maxAverageAcceleration);
- topSpeed = max<float>(max<float>(temp, startSpeed), endSpeed);
- }
-
- //DEBUG
- debugPrintf("ots %f nts %f ss %f es %f\n", oldTopSpeed, topSpeed, startSpeed, endSpeed);
-
- // Recalculate parameters
- accelDistance = (fsquare(topSpeed) - fsquare(startSpeed))/(2 * acceleration);
- decelDistance = (fsquare(topSpeed) - fsquare(endSpeed))/(2 * acceleration);
- params.decelStartDistance = totalDistance - decelDistance;
- accelStopTime = (topSpeed - startSpeed)/acceleration;
- decelStartTime = accelStopTime + (params.decelStartDistance - accelDistance)/topSpeed;
- totalTime = decelStartTime + (topSpeed - endSpeed)/acceleration;
- }
- }
-
clocksNeeded = (uint32_t)(totalTime * stepClockRate);
params.startSpeedTimesCdivA = (uint32_t)((startSpeed * stepClockRate)/acceleration);
diff --git a/src/Movement/DDA.h b/src/Movement/DDA.h
index 642a1526..e0ceb1d6 100644
--- a/src/Movement/DDA.h
+++ b/src/Movement/DDA.h
@@ -47,7 +47,7 @@ public:
void Prepare(); // Calculate all the values and freeze this DDA
float CalcTime() const; // Calculate the time needed for this move (used for simulation)
bool HasStepError() const;
- bool CanPause() const { return canPause; }
+ bool CanPauseAfter() const { return canPauseAfter; }
bool IsPrintingMove() const { return isPrintingMove; } // Return true if this involves both XY movement and extrusion
DDAState GetState() const { return state; }
@@ -117,7 +117,7 @@ private:
volatile DDAState state; // what state this DDA is in
uint8_t endCoordinatesValid : 1; // True if endCoordinates can be relied on
uint8_t isDeltaMovement : 1; // True if this is a delta printer movement
- uint8_t canPause : 1; // True if we can pause at the end of this move
+ uint8_t canPauseAfter : 1; // True if we can pause at the end of this move
uint8_t goingSlow : 1; // True if we have reduced speed during homing
uint8_t isPrintingMove : 1; // True if this move includes XY movement and extrusion
uint8_t usePressureAdvance : 1; // True if pressure advance should be applied to any forward extrusion
diff --git a/src/Movement/Move.cpp b/src/Movement/Move.cpp
index e9ed842d..278ecc8d 100644
--- a/src/Movement/Move.cpp
+++ b/src/Movement/Move.cpp
@@ -46,6 +46,7 @@ void Move::Init()
currentDda = nullptr;
addNoMoreMoves = false;
+ babysteppingLeft = 0.0;
stepErrors = 0;
numLookaheadUnderruns = numPrepareUnderruns = 0;
@@ -311,11 +312,13 @@ FilePosition Move::PausePrint(float positions[DRIVES], float& pausedFeedRate, ui
const DDA *savedDdaRingAddPointer = ddaRingAddPointer;
cpu_irq_disable();
DDA *dda = currentDda;
+ FilePosition fPos = noFilePosition;
if (dda != nullptr)
{
// A move is being executed. See if we can safely pause at the end of it.
- if (dda->CanPause())
+ if (dda->CanPauseAfter())
{
+ fPos = dda->GetFilePosition();
ddaRingAddPointer = dda->GetNext();
}
else
@@ -325,8 +328,9 @@ FilePosition Move::PausePrint(float positions[DRIVES], float& pausedFeedRate, ui
dda = ddaRingGetPointer;
while (dda != ddaRingAddPointer)
{
- if (dda->CanPause())
+ if (dda->CanPauseAfter())
{
+ fPos = dda->GetFilePosition();
ddaRingAddPointer = dda->GetNext();
if (ddaRingAddPointer->GetState() == DDA::frozen)
{
@@ -347,8 +351,6 @@ FilePosition Move::PausePrint(float positions[DRIVES], float& pausedFeedRate, ui
cpu_irq_enable();
- FilePosition fPos = noFilePosition;
-
if (ddaRingAddPointer != savedDdaRingAddPointer)
{
const size_t numAxes = reprap.GetGCodes()->GetNumAxes();
@@ -372,10 +374,6 @@ FilePosition Move::PausePrint(float positions[DRIVES], float& pausedFeedRate, ui
{
positions[drive] += dda->GetEndCoordinate(drive, true); // update the amount of extrusion we are going to skip
}
- if (fPos == noFilePosition)
- {
- fPos = dda->GetFilePosition();
- }
(void)dda->Free();
dda = dda->GetNext();
}
@@ -389,6 +387,13 @@ FilePosition Move::PausePrint(float positions[DRIVES], float& pausedFeedRate, ui
return fPos;
}
+// Request babystepping
+void Move::Babystep(float zMovement)
+{
+ babysteppingLeft += zMovement;
+ // TODO use this value somewhere
+}
+
uint32_t maxReps = 0;
#if 0
@@ -402,7 +407,7 @@ void Move::Diagnostics(MessageType mtype)
Platform * const p = reprap.GetPlatform();
p->Message(mtype, "=== Move ===\n");
p->MessageF(mtype, "MaxReps: %u, StepErrors: %u, MaxWait: %ums, Underruns: %u, %u\n",
- maxReps, stepErrors, longestGcodeWaitInterval, numLookaheadUnderruns, numPrepareUnderruns);
+ maxReps, stepErrors, longestGcodeWaitInterval, numLookaheadUnderruns, numPrepareUnderruns);
maxReps = 0;
numLookaheadUnderruns = numPrepareUnderruns = 0;
longestGcodeWaitInterval = 0;
diff --git a/src/Movement/Move.h b/src/Movement/Move.h
index 698fae2f..ad946261 100644
--- a/src/Movement/Move.h
+++ b/src/Movement/Move.h
@@ -117,6 +117,7 @@ public:
void UseHeightMap(bool b) { useGridHeights = b; } // Start or stop using the height map
bool UsingHeightMap() const { return useGridHeights; } // Are we doing grid bed compensation?
+ void Babystep(float zMovement); // Request babystepping
private:
@@ -192,6 +193,8 @@ private:
int coreXYMode; // 0 = Cartesian, 1 = CoreXY, 2 = CoreXZ, 3 = CoreYZ
float axisFactors[MAX_AXES]; // How much further the motors need to move for each axis movement, on a CoreXY/CoreXZ/CoreYZ machine
unsigned int stepErrors; // count of step errors, for diagnostics
+
+ float babysteppingLeft; // the amount of Z babystepping left to do
};
//******************************************************************************************************
diff --git a/src/Platform.cpp b/src/Platform.cpp
index 3fb43cf9..95ca1edf 100644
--- a/src/Platform.cpp
+++ b/src/Platform.cpp
@@ -227,8 +227,6 @@ void Platform::Init()
stepperDacVoltageOffset = STEPPER_DAC_VOLTAGE_OFFSET;
#endif
- maxAverageAcceleration = 10000.0; // high enough to have no effect until it is changed
-
// Z PROBE
zProbePin = Z_PROBE_PIN;
zProbeAdcChannel = PinToAdcChannel(zProbePin);
@@ -326,12 +324,17 @@ void Platform::Init()
TMC2660::Init(ENABLE_PINS, numTMC2660Drivers);
#endif
+ // Allow extrusion ancilliary PWM to use FAN0 even if FAN0 has not been disabled, for backwards compatibility
extrusionAncilliaryPwmValue = 0.0;
- extrusionAncilliaryPwmLogicalPin = -1;
- extrusionAncilliaryPwmFirmwarePin = NoPin;
- extrusionAncilliaryPwmInvert = false;
- SetExtrusionAncilliaryPwmPin(Fan0LogicalPin);
-
+ extrusionAncilliaryPwmFrequency = DefaultPinWritePwmFreq;
+ extrusionAncilliaryPwmLogicalPin = Fan0LogicalPin;
+ extrusionAncilliaryPwmFirmwarePin = COOLING_FAN_PINS[0];
+ extrusionAncilliaryPwmInvert =
+#if defined(DUET_NG) || defined(__RADDS__)
+ false;
+#else
+ (board == BoardType::Duet_06 || board == BoardType::Duet_07);
+#endif
ARRAY_INIT(tempSensePins, TEMP_SENSE_PINS);
ARRAY_INIT(heatOnPins, HEAT_ON_PINS);
ARRAY_INIT(spiTempSenseCsPins, SpiTempSensorCsPins);
@@ -1243,14 +1246,41 @@ void Platform::SoftwareReset(uint16_t reason)
reason |= (uint16_t)reprap.GetSpinningModule();
// Record the reason for the software reset
- SoftwareResetData temp;
- temp.magic = SoftwareResetData::magicValue;
- temp.version = SoftwareResetData::versionValue;
- temp.resetReason = reason;
- GetStackUsage(NULL, NULL, &temp.neverUsedRam);
+ // First find a free slot (wear levelling)
+ size_t slot = SoftwareResetData::numberOfSlots;
+ SoftwareResetData srdBuf[SoftwareResetData::numberOfSlots];
+
+#ifdef DUET_NG
+ if (flash_read_user_signature(reinterpret_cast<uint32_t*>(srdBuf), sizeof(srdBuf)/sizeof(uint32_t)) == FLASH_RC_OK)
+#else
+ DueFlashStorage::read(SoftwareResetData::nvAddress, srdBuf, sizeof(srdBuf));
+#endif
+ {
+ while (slot != 0 && srdBuf[slot - 1].isVacant())
+ {
+ --slot;
+ }
+ }
+
+ if (slot == SoftwareResetData::numberOfSlots)
+ {
+ // No free slots, so erase the area
+#ifdef DUET_NG
+ flash_erase_user_signature();
+#endif
+ memset(srdBuf, 0xFF, sizeof(srdBuf));
+ slot = 0;
+ }
+ srdBuf[slot].magic = SoftwareResetData::magicValue;
+ srdBuf[slot].resetReason = reason;
+ GetStackUsage(NULL, NULL, &srdBuf[slot].neverUsedRam);
- // Save diagnostics data to Flash and reset the software
- DueFlashStorage::write(SoftwareResetData::nvAddress, &temp, sizeof(SoftwareResetData));
+ // Save diagnostics data to Flash
+#ifdef DUET_NG
+ flash_write_user_signature(srdBuf, sizeof(srdBuf)/sizeof(uint32_t));
+#else
+ DueFlashStorage::write(SoftwareResetData::nvAddress, srdBuf, sizeof(srdBuf));
+#endif
}
Reset();
for(;;) {}
@@ -1365,7 +1395,7 @@ void Platform::Diagnostics(MessageType mtype)
MessageF(mtype, "Program static ram used: %d\n", &_end - ramstart);
MessageF(mtype, "Dynamic ram used: %d\n", mi.uordblks);
MessageF(mtype, "Recycled dynamic ram: %d\n", mi.fordblks);
- size_t currentStack, maxStack, neverUsed;
+ uint32_t currentStack, maxStack, neverUsed;
GetStackUsage(&currentStack, &maxStack, &neverUsed);
MessageF(mtype, "Current stack ram used: %d\n", currentStack);
MessageF(mtype, "Maximum stack ram used: %d\n", maxStack);
@@ -1373,20 +1403,40 @@ void Platform::Diagnostics(MessageType mtype)
// Show the up time and reason for the last reset
const uint32_t now = (uint32_t)Time(); // get up time in seconds
- const char* resetReasons[8] = { "power up", "backup", "watchdog", "software", "external", "?", "?", "?" };
+ const char* resetReasons[8] = { "power up", "backup", "watchdog", "software", "reset button", "?", "?", "?" };
MessageF(mtype, "Last reset %02d:%02d:%02d ago, cause: %s\n",
(unsigned int)(now/3600), (unsigned int)((now % 3600)/60), (unsigned int)(now % 60),
resetReasons[(REG_RSTC_SR & RSTC_SR_RSTTYP_Msk) >> RSTC_SR_RSTTYP_Pos]);
// Show the reset code stored at the last software reset
+ Message(mtype, "Last software reset code & available RAM: ");
{
- SoftwareResetData temp;
- temp.magic = 0;
- DueFlashStorage::read(SoftwareResetData::nvAddress, &temp, sizeof(SoftwareResetData));
- if (temp.magic == SoftwareResetData::magicValue && temp.version == SoftwareResetData::versionValue)
+ SoftwareResetData srdBuf[SoftwareResetData::numberOfSlots];
+ memset(srdBuf, 0, sizeof(srdBuf));
+ int slot = -1;
+
+#ifdef DUET_NG
+ if (flash_read_user_signature(reinterpret_cast<uint32_t*>(srdBuf), sizeof(srdBuf)/sizeof(uint32_t)) == FLASH_RC_OK)
+#else
+ DueFlashStorage::read(SoftwareResetData::nvAddress, srdBuf, sizeof(srdBuf));
+#endif
+ {
+ // Find the last slot written
+ slot = SoftwareResetData::numberOfSlots - 1;
+ while (slot >= 0 && srdBuf[slot].magic == 0xFFFF)
+ {
+ --slot;
+ }
+ }
+
+ if (slot >= 0 && srdBuf[slot].magic == SoftwareResetData::magicValue)
{
- MessageF(mtype, "Last software reset code & available RAM: 0x%04x, %u\n", temp.resetReason, temp.neverUsedRam);
- MessageF(mtype, "Spinning module during software reset: %s\n", moduleName[temp.resetReason & 0x0F]);
+ MessageF(mtype, "0x%04x, %u (slot %d)\n", srdBuf[slot].resetReason, srdBuf[slot].neverUsedRam, slot);
+ MessageF(mtype, "Spinning module during software reset: %s\n", moduleName[srdBuf[slot].resetReason & 0x0F]);
+ }
+ else
+ {
+ Message(mtype, "not available\n");
}
}
@@ -1447,13 +1497,18 @@ void Platform::Diagnostics(MessageType mtype)
#endif
// Show current RTC time
+ Message(mtype, "Current date and time: ");
struct tm timeInfo;
if (gmtime_r(&realTime, &timeInfo) != nullptr)
{
- MessageF(mtype, "Current date and time: %04u-%02u-%02u %02u:%02u:%02u\n",
+ MessageF(mtype, "%04u-%02u-%02u %02u:%02u:%02u\n",
timeInfo.tm_year + 1900, timeInfo.tm_mon + 1, timeInfo.tm_mday,
timeInfo.tm_hour, timeInfo.tm_min, timeInfo.tm_sec);
}
+ else
+ {
+ Message(mtype, "clock not set\n");
+ }
// Debug
//MessageF(mtype, "TC_FMR = %08x, PWM_FPE = %08x, PWM_FSR = %08x\n", TC2->TC_FMR, PWM->PWM_FPE, PWM->PWM_FSR);
@@ -1503,24 +1558,24 @@ void Platform::DiagnosticTest(int d)
}
// Return the stack usage and amount of memory that has never been used, in bytes
-void Platform::GetStackUsage(size_t* currentStack, size_t* maxStack, size_t* neverUsed) const
+void Platform::GetStackUsage(uint32_t* currentStack, uint32_t* maxStack, uint32_t* neverUsed) const
{
- const char *ramend = (const char *)
-#ifdef DUET_NG
- 0x20020000; // 0x20000000 + 128Kb
+ const char * const ramend = (const char *)
+#if SAM4E
+ IRAM_ADDR + IRAM_SIZE;
#else
- 0x20088000; // 0x20070000 + 96Kb
+ IRAM0_ADDR + IRAM_SIZE;
#endif
register const char * stack_ptr asm ("sp");
- const char *heapend = sbrk(0);
- const char* stack_lwm = heapend;
+ const char * const heapend = sbrk(0);
+ const char * stack_lwm = heapend;
while (stack_lwm < stack_ptr && *stack_lwm == memPattern)
{
++stack_lwm;
}
- if (currentStack) { *currentStack = ramend - stack_ptr; }
- if (maxStack) { *maxStack = ramend - stack_lwm; }
- if (neverUsed) { *neverUsed = stack_lwm - heapend; }
+ if (currentStack != nullptr) { *currentStack = ramend - stack_ptr; }
+ if (maxStack != nullptr) { *maxStack = ramend - stack_lwm; }
+ if (neverUsed != nullptr) { *neverUsed = stack_lwm - heapend; }
}
void Platform::ClassReport(float &lastTime)
@@ -2541,11 +2596,11 @@ void Platform::SetBoardType(BoardType bt)
#else
// Determine whether this is a Duet 0.6 or a Duet 0.8.5 board.
// If it is a 0.85 board then DAC0 (AKA digital pin 67) is connected to ground via a diode and a 2.15K resistor.
- // So we enable the pullup (value 150K-150K) on pin 67 and read it, expecting a LOW on a 0.8.5 board and a HIGH on a 0.6 board.
+ // So we enable the pullup (value 100K-150K) on pin 67 and read it, expecting a LOW on a 0.8.5 board and a HIGH on a 0.6 board.
// This may fail if anyone connects a load to the DAC0 pin on a Duet 0.6, hence we implement board selection in M115 as well.
pinMode(Dac0DigitalPin, INPUT_PULLUP);
board = (digitalRead(Dac0DigitalPin)) ? BoardType::Duet_06 : BoardType::Duet_085;
- pinMode(Dac0DigitalPin, INPUT); // turn pullup off
+ pinMode(Dac0DigitalPin, INPUT); // turn pullup off
#endif
}
else
@@ -2628,6 +2683,9 @@ bool Platform::GetFirmwarePin(int logicalPin, PinAccess access, Pin& firmwarePin
)
{
firmwarePin = COOLING_FAN_PINS[logicalPin - Fan0LogicalPin];
+#if !defined(DUET_NG) && !defined(__RADDS__)
+ invert = (board == BoardType::Duet_06 || board == BoardType::Duet_07);
+#endif
}
}
else if (logicalPin >= EndstopXLogicalPin && logicalPin < EndstopXLogicalPin + (int)ARRAY_SIZE(endStopPins)) // pins 40-49 correspond to endstop pins
diff --git a/src/Platform.h b/src/Platform.h
index 8c9af3cb..86668c7a 100644
--- a/src/Platform.h
+++ b/src/Platform.h
@@ -509,10 +509,6 @@ public:
float Acceleration(size_t drive) const;
const float* Accelerations() const;
void SetAcceleration(size_t drive, float value);
- const float GetMaxAverageAcceleration() const
- { return maxAverageAcceleration; }
- void SetMaxAverageAcceleration(float f)
- { maxAverageAcceleration = f; }
float MaxFeedrate(size_t drive) const;
const float* MaxFeedrates() const;
void SetMaxFeedrate(size_t drive, float value);
@@ -567,6 +563,8 @@ public:
void SetExtrusionAncilliaryPwmValue(float v);
float GetExtrusionAncilliaryPwmValue() const;
+ void SetExtrusionAncilliaryPwmFrequency(float f);
+ float GetExtrusionAncilliaryPwmFrequency() const;
bool SetExtrusionAncilliaryPwmPin(int logicalPin);
int GetExtrusionAncilliaryPwmPin() const { return extrusionAncilliaryPwmLogicalPin; }
void ExtrudeOn();
@@ -681,31 +679,41 @@ private:
static float AdcReadingToPowerVoltage(uint16_t reading);
#endif
- // These are the structures used to hold out non-volatile data.
- // The SAM3X doesn't have EEPROM so we save the data to flash. This unfortunately means that it gets cleared
+ // These are the structures used to hold our non-volatile data.
+ // The SAM3X and SAM4E don't have EEPROM so we save the data to flash. This unfortunately means that it gets cleared
// every time we reprogram the firmware via bossa, but it can be retained when firmware updates are performed
// via the web interface. That's why it's a good idea to implement versioning here - increase these values
// whenever the fields of the following structs have changed.
-
+ //
+ // The SAM4E has a large page erase size (8K). For this reason we store the software reset data in the 512-byte user signature area
+ // instead, which doesn't get cleared when the Erase button is pressed. The SoftareResetData struct must have at least one 32-bit
+ // field to guarantee that values of this type will be 32-bit aligned. It must have no virtual members because it is read/written
+ // directly form/to flash memory.
struct SoftwareResetData
{
- static const uint16_t magicValue = 0x7C5F; // value we use to recognise that all the flash data has been written
- static const uint16_t versionValue = 1; // increment this whenever this struct changes
+ static const uint16_t versionValue = 2; // increment this whenever this struct changes
+ static const uint16_t magicValue = 0x7D00 | versionValue; // value we use to recognise that all the flash data has been written
static const uint32_t nvAddress = 0; // must be 4-byte aligned
+ static const size_t numberOfSlots = 8; // number of storage slots used to implement wear levelling
- uint16_t magic;
- uint16_t version;
-
+ uint16_t magic; // the magic number, including the version
uint16_t resetReason; // this records why we did a software reset, for diagnostic purposes
- uint16_t dummy; // padding to align the next field (should happen automatically I think)
- size_t neverUsedRam; // the amount of never used RAM at the last abnormal software reset
+ uint32_t neverUsedRam; // the amount of never used RAM at the last abnormal software reset
+
+ bool isVacant() const // return true if this struct can be written without erasing it first
+ {
+ return magic == 0xFFFF && resetReason == 0xFFFF && neverUsedRam == 0xFFFFFFFF;
+ }
};
+ static_assert(SoftwareResetData::numberOfSlots * sizeof(SoftwareResetData) <= 512, "Can't fit software reset data in SAM4E user signature area");
+
+ // The following struct is due to be replaced by the config-override.g file.
struct FlashData
{
static const uint16_t magicValue = 0xE6C4; // value we use to recognise that the flash data has been written
static const uint16_t versionValue = 5; // increment this whenever this struct changes
- static const uint32_t nvAddress = (SoftwareResetData::nvAddress + sizeof(SoftwareResetData) + 3) & (~3);
+ static const uint32_t nvAddress = SoftwareResetData::nvAddress + (SoftwareResetData::numberOfSlots * sizeof(SoftwareResetData));
uint16_t magic;
uint16_t version;
@@ -742,7 +750,7 @@ private:
uint32_t errorCodeBits;
void InitialiseInterrupts();
- void GetStackUsage(size_t* currentStack, size_t* maxStack, size_t* neverUsed) const;
+ void GetStackUsage(uint32_t* currentStack, uint32_t* maxStack, uint32_t* neverUsed) const;
// DRIVES
@@ -770,7 +778,6 @@ private:
uint32_t slowDriverStepPulseClocks; // minimum high and low step pulse widths, in processor clocks
uint32_t slowDrivers; // bitmap of driver port bits that need extended step pulse timing
float idleCurrentFactor;
- float maxAverageAcceleration;
#if defined(DUET_NG)
size_t numTMC2660Drivers; // the number of TMC2660 drivers we have, the remaining are simple enable/step/dir drivers
@@ -793,6 +800,7 @@ private:
volatile ThermistorAveragingFilter thermistorFilters[HEATERS]; // bed and extruder thermistor readings
float extrusionAncilliaryPwmValue;
+ float extrusionAncilliaryPwmFrequency;
int extrusionAncilliaryPwmLogicalPin;
Pin extrusionAncilliaryPwmFirmwarePin;
bool extrusionAncilliaryPwmInvert;
@@ -1125,6 +1133,16 @@ inline float Platform::GetExtrusionAncilliaryPwmValue() const
return extrusionAncilliaryPwmValue;
}
+inline void Platform::SetExtrusionAncilliaryPwmFrequency(float f)
+{
+ extrusionAncilliaryPwmFrequency = f;
+}
+
+inline float Platform::GetExtrusionAncilliaryPwmFrequency() const
+{
+ return extrusionAncilliaryPwmFrequency;
+}
+
// For the Duet we use the fan output for this
// DC 2015-03-21: To allow users to control the cooling fan via gcodes generated by slic3r etc.,
// only turn the fan on/off if the extruder ancilliary PWM has been set nonzero.
@@ -1133,7 +1151,8 @@ inline void Platform::ExtrudeOn()
{
if (extrusionAncilliaryPwmValue > 0.0)
{
- WriteAnalog(extrusionAncilliaryPwmFirmwarePin, extrusionAncilliaryPwmValue, DefaultPinWritePwmFreq);
+ WriteAnalog(extrusionAncilliaryPwmFirmwarePin,
+ (extrusionAncilliaryPwmInvert) ? 1.0 - extrusionAncilliaryPwmValue : extrusionAncilliaryPwmValue, extrusionAncilliaryPwmFrequency);
}
}
@@ -1144,7 +1163,8 @@ inline void Platform::ExtrudeOff()
{
if (extrusionAncilliaryPwmValue > 0.0)
{
- WriteAnalog(extrusionAncilliaryPwmFirmwarePin, 0.0, DefaultPinWritePwmFreq);
+ WriteAnalog(extrusionAncilliaryPwmFirmwarePin,
+ (extrusionAncilliaryPwmInvert) ? 1.0 : 0.0, extrusionAncilliaryPwmFrequency);
}
}
diff --git a/src/Tool.cpp b/src/Tool.cpp
index 5c6dd0be..e5e4bcbe 100644
--- a/src/Tool.cpp
+++ b/src/Tool.cpp
@@ -306,15 +306,22 @@ void Tool::SetVariables(const float* standby, const float* active)
else
{
const float temperatureLimit = reprap.GetHeat()->GetTemperatureLimit(heaters[heater]);
+ const Tool * const currentTool = reprap.GetCurrentTool();
if (active[heater] < temperatureLimit)
{
activeTemperatures[heater] = active[heater];
- reprap.GetHeat()->SetActiveTemperature(heaters[heater], activeTemperatures[heater]);
+ if (currentTool == nullptr || currentTool == this)
+ {
+ reprap.GetHeat()->SetActiveTemperature(heaters[heater], activeTemperatures[heater]);
+ }
}
if (standby[heater] < temperatureLimit)
{
standbyTemperatures[heater] = standby[heater];
- reprap.GetHeat()->SetStandbyTemperature(heaters[heater], standbyTemperatures[heater]);
+ if (currentTool == nullptr || currentTool == this)
+ {
+ reprap.GetHeat()->SetStandbyTemperature(heaters[heater], standbyTemperatures[heater]);
+ }
}
}
}