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
diff options
context:
space:
mode:
authorDavid Crocker <dcrocker@eschertech.com>2021-06-13 01:21:27 +0300
committerDavid Crocker <dcrocker@eschertech.com>2021-06-13 01:21:27 +0300
commita7fde45b618c76c03516696d670dd665282873da (patch)
tree250ec090839017aeac12e7cefa9d1f19dea35835
parent92b7d130d974b6b62780e68d32717a7c6567db6e (diff)
Various
Support layer counting in GCode files generated by SuperSlicer When reporting a bad command, display any non-printing characters in hex Support measuring fan RPMs down to 160 instead of down to 320 After turning a remote heater on, if it was previously off then set its status to 'heating' pending receiving updated status for it, to make sure that M116 waits for it
-rw-r--r--src/CAN/CanInterface.cpp40
-rw-r--r--src/CAN/CanInterface.h3
-rw-r--r--src/CAN/CanMotion.cpp10
-rw-r--r--src/Fans/LocalFan.h2
-rw-r--r--src/GCodes/GCodeBuffer/StringParser.cpp16
-rw-r--r--src/GCodes/GCodeBuffer/StringParser.h2
-rw-r--r--src/GCodes/GCodes3.cpp28
-rw-r--r--src/Heating/RemoteHeater.cpp9
-rw-r--r--src/Movement/DDA.cpp2
-rw-r--r--src/Movement/DDA.h10
-rw-r--r--src/Movement/DDARing.cpp7
-rw-r--r--src/Platform/TaskPriorities.h4
-rw-r--r--src/PrintMonitor/PrintMonitor.cpp8
-rw-r--r--src/PrintMonitor/PrintMonitor.h1
-rw-r--r--src/Version.h2
15 files changed, 105 insertions, 39 deletions
diff --git a/src/CAN/CanInterface.cpp b/src/CAN/CanInterface.cpp
index 764a73c2..710f14e9 100644
--- a/src/CAN/CanInterface.cpp
+++ b/src/CAN/CanInterface.cpp
@@ -179,8 +179,12 @@ static Task<CanReceiverTaskStackWords> canReceiverTask;
constexpr size_t CanClockTaskStackWords = 400; // used to be 300 but RD had a stack overflow
static Task<CanSenderTaskStackWords> canClockTask;
-static CanMessageBuffer * volatile pendingBuffers;
-static CanMessageBuffer * volatile lastBuffer; // only valid when pendingBuffers != nullptr
+static CanMessageBuffer * volatile pendingMotionBuffers = nullptr;
+static CanMessageBuffer * volatile lastMotionBuffer; // only valid when pendingBuffers != nullptr
+
+#if 0 //unused
+static unsigned int numPendingMotionBuffers = 0;
+#endif
extern "C" [[noreturn]] void CanSenderLoop(void *) noexcept;
extern "C" [[noreturn]] void CanClockLoop(void *) noexcept;
@@ -239,7 +243,7 @@ void TxCallback(uint8_t marker, CanId id, uint16_t timeStamp) noexcept
void CanInterface::Init() noexcept
{
CanMessageBuffer::Init(NumCanBuffers);
- pendingBuffers = nullptr;
+ pendingMotionBuffers = nullptr;
transactionMutex.Create("CanTrans");
@@ -369,13 +373,16 @@ extern "C" [[noreturn]] void CanSenderLoop(void *) noexcept
{
can0dev->SendMessage(TxBufferIndexUrgent, MaxUrgentSendWait, urgentMessage);
}
- else if (pendingBuffers != nullptr)
+ else if (pendingMotionBuffers != nullptr)
{
CanMessageBuffer *buf;
{
TaskCriticalSectionLocker lock;
- buf = pendingBuffers;
- pendingBuffers = buf->next;
+ buf = pendingMotionBuffers;
+ pendingMotionBuffers = buf->next;
+#if 0 //unused
+ --numPendingMotionBuffers;
+#endif
}
// Send the message
@@ -617,20 +624,33 @@ void CanInterface::SendMotion(CanMessageBuffer *buf) noexcept
{
TaskCriticalSectionLocker lock;
- if (pendingBuffers == nullptr)
+ if (pendingMotionBuffers == nullptr)
{
- pendingBuffers = buf;
+ pendingMotionBuffers = buf;
}
else
{
- lastBuffer->next = buf;
+ lastMotionBuffer->next = buf;
}
- lastBuffer = buf;
+ lastMotionBuffer = buf;
+#if 0 //unused
+ ++numPendingMotionBuffers;
+#endif
}
canSenderTask.Give();
}
+#if 0 // not currently used
+
+// Get the number of motion messages waiting to be sent through the Tx fifo
+unsigned int CanInterface::GetNumPendingMotionMessages() noexcept
+{
+ return can0dev->NumTxMessagesPending(TxBufferIndexMotion) + numPendingMotionBuffers;
+}
+
+#endif
+
// Send a request to an expansion board and append the response to 'reply'
GCodeResult CanInterface::SendRequestAndGetStandardReply(CanMessageBuffer *buf, CanRequestId rid, const StringRef& reply, uint8_t *extra) noexcept
{
diff --git a/src/CAN/CanInterface.h b/src/CAN/CanInterface.h
index 50aecfd7..8ee3b0b1 100644
--- a/src/CAN/CanInterface.h
+++ b/src/CAN/CanInterface.h
@@ -106,6 +106,9 @@ namespace CanInterface
GCodeResult SetRemoteDriverStepsPerMmAndMicrostepping(const CanDriversData<StepsPerUnitAndMicrostepping>& data, const StringRef& reply) noexcept;
GCodeResult ConfigureRemoteDriver(DriverId driver, GCodeBuffer& gb, const StringRef& reply) THROWS(GCodeException);
GCodeResult GetSetRemoteDriverStallParameters(const CanDriversList& drivers, GCodeBuffer& gb, const StringRef& reply, OutputBuffer *& buf) THROWS(GCodeException);
+#if 0 // not currently used
+ unsigned int GetNumPendingMotionMessages() noexcept;
+#endif
void WakeAsyncSenderFromIsr() noexcept;
// Remote handle functions
diff --git a/src/CAN/CanMotion.cpp b/src/CAN/CanMotion.cpp
index 6c8e72b6..c1c82dc2 100644
--- a/src/CAN/CanMotion.cpp
+++ b/src/CAN/CanMotion.cpp
@@ -17,6 +17,10 @@ static CanMessageBuffer *movementBufferList = nullptr;
static CanMessageBuffer *urgentMessageBuffer = nullptr;
static uint32_t currentMoveClocks;
+#if 0
+static unsigned int numMotionMessagesSentLast = 0;
+#endif
+
static volatile uint32_t hiccupToInsert = 0;
static CanDriversList driversToStop[2];
static size_t driversToStopIndexBeingFilled = 0;
@@ -128,6 +132,9 @@ uint32_t CanMotion::FinishMovement(uint32_t moveStartTime) noexcept
return 0;
}
+#if 0
+ numMotionMessagesSentLast = 0;
+#endif
do
{
boardsActiveInLastMove.SetBit(buf->id.Dst()); //TODO should we set this if there were no steps for drives on the board, just drives to be enabled?
@@ -138,6 +145,9 @@ uint32_t CanMotion::FinishMovement(uint32_t moveStartTime) noexcept
buf->dataLength = buf->msg.moveLinear.GetActualDataLength();
CanMessageBuffer * const nextBuffer = buf->next; // must get this before sending the buffer, because sending the buffer releases it
CanInterface::SendMotion(buf); // queues the buffer for sending and frees it when done
+#if 0
+ ++numMotionMessagesSentLast;
+#endif
buf = nextBuffer;
} while (buf != nullptr);
diff --git a/src/Fans/LocalFan.h b/src/Fans/LocalFan.h
index 469053a7..7178833f 100644
--- a/src/Fans/LocalFan.h
+++ b/src/Fans/LocalFan.h
@@ -46,7 +46,7 @@ private:
float lastVal; // the last PWM value we sent to the fan, not allowing for blipping, or -1 if we don't know it
// Variables used to read the tacho
- static constexpr uint32_t fanMaxInterruptCount = 32; // number of fan interrupts that we average over
+ static constexpr uint32_t fanMaxInterruptCount = 16; // number of fan interrupts that we average over. We time out after 3 seconds, so a count of 16 allows us to read rpm down to (16/3) * (60/2) = 160.
uint32_t fanInterruptCount; // accessed only in ISR, so no need to declare it volatile
volatile uint32_t fanLastResetTime; // time (in step clocks) at which we last reset the interrupt count, accessed inside and outside ISR
volatile uint32_t fanInterval; // written by ISR, read outside the ISR
diff --git a/src/GCodes/GCodeBuffer/StringParser.cpp b/src/GCodes/GCodeBuffer/StringParser.cpp
index abf822e5..8b4df0f0 100644
--- a/src/GCodes/GCodeBuffer/StringParser.cpp
+++ b/src/GCodes/GCodeBuffer/StringParser.cpp
@@ -266,7 +266,7 @@ bool StringParser::Put(char c) noexcept
// This is called when we are fed a null, CR or LF character.
// Return true if there is a completed command ready to be executed.
-bool StringParser::LineFinished()
+bool StringParser::LineFinished() noexcept
{
if (hadLineNumber)
{
@@ -1486,9 +1486,21 @@ void StringParser::PrintCommand(const StringRef& s) const noexcept
}
// Append the full command content to a string
+// This is called when we report a "Bad command" error, so make sure we display any control characters.
void StringParser::AppendFullCommand(const StringRef &s) const noexcept
{
- s.cat(gb.buffer);
+ for (size_t i = commandStart; i < commandEnd; ++i)
+ {
+ const char c = gb.buffer[i];
+ if (c < 0x20)
+ {
+ s.catf("[0x%02x]", (unsigned int)c);
+ }
+ else
+ {
+ s.cat(c);
+ }
+ }
}
// Called when we start a new file
diff --git a/src/GCodes/GCodeBuffer/StringParser.h b/src/GCodes/GCodeBuffer/StringParser.h
index a4b828fe..3e7c515b 100644
--- a/src/GCodes/GCodeBuffer/StringParser.h
+++ b/src/GCodes/GCodeBuffer/StringParser.h
@@ -92,7 +92,7 @@ private:
void AddToChecksum(char c) noexcept;
void StoreAndAddToChecksum(char c) noexcept;
- bool LineFinished() THROWS(GCodeException); // Deal with receiving end-of-line and return true if we have a command
+ bool LineFinished() noexcept; // Deal with receiving end-of-line and return true if we have a command
void InternalGetQuotedString(const StringRef& str) THROWS(GCodeException)
pre (readPointer >= 0; gb.buffer[readPointer] == '"'; str.IsEmpty());
void InternalGetPossiblyQuotedString(const StringRef& str) THROWS(GCodeException)
diff --git a/src/GCodes/GCodes3.cpp b/src/GCodes/GCodes3.cpp
index ed140fb7..b48ae06b 100644
--- a/src/GCodes/GCodes3.cpp
+++ b/src/GCodes/GCodes3.cpp
@@ -38,9 +38,11 @@
#endif
#ifdef I2C_IFACE
-# include "Wire.h"
+# include <Wire.h>
#endif
+#include <cctype>
+
// Deal with G60
GCodeResult GCodes::SavePosition(GCodeBuffer& gb, const StringRef& reply) THROWS(GCodeException)
{
@@ -1650,29 +1652,29 @@ bool GCodes::ProcessWholeLineComment(GCodeBuffer& gb, const StringRef& reply) TH
"BEGIN_LAYER_OBJECT z=", // KISSlicer (followed by Z height)
"HEIGHT", // Ideamaker
"PRINTING", // Ideamaker
- "REMAINING_TIME" // Ideamaker
+ "REMAINING_TIME", // Ideamaker
+ "LAYER_CHANGE" // SuperSlicer
};
String<StringLength100> comment;
gb.GetCompleteParameters(comment.GetRef());
- const char *text = comment.c_str();
- while (*text == ' ')
+ const char *fullText = comment.c_str();
+ while (*fullText == ' ')
{
- ++text;
+ ++fullText;
}
for (size_t i = 0; i < ARRAY_SIZE(StartStrings); ++i)
{
- if (StringStartsWith(text, StartStrings[i]))
+ if (StringStartsWith(fullText, StartStrings[i]))
{
- text += strlen(StartStrings[i]);
- if (*text == ' ' || *text == ':') // need this test to avoid recognising "processName" as "process"
+ const char *text = fullText + strlen(StartStrings[i]);
+ if (!isalpha(*text) && *text != '_') // need this test to avoid recognising "processName" as "process"
{
- do
+ while (*text == ' ' || *text == ':')
{
++text;
}
- while (*text == ' ' || *text == ':');
switch (i)
{
@@ -1717,7 +1719,7 @@ bool GCodes::ProcessWholeLineComment(GCodeBuffer& gb, const StringRef& reply) TH
case 4: // layer (counting from 1)
case 5: // layer (counting from 0)
- case 6: // later (counting from 0)
+ case 6: // layer (counting from 0)
{
const char *endptr;
const int32_t layer = StrToI32(text, &endptr); // IdeaMaker uses negative layer numbers for the raft, so read a signed number here
@@ -1756,6 +1758,10 @@ bool GCodes::ProcessWholeLineComment(GCodeBuffer& gb, const StringRef& reply) TH
}
}
break;
+
+ case 11: // LAYER_CHANGE (SuperSlicer). No layer number provided.
+ reprap.GetPrintMonitor().LayerChange();
+ break;
}
break;
}
diff --git a/src/Heating/RemoteHeater.cpp b/src/Heating/RemoteHeater.cpp
index e4cf368d..8bdfe5f3 100644
--- a/src/Heating/RemoteHeater.cpp
+++ b/src/Heating/RemoteHeater.cpp
@@ -385,7 +385,14 @@ GCodeResult RemoteHeater::SwitchOn(const StringRef& reply) noexcept
msg->heaterNumber = GetHeaterNumber();
msg->setPoint = GetTargetTemperature();
msg->command = CanMessageSetHeaterTemperature::commandOn;
- return CanInterface::SendRequestAndGetStandardReply(buf, rid, reply);
+ const GCodeResult rslt = CanInterface::SendRequestAndGetStandardReply(buf, rid, reply);
+ if (lastMode == HeaterMode::off && rslt <= GCodeResult::warning)
+ {
+ // If the heater was previously off then we need to change lastMode, otherwise if M116 is executed before we get an update from the expansion board
+ // then it will treat the heater as inactive and not wait for it to reach temperature
+ lastMode = HeaterMode::heating;
+ }
+ return rslt;
}
// This is called when the heater model has been updated
diff --git a/src/Movement/DDA.cpp b/src/Movement/DDA.cpp
index 5870f59c..89959ee0 100644
--- a/src/Movement/DDA.cpp
+++ b/src/Movement/DDA.cpp
@@ -1576,7 +1576,7 @@ void DDA::Prepare(uint8_t simMode, float extrusionPending[]) noexcept
const DDAState st = prev->state;
afterPrepare.moveStartTime = (st == DDAState::executing || st == DDAState::frozen)
? prev->afterPrepare.moveStartTime + prev->clocksNeeded // this move will follow the previous one, so calculate the start time assuming no more hiccups
- : StepTimer::GetTimerTicks() + MovementStartDelayClocks; // else this move is the first so start it after a short delay
+ : StepTimer::GetTimerTicks() + AbsoluteMinimumPreparedTime; // else this move is the first so start it after a short delay
if (flags.checkEndstops)
{
diff --git a/src/Movement/DDA.h b/src/Movement/DDA.h
index 22c65780..3db44ded 100644
--- a/src/Movement/DDA.h
+++ b/src/Movement/DDA.h
@@ -113,6 +113,7 @@ public:
#if SUPPORT_LASER || SUPPORT_IOBITS
LaserPwmOrIoBits GetLaserPwmOrIoBits() const noexcept { return laserPwmOrIoBits; }
+ bool ControlLaser() const noexcept { return flags.controlLaser; }
#endif
#if SUPPORT_LASER
@@ -135,6 +136,8 @@ public:
void DebugPrint(const char *tag) const noexcept; // print the DDA only
void DebugPrintAll(const char *tag) const noexcept; // print the DDA and active DMs
+ static void PrintMoves() noexcept; // print saved moves for debugging
+
// Note on the following constant:
// If we calculate the step interval on every clock, we reach a point where the calculation time exceeds the step interval.
// The worst case is pure Z movement on a delta. On a Mini Kossel with 80 steps/mm with this firmware running on a Duet (84MHx SAM3X8 processor),
@@ -163,7 +166,8 @@ public:
static constexpr uint32_t WakeupTime = (100 * StepTimer::StepClockRate)/1000000; // stop resting 100us before the move is due to end
static constexpr uint32_t HiccupIncrement = HiccupTime/2; // how much we increase the hiccup time by on each attempt
- static void PrintMoves() noexcept; // print saved moves for debugging
+ static constexpr uint32_t UsualMinimumPreparedTime = StepTimer::StepClockRate/10; // 100ms
+ static constexpr uint32_t AbsoluteMinimumPreparedTime = StepTimer::StepClockRate/20; // 50ms
#if DDA_LOG_PROBE_CHANGES
static const size_t MaxLoggedProbePositions = 40;
@@ -171,10 +175,6 @@ public:
static int32_t loggedProbePositions[XYZ_AXES * MaxLoggedProbePositions];
#endif
-#if SUPPORT_LASER || SUPPORT_IOBITS
- bool ControlLaser() const noexcept { return flags.controlLaser; }
-#endif
-
static uint32_t lastStepLowTime; // when we last completed a step pulse to a slow driver
static uint32_t lastDirChangeTime; // when we last change the DIR signal to a slow driver
diff --git a/src/Movement/DDARing.cpp b/src/Movement/DDARing.cpp
index cb765e53..11108208 100644
--- a/src/Movement/DDARing.cpp
+++ b/src/Movement/DDARing.cpp
@@ -15,9 +15,6 @@
# include "CAN/CanMotion.h"
#endif
-constexpr uint32_t UsualMinimumPreparedTime = StepTimer::StepClockRate/10; // 100ms
-constexpr uint32_t AbsoluteMinimumPreparedTime = StepTimer::StepClockRate/20; // 50ms
-
// Object model table and functions
// Note: if using GCC version 7.3.1 20180622 and lambda functions are used in this table, you must compile this file with option -std=gnu++17.
// Otherwise the table will be allocated in RAM instead of flash, which wastes too much RAM.
@@ -357,9 +354,9 @@ void DDARing::PrepareMoves(DDA *firstUnpreparedMove, int32_t moveTimeLeft, unsig
// If the number of prepared moves will execute in less than the minimum time, prepare another move.
// Try to avoid preparing deceleration-only moves too early
while ( firstUnpreparedMove->GetState() == DDA::provisional
- && moveTimeLeft < (int32_t)UsualMinimumPreparedTime // prepare moves one eighth of a second ahead of when they will be needed
+ && moveTimeLeft < (int32_t)DDA::UsualMinimumPreparedTime // prepare moves one tenth of a second ahead of when they will be needed
&& alreadyPrepared * 2 < numDdasInRing // but don't prepare more than half the ring
- && (firstUnpreparedMove->IsGoodToPrepare() || moveTimeLeft < (int32_t)AbsoluteMinimumPreparedTime)
+ && (firstUnpreparedMove->IsGoodToPrepare() || moveTimeLeft < (int32_t)DDA::AbsoluteMinimumPreparedTime)
#if SUPPORT_CAN_EXPANSION
&& CanMotion::CanPrepareMove()
#endif
diff --git a/src/Platform/TaskPriorities.h b/src/Platform/TaskPriorities.h
index b65f1568..36545a55 100644
--- a/src/Platform/TaskPriorities.h
+++ b/src/Platform/TaskPriorities.h
@@ -14,7 +14,7 @@ namespace TaskPriority
constexpr int IdlePriority = 0;
constexpr int SpinPriority = 1; // priority for tasks that rarely block
#if HAS_LINUX_INTERFACE
- constexpr int SbcPriority = 1; // priority for SBC task
+ constexpr int SbcPriority = 1; // priority for SBC task. TODO increase this when we are certain that it never spins.
#endif
#if defined(LPC_NETWORKING)
constexpr int TcpPriority = 2;
@@ -26,7 +26,9 @@ namespace TaskPriority
constexpr int TmcPriority = 4;
constexpr int AinPriority = 4;
constexpr int HeightFollowingPriority = 4;
+#ifdef DUET_NG
constexpr int DueXPriority = 5;
+#endif
constexpr int LaserPriority = 5;
constexpr int CanSenderPriority = 5;
constexpr int CanReceiverPriority = 5;
diff --git a/src/PrintMonitor/PrintMonitor.cpp b/src/PrintMonitor/PrintMonitor.cpp
index 64661cb9..4cf8f2ed 100644
--- a/src/PrintMonitor/PrintMonitor.cpp
+++ b/src/PrintMonitor/PrintMonitor.cpp
@@ -346,6 +346,14 @@ void PrintMonitor::SetLayerZ(float layerZ) noexcept
// Currently we don't use the layerZ value
}
+// Report that a new layer has started
+void PrintMonitor::LayerChange() noexcept
+{
+ ++currentLayer;
+ lastLayerChangeTime = millis64();
+ lastLayerChangeNonPrintingTime = GetWarmUpDuration() + GetPauseDuration();
+}
+
float PrintMonitor::FractionOfFilePrinted() const noexcept
{
ReadLocker locker(printMonitorLock);
diff --git a/src/PrintMonitor/PrintMonitor.h b/src/PrintMonitor/PrintMonitor.h
index 16ae6b62..5ff5406f 100644
--- a/src/PrintMonitor/PrintMonitor.h
+++ b/src/PrintMonitor/PrintMonitor.h
@@ -44,6 +44,7 @@ public:
void StoppedPrint() noexcept; // Called whenever a file print has stopped
void SetLayerNumber(uint32_t layerNumber) noexcept; // Set the current layer number
void SetLayerZ(float layerZ) noexcept; // Set the printing height of the new layer
+ void LayerChange() noexcept; // Report that a new layer has started
float FractionOfFilePrinted() const noexcept; // Return the fraction printed (0..1)
// Return an estimate in seconds based on a specific estimation method
diff --git a/src/Version.h b/src/Version.h
index f31ac080..f1076245 100644
--- a/src/Version.h
+++ b/src/Version.h
@@ -9,7 +9,7 @@
#define SRC_VERSION_H_
#ifndef VERSION
-# define MAIN_VERSION "3.3RC3+6"
+# define MAIN_VERSION "3.3RC3+7"
# ifdef USE_CAN0
# define VERSION_SUFFIX " (CAN0)"
# else