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:
Diffstat (limited to 'src/FilamentMonitors/PulsedFilamentMonitor.cpp')
-rw-r--r--src/FilamentMonitors/PulsedFilamentMonitor.cpp251
1 files changed, 251 insertions, 0 deletions
diff --git a/src/FilamentMonitors/PulsedFilamentMonitor.cpp b/src/FilamentMonitors/PulsedFilamentMonitor.cpp
new file mode 100644
index 00000000..d1e2522a
--- /dev/null
+++ b/src/FilamentMonitors/PulsedFilamentMonitor.cpp
@@ -0,0 +1,251 @@
+/*
+ * PulsedFilamentSensor.cpp
+ *
+ * Created on: 9 Jan 2018
+ * Author: David
+ */
+
+#include "PulsedFilamentMonitor.h"
+#include "GCodes/GCodeBuffer.h"
+#include "Platform.h"
+#include "RepRap.h"
+
+PulsedFilamentMonitor::PulsedFilamentMonitor(int type)
+ : FilamentMonitor(type),
+ mmPerPulse(DefaultMmPerPulse), tolerance(DefaultTolerance), minimumExtrusionCheckLength(DefaultMinimumExtrusionCheckLength)
+{
+ Init();
+}
+
+void PulsedFilamentMonitor::Init()
+{
+ sensorValue = 0;
+ calibrationStarted = dataReceived = false;
+ Reset();
+}
+
+void PulsedFilamentMonitor::Reset()
+{
+ extrusionCommanded = movementMeasured = extrusionCommandedAtLastMeasurement = movementMeasuredAtLastCheck = 0.0;
+ samplesReceived = 0;
+ comparisonStarted = false;
+}
+
+// Configure this sensor, returning true if error and setting 'seen' if we processed any configuration parameters
+bool PulsedFilamentMonitor::Configure(GCodeBuffer& gb, StringRef& reply, bool& seen)
+{
+ if (ConfigurePin(gb, reply, RISING, seen))
+ {
+ return true;
+ }
+
+ gb.TryGetFValue('S', mmPerPulse, seen); // this is mm per rev for Duet3D sensors, mm per pulse for pulsed sensors
+ gb.TryGetFValue('E', minimumExtrusionCheckLength, seen);
+
+ if (gb.Seen('R'))
+ {
+ seen = true;
+ tolerance = gb.GetFValue() * 0.01;
+ }
+
+ if (seen)
+ {
+ Init();
+ }
+ else
+ {
+ reply.printf("Pulse-type filament monitor on endstop input %u, sensitivity %.2fmm/pulse, check every %.1fmm, tolerance %.1f%%, ",
+ GetEndstopNumber(),
+ (double)mmPerPulse,
+ (double)minimumExtrusionCheckLength,
+ (double)(tolerance * 100.0));
+
+ if (!dataReceived)
+ {
+ reply.cat("no data received");
+ }
+ else
+ {
+ reply.catf("current position %.1f, ", (double)GetCurrentPosition());
+ if (calibrationStarted && fabsf(totalMovementMeasured) > 1.0 && totalExtrusionCommanded > 20.0)
+ {
+ const float measuredCalibration = totalExtrusionCommanded/totalMovementMeasured;
+ const float normalRatio = 1.0/measuredCalibration;
+ const int measuredPosTolerance = lrintf(100.0 * (((normalRatio > 0.0) ? maxMovementRatio : minMovementRatio) - normalRatio)/normalRatio);
+ const int measuredNegTolerance = lrintf(100.0 * (normalRatio - ((normalRatio > 0.0) ? minMovementRatio : maxMovementRatio))/normalRatio);
+ reply.catf("measured sensitivity %.2fmm/pulse over %.1fmm, tolerance +%d%% -%d%%",
+ (double)measuredCalibration,
+ (double)totalExtrusionCommanded,
+ measuredPosTolerance,
+ measuredNegTolerance);
+ }
+ else
+ {
+ reply.cat("no calibration data");
+ }
+ }
+ }
+
+ return false;
+}
+
+// ISR for when the pin state changes
+void PulsedFilamentMonitor::Interrupt()
+{
+ ++sensorValue;
+ extrusionCommandedAtLastMeasurement = extrusionCommanded;
+ if (samplesReceived < 100)
+ {
+ ++samplesReceived;
+ }
+}
+
+// Call the following regularly to keep the status up to date
+void PulsedFilamentMonitor::Poll()
+{
+ cpu_irq_disable();
+ const uint16_t locSensorVal = sensorValue;
+ sensorValue = 0;
+ cpu_irq_enable();
+ movementMeasured += (float)locSensorVal;
+ extrusionCommandedAtLastMeasurement = extrusionCommanded;
+}
+
+// Return the current wheel angle
+float PulsedFilamentMonitor::GetCurrentPosition() const
+{
+ return (float)sensorValue;
+}
+
+// Call the following at intervals to check the status. This is only called when extrusion is in progress or imminent.
+// 'filamentConsumed' is the net amount of extrusion since the last call to this function.
+// 'hadNonPrintingMove' is called if filamentConsumed includes extruder movement form non-printing moves.
+FilamentSensorStatus PulsedFilamentMonitor::Check(bool full, bool hadNonPrintingMove, float filamentConsumed)
+{
+ Poll(); // this may update movementMeasured
+
+ FilamentSensorStatus ret = FilamentSensorStatus::ok;
+ if (!hadNonPrintingMove)
+ {
+ // We have had a non-printing move recently and we are configured to not check non-printing moves. Reset the counters.
+ movementMeasured = movementMeasuredAtLastCheck; // ignore measured extrusion since last check
+ }
+ else
+ {
+ extrusionCommanded += filamentConsumed; // include the extrusion we have just been told about
+ movementMeasuredAtLastCheck = movementMeasured; // save for next time
+
+ if (full)
+ {
+ if (extrusionCommandedAtLastMeasurement >= minimumExtrusionCheckLength)
+ {
+ ret = CheckFilament(extrusionCommandedAtLastMeasurement, false);
+ }
+ else if (extrusionCommanded >= minimumExtrusionCheckLength * 1.1 && millis() - lastMeasurementTime > 110)
+ {
+ ret = CheckFilament(extrusionCommanded, true);
+ }
+ }
+ }
+
+ return ret;
+}
+
+// Compare the amount commanded with the amount of extrusion measured, and set up for the next comparison
+FilamentSensorStatus PulsedFilamentMonitor::CheckFilament(float amountCommanded, bool overdue)
+{
+ const float extrusionMeasured = movementMeasured * mmPerPulse;
+ if (reprap.Debug(moduleFilamentSensors))
+ {
+ debugPrintf("Extr req %.3f meas %.3f rem %.3f %s\n", (double)amountCommanded, (double)extrusionMeasured, (double)(extrusionCommanded - amountCommanded),
+ (overdue) ? " overdue" : "");
+ }
+
+ FilamentSensorStatus ret = FilamentSensorStatus::ok;
+ if (!comparisonStarted)
+ {
+ // The first measurement after we start extruding is often a long way out, so discard it
+ comparisonStarted = true;
+ calibrationStarted = false;
+ }
+ else if (tolerance >= 0.0)
+ {
+ const float minExtrusionExpected = (amountCommanded >= 0.0)
+ ? amountCommanded * (1.0 - tolerance)
+ : amountCommanded * (1.0 + tolerance);
+ if (extrusionMeasured < minExtrusionExpected)
+ {
+ ret = FilamentSensorStatus::tooLittleMovement;
+ }
+ else
+ {
+ const float maxExtrusionExpected = (amountCommanded >= 0.0)
+ ? amountCommanded * (1.0 + tolerance)
+ : amountCommanded * (1.0 - tolerance);
+ if (extrusionMeasured > maxExtrusionExpected)
+ {
+ ret = FilamentSensorStatus::tooMuchMovement;
+ }
+ }
+ }
+
+ // Update the calibration accumulators, even if the user hasn't asked to do calibration
+ const float ratio = movementMeasured/amountCommanded;
+ if (calibrationStarted)
+ {
+ if (ratio < minMovementRatio)
+ {
+ minMovementRatio = ratio;
+ }
+ if (ratio > maxMovementRatio)
+ {
+ maxMovementRatio = ratio;
+ }
+ totalExtrusionCommanded += amountCommanded;
+ totalMovementMeasured += movementMeasured;
+ }
+ else
+ {
+ minMovementRatio = maxMovementRatio = ratio;
+ totalExtrusionCommanded = amountCommanded;
+ totalMovementMeasured = movementMeasured;
+ calibrationStarted = true;
+ }
+
+ extrusionCommanded -= amountCommanded;
+ extrusionCommandedAtLastMeasurement = movementMeasured = 0.0;
+
+ return ret;
+}
+
+// Clear the measurement state - called when we are not printing a file. Return the present/not present status if available.
+FilamentSensorStatus PulsedFilamentMonitor::Clear(bool full)
+{
+ Poll(); // to keep the diagnostics up to date
+ Reset();
+
+ return FilamentSensorStatus::ok;
+}
+
+// Print diagnostic info for this sensor
+void PulsedFilamentMonitor::Diagnostics(MessageType mtype, unsigned int extruder)
+{
+ Poll();
+ const char* const statusText = (!dataReceived) ? "no data received" : "ok";
+ reprap.GetPlatform().MessageF(mtype, "Extruder %u sensor: position %.2f, %s, ", extruder, (double)GetCurrentPosition(), statusText);
+ if (calibrationStarted && fabsf(totalMovementMeasured) > 1.0 && totalExtrusionCommanded > 20.0)
+ {
+ const float measuredMmPerRev = totalExtrusionCommanded/totalMovementMeasured;
+ const float normalRatio = 1.0/measuredMmPerRev;
+ const int measuredPosTolerance = lrintf(100.0 * (((normalRatio > 0.0) ? maxMovementRatio : minMovementRatio) - normalRatio)/normalRatio);
+ const int measuredNegTolerance = lrintf(100.0 * (normalRatio - ((normalRatio > 0.0) ? minMovementRatio : maxMovementRatio))/normalRatio);
+ reprap.GetPlatform().MessageF(mtype,"measured sensitivity %.2fmm/pulse +%d%% -%d%%\n",
+ (double)measuredMmPerRev, measuredPosTolerance, measuredNegTolerance);
+ }
+ else
+ {
+ reprap.GetPlatform().Message(mtype, "no calibration data\n");
+ }
+}
+
+// End