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>2018-12-15 14:47:19 +0300
committerDavid Crocker <dcrocker@eschertech.com>2018-12-15 14:47:19 +0300
commita25f8204d2fe36ad174b98dea673a114503cc457 (patch)
tree69c4bbd7abafb97a86a04705b80291875c62738a
parenta15773859dabee6e88cce157f7c00d17e29171b4 (diff)
Release 2.02RC62.02RC6
Fix for extruder movement less than 1 microstep Fix for G30 on SCARA immediately after homing prox+distal arms Fix babystepping move immediately after extruding move Added nanoDLP compatibility option Corrected PCCB pin assignments G1 R moves never use machine coordinates
-rw-r--r--.cproject11
-rw-r--r--src/Alligator/Microstepping.cpp8
-rw-r--r--src/Alligator/Pins_Alligator.h24
-rw-r--r--src/BugList.txt35
-rw-r--r--src/Configuration.h8
-rw-r--r--src/GCodes/GCodeMachineState.h2
-rw-r--r--src/GCodes/GCodes.cpp233
-rw-r--r--src/GCodes/GCodes.h17
-rw-r--r--src/GCodes/GCodes2.cpp47
-rw-r--r--src/GCodes/GCodes3.cpp44
-rw-r--r--src/Movement/DDA.cpp67
-rw-r--r--src/Movement/DDA.h5
-rw-r--r--src/Movement/DriveMovement.cpp57
-rw-r--r--src/Movement/DriveMovement.h2
-rw-r--r--src/Movement/Kinematics/ScaraKinematics.cpp35
-rw-r--r--src/Movement/Move.cpp48
-rw-r--r--src/Movement/Move.h4
-rw-r--r--src/Movement/StepTimer.cpp12
-rw-r--r--src/Movement/StepTimer.h16
-rw-r--r--src/ObjectModel/ObjectModel.cpp2
-rw-r--r--src/Pccb/Pins_Pccb.h52
-rw-r--r--src/Platform.cpp32
-rw-r--r--src/Tasks.cpp2
-rw-r--r--src/Version.h4
24 files changed, 424 insertions, 343 deletions
diff --git a/.cproject b/.cproject
index 0a6dc1e9..6aaa4961 100644
--- a/.cproject
+++ b/.cproject
@@ -257,7 +257,7 @@
</extensions>
</storageModule>
<storageModule moduleId="cdtBuildSystem" version="4.0.0">
- <configuration artifactExtension="elf" artifactName="${ProjName}-Alligator" buildArtefactType="org.eclipse.cdt.build.core.buildArtefactType.exe" buildProperties="org.eclipse.cdt.build.core.buildArtefactType=org.eclipse.cdt.build.core.buildArtefactType.exe,org.eclipse.cdt.build.core.buildType=org.eclipse.cdt.build.core.buildType.release" cleanCommand="rm -rf" description="" id="cdt.managedbuild.config.gnu.cross.exe.release.516195201.976458850.1745168887" name="Alligator" parent="cdt.managedbuild.config.gnu.cross.exe.release" postannouncebuildStep="Generating binary file" postbuildStep="arm-none-eabi-objcopy -O binary ${workspace_loc:/${ProjName}/${ConfigName}}/${BuildArtifactFileBaseName}.elf ${workspace_loc:/${ProjName}/${ConfigName}}/${BuildArtifactFileBaseName}.bin">
+ <configuration artifactExtension="elf" artifactName="${ProjName}-Alligator" buildArtefactType="org.eclipse.cdt.build.core.buildArtefactType.exe" buildProperties="org.eclipse.cdt.build.core.buildArtefactType=org.eclipse.cdt.build.core.buildArtefactType.exe,org.eclipse.cdt.build.core.buildType=org.eclipse.cdt.build.core.buildType.release" cleanCommand="rm -rf" description="" id="cdt.managedbuild.config.gnu.cross.exe.release.516195201.976458850.1745168887" name="Alligator" optionalBuildProperties="org.eclipse.cdt.docker.launcher.containerbuild.property.selectedvolumes=,org.eclipse.cdt.docker.launcher.containerbuild.property.volumes=" parent="cdt.managedbuild.config.gnu.cross.exe.release" postannouncebuildStep="Generating binary file" postbuildStep="arm-none-eabi-objcopy -O binary ${workspace_loc:/${ProjName}/${ConfigName}}/${BuildArtifactFileBaseName}.elf ${workspace_loc:/${ProjName}/${ConfigName}}/${BuildArtifactFileBaseName}.bin">
<folderInfo id="cdt.managedbuild.config.gnu.cross.exe.release.516195201.976458850.1745168887." name="/" resourcePath="">
<toolChain id="cdt.managedbuild.toolchain.gnu.cross.exe.release.623324432" name="Cross GCC" superClass="cdt.managedbuild.toolchain.gnu.cross.exe.release">
<option id="cdt.managedbuild.option.gnu.cross.path.645044151" name="Path" superClass="cdt.managedbuild.option.gnu.cross.path" useByScannerDiscovery="false" value="${GccPath}" valueType="string"/>
@@ -302,9 +302,11 @@
<option id="gnu.cpp.link.option.nostdlibs.760089516" name="No startup or default libs (-nostdlib)" superClass="gnu.cpp.link.option.nostdlibs" useByScannerDiscovery="false" value="false" valueType="boolean"/>
<option IS_BUILTIN_EMPTY="false" IS_VALUE_EMPTY="false" id="gnu.cpp.link.option.paths.1593340130" name="Library search path (-L)" superClass="gnu.cpp.link.option.paths" useByScannerDiscovery="false" valueType="libPaths">
<listOptionValue builtIn="false" value="&quot;${workspace_loc:/${CoreName}/Alligator/}&quot;"/>
+ <listOptionValue builtIn="false" value="&quot;${workspace_loc:/RRFLibraries/SAM3X}&quot;"/>
</option>
<option IS_BUILTIN_EMPTY="false" IS_VALUE_EMPTY="false" id="gnu.cpp.link.option.libs.1260510068" name="Libraries (-l)" superClass="gnu.cpp.link.option.libs" useByScannerDiscovery="false" valueType="libs">
<listOptionValue builtIn="false" value="${CoreName}"/>
+ <listOptionValue builtIn="false" value="RRFLibraries"/>
</option>
<option id="gnu.cpp.link.option.flags.1376831701" name="Linker flags" superClass="gnu.cpp.link.option.flags" useByScannerDiscovery="false" value="-Os -Wl,--gc-sections -Wl,--fatal-warnings -mcpu=cortex-m3 -T&quot;${workspace_loc:/${CoreName}/variants/alligator/linker_scripts/gcc/flash.ld&quot; -Wl,-Map,&quot;${workspace_loc:/${ProjName}/${ConfigName}}/${BuildArtifactFileBaseName}.map&quot;" valueType="string"/>
<inputType id="cdt.managedbuild.tool.gnu.cpp.linker.input.1951368129" superClass="cdt.managedbuild.tool.gnu.cpp.linker.input">
@@ -339,6 +341,7 @@
<listOptionValue builtIn="false" value="&quot;${workspace_loc:/${ProjName}/src/Duet}&quot;"/>
<listOptionValue builtIn="false" value="&quot;${workspace_loc:/${ProjName}/src/Duet/Lwip}&quot;"/>
<listOptionValue builtIn="false" value="&quot;${workspace_loc:/${ProjName}/src/Duet/EMAC}&quot;"/>
+ <listOptionValue builtIn="false" value="&quot;${workspace_loc:/RRFLibraries/src}&quot;"/>
</option>
<option IS_BUILTIN_EMPTY="false" IS_VALUE_EMPTY="false" id="gnu.cpp.compiler.option.preprocessor.def.890621467" name="Defined symbols (-D)" superClass="gnu.cpp.compiler.option.preprocessor.def" useByScannerDiscovery="false" valueType="definedSymbols">
<listOptionValue builtIn="false" value="__SAM3X8E__"/>
@@ -378,7 +381,7 @@
</extensions>
</storageModule>
<storageModule moduleId="cdtBuildSystem" version="4.0.0">
- <configuration artifactExtension="elf" artifactName="Duet2CombinedFirmware" buildArtefactType="org.eclipse.cdt.build.core.buildArtefactType.exe" buildProperties="org.eclipse.cdt.build.core.buildArtefactType=org.eclipse.cdt.build.core.buildArtefactType.exe,org.eclipse.cdt.build.core.buildType=org.eclipse.cdt.build.core.buildType.release" cleanCommand="rm -rf" description="" id="cdt.managedbuild.config.gnu.cross.exe.release.516195201.976458850.241502451.170574622" name="Duet2_RTOS" optionalBuildProperties="org.eclipse.cdt.docker.launcher.containerbuild.property.volumes=,org.eclipse.cdt.docker.launcher.containerbuild.property.selectedvolumes=" parent="cdt.managedbuild.config.gnu.cross.exe.release" postannouncebuildStep="Generating binary file" postbuildStep="arm-none-eabi-objcopy -O binary ${workspace_loc:/${ProjName}/${ConfigName}}/${BuildArtifactFileBaseName}.elf ${workspace_loc:/${ProjName}/${ConfigName}}/${BuildArtifactFileBaseName}.bin">
+ <configuration artifactExtension="elf" artifactName="Duet2CombinedFirmware" buildArtefactType="org.eclipse.cdt.build.core.buildArtefactType.exe" buildProperties="org.eclipse.cdt.build.core.buildArtefactType=org.eclipse.cdt.build.core.buildArtefactType.exe,org.eclipse.cdt.build.core.buildType=org.eclipse.cdt.build.core.buildType.release" cleanCommand="rm -rf" description="" id="cdt.managedbuild.config.gnu.cross.exe.release.516195201.976458850.241502451.170574622" name="Duet2_RTOS" optionalBuildProperties="org.eclipse.cdt.docker.launcher.containerbuild.property.selectedvolumes=,org.eclipse.cdt.docker.launcher.containerbuild.property.volumes=" parent="cdt.managedbuild.config.gnu.cross.exe.release" postannouncebuildStep="Generating binary file" postbuildStep="arm-none-eabi-objcopy -O binary ${workspace_loc:/${ProjName}/${ConfigName}}/${BuildArtifactFileBaseName}.elf ${workspace_loc:/${ProjName}/${ConfigName}}/${BuildArtifactFileBaseName}.bin">
<folderInfo id="cdt.managedbuild.config.gnu.cross.exe.release.516195201.976458850.241502451.170574622." name="/" resourcePath="">
<toolChain id="cdt.managedbuild.toolchain.gnu.cross.exe.release.435431950" name="Cross GCC" nonInternalBuilderId="cdt.managedbuild.builder.gnu.cross" superClass="cdt.managedbuild.toolchain.gnu.cross.exe.release">
<option id="cdt.managedbuild.option.gnu.cross.path.1881231799" name="Path" superClass="cdt.managedbuild.option.gnu.cross.path" useByScannerDiscovery="false" value="${GccPath}" valueType="string"/>
@@ -763,7 +766,7 @@
</extensions>
</storageModule>
<storageModule moduleId="cdtBuildSystem" version="4.0.0">
- <configuration artifactExtension="elf" artifactName="PccbFirmware" buildArtefactType="org.eclipse.cdt.build.core.buildArtefactType.exe" buildProperties="org.eclipse.cdt.build.core.buildArtefactType=org.eclipse.cdt.build.core.buildArtefactType.exe,org.eclipse.cdt.build.core.buildType=org.eclipse.cdt.build.core.buildType.release" cleanCommand="rm -rf" description="" id="cdt.managedbuild.config.gnu.cross.exe.release.516195201.976458850.241502451.170574622.649587786.1798324396" name="PCCB" parent="cdt.managedbuild.config.gnu.cross.exe.release" postannouncebuildStep="Generating binary file" postbuildStep="arm-none-eabi-objcopy -O binary ${workspace_loc:/${ProjName}/${ConfigName}}/${BuildArtifactFileBaseName}.elf ${workspace_loc:/${ProjName}/${ConfigName}}/${BuildArtifactFileBaseName}.bin">
+ <configuration artifactExtension="elf" artifactName="PccbFirmware" buildArtefactType="org.eclipse.cdt.build.core.buildArtefactType.exe" buildProperties="org.eclipse.cdt.build.core.buildArtefactType=org.eclipse.cdt.build.core.buildArtefactType.exe,org.eclipse.cdt.build.core.buildType=org.eclipse.cdt.build.core.buildType.release" cleanCommand="rm -rf" description="" id="cdt.managedbuild.config.gnu.cross.exe.release.516195201.976458850.241502451.170574622.649587786.1798324396" name="PCCB" optionalBuildProperties="" parent="cdt.managedbuild.config.gnu.cross.exe.release" postannouncebuildStep="Generating binary file" postbuildStep="arm-none-eabi-objcopy -O binary ${workspace_loc:/${ProjName}/${ConfigName}}/${BuildArtifactFileBaseName}.elf ${workspace_loc:/${ProjName}/${ConfigName}}/${BuildArtifactFileBaseName}.bin">
<folderInfo id="cdt.managedbuild.config.gnu.cross.exe.release.516195201.976458850.241502451.170574622.649587786.1798324396." name="/" resourcePath="">
<toolChain id="cdt.managedbuild.toolchain.gnu.cross.exe.release.1017317107" name="Cross GCC" superClass="cdt.managedbuild.toolchain.gnu.cross.exe.release">
<option id="cdt.managedbuild.option.gnu.cross.path.1932906636" name="Path" superClass="cdt.managedbuild.option.gnu.cross.path" useByScannerDiscovery="false" value="${GccPath}" valueType="string"/>
@@ -885,7 +888,7 @@
</extensions>
</storageModule>
<storageModule moduleId="cdtBuildSystem" version="4.0.0">
- <configuration artifactExtension="elf" artifactName="PccbFirmware_X5" buildArtefactType="org.eclipse.cdt.build.core.buildArtefactType.exe" buildProperties="org.eclipse.cdt.build.core.buildArtefactType=org.eclipse.cdt.build.core.buildArtefactType.exe,org.eclipse.cdt.build.core.buildType=org.eclipse.cdt.build.core.buildType.release" cleanCommand="rm -rf" description="" id="cdt.managedbuild.config.gnu.cross.exe.release.516195201.976458850.241502451.170574622.649587786.1798324396.239853003" name="PCCB_X5" parent="cdt.managedbuild.config.gnu.cross.exe.release" postannouncebuildStep="Generating binary file" postbuildStep="arm-none-eabi-objcopy -O binary ${workspace_loc:/${ProjName}/${ConfigName}}/${BuildArtifactFileBaseName}.elf ${workspace_loc:/${ProjName}/${ConfigName}}/${BuildArtifactFileBaseName}.bin">
+ <configuration artifactExtension="elf" artifactName="PccbFirmware_X5" buildArtefactType="org.eclipse.cdt.build.core.buildArtefactType.exe" buildProperties="org.eclipse.cdt.build.core.buildArtefactType=org.eclipse.cdt.build.core.buildArtefactType.exe,org.eclipse.cdt.build.core.buildType=org.eclipse.cdt.build.core.buildType.release" cleanCommand="rm -rf" description="" id="cdt.managedbuild.config.gnu.cross.exe.release.516195201.976458850.241502451.170574622.649587786.1798324396.239853003" name="PCCB_X5" optionalBuildProperties="" parent="cdt.managedbuild.config.gnu.cross.exe.release" postannouncebuildStep="Generating binary file" postbuildStep="arm-none-eabi-objcopy -O binary ${workspace_loc:/${ProjName}/${ConfigName}}/${BuildArtifactFileBaseName}.elf ${workspace_loc:/${ProjName}/${ConfigName}}/${BuildArtifactFileBaseName}.bin">
<folderInfo id="cdt.managedbuild.config.gnu.cross.exe.release.516195201.976458850.241502451.170574622.649587786.1798324396.239853003." name="/" resourcePath="">
<toolChain id="cdt.managedbuild.toolchain.gnu.cross.exe.release.2113529528" name="Cross GCC" superClass="cdt.managedbuild.toolchain.gnu.cross.exe.release">
<option id="cdt.managedbuild.option.gnu.cross.path.1216992967" name="Path" superClass="cdt.managedbuild.option.gnu.cross.path" useByScannerDiscovery="false" value="${GccPath}" valueType="string"/>
diff --git a/src/Alligator/Microstepping.cpp b/src/Alligator/Microstepping.cpp
index baf62efc..af83e759 100644
--- a/src/Alligator/Microstepping.cpp
+++ b/src/Alligator/Microstepping.cpp
@@ -11,7 +11,7 @@
//***************************************************************************************************
// Alligator Microstepping static class
-uint8_t microsteppingPins[ DRIVES - MinAxes ];
+uint8_t microsteppingPins[ NumDirectDrivers - MinAxes ];
void Microstepping::Init() {
@@ -19,7 +19,7 @@ void Microstepping::Init() {
static_assert(sizeof(microsteppingPins) == sizeof(MICROSTEPPING_PINS), "Incompatible array types");
memcpy(microsteppingPins, MICROSTEPPING_PINS, sizeof(MICROSTEPPING_PINS));
- for(uint8_t pin=0; pin < (DRIVES-MinAxes); pin++ ) {
+ for(uint8_t pin=0; pin < (NumDirectDrivers - MinAxes); pin++ ) {
pinMode( microsteppingPins[pin], OUTPUT_HIGH);
}
}
@@ -27,7 +27,7 @@ void Microstepping::Init() {
bool Microstepping::Set(uint8_t drive, uint8_t value) {
// Do not exceed the maximum value
- if ( drive >= (DRIVES - MinAxes) )
+ if ( drive >= (NumDirectDrivers - MinAxes) )
{
return false;
}
@@ -45,7 +45,7 @@ bool Microstepping::Set(uint8_t drive, uint8_t value) {
uint8_t Microstepping::Read( uint8_t drive ) {
// Do not exceed the maximum value
- if ( drive < (DRIVES - MinAxes) )
+ if ( drive < (NumDirectDrivers - MinAxes) )
{
return ( digitalRead(microsteppingPins[drive]) == LOW ? 16 : 32 );
}
diff --git a/src/Alligator/Pins_Alligator.h b/src/Alligator/Pins_Alligator.h
index 6cdc61ce..859efd6b 100644
--- a/src/Alligator/Pins_Alligator.h
+++ b/src/Alligator/Pins_Alligator.h
@@ -27,11 +27,10 @@ const size_t NumFirmwareUpdateModules = 1;
// The physical capabilities of the machine
// Alligator + Piggy module max 7 stepper driver
-const size_t DRIVES = 7; // The number of drives in the machine, including X, Y, and Z plus extruder drives
-#define DRIVES_(a,b,c,d,e,f,g,h,i,j,k,l) { a,b,c,d,e,f,g }
-const size_t MaxDriversPerAxis = 4; // The maximum number of stepper drivers assigned to one axis
-// Initialization macro used in statements needing to initialize values in arrays of size MAX_AXES
-#define AXES_(a,b,c,d,e,f,g,h,i) { a,b,c,d,e,f }
+constexpr size_t NumDirectDrivers = 7; // The number of drives in the machine, including X, Y, and Z plus extruder drives
+constexpr size_t MaxTotalDrivers = NumDirectDrivers;
+
+constexpr size_t MaxDriversPerAxis = 4; // The maximum number of stepper drivers assigned to one axis
constexpr size_t NumEndstops = 6; // The number of inputs we have for endstops, filament sensors etc.
// Alligator + Piggy module max 5 heaters
@@ -42,21 +41,22 @@ constexpr size_t NumThermistorInputs = 5;
constexpr size_t MaxAxes = 7; // The maximum number of movement axes in the machine, usually just X, Y and Z, <= DRIVES
constexpr size_t MinAxes = 3; // The minimum and default number of axes
-constexpr size_t MaxExtruders = DRIVES - MinAxes; // The maximum number of extruders
+constexpr size_t MaxExtruders = NumDirectDrivers - MinAxes; // The maximum number of extruders
constexpr size_t NUM_SERIAL_CHANNELS = 3; // The number of serial IO channels (USB and two auxiliary UARTs)
#define SERIAL_MAIN_DEVICE SerialUSB
#define SERIAL_AUX_DEVICE Serial
#define SERIAL_AUX2_DEVICE Serial1
-// The numbers of entries in each array must correspond with the values of DRIVES, AXES, or HEATERS. Set values to NoPin to flag unavailability.
-// DRIVES
-const Pin ENABLE_PINS[DRIVES] = { 24, NoPin, NoPin, NoPin, NoPin, NoPin, NoPin };
-const Pin STEP_PINS[DRIVES] = { X16, X14, X1, 5, 28, 11, X9 };
-const Pin DIRECTION_PINS[DRIVES] = { 2, 78, X13, 4, 27, 29, 12};
+constexpr Pin UsbVBusPin = NoPin; // Pin used to monitor VBUS on USB port. Not needed for SAM3X.
+
+// The numbers of entries in each array must correspond with the values of NumDirectDrivers, MaxAxes, or NumHeaters. Set values to NoPin to flag unavailability.
+const Pin ENABLE_PINS[NumDirectDrivers] = { 24, NoPin, NoPin, NoPin, NoPin, NoPin, NoPin };
+const Pin STEP_PINS[NumDirectDrivers] = { X16, X14, X1, 5, 28, 11, X9 };
+const Pin DIRECTION_PINS[NumDirectDrivers] = { 2, 78, X13, 4, 27, 29, 12};
// MICROSTEPPING Pins
-const Pin MICROSTEPPING_PINS[DRIVES - MinAxes] = { X12, X10, 44, 45 };
+const Pin MICROSTEPPING_PINS[NumDirectDrivers - MinAxes] = { X12, X10, 44, 45 };
// Motor FAULT Pin
const Pin MotorFaultDetectPin = 22;
diff --git a/src/BugList.txt b/src/BugList.txt
index 4d01c50d..5a6b2eaa 100644
--- a/src/BugList.txt
+++ b/src/BugList.txt
@@ -167,7 +167,7 @@ To be investigated for 2.02RC5 or release:
- [probing speed was too high] Multiple G29 commands in succession, https://forum.duet3d.com/topic/7920/bed-compensation-g29-problems
- [may be fixed by possible fix for for Z and U moving at different speeds] investigate slow movement, https://forum.duet3d.com/topic/6974/problem-with-3-independent-z-axis-motors-and-endstops/32
-To be fixed in 2.02RC5:
+Fixed in 2.02RC5:
- [done, ok] 12864 display of speed factor wrong, https://forum.duet3d.com/topic/7747/reprapfirmware-2-02rc4-released/10
- [done, ok] 12864 button menu handling wrong, https://forum.duet3d.com/topic/7747/reprapfirmware-2-02rc4-released/14
- [done, ok] 12864 items 510- display user position not machine position
@@ -184,14 +184,41 @@ To be fixed in 2.02RC5:
- [done, ok] M106 Pnn Svv always set full PWM if vv > 1 and there were additional parameters e.g. F, https://forum.duet3d.com/topic/7810/question-about-m106/6
- [done] Possible fix for Z and U moving at different speeds, https://forum.duet3d.com/topic/7755/drive-3-is-slower-as-drive-2-at-homing-in-z-solved/32
- [done, ok] For SimpleFilamentMonitor, include filament present/not present status in M591 report
-- [done, ok] Heater turn on momentarily when Duet is reset
+- [done, ok] Heaters turn on momentarily when Duet is reset
- [done, ok] When G53 is in effect, don't apply tool offsets or axis mapping
-- [done, ok] Don't alow both S0 and T0 in M291, it creates a message that can't be dismissed
+- [done, ok] Don't allow both S0 and T0 in M291, it creates a message that can't be dismissed
+
+To be fixed in 2.02RC6:
+- [done] When VIN power comes up (again), clear out open-load status bits to avoid spurious open load warnings
+- [done, ok] Fix behaviour when extrusion per move is < 1 step, https://forum.duet3d.com/topic/7949/my-experience-with-relative-extrusion-problem-and-solution/13
+- [still can't reproduce] Investigate macro using M291 again, https://forum.duet3d.com/topic/7782/issues-with-macros-halting-the-printer/26
+- [done, ok] 12864 fallback: if 'menu' action is used with no parameter, use the F parameter
+- [done, ok] Different U and Z homing speeds is back and worse, https://forum.duet3d.com/topic/7755/drive-3-is-slower-as-drive-2-at-homing-in-z-solved/30
+- [done, ok] A baby stepping move after an extruding move when the printer is idle replicates the same extrusion, https://forum.duet3d.com/topic/7940/firmware-2-02rc5-now-available
+- [done, test] Suppress motor disconnected message if motor current is very low, https://forum.duet3d.com/topic/7994/possible-bug/4
+- [done, ok] When entering a subfolder on the 12864 display from a file list, the screen does not update until you rotate the encoder, https://forum.duet3d.com/topic/8014/12864-display-sd-print-subfolder-screen-update
+- [done, ok] Add date/time if known to config-override.g
+- [done, ok] Resume after pause doesn't use workplace coordinate offsets, https://forum.duet3d.com/topic/4557/cnc-coordinate-systems/29 and https://forum.duet3d.com/topic/7940/firmware-2-02rc5-now-available/16
+- [done, ok] Add nanoDLP to compatibility options, also add M650 and M651 support
+- [done] Return a 503 http error when we run out of buffers while trying to compose a http reply
+- [done] M206 now sets offsets for the current workplace, not workplace 0
+- [done] memory for 12864 display and menu system is not allocated until M918 is processed
+- [done, test] scheduled vs. completed move count wrong, https://forum.duet3d.com/topic/8052/print-stopped-at-83-for-seemingly-no-reason/2
+- [done, ok] G2/G3 moves use a variable arg segment length
+- [done, ok] Add sin + cosine calculation time
+- [done, ok] New version of FatFS
+- [done, ok] Allow M226 and M600 even when no file is being printed
+- [done, test] Print progress based on requested extrusion *before* mixing, for ditto printing
+- [done, ok] G30 after SCARA homing prox and distal sometimes failed due to rounding error in arm calculation, https://forum.duet3d.com/post/72199
Future:
+- Run script if thermal error? https://forum.duet3d.com/topic/8038/suggestion-run-script-in-case-of-thermal-error
+- Run script on filament error?
+- In CNC mode, allow Fanuc-style X and/or Y coordinates without repeating the G0 or G1 command
- Option for an endstop input to trigger an emergency pause
+- Count steps until homing switch is triggered compared to original, https://forum.duet3d.com/topic/8017/request-check-for-lost-steps
- In CNC or laser mode, don't segment G0 moves for mesh bed compensation, https://forum.duet3d.com/topic/7728/go-vs-g1-movement/11
-- Z homing switch offset in M208 or elswhere, https://forum.duet3d.com/topic/7767/z-offset-is-negated-in-homing-g-macro
+- Z homing switch offset in M208 or elsewhere, https://forum.duet3d.com/topic/7767/z-offset-is-negated-in-homing-g-macro
- After looking for G1 Z commands in gcode file analyser, check that there is extrusion after it
- M260 allow bytes to be specified in hex, more generally allow hex anywhere?
- Auto mount SD card when it is inserted
diff --git a/src/Configuration.h b/src/Configuration.h
index a0285afd..7dcde5b7 100644
--- a/src/Configuration.h
+++ b/src/Configuration.h
@@ -47,6 +47,11 @@ constexpr float DefaultXYInstantDv = 15.0; // mm/sec
constexpr float DefaultZInstantDv = 0.2;
constexpr float DefaultEInstantDv = 2.0;
+constexpr float DefaultAxisMinimum = 0.0;
+constexpr float DefaultAxisMaximum = 200.0;
+
+constexpr float MinimumOpenLoadMotorCurrent = 300; // minimum current in mA for the open load status to be taken seriously
+
// Timeouts
constexpr uint32_t FanCheckInterval = 500; // Milliseconds
constexpr uint32_t OpenLoadTimeout = 500; // Milliseconds
@@ -205,7 +210,7 @@ constexpr int DefaultZProbeADValue = 500; // Default trigger threshold
constexpr float TRIANGLE_ZERO = -0.001; // Millimetres
constexpr float SILLY_Z_VALUE = -9999.0; // Millimetres
-// String lengths. Try not to have too many different ones.
+// String lengths. Try not to have too many different ones, because each one causes an instantiation of the String template
constexpr size_t MaxMessageLength = 256;
constexpr size_t MaxTitleLength = 61;
@@ -221,6 +226,7 @@ constexpr size_t MaxHeaterNameLength = 20; // Maximum number of characters in
constexpr size_t MaxFanNameLength = 20; // Maximum number of characters in a fan name
constexpr size_t FormatStringLength = 256;
+constexpr size_t GCodeReplyLength = 256; // Maximum number of characters in a GCode reply that doesn't use an OutputBuffer
constexpr size_t MachineNameLength = 40;
constexpr size_t RepRapPasswordLength = 20;
constexpr size_t MediumStringLength = MaxFilenameLength;
diff --git a/src/GCodes/GCodeMachineState.h b/src/GCodes/GCodeMachineState.h
index 7e015aea..443a5e2f 100644
--- a/src/GCodes/GCodeMachineState.h
+++ b/src/GCodes/GCodeMachineState.h
@@ -120,7 +120,7 @@ public:
post(!result.IsLive(); result.state == GCodeState::normal);
// Return true if the G54 command is in effect
- bool UsingG54() const { return useMachineCoordinates || useMachineCoordinatesSticky; }
+ bool UsingMachineCoordinates() const { return useMachineCoordinates || useMachineCoordinatesSticky; }
// Copy values that may have been altered by config.g into this state record
void CopyStateFrom(const GCodeMachineState& other)
diff --git a/src/GCodes/GCodes.cpp b/src/GCodes/GCodes.cpp
index 38590f75..7857d44a 100644
--- a/src/GCodes/GCodes.cpp
+++ b/src/GCodes/GCodes.cpp
@@ -44,21 +44,6 @@
# include "Fans/DotStarLed.h"
#endif
-const size_t gcodeReplyLength = 2048; // long enough to pass back a reasonable number of files in response to M20
-
-// Set up some default values for special moves, e.g. for Z probing and firmware retraction
-void GCodes::RawMove::SetDefaults()
-{
- moveType = 0;
- isCoordinated = false;
- usingStandardFeedrate = false;
- usePressureAdvance = false;
- endStopsToCheck = 0;
- filePos = noFilePosition;
- xAxes = DefaultXAxisMapping;
- yAxes = DefaultYAxisMapping;
-}
-
#if SUPPORT_OBJECT_MODEL
// Object model table and functions
@@ -146,11 +131,10 @@ void GCodes::Init()
Reset();
distanceScale = 1.0;
- arcSegmentLength = DefaultArcSegmentLength;
virtualExtruderPosition = rawExtruderTotal = 0.0;
- for (size_t extruder = 0; extruder < MaxExtruders; extruder++)
+ for (float& f : rawExtruderTotalByDrive)
{
- rawExtruderTotalByDrive[extruder] = 0.0;
+ f = 0.0;
}
runningConfigFile = false;
@@ -160,9 +144,9 @@ void GCodes::Init()
limitAxes = noMovesBeforeHoming = true;
SetAllAxesNotHomed();
- for (size_t i = 0; i < NUM_FANS; ++i)
+ for (float& f : pausedFanSpeeds)
{
- pausedFanSpeeds[i] = 0.0;
+ f = 0.0;
}
lastDefaultFanSpeed = pausedDefaultFanSpeed = 0.0;
@@ -237,9 +221,9 @@ void GCodes::Reset()
currentCoordinateSystem = 0;
#endif
- for (size_t i = 0; i < MaxTotalDrivers; ++i)
+ for (float& f : moveBuffer.coords)
{
- moveBuffer.coords[i] = 0.0; // clear out all axis and extruder coordinates
+ f = 0.0; // clear out all axis and extruder coordinates
}
ClearMove();
@@ -287,17 +271,17 @@ void GCodes::Reset()
codeQueue->Clear();
cancelWait = isWaiting = displayNoToolWarning = false;
- for (size_t i = 0; i < NumResources; ++i)
+ for (const GCodeBuffer*& gbp : resourceOwners)
{
- resourceOwners[i] = nullptr;
+ gbp = nullptr;
}
}
bool GCodes::DoingFileMacro() const
{
- for (const GCodeBuffer *gb : gcodeSources)
+ for (const GCodeBuffer *gbp : gcodeSources)
{
- if (gb != nullptr && gb->IsDoingFileMacro())
+ if (gbp != nullptr && gbp->IsDoingFileMacro())
{
return true;
}
@@ -408,7 +392,7 @@ void GCodes::Spin()
GCodeBuffer& gb = *gbp;
// Set up a buffer for the reply
- String<gcodeReplyLength> reply;
+ String<GCodeReplyLength> reply;
if (gb.GetState() == GCodeState::normal)
{
@@ -481,6 +465,11 @@ void GCodes::RunStateMachine(GCodeBuffer& gb, const StringRef& reply)
}
}
}
+
+ if (platform.Emulating() == Compatibility::nanoDLP && &gb == serialGCode && !DoingFileMacro())
+ {
+ reply.copy("Z_move_comp");
+ }
gb.SetState(GCodeState::normal);
}
break;
@@ -526,7 +515,8 @@ void GCodes::RunStateMachine(GCodeBuffer& gb, const StringRef& reply)
// went (i.e. the difference between our start and end positions) and if we need to
// incorporate any correction factors. That's why we only need to set the final tool
// offset to this value in order to finish the tool probing.
- currentTool->SetOffset(axis, (toolChangeRestorePoint.moveCoords[axis] - currentUserPosition[axis]) + gb.GetFValue(), true);
+ const float coord = toolChangeRestorePoint.moveCoords[axis] - currentUserPosition[axis] + gb.GetFValue();
+ currentTool->SetOffset(axis, coord, true);
break;
}
}
@@ -542,7 +532,7 @@ void GCodes::RunStateMachine(GCodeBuffer& gb, const StringRef& reply)
}
else
{
- String<PASSWORD_LENGTH> nextHomingFileName;
+ String<RepRapPasswordLength> nextHomingFileName;
AxesBitmap mustHomeFirst = reprap.GetMove().GetKinematics().GetHomingFileName(toBeHomed, axesHomed, numVisibleAxes, nextHomingFileName.GetRef());
if (mustHomeFirst != 0)
{
@@ -590,8 +580,7 @@ void GCodes::RunStateMachine(GCodeBuffer& gb, const StringRef& reply)
case GCodeState::m109ToolChange0: // Run tfree for the old tool (if any)
doingToolChange = true;
SaveFanSpeeds();
- memcpy(toolChangeRestorePoint.moveCoords, currentUserPosition, MaxAxes * sizeof(currentUserPosition[0]));
- toolChangeRestorePoint.feedRate = gb.MachineState().feedRate;
+ SavePosition(toolChangeRestorePoint, gb);
gb.AdvanceState();
if ((gb.MachineState().toolChangeParam & TFreeBit) != 0)
{
@@ -725,16 +714,12 @@ void GCodes::RunStateMachine(GCodeBuffer& gb, const StringRef& reply)
if (LockMovementAndWaitForStandstill(gb))
{
float currentZ = moveBuffer.coords[Z_AXIS];
- for (size_t drive = 0; drive < numVisibleAxes; ++drive)
+ for (size_t axis = 0; axis < numVisibleAxes; ++axis)
{
- currentUserPosition[drive] = pauseRestorePoint.moveCoords[drive];
+ currentUserPosition[axis] = pauseRestorePoint.moveCoords[axis];
}
ToolOffsetTransform(currentUserPosition, moveBuffer.coords);
- for (size_t drive = numTotalAxes; drive < MaxTotalDrivers; ++drive)
- {
- moveBuffer.coords[drive] = 0.0;
- }
- moveBuffer.SetDefaults();
+ SetMoveBufferDefaults();
moveBuffer.feedRate = DefaultFeedRate * SecondsToMinutes; // ask for a good feed rate, we may have paused during a slow move
if (gb.GetState() == GCodeState::resuming1 && currentZ > pauseRestorePoint.moveCoords[Z_AXIS])
{
@@ -847,7 +832,7 @@ void GCodes::RunStateMachine(GCodeBuffer& gb, const StringRef& reply)
{
if (move.IsAccessibleProbePoint(x, y))
{
- moveBuffer.SetDefaults();
+ SetMoveBufferDefaults();
moveBuffer.coords[X_AXIS] = x - platform.GetCurrentZProbeParameters().xOffset;
moveBuffer.coords[Y_AXIS] = y - platform.GetCurrentZProbeParameters().yOffset;
moveBuffer.coords[Z_AXIS] = platform.GetZProbeStartingHeight();
@@ -924,7 +909,7 @@ void GCodes::RunStateMachine(GCodeBuffer& gb, const StringRef& reply)
{
zProbeTriggered = false;
platform.SetProbing(true);
- moveBuffer.SetDefaults();
+ SetMoveBufferDefaults();
moveBuffer.endStopsToCheck = ZProbeActive;
moveBuffer.coords[Z_AXIS] = -platform.GetZProbeDiveHeight();
moveBuffer.feedRate = platform.GetCurrentZProbeParameters().probeSpeed;
@@ -973,7 +958,7 @@ void GCodes::RunStateMachine(GCodeBuffer& gb, const StringRef& reply)
case GCodeState::gridProbing4a: // ready to lift the probe after probing the current grid probe point
// Move back up to the dive height
- moveBuffer.SetDefaults();
+ SetMoveBufferDefaults();
moveBuffer.coords[Z_AXIS] = platform.GetZProbeStartingHeight();
moveBuffer.feedRate = platform.GetZProbeTravelSpeed();
NewMoveAvailable(1);
@@ -1103,7 +1088,7 @@ void GCodes::RunStateMachine(GCodeBuffer& gb, const StringRef& reply)
// States used for G30 probing
case GCodeState::probingAtPoint0:
// Initial state when executing G30 with a P parameter. Start by moving to the dive height at the current position.
- moveBuffer.SetDefaults();
+ SetMoveBufferDefaults();
moveBuffer.coords[Z_AXIS] = platform.GetZProbeStartingHeight();
moveBuffer.feedRate = platform.GetZProbeTravelSpeed();
NewMoveAvailable(1);
@@ -1114,9 +1099,8 @@ void GCodes::RunStateMachine(GCodeBuffer& gb, const StringRef& reply)
// The move to raise/lower the head to the correct dive height has been commanded.
if (LockMovementAndWaitForStandstill(gb))
{
- // Head is at the dive height but needs to be moved to the correct XY position.
- // The XY coordinates have already been stored.
- moveBuffer.SetDefaults();
+ // Head is at the dive height but needs to be moved to the correct XY position. The XY coordinates have already been stored.
+ SetMoveBufferDefaults();
(void)reprap.GetMove().GetProbeCoordinates(g30ProbePointIndex, moveBuffer.coords[X_AXIS], moveBuffer.coords[Y_AXIS], true);
moveBuffer.coords[Z_AXIS] = platform.GetZProbeStartingHeight();
moveBuffer.feedRate = platform.GetZProbeTravelSpeed();
@@ -1186,7 +1170,7 @@ void GCodes::RunStateMachine(GCodeBuffer& gb, const StringRef& reply)
{
zProbeTriggered = false;
platform.SetProbing(true);
- moveBuffer.SetDefaults();
+ SetMoveBufferDefaults();
moveBuffer.endStopsToCheck = ZProbeActive;
moveBuffer.coords[Z_AXIS] = (GetAxisIsHomed(Z_AXIS))
? -platform.GetZProbeDiveHeight() // Z axis has been homed, so no point in going very far
@@ -1267,7 +1251,7 @@ void GCodes::RunStateMachine(GCodeBuffer& gb, const StringRef& reply)
case GCodeState::probingAtPoint4a:
// Move back up to the dive height before we change anything, in particular before we adjust leadscrews
- moveBuffer.SetDefaults();
+ SetMoveBufferDefaults();
moveBuffer.coords[Z_AXIS] = platform.GetZProbeStartingHeight();
moveBuffer.feedRate = platform.GetZProbeTravelSpeed();
NewMoveAvailable(1);
@@ -1387,12 +1371,8 @@ void GCodes::RunStateMachine(GCodeBuffer& gb, const StringRef& reply)
const AxesBitmap xAxes = reprap.GetCurrentXAxes();
const AxesBitmap yAxes = reprap.GetCurrentYAxes();
reprap.GetMove().GetCurrentUserPosition(moveBuffer.coords, 0, xAxes, yAxes);
+ SetMoveBufferDefaults();
moveBuffer.coords[Z_AXIS] += retractHop;
- for (size_t i = numTotalAxes; i < MaxTotalDrivers; ++i)
- {
- moveBuffer.coords[i] = 0.0;
- }
- moveBuffer.SetDefaults();
moveBuffer.feedRate = platform.MaxFeedrate(Z_AXIS);
moveBuffer.filePos = (&gb == fileGCode) ? gb.GetFilePosition(fileInput->BytesCached()) : noFilePosition;
moveBuffer.canPauseAfter = false; // don't pause after a retraction because that could cause too much retraction
@@ -1412,15 +1392,11 @@ void GCodes::RunStateMachine(GCodeBuffer& gb, const StringRef& reply)
const uint32_t xAxes = reprap.GetCurrentXAxes();
const uint32_t yAxes = reprap.GetCurrentYAxes();
reprap.GetMove().GetCurrentUserPosition(moveBuffer.coords, 0, xAxes, yAxes);
- for (size_t i = numTotalAxes; i < MaxTotalDrivers; ++i)
- {
- moveBuffer.coords[i] = 0.0;
- }
+ SetMoveBufferDefaults();
for (size_t i = 0; i < tool->DriveCount(); ++i)
{
moveBuffer.coords[numTotalAxes + tool->Drive(i)] = retractLength + retractExtra;
}
- moveBuffer.SetDefaults();
moveBuffer.feedRate = unRetractSpeed;
moveBuffer.isFirmwareRetraction = true;
moveBuffer.filePos = (&gb == fileGCode) ? gb.MachineState().fileState.GetPosition() - fileInput->BytesCached() : noFilePosition;
@@ -1634,7 +1610,7 @@ void GCodes::EndSimulation(GCodeBuffer *gb)
// Ending a simulation, so restore the position
RestorePosition(simulationRestorePoint, gb);
ToolOffsetTransform(currentUserPosition, moveBuffer.coords);
- reprap.GetMove().SetNewPosition(simulationRestorePoint.moveCoords, true);
+ reprap.GetMove().SetNewPosition(moveBuffer.coords, true);
axesHomed = axesHomedBeforeSimulation;
}
@@ -1775,7 +1751,7 @@ void GCodes::DoPause(GCodeBuffer& gb, PauseReason reason, const char *msg)
#endif
}
- // Replace the paused machine coordinates by user coordinates, which we updated earlier
+ // Replace the paused machine coordinates by user coordinates, which we updated earlier if they were returned by Move::PausePrint
for (size_t axis = 0; axis < numVisibleAxes; ++axis)
{
pauseRestorePoint.moveCoords[axis] = currentUserPosition[axis];
@@ -1901,6 +1877,10 @@ bool GCodes::DoEmergencyPause()
// Save the resume info, stop movement immediately and run the low voltage pause script to lift the nozzle etc.
GrabMovement(*autoPauseGCode);
+ // When we use RTOS there is a possible race condition in the following, because we might try to pause when a waiting move has just been added
+ // but before the gcode buffer has been re-initialised ready for the next command. So start a critical section.
+ TaskCriticalSectionLocker lock;
+
const bool movesSkipped = reprap.GetMove().LowPowerOrStallPause(pauseRestorePoint);
if (movesSkipped)
{
@@ -1927,8 +1907,6 @@ bool GCodes::DoEmergencyPause()
pauseRestorePoint.feedRate = fileGCode->MachineState().feedRate;
pauseRestorePoint.virtualExtruderPosition = virtualExtruderPosition;
- // TODO: when we use RTOS there is a possible race condition in the following,
- // because we might try to pause when a waiting move has just been added but before the gcode buffer has been re-initialised ready for the next command
pauseRestorePoint.filePos = fileGCode->GetFilePosition(fileInput->BytesCached());
pauseRestorePoint.proportionDone = 0.0;
#if SUPPORT_LASER || SUPPORT_IOBITS
@@ -1936,6 +1914,8 @@ bool GCodes::DoEmergencyPause()
#endif
}
+ codeQueue->PurgeEntries();
+
// Replace the paused machine coordinates by user coordinates, which we updated earlier
for (size_t axis = 0; axis < numVisibleAxes; ++axis)
{
@@ -2038,7 +2018,7 @@ bool GCodes::PauseOnStall(DriversBitmap stalledDrivers)
return false;
}
- String<100> stallErrorString;
+ String<MediumStringLength> stallErrorString;
stallErrorString.printf("Stall detected on driver(s)");
ListDrivers(stallErrorString.GetRef(), stalledDrivers);
DoPause(*autoPauseGCode, PauseReason::stall, stallErrorString.c_str());
@@ -2331,6 +2311,13 @@ bool GCodes::LoadExtrusionAndFeedrateFromGCode(GCodeBuffer& gb)
virtualExtruderPosition = moveArg;
}
+ // rawExtruderTotal is used to calculate print progress, so it must be based on the requested extrusion before accounting for mixing,
+ // otherwise IDEX ditto printing and similar gives strange results
+ if (moveBuffer.moveType == 0 && !doingToolChange)
+ {
+ rawExtruderTotal += requestedExtrusionAmount;
+ }
+
for (size_t eDrive = 0; eDrive < eMoveCount; eDrive++)
{
const int drive = tool->Drive(eDrive);
@@ -2344,10 +2331,6 @@ bool GCodes::LoadExtrusionAndFeedrateFromGCode(GCodeBuffer& gb)
rawExtruderTotalByDrive[drive] += extrusionAmount;
// Don't count extrusion done in filament loading or tool change macros towards total filament consumed, it distorts the print progress
- if (moveBuffer.moveType == 0 && !doingToolChange)
- {
- rawExtruderTotal += extrusionAmount;
- }
moveBuffer.coords[drive + numTotalAxes] = extrusionAmount * extrusionFactors[drive];
#if HAS_SMART_DRIVERS
if (moveBuffer.moveType == 1)
@@ -2431,13 +2414,6 @@ const char* GCodes::DoStraightMove(GCodeBuffer& gb, bool isCoordinated)
moveBuffer.yAxes = DefaultYAxisMapping;
}
}
-#if SUPPORT_WORKPLACE_COORDINATES
- else if (gb.MachineState().UsingG54())
- {
- moveBuffer.xAxes = DefaultXAxisMapping;
- moveBuffer.yAxes = DefaultYAxisMapping;
- }
-#endif
// Check for 'R' parameter to move relative to a restore point
const RestorePoint * rp = nullptr;
@@ -2454,6 +2430,14 @@ const char* GCodes::DoStraightMove(GCodeBuffer& gb, bool isCoordinated)
}
}
+#if SUPPORT_WORKPLACE_COORDINATES
+ if (moveBuffer.moveType == 0 && rp == nullptr && gb.MachineState().UsingMachineCoordinates())
+ {
+ moveBuffer.xAxes = DefaultXAxisMapping;
+ moveBuffer.yAxes = DefaultYAxisMapping;
+ }
+#endif
+
// Check for laser power setting or IOBITS
#if SUPPORT_LASER || SUPPORT_IOBITS
if (rp != nullptr)
@@ -2493,7 +2477,7 @@ const char* GCodes::DoStraightMove(GCodeBuffer& gb, bool isCoordinated)
#endif
#endif
- if (moveBuffer.moveType != 0 || gb.MachineState().UsingG54())
+ if (moveBuffer.moveType != 0 || (rp == nullptr && gb.MachineState().UsingMachineCoordinates()))
{
// This may be a raw motor move, in which case we need the current raw motor positions in moveBuffer.coords.
// If it isn't a raw motor move, it will still be applied without axis or bed transform applied,
@@ -2520,7 +2504,7 @@ const char* GCodes::DoStraightMove(GCodeBuffer& gb, bool isCoordinated)
SetBit(axesMentioned, axis);
const float moveArg = gb.GetFValue() * distanceScale;
- if (moveBuffer.moveType != 0 || gb.MachineState().UsingG54())
+ if (moveBuffer.moveType != 0 || (rp == nullptr && gb.MachineState().UsingMachineCoordinates()))
{
if (gb.MachineState().axesRelative)
{
@@ -2586,7 +2570,7 @@ const char* GCodes::DoStraightMove(GCodeBuffer& gb, bool isCoordinated)
}
else
{
- if (gb.MachineState().UsingG54())
+ if (rp == nullptr && gb.MachineState().UsingMachineCoordinates())
{
gb.SetState(GCodeState::waitingForSpecialMoveToComplete); // we need to update the user coordinates after the move
}
@@ -2598,6 +2582,12 @@ const char* GCodes::DoStraightMove(GCodeBuffer& gb, bool isCoordinated)
}
ToolOffsetTransform(currentUserPosition, moveBuffer.coords, axesMentioned); // apply tool offset, axis mapping, baby stepping, Z hop and axis scaling
+
+ // If we are emulating Marlin for nanoDLP then we need to set a special end state
+ if (platform.Emulating() == Compatibility::nanoDLP && &gb == serialGCode && !DoingFileMacro())
+ {
+ gb.SetState(GCodeState::waitingForSpecialMoveToComplete);
+ }
}
AxesBitmap effectiveAxesHomed = axesHomed;
@@ -2830,6 +2820,9 @@ const char* GCodes::DoArcMove(GCodeBuffer& gb, bool clockwise)
}
// Compute how many segments we need to move, but don't store it yet
+ // For the arc to deviate up to MaxArcDeviation from the ideal, the segment length should be sqrt(8 * arcRadius * MaxArcDeviation + fsquare(MaxArcDeviation))
+ // We leave out the square term because it is very small
+ const float arcSegmentLength = constrain<float>(sqrt(8 * arcRadius * MaxArcDeviation), MinArcSegmentLength, MaxArcSegmentLength);
totalSegments = max<unsigned int>((unsigned int)((arcRadius * totalArc)/arcSegmentLength + 0.8), 1u);
arcAngleIncrement = totalArc/totalSegments;
if (clockwise)
@@ -3782,6 +3775,7 @@ void GCodes::HandleReply(GCodeBuffer& gb, GCodeResult rslt, const char* reply)
}
break;
+ case Compatibility::nanoDLP: // nanoDLP is like Marlin except that G0 and G1 commands return "Z_move_comp<LF>" before "ok<LF>"
case Compatibility::marlin:
// We don't need to handle M20 here because we always allocate an output buffer for that one
if (gb.GetCommandLetter() == 'M' && gb.GetCommandNumber() == 28)
@@ -3854,6 +3848,7 @@ void GCodes::HandleReply(GCodeBuffer& gb, OutputBuffer *reply)
return;
case Compatibility::marlin:
+ case Compatibility::nanoDLP:
if (gb.GetCommandLetter() =='M' && gb.GetCommandNumber() == 20)
{
platform.Message(type, "Begin file list\n");
@@ -4171,11 +4166,7 @@ GCodeResult GCodes::RetractFilament(GCodeBuffer& gb, bool retract)
const uint32_t xAxes = reprap.GetCurrentXAxes();
const uint32_t yAxes = reprap.GetCurrentYAxes();
reprap.GetMove().GetCurrentUserPosition(moveBuffer.coords, 0, xAxes, yAxes);
- for (size_t i = numTotalAxes; i < MaxTotalDrivers; ++i)
- {
- moveBuffer.coords[i] = 0.0;
- }
- moveBuffer.SetDefaults();
+ SetMoveBufferDefaults();
moveBuffer.isFirmwareRetraction = true;
moveBuffer.filePos = (&gb == fileGCode) ? gb.GetFilePosition(fileInput->BytesCached()) : noFilePosition;
moveBuffer.xAxes = xAxes;
@@ -4421,7 +4412,7 @@ void GCodes::StopPrint(StopPrintReason reason)
}
}
- if (platform.Emulating() == Compatibility::marlin)
+ if (platform.EmulatingMarlin())
{
// Pronterface expects a "Done printing" message
platform.Message(UsbMessage, "Done printing file\n");
@@ -4470,7 +4461,8 @@ void GCodes::UpdateCurrentUserPosition()
ToolOffsetInverseTransform(moveBuffer.coords, currentUserPosition);
}
-// Save position to a restore point
+// Save position to a restore point.
+// Note that restore point coordinates are not affected by workplace coordinate offsets. This allows them to be use din resume.g.
void GCodes::SavePosition(RestorePoint& rp, const GCodeBuffer& gb) const
{
for (size_t axis = 0; axis < numVisibleAxes; ++axis)
@@ -4514,13 +4506,7 @@ void GCodes::ToolOffsetTransform(const float coordsIn[MaxAxes], float coordsOut[
{
for (size_t axis = 0; axis < numVisibleAxes; ++axis)
{
- const float totalOffset =
-#if SUPPORT_WORKPLACE_COORDINATES
- workplaceCoordinates[currentCoordinateSystem][axis];
-#else
- axisOffsets[axis];
-#endif
- coordsOut[axis] = (coordsIn[axis] * axisScaleFactors[axis]) + totalOffset;
+ coordsOut[axis] = (coordsIn[axis] * axisScaleFactors[axis]) + GetWorkplaceOffset(axis);
}
}
else
@@ -4533,13 +4519,7 @@ void GCodes::ToolOffsetTransform(const float coordsIn[MaxAxes], float coordsOut[
&& (axis != Y_AXIS || IsBitSet(yAxes, Y_AXIS))
)
{
- const float totalOffset =
-#if SUPPORT_WORKPLACE_COORDINATES
- workplaceCoordinates[currentCoordinateSystem][axis]
-#else
- axisOffsets[axis]
-#endif
- - currentTool->GetOffset(axis);
+ const float totalOffset = GetWorkplaceOffset(axis) - currentTool->GetOffset(axis);
const size_t inputAxis = (IsBitSet(explicitAxes, axis)) ? axis
: (IsBitSet(xAxes, axis)) ? X_AXIS
: (IsBitSet(yAxes, axis)) ? Y_AXIS
@@ -4560,13 +4540,7 @@ void GCodes::ToolOffsetInverseTransform(const float coordsIn[MaxAxes], float coo
{
for (size_t axis = 0; axis < numVisibleAxes; ++axis)
{
- const float totalOffset =
-#if SUPPORT_WORKPLACE_COORDINATES
- workplaceCoordinates[currentCoordinateSystem][axis];
-#else
- axisOffsets[axis];
-#endif
- coordsOut[axis] = (coordsIn[axis] - totalOffset) / axisScaleFactors[axis];
+ coordsOut[axis] = (coordsIn[axis] - GetWorkplaceOffset(axis)) / axisScaleFactors[axis];
}
}
else
@@ -4577,13 +4551,7 @@ void GCodes::ToolOffsetInverseTransform(const float coordsIn[MaxAxes], float coo
size_t numXAxes = 0, numYAxes = 0;
for (size_t axis = 0; axis < numVisibleAxes; ++axis)
{
- const float totalOffset =
-#if SUPPORT_WORKPLACE_COORDINATES
- workplaceCoordinates[currentCoordinateSystem][axis]
-#else
- axisOffsets[axis]
-#endif
- - currentTool->GetOffset(axis);
+ const float totalOffset = GetWorkplaceOffset(axis) - currentTool->GetOffset(axis);
coordsOut[axis] = coordsIn[axis]/axisScaleFactors[axis] - totalOffset;
if (IsBitSet(xAxes, axis))
{
@@ -4725,7 +4693,7 @@ GCodeResult GCodes::WriteConfigOverrideFile(GCodeBuffer& gb, const StringRef& re
return GCodeResult::error;
}
- bool ok = f->Write("; This is a system-generated file - do not edit\n");
+ bool ok = WriteConfigOverrideHeader(f);
if (ok)
{
ok = reprap.GetMove().GetKinematics().WriteCalibrationParameters(f);
@@ -4773,6 +4741,28 @@ GCodeResult GCodes::WriteConfigOverrideFile(GCodeBuffer& gb, const StringRef& re
return GCodeResult::ok;
}
+// Write the config-override header returning true if success
+// This is implemented as a separate function to avoid allocating a buffer on the stack and then calling functions that also allocate buffers on the stack
+bool GCodes::WriteConfigOverrideHeader(FileStore *f) const
+{
+ String<MaxFilenameLength> buf;
+ buf.copy("; config-override.g file generated in response to M500");
+ if (platform.IsDateTimeSet())
+ {
+ time_t timeNow = platform.GetDateTime();
+ const struct tm * const timeInfo = gmtime(&timeNow);
+ buf.catf(" at %04u-%02u-%02u %02u:%02u",
+ timeInfo->tm_year + 1900, timeInfo->tm_mon + 1, timeInfo->tm_mday, timeInfo->tm_hour, timeInfo->tm_min);
+ }
+ buf.cat('\n');
+ bool ok = f->Write(buf.c_str());
+ if (ok)
+ {
+ ok = f->Write("; This is a system-generated file - do not edit\n");
+ }
+ return ok;
+}
+
// Report the temperatures of one tool in M105 format
void GCodes::ReportToolTemperatures(const StringRef& reply, const Tool *tool, bool includeNumber) const
{
@@ -4861,7 +4851,7 @@ void GCodes::CheckReportDue(GCodeBuffer& gb, const StringRef& reply) const
{
if (now - gb.whenTimerStarted >= 1000)
{
- if (platform.Emulating() == Compatibility::marlin && (&gb == serialGCode || &gb == telnetGCode))
+ if (platform.EmulatingMarlin() && (&gb == serialGCode || &gb == telnetGCode))
{
// In Marlin emulation mode we should return a standard temperature report every second
GenerateTemperatureReport(reply);
@@ -4920,6 +4910,23 @@ OutputBuffer *GCodes::GenerateJsonStatusResponse(int type, int seq, ResponseSour
return statusResponse;
}
+// Set up some default values in the move buffer for special moves, e.g. for Z probing and firmware retraction
+void GCodes::SetMoveBufferDefaults()
+{
+ moveBuffer.moveType = 0;
+ moveBuffer.isCoordinated = false;
+ moveBuffer.usingStandardFeedrate = false;
+ moveBuffer.usePressureAdvance = false;
+ moveBuffer.endStopsToCheck = 0;
+ moveBuffer.filePos = noFilePosition;
+ moveBuffer.xAxes = DefaultXAxisMapping;
+ moveBuffer.yAxes = DefaultYAxisMapping;
+ for (size_t drive = numTotalAxes; drive < MaxTotalDrivers; ++drive)
+ {
+ moveBuffer.coords[drive] = 0.0; // clear extrusion
+ }
+}
+
// Resource locking/unlocking
// Lock the resource, returning true if success.
diff --git a/src/GCodes/GCodes.h b/src/GCodes/GCodes.h
index 059cf400..ac096872 100644
--- a/src/GCodes/GCodes.h
+++ b/src/GCodes/GCodes.h
@@ -130,8 +130,6 @@ public:
uint8_t hasExtrusion : 1; // true if the move includes extrusion - only valid if the move was set up by SetupMove
uint8_t isCoordinated : 1; // true if this is a coordinates move
uint8_t usingStandardFeedrate : 1; // true if this move uses the standard feed rate
-
- void SetDefaults(); // set up default values
};
GCodes(Platform& p);
@@ -367,6 +365,8 @@ private:
GCodeResult ChangeSimulationMode(GCodeBuffer& gb, const StringRef &reply, uint32_t newSimulationMode); // Handle M37 to change the simulation mode
GCodeResult WriteConfigOverrideFile(GCodeBuffer& gb, const StringRef& reply) const; // Write the config-override file
+ bool WriteConfigOverrideHeader(FileStore *f) const; // Write the config-override header
+
void CopyConfigFinalValues(GCodeBuffer& gb); // Copy the feed rate etc. from the daemon to the input channels
void ClearBabyStepping() { currentBabyStepZOffset = 0.0; }
@@ -386,11 +386,22 @@ private:
void NewMoveAvailable(unsigned int sl); // Flag that a new move is available
void NewMoveAvailable(); // Flag that a new move is available
+ void SetMoveBufferDefaults(); // Set up default values in the move buffer
+
#if SUPPORT_12864_LCD
int GetHeaterNumber(unsigned int itemNumber) const;
#endif
Pwm_t ConvertLaserPwm(float reqVal) const;
+ inline float GetWorkplaceOffset(size_t axis) const
+ {
+#if SUPPORT_WORKPLACE_COORDINATES
+ return workplaceCoordinates[currentCoordinateSystem][axis];
+#else
+ return axisOffsets[axis];
+#endif
+ }
+
#ifdef SERIAL_AUX_DEVICE
static bool emergencyStopCommanded;
static void CommandEmergencyStop(UARTClass *p);
@@ -482,7 +493,6 @@ private:
float rawExtruderTotalByDrive[MaxExtruders]; // Extrusion amount in the last G1 command with an E parameter when in absolute extrusion mode
float rawExtruderTotal; // Total extrusion amount fed to Move class since starting print, before applying extrusion factor, summed over all drives
float distanceScale; // MM or inches
- float arcSegmentLength; // Length of segments that we split arc moves into
#if SUPPORT_WORKPLACE_COORDINATES
static const size_t NumCoordinateSystems = 9;
@@ -599,6 +609,7 @@ private:
static constexpr const char* RESUME_AFTER_POWER_FAIL_G = "resurrect.g";
static constexpr const char* RESUME_PROLOGUE_G = "resurrect-prologue.g";
static constexpr const char* FILAMENT_CHANGE_G = "filament-change.g";
+ static constexpr const char* PEEL_MOVE_G = "peel-move.g";
#if HAS_SMART_DRIVERS
static constexpr const char* REHOME_G = "rehome.g";
#endif
diff --git a/src/GCodes/GCodes2.cpp b/src/GCodes/GCodes2.cpp
index 1ef0c8d1..a62735ce 100644
--- a/src/GCodes/GCodes2.cpp
+++ b/src/GCodes/GCodes2.cpp
@@ -615,7 +615,7 @@ bool GCodes::HandleMcode(GCodeBuffer& gb, const StringRef& reply)
outBuf->copy("GCode files:\n");
}
- bool encapsulateList = ((&gb != serialGCode && &gb != telnetGCode) || platform.Emulating() != Compatibility::marlin);
+ bool encapsulateList = ((&gb != serialGCode && &gb != telnetGCode) || !platform.EmulatingMarlin());
FileInfo fileInfo;
if (platform.GetMassStorage()->FindFirst(dir.c_str(), fileInfo))
{
@@ -623,11 +623,11 @@ bool GCodes::HandleMcode(GCodeBuffer& gb, const StringRef& reply)
do {
if (encapsulateList)
{
- outBuf->catf("%c%s%c%c", FILE_LIST_BRACKET, fileInfo.fileName, FILE_LIST_BRACKET, FILE_LIST_SEPARATOR);
+ outBuf->catf("%c%s%c%c", FILE_LIST_BRACKET, fileInfo.fileName.c_str(), FILE_LIST_BRACKET, FILE_LIST_SEPARATOR);
}
else
{
- outBuf->catf("%s\n", fileInfo.fileName);
+ outBuf->catf("%s\n", fileInfo.fileName.c_str());
}
} while (platform.GetMassStorage()->FindNext(fileInfo));
@@ -688,7 +688,7 @@ bool GCodes::HandleMcode(GCodeBuffer& gb, const StringRef& reply)
if (QueueFileToPrint(filename.c_str(), reply))
{
reprap.GetPrintMonitor().StartingPrint(filename.c_str());
- if (platform.Emulating() == Compatibility::marlin && (&gb == serialGCode || &gb == telnetGCode))
+ if (platform.EmulatingMarlin() && (&gb == serialGCode || &gb == telnetGCode))
{
reply.copy("File opened\nFile selected");
}
@@ -779,8 +779,8 @@ bool GCodes::HandleMcode(GCodeBuffer& gb, const StringRef& reply)
}
break;
- case 226: // Gcode Initiated Pause
- if (&gb == fileGCode) // ignore M226 if it did't come from within a file being printed
+ case 226: // Synchronous pause, normally initiated from within the file being printed
+ if (!isPaused && !IsPausing())
{
if (gb.IsDoingFileMacro())
{
@@ -788,7 +788,7 @@ bool GCodes::HandleMcode(GCodeBuffer& gb, const StringRef& reply)
}
else
{
- if (!LockMovement(gb)) // lock movement before calling DoPause
+ if (!LockMovementAndWaitForStandstill(gb)) // lock movement before calling DoPause, also wait for movement to complete
{
return false;
}
@@ -797,8 +797,8 @@ bool GCodes::HandleMcode(GCodeBuffer& gb, const StringRef& reply)
}
break;
- case 600: // Filament change pause
- if (&gb == fileGCode) // ignore M600 if it did't come from within a file being printed
+ case 600: // Filament change pause, synchronous
+ if (!isPaused && !IsPausing())
{
if (gb.IsDoingFileMacro())
{
@@ -806,7 +806,7 @@ bool GCodes::HandleMcode(GCodeBuffer& gb, const StringRef& reply)
}
else
{
- if (!LockMovement(gb)) // lock movement before calling DoPause
+ if (!LockMovementAndWaitForStandstill(gb)) // lock movement before calling DoPause, also wait for movement to complete
{
return false;
}
@@ -1533,7 +1533,7 @@ bool GCodes::HandleMcode(GCodeBuffer& gb, const StringRef& reply)
case 117: // Display message
{
- String<MaxFilenameLength> msg;
+ String<MediumStringLength> msg;
gb.GetUnprecedentedString(msg.GetRef());
reprap.SetMessage(msg.c_str());
}
@@ -2180,7 +2180,7 @@ bool GCodes::HandleMcode(GCodeBuffer& gb, const StringRef& reply)
if (amountPushed != difference && segmentsLeft == 0 && reprap.GetMove().AllMovesAreFinished())
{
// The pipeline is empty, so execute the babystepping move immediately
- moveBuffer.SetDefaults();
+ SetMoveBufferDefaults();
moveBuffer.feedRate = platform.MaxFeedrate(Z_AXIS);
NewMoveAvailable(1);
}
@@ -2527,7 +2527,7 @@ bool GCodes::HandleMcode(GCodeBuffer& gb, const StringRef& reply)
#if SUPPORT_OBJECT_MODEL
case 1:
{
- String<MaxFilenameLength> filter;
+ String<MediumStringLength> filter;
bool dummy;
gb.TryGetQuotedString('F', filter.GetRef(), dummy);
if (!OutputBuffer::Allocate(outBuf))
@@ -2755,7 +2755,7 @@ bool GCodes::HandleMcode(GCodeBuffer& gb, const StringRef& reply)
case 550: // Set/report machine name
{
- String<MACHINE_NAME_LENGTH> name;
+ String<MachineNameLength> name;
bool seen = false;
gb.TryGetPossiblyQuotedString('P', name.GetRef(), seen);
if (seen)
@@ -2771,7 +2771,7 @@ bool GCodes::HandleMcode(GCodeBuffer& gb, const StringRef& reply)
case 551: // Set password (no option to report it)
{
- String<PASSWORD_LENGTH> password;
+ String<RepRapPasswordLength> password;
bool seen = false;
gb.TryGetPossiblyQuotedString('P', password.GetRef(), seen);
if (seen)
@@ -2899,7 +2899,7 @@ bool GCodes::HandleMcode(GCodeBuffer& gb, const StringRef& reply)
{
case Compatibility::me:
case Compatibility::reprapFirmware:
- reply.cat("RepRap Firmware (i.e. in native mode)");
+ reply.cat("RepRapFirmware (i.e. in native mode)");
break;
case Compatibility::marlin:
@@ -2918,6 +2918,10 @@ bool GCodes::HandleMcode(GCodeBuffer& gb, const StringRef& reply)
reply.cat("Repetier");
break;
+ case Compatibility::nanoDLP:
+ reply.cat("nanoDLP");
+ break;
+
default:
reply.catf("Unknown: (%u)", (unsigned int)platform.Emulating());
}
@@ -3534,6 +3538,17 @@ bool GCodes::HandleMcode(GCodeBuffer& gb, const StringRef& reply)
// For case 600, see 226
+ case 650: // Set peel move parameters - ignored
+ break;
+
+ case 651: // Execute DLP peel move
+ if (!LockMovementAndWaitForStandstill(gb))
+ {
+ return false;
+ }
+ DoFileMacro(gb, PEEL_MOVE_G, true);
+ break;
+
case 665: // Set delta configuration
if (!LockMovementAndWaitForStandstill(gb))
{
diff --git a/src/GCodes/GCodes3.cpp b/src/GCodes/GCodes3.cpp
index 0eb7120b..428b2ab0 100644
--- a/src/GCodes/GCodes3.cpp
+++ b/src/GCodes/GCodes3.cpp
@@ -120,7 +120,7 @@ GCodeResult GCodes::SetPrintZProbe(GCodeBuffer& gb, const StringRef& reply)
}
// Deal with G60
-GCodeResult GCodes::SavePosition(GCodeBuffer& gb,const StringRef& reply)
+GCodeResult GCodes::SavePosition(GCodeBuffer& gb, const StringRef& reply)
{
const uint32_t sParam = (gb.Seen('S')) ? gb.GetUIValue() : 0;
if (sParam < ARRAY_SIZE(numberedRestorePoints))
@@ -201,7 +201,7 @@ GCodeResult GCodes::OffsetAxes(GCodeBuffer& gb, const StringRef& reply)
if (gb.Seen(axisLetters[axis]))
{
#if SUPPORT_WORKPLACE_COORDINATES
- workplaceCoordinates[0][axis]
+ workplaceCoordinates[currentCoordinateSystem][axis]
#else
axisOffsets[axis]
#endif
@@ -450,7 +450,7 @@ GCodeResult GCodes::SimulateFile(GCodeBuffer& gb, const StringRef &reply, const
{
axesHomedBeforeSimulation = axesHomed;
axesHomed = LowestNBits<AxesBitmap>(numVisibleAxes); // pretend all axes are homed
- reprap.GetMove().GetCurrentUserPosition(simulationRestorePoint.moveCoords, 0, reprap.GetCurrentXAxes(), reprap.GetCurrentYAxes());
+ SavePosition(simulationRestorePoint, gb);
simulationRestorePoint.feedRate = gb.MachineState().feedRate;
}
simulationTime = 0.0;
@@ -488,8 +488,7 @@ GCodeResult GCodes::ChangeSimulationMode(GCodeBuffer& gb, const StringRef &reply
// Starting a new simulation, so save the current position
axesHomedBeforeSimulation = axesHomed;
axesHomed = LowestNBits<AxesBitmap>(numVisibleAxes); // pretend all axes are homed
- reprap.GetMove().GetCurrentUserPosition(simulationRestorePoint.moveCoords, 0, reprap.GetCurrentXAxes(), reprap.GetCurrentYAxes());
- simulationRestorePoint.feedRate = gb.MachineState().feedRate;
+ SavePosition(simulationRestorePoint, gb);
}
simulationTime = 0.0;
}
@@ -736,22 +735,20 @@ GCodeResult GCodes::DoDriveMapping(GCodeBuffer& gb, const StringRef& reply)
{
++drive;
}
- if (drive < MaxAxes)
+ if (drive == numTotalAxes && drive < MaxAxes)
{
- if (drive == numTotalAxes)
- {
- axisLetters[drive] = c; // assign the drive to this drive letter
- moveBuffer.coords[drive] = 0.0; // user has defined a new axis, so set its position
- currentUserPosition[drive] = 0.0; // set its requested user position too in case it is visible
- ++numTotalAxes;
- numVisibleAxes = numTotalAxes; // assume any new axes are visible unless there is a P parameter
- reprap.GetMove().SetNewPosition(moveBuffer.coords, true); // tell the Move system where the new axis is
- }
- platform.SetAxisDriversConfig(drive, config);
- if (numTotalAxes + numExtruders > MaxTotalDrivers)
- {
- numExtruders = MaxTotalDrivers - numTotalAxes; // if we added axes, we may have fewer extruders now
- }
+ axisLetters[drive] = c; // assign the drive to this drive letter
+ ++numTotalAxes;
+ numVisibleAxes = numTotalAxes; // assume any new axes are visible unless there is a P parameter
+ float initialCoords[MaxAxes];
+ reprap.GetMove().GetKinematics().GetAssumedInitialPosition(drive + 1, initialCoords);
+ moveBuffer.coords[drive] = initialCoords[drive]; // user has defined a new axis, so set its position
+ ToolOffsetInverseTransform(moveBuffer.coords, currentUserPosition);
+ }
+ platform.SetAxisDriversConfig(drive, config);
+ if (numTotalAxes + numExtruders > MaxTotalDrivers)
+ {
+ numExtruders = MaxTotalDrivers - numTotalAxes; // if we added axes, we may have fewer extruders now
}
}
++lettersToTry;
@@ -787,7 +784,10 @@ GCodeResult GCodes::DoDriveMapping(GCodeBuffer& gb, const StringRef& reply)
if (seen)
{
- UpdateCurrentUserPosition(); // make sure that any new visible axes are up to date
+ // In the DDA ring, the axis positions for invisible non-moving axes are not always copied over from previous moves.
+ // So if we have more visible axes than before, then we need to update their positions to get them in sync.
+ // We could do this only when we increase the number of visible axes, but for simplicity we do it always.
+ reprap.GetMove().SetNewPosition(moveBuffer.coords, true); // tell the Move system where the axes are
}
else
{
@@ -844,7 +844,7 @@ GCodeResult GCodes::ProbeTool(GCodeBuffer& gb, const StringRef& reply)
}
// Save the current axis coordinates
- memcpy(toolChangeRestorePoint.moveCoords, currentUserPosition, ARRAY_SIZE(currentUserPosition) * sizeof(currentUserPosition[0]));
+ SavePosition(toolChangeRestorePoint, gb);
// Prepare another move similar to G1 .. S3
moveBuffer.moveType = 3;
diff --git a/src/Movement/DDA.cpp b/src/Movement/DDA.cpp
index 0278e53a..ae0a5bc6 100644
--- a/src/Movement/DDA.cpp
+++ b/src/Movement/DDA.cpp
@@ -290,17 +290,17 @@ bool DDA::Init(GCodes::RawMove &nextMove, bool doMotorMapping)
for (size_t drive = 0; drive < MaxTotalDrivers; drive++)
{
accelerations[drive] = normalAccelerations[drive];
- if (drive >= numTotalAxes || (!doMotorMapping && drive < numVisibleAxes))
- {
- endPoint[drive] = Move::MotorEndPointToMachine(drive, nextMove.coords[drive]);
- }
-
endCoordinates[drive] = nextMove.coords[drive];
- int32_t delta;
+ int32_t delta; // this will be the net number of steps
+
if (drive < numTotalAxes)
{
+ if (!doMotorMapping && drive < numVisibleAxes)
+ {
+ endPoint[drive] = Move::MotorMovementToSteps(drive, nextMove.coords[drive]);
+ }
delta = endPoint[drive] - positionNow[drive];
- if (k.IsContinuousRotationAxis(drive) && nextMove.moveType != 1 && nextMove.moveType != 2)
+ if (k.IsContinuousRotationAxis(drive) && nextMove.moveType == 0)
{
const int32_t stepsPerRotation = lrintf(360.0 * reprap.GetPlatform().DriveStepsPerUnit(drive));
if (delta > stepsPerRotation/2)
@@ -312,27 +312,34 @@ bool DDA::Init(GCodes::RawMove &nextMove, bool doMotorMapping)
delta += stepsPerRotation;
}
}
- }
- else
- {
- delta = endPoint[drive];
- }
-
- if (drive < numTotalAxes && doMotorMapping)
- {
- const float positionDelta = nextMove.coords[drive] - prev->GetEndCoordinate(drive, false);
- directionVector[drive] = positionDelta;
- if (positionDelta != 0.0 && (IsBitSet(nextMove.yAxes, drive) || IsBitSet(nextMove.xAxes, drive)))
+ if (doMotorMapping)
+ {
+ const float positionDelta = nextMove.coords[drive] - prev->GetEndCoordinate(drive, false);
+ directionVector[drive] = positionDelta;
+ if (positionDelta != 0.0 && (IsBitSet(nextMove.yAxes, drive) || IsBitSet(nextMove.xAxes, drive)))
+ {
+ xyMoving = true;
+ }
+ }
+ else
{
- xyMoving = true;
+ directionVector[drive] = (float)delta/reprap.GetPlatform().DriveStepsPerUnit(drive);
}
}
else
{
- directionVector[drive] = (float)delta/reprap.GetPlatform().DriveStepsPerUnit(drive);
- if (drive >= numTotalAxes && nextMove.coords[drive] > 0.0)
+ // It's an extruder drive. We defer calculating the steps because they may be affected by nonlinear extrusion, which we can't calculate until we
+ // know the speed of the move, and because extruder movement is relative so we need to accumulate fractions of a whole step between moves.
+ const float movement = nextMove.coords[drive];
+ directionVector[drive] = movement;
+ if (movement != 0.0)
{
- extruding = true; // flag this move as extruding even if the number of extruder microsteps is zero
+ extruding = true;
+ delta = (movement > 0.0) ? 1 : -1; // set 1 step for now, it will be recalculated later
+ }
+ else
+ {
+ delta = 0;
}
}
@@ -347,8 +354,6 @@ bool DDA::Init(GCodes::RawMove &nextMove, bool doMotorMapping)
if (drive >= numTotalAxes)
{
// It's an extruder movement
- nextMove.coords[drive] -= directionVector[drive];
- // subtract the amount of extrusion we actually did to leave the residue outstanding
if (xyMoving && nextMove.usePressureAdvance)
{
const float compensationTime = reprap.GetPlatform().GetPressureAdvance(drive - numTotalAxes);
@@ -1044,7 +1049,7 @@ pre(disableDeltaMapping || drive < MaxAxes)
{
if (disableMotorMapping)
{
- return Move::MotorEndpointToPosition(endPoint[drive], drive);
+ return Move::MotorStepsToMovement(drive, endPoint[drive]);
}
else
{
@@ -1177,7 +1182,7 @@ inline void DDA::AdjustAcceleration()
// Prepare this DDA for execution.
// This must not be called with interrupts disabled, because it calls Platform::EnableDrive.
-void DDA::Prepare(uint8_t simMode)
+void DDA::Prepare(uint8_t simMode, float extrusionPending[])
{
if ( xyMoving
&& reprap.GetMove().IsDRCenabled()
@@ -1246,7 +1251,7 @@ void DDA::Prepare(uint8_t simMode)
#endif
// Handle all drivers
- const size_t numAxes = reprap.GetGCodes().GetTotalAxes();
+ const size_t numTotalAxes = reprap.GetGCodes().GetTotalAxes();
Platform& platform = reprap.GetPlatform();
for (size_t drive = 0; drive < NumDirectDrivers; ++drive)
{
@@ -1269,7 +1274,7 @@ void DDA::Prepare(uint8_t simMode)
else
{
reprap.GetPlatform().EnableDrive(drive);
- if (drive >= numAxes)
+ if (drive >= numTotalAxes)
{
// If there is any extruder jerk in this move, in theory that means we need to instantly extrude or retract some amount of filament.
// Pass the speed change to PrepareExtruder
@@ -1283,7 +1288,7 @@ void DDA::Prepare(uint8_t simMode)
{
speedChange = 0.0;
}
- pdm->PrepareExtruder(*this, params, speedChange, usePressureAdvance);
+ pdm->PrepareExtruder(*this, params, extrusionPending[drive - numTotalAxes], speedChange, usePressureAdvance);
// Check for sensible values, print them if they look dubious
if (reprap.Debug(moduleDda)
@@ -1350,7 +1355,7 @@ void DDA::Prepare(uint8_t simMode)
}
else
{
- if (drive < numAxes)
+ if (drive < numTotalAxes)
{
const AxisDriversConfig& config = platform.GetAxisDriversConfig(drive);
for (size_t i = 0; i < config.numDrivers; ++i)
@@ -1364,7 +1369,7 @@ void DDA::Prepare(uint8_t simMode)
}
else
{
- const uint8_t driver = platform.GetExtruderDriver(drive - numAxes);
+ const uint8_t driver = platform.GetExtruderDriver(drive - numTotalAxes);
if (driver >= NumDirectDrivers)
{
CanInterface::AddMovement(*this, params, driver - NumDirectDrivers, *pdm);
diff --git a/src/Movement/DDA.h b/src/Movement/DDA.h
index f506373e..452bcdd5 100644
--- a/src/Movement/DDA.h
+++ b/src/Movement/DDA.h
@@ -39,7 +39,8 @@ public:
DDA(DDA* n);
- bool Init(GCodes::RawMove &nextMove, bool doMotorMapping) __attribute__ ((hot)); // Set up a new move, returning true if it represents real movement
+ bool Init(GCodes::RawMove &nextMove, bool doMotorMapping) __attribute__ ((hot));
+ // Set up a new move, returning true if it represents real movement
bool Init(const float_t steps[MaxTotalDrivers]); // Set up a raw (unmapped) motor move
void Init(); // Set up initial positions for machine startup
bool Start(uint32_t tim) __attribute__ ((hot)); // Start executing the DDA, i.e. move the move.
@@ -48,7 +49,7 @@ public:
void SetPrevious(DDA *p) { prev = p; }
void Complete() { state = completed; }
bool Free();
- void Prepare(uint8_t simMode) __attribute__ ((hot)); // Calculate all the values and freeze this DDA
+ void Prepare(uint8_t simMode, float extrusionPending[]) __attribute__ ((hot)); // Calculate all the values and freeze this DDA
bool HasStepError() const;
bool CanPauseAfter() const { return canPauseAfter; }
bool IsPrintingMove() const { return isPrintingMove; } // Return true if this involves both XY movement and extrusion
diff --git a/src/Movement/DriveMovement.cpp b/src/Movement/DriveMovement.cpp
index 54805798..02c9078d 100644
--- a/src/Movement/DriveMovement.cpp
+++ b/src/Movement/DriveMovement.cpp
@@ -171,35 +171,45 @@ void DriveMovement::PrepareDeltaAxis(const DDA& dda, const PrepParams& params)
}
// Prepare this DM for an extruder move
-void DriveMovement::PrepareExtruder(const DDA& dda, const PrepParams& params, float speedChange, bool doCompensation)
+void DriveMovement::PrepareExtruder(const DDA& dda, const PrepParams& params, float& extrusionPending, float speedChange, bool doCompensation)
{
- const float dv = dda.directionVector[drive];
- float stepsPerMm = reprap.GetPlatform().DriveStepsPerUnit(drive) * fabsf(dv);
+ // Calculate the requested extrusion amount and a few other things
+ float dv = dda.directionVector[drive];
+ float extrusionRequired = dda.totalDistance * dv;
const size_t extruder = drive - reprap.GetGCodes().GetTotalAxes();
#if SUPPORT_NONLINEAR_EXTRUSION
+ // Add the nonlinear extrusion correction to totalExtrusion
if (dda.isPrintingMove)
{
float a, b, limit;
if (reprap.GetPlatform().GetExtrusionCoefficients(extruder, a, b, limit))
{
- const float averageExtrusionSpeed = (dda.totalDistance * dv * StepTimer::StepClockRate)/dda.clocksNeeded;
+ const float averageExtrusionSpeed = (extrusionRequired * StepTimer::StepClockRate)/dda.clocksNeeded;
const float factor = 1.0 + min<float>((averageExtrusionSpeed * a) + (averageExtrusionSpeed * averageExtrusionSpeed * b), limit);
- stepsPerMm *= factor;
+ extrusionRequired *= factor;
}
}
#endif
+ // Add on any fractional extrusion pending from the previous move
+ extrusionRequired += extrusionPending;
+ dv = extrusionRequired/dda.totalDistance;
+ direction = (dv >= 0.0);
+
+ const float rawStepsPerMm = reprap.GetPlatform().DriveStepsPerUnit(drive);
+ const float effectiveStepsPerMm = fabsf(dv) * rawStepsPerMm;
+
float compensationTime;
float accelCompensationDistance;
- int32_t netSteps;
- if (doCompensation && dv > 0.0)
+ if (doCompensation && direction)
{
// Calculate the pressure advance parameters
compensationTime = reprap.GetPlatform().GetPressureAdvance(extruder);
- mp.cart.compensationClocks = roundU32(compensationTime * (float)StepTimer::StepClockRate);
- mp.cart.accelCompensationClocks = roundU32(compensationTime * (float)StepTimer::StepClockRate * params.compFactor);
+ const float compensationClocks = compensationTime * (float)StepTimer::StepClockRate;
+ mp.cart.compensationClocks = roundU32(compensationClocks);
+ mp.cart.accelCompensationClocks = roundU32(compensationClocks * params.compFactor);
#ifdef COMPENSATE_SPEED_CHANGES
// If there is a speed change at the start of the move, theoretically we should instantly advance or retard the filament by the associated compensation amount.
@@ -207,33 +217,40 @@ void DriveMovement::PrepareExtruder(const DDA& dda, const PrepParams& params, fl
const float factor = 1.0 + (speedChange * compensationTime)/dda.totalDistance;
stepsPerMm *= factor;
#endif
- // Recalculate the net total step count to allow for compensation. It may be negative.
- const float compensationDistance = (dda.endSpeed - dda.startSpeed) * compensationTime;
- netSteps = (int32_t)((dda.totalDistance + compensationDistance) * stepsPerMm);
+ // Calculate the net total extrusion to allow for compensation. It may be negative.
+ extrusionRequired += (dda.endSpeed - dda.startSpeed) * compensationTime * dv;
// Calculate the acceleration phase parameters
accelCompensationDistance = compensationTime * (dda.topSpeed - dda.startSpeed);
- mp.cart.accelStopStep = (uint32_t)((dda.accelDistance + accelCompensationDistance) * stepsPerMm) + 1;
+ mp.cart.accelStopStep = (uint32_t)((dda.accelDistance + accelCompensationDistance) * effectiveStepsPerMm) + 1;
}
else
{
accelCompensationDistance = compensationTime = 0.0;
mp.cart.compensationClocks = mp.cart.accelCompensationClocks = 0;
- netSteps = (int32_t)(dda.totalDistance * stepsPerMm); // it may have changed from totalSteps if we are using nonlinear extrusion
// Calculate the acceleration phase parameters
- mp.cart.accelStopStep = (uint32_t)(dda.accelDistance * stepsPerMm) + 1;
+ mp.cart.accelStopStep = (uint32_t)(dda.accelDistance * effectiveStepsPerMm) + 1;
}
- mp.cart.twoCsquaredTimesMmPerStepDivA = roundU64((double)(StepTimer::StepClockRateSquared * 2)/((double)stepsPerMm * (double)dda.acceleration));
- mp.cart.twoCsquaredTimesMmPerStepDivD = roundU64((double)(StepTimer::StepClockRateSquared * 2)/((double)stepsPerMm * (double)dda.deceleration));
+ int32_t netSteps = (int32_t)(extrusionRequired * rawStepsPerMm);
+ extrusionPending = extrusionRequired - (float)netSteps/rawStepsPerMm;
+
+ if (!direction)
+ {
+ netSteps = -netSteps;
+ }
+
+ // Note, netSteps may be negative at this point if we are applying pressure advance
+ mp.cart.twoCsquaredTimesMmPerStepDivA = roundU64((double)(StepTimer::StepClockRateSquared * 2)/((double)effectiveStepsPerMm * (double)dda.acceleration));
+ mp.cart.twoCsquaredTimesMmPerStepDivD = roundU64((double)(StepTimer::StepClockRateSquared * 2)/((double)effectiveStepsPerMm * (double)dda.deceleration));
// Constant speed phase parameters
- mp.cart.mmPerStepTimesCKdivtopSpeed = (uint32_t)((float)((uint64_t)StepTimer::StepClockRate * K1)/(stepsPerMm * dda.topSpeed));
+ mp.cart.mmPerStepTimesCKdivtopSpeed = (uint32_t)((float)((uint64_t)StepTimer::StepClockRate * K1)/(effectiveStepsPerMm * dda.topSpeed));
// Calculate the deceleration and reverse phase parameters and update totalSteps
// 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) // if less than 1 deceleration step
+ if (dda.decelDistance * effectiveStepsPerMm < 0.5) // if less than 1 deceleration step
{
totalSteps = (uint32_t)max<int32_t>(netSteps, 0);
mp.cart.decelStartStep = reverseStartStep = netSteps + 1;
@@ -242,7 +259,7 @@ void DriveMovement::PrepareExtruder(const DDA& dda, const PrepParams& params, fl
}
else
{
- mp.cart.decelStartStep = (uint32_t)((params.decelStartDistance + accelCompensationDistance) * stepsPerMm) + 1;
+ mp.cart.decelStartStep = (uint32_t)((params.decelStartDistance + accelCompensationDistance) * effectiveStepsPerMm) + 1;
const int32_t initialDecelSpeedTimesCdivD = (int32_t)params.topSpeedTimesCdivD - (int32_t)mp.cart.compensationClocks; // signed because it may be negative and we square it
const uint64_t initialDecelSpeedTimesCdivDSquared = isquare64(initialDecelSpeedTimesCdivD);
twoDistanceToStopTimesCsquaredDivD =
diff --git a/src/Movement/DriveMovement.h b/src/Movement/DriveMovement.h
index c0ed0cc6..7099feee 100644
--- a/src/Movement/DriveMovement.h
+++ b/src/Movement/DriveMovement.h
@@ -135,7 +135,7 @@ public:
bool CalcNextStepTimeDelta(const DDA &dda, bool live) __attribute__ ((hot));
void PrepareCartesianAxis(const DDA& dda, const PrepParams& params) __attribute__ ((hot));
void PrepareDeltaAxis(const DDA& dda, const PrepParams& params) __attribute__ ((hot));
- void PrepareExtruder(const DDA& dda, const PrepParams& params, float speedChange, bool doCompensation) __attribute__ ((hot));
+ void PrepareExtruder(const DDA& dda, const PrepParams& params, float& extrusionPending, float speedChange, bool doCompensation) __attribute__ ((hot));
void ReduceSpeed(const DDA& dda, uint32_t inverseSpeedFactor);
void DebugPrint(char c, bool withDelta) const;
int32_t GetNetStepsLeft() const;
diff --git a/src/Movement/Kinematics/ScaraKinematics.cpp b/src/Movement/Kinematics/ScaraKinematics.cpp
index 4ec47dc1..eec4e998 100644
--- a/src/Movement/Kinematics/ScaraKinematics.cpp
+++ b/src/Movement/Kinematics/ScaraKinematics.cpp
@@ -98,6 +98,12 @@ bool ScaraKinematics::CalculateThetaAndPsi(const float machinePos[], bool isCoor
armMode = !armMode;
}
+ // Save the original and transformed coordinates so that we don't need to calculate them again if we are commanded to move to this position
+ cachedX = machinePos[0];
+ cachedY = machinePos[1];
+ cachedTheta = theta;
+ cachedPsi = psi;
+ cachedArmMode = armMode;
return true;
}
@@ -143,8 +149,12 @@ void ScaraKinematics::MotorStepsToCartesian(const int32_t motorPos[], const floa
const float theta = ((float)motorPos[X_AXIS]/stepsPerMm[X_AXIS]);
const float psi = ((float)motorPos[Y_AXIS]/stepsPerMm[Y_AXIS]) + (crosstalk[0] * theta);
- machinePos[X_AXIS] = (cosf(theta * DegreesToRadians) * proximalArmLength + cosf((psi + theta) * DegreesToRadians) * distalArmLength) - xOffset;
- machinePos[Y_AXIS] = (sinf(theta * DegreesToRadians) * proximalArmLength + sinf((psi + theta) * DegreesToRadians) * distalArmLength) - yOffset;
+ // Cache the current values so that a Z probe at this position won't fail due to rounding error when transforming the XY coordinates back
+ currentArmMode = cachedArmMode = (motorPos[Y_AXIS] >= 0);
+ cachedTheta = theta;
+ cachedPsi = psi;
+ cachedX = machinePos[X_AXIS] = (cosf(theta * DegreesToRadians) * proximalArmLength + cosf((psi + theta) * DegreesToRadians) * distalArmLength) - xOffset;
+ cachedY = machinePos[Y_AXIS] = (sinf(theta * DegreesToRadians) * proximalArmLength + sinf((psi + theta) * DegreesToRadians) * distalArmLength) - yOffset;
// On some machines (e.g. Helios), the X and/or Y arm motors also affect the Z height
machinePos[Z_AXIS] = ((float)motorPos[Z_AXIS]/stepsPerMm[Z_AXIS]) + (crosstalk[1] * theta) + (crosstalk[2] * psi);
@@ -221,18 +231,7 @@ bool ScaraKinematics::IsReachable(float x, float y, bool isCoordinated) const
// See if we can transform the position
float theta, psi;
bool armMode = currentArmMode;
- const bool reachable = CalculateThetaAndPsi(coords, isCoordinated, theta, psi, armMode);
- if (reachable)
- {
- // Save the original and transformed coordinates so that we don't need to calculate them again if we are commanded to move to this position
- cachedX = x;
- cachedY = y;
- cachedTheta = theta;
- cachedPsi = psi;
- cachedArmMode = armMode;
- }
-
- return reachable;
+ return CalculateThetaAndPsi(coords, isCoordinated, theta, psi, armMode);
}
// Limit the Cartesian position that the user wants to move to, returning true if any coordinates were changed
@@ -245,12 +244,6 @@ bool ScaraKinematics::LimitPosition(float coords[], size_t numVisibleAxes, AxesB
bool armMode = currentArmMode;
if (CalculateThetaAndPsi(coords, isCoordinated, theta, psi, armMode))
{
- // Save the original and transformed coordinates so that we don't need to calculate them again if we are commanded to move to this position
- cachedX = coords[0];
- cachedY = coords[1];
- cachedTheta = theta;
- cachedPsi = psi;
- cachedArmMode = armMode;
return m208Limited;
}
@@ -392,7 +385,7 @@ bool ScaraKinematics::QueryTerminateHomingMove(size_t axis) const
}
// This function is called from the step ISR when an endstop switch is triggered during homing after stopping just one motor or all motors.
-// Take the action needed to define the current position, normally by calling dda.SetDriveCoordinate() and return false.
+// Take the action needed to define the current position, normally by calling dda.SetDriveCoordinate().
void ScaraKinematics::OnHomingSwitchTriggered(size_t axis, bool highEnd, const float stepsPerMm[], DDA& dda) const
{
switch (axis)
diff --git a/src/Movement/Move.cpp b/src/Movement/Move.cpp
index bd81d352..b2a648f5 100644
--- a/src/Movement/Move.cpp
+++ b/src/Movement/Move.cpp
@@ -244,6 +244,7 @@ void Move::Spin()
if (ddaRingAddPointer->Init(specialMoveCoords))
{
ddaRingAddPointer = ddaRingAddPointer->GetNext();
+ scheduledMoves++;
if (moveState == MoveState::idle || moveState == MoveState::timing)
{
// We were previously idle, so we have a state change
@@ -268,14 +269,6 @@ void Move::Spin()
{
if (simulationMode < 2) // in simulation mode 2 and higher, we don't process incoming moves beyond this point
{
-#if 0 // disabled this because it causes jerky movements on the SCARA printer
- // Add on the extrusion left over from last time.
- const size_t numAxes = reprap.GetGCodes().GetTotalAxes();
- for (size_t drive = numAxes; drive < DRIVES; ++drive)
- {
- nextMove.coords[drive] += extrusionPending[drive - numAxes];
- }
-#endif
if (nextMove.moveType == 0)
{
AxisAndBedTransform(nextMove.coords, nextMove.xAxes, nextMove.yAxes, true);
@@ -284,8 +277,8 @@ void Move::Spin()
if (ddaRingAddPointer->Init(nextMove, !IsRawMotorMove(nextMove.moveType)))
{
ddaRingAddPointer = ddaRingAddPointer->GetNext();
- idleCount = 0;
scheduledMoves++;
+ idleCount = 0;
if (moveState == MoveState::idle || moveState == MoveState::timing)
{
moveState = MoveState::collecting;
@@ -298,14 +291,6 @@ void Move::Spin()
lastStateChangeTime = now;
}
}
-
-#if 0 // see above
- // Save the amount of extrusion not done
- for (size_t drive = numAxes; drive < DRIVES; ++drive)
- {
- extrusionPending[drive - numAxes] = nextMove.coords[drive];
- }
-#endif
}
}
}
@@ -338,7 +323,7 @@ void Move::Spin()
#endif
)
{
- dda->Prepare(simulationMode);
+ dda->Prepare(simulationMode, extrusionPending);
}
if (dda->GetState() == DDA::frozen)
{
@@ -402,7 +387,7 @@ void Move::Spin()
#endif
)
{
- cdda->Prepare(simulationMode);
+ cdda->Prepare(simulationMode, extrusionPending);
}
preparedTime += cdda->GetTimeLeft();
++preparedCount;
@@ -569,9 +554,16 @@ bool Move::LowPowerOrStallPause(RestorePoint& rp)
{
// We are executing a move that has a file address, so we can interrupt it
StepTimer::DisableStepInterrupt();
+#if SUPPORT_LASER
+ if (reprap.GetGCodes().GetMachineType() == MachineType::laser)
+ {
+ reprap.GetPlatform().SetLaserPwm(0);
+ }
+#endif
dda->MoveAborted();
CurrentMoveCompleted(); // updates live endpoints, extrusion, ddaRingGetPointer, currentDda etc.
--completedMoves; // this move wasn't really completed
+ --scheduledMoves; // ...but it is no longer scheduled either
abortedMove = true;
}
else
@@ -720,13 +712,13 @@ void Move::EndPointToMachine(const float coords[], int32_t ep[], size_t numDrive
const size_t numAxes = reprap.GetGCodes().GetTotalAxes();
for (size_t drive = numAxes; drive < numDrives; ++drive)
{
- ep[drive] = MotorEndPointToMachine(drive, coords[drive]);
+ ep[drive] = MotorMovementToSteps(drive, coords[drive]);
}
}
}
// Convert distance to steps for a particular drive
-int32_t Move::MotorEndPointToMachine(size_t drive, float coord)
+int32_t Move::MotorMovementToSteps(size_t drive, float coord)
{
return lrintf(coord * reprap.GetPlatform().DriveStepsPerUnit(drive));
}
@@ -744,16 +736,16 @@ bool Move::CartesianToMotorSteps(const float machinePos[MaxAxes], int32_t motorP
{
const bool b = kinematics->CartesianToMotorSteps(machinePos, reprap.GetPlatform().GetDriveStepsPerUnit(),
reprap.GetGCodes().GetVisibleAxes(), reprap.GetGCodes().GetTotalAxes(), motorPos, isCoordinated);
- if (reprap.Debug(moduleMove) && reprap.Debug(moduleDda))
+ if (b)
{
- if (b)
+ if (reprap.Debug(moduleMove) && reprap.Debug(moduleDda))
{
debugPrintf("Transformed %.2f %.2f %.2f to %" PRIu32 " %" PRIu32 " %" PRIu32 "\n", (double)machinePos[0], (double)machinePos[1], (double)machinePos[2], motorPos[0], motorPos[1], motorPos[2]);
}
- else
- {
- debugPrintf("Unable to transform %.2f %.2f %.2f\n", (double)machinePos[0], (double)machinePos[1], (double)machinePos[2]);
- }
+ }
+ else if (reprap.Debug(moduleMove))
+ {
+ debugPrintf("Unable to transform %.2f %.2f %.2f\n", (double)machinePos[0], (double)machinePos[1], (double)machinePos[2]);
}
return b;
}
@@ -1129,7 +1121,7 @@ void Move::GetCurrentMachinePosition(float m[MaxAxes], bool disableMotorMapping)
}
}
-/*static*/ float Move::MotorEndpointToPosition(int32_t endpoint, size_t drive)
+/*static*/ float Move::MotorStepsToMovement(size_t drive, int32_t endpoint)
{
return ((float)(endpoint))/reprap.GetPlatform().DriveStepsPerUnit(drive);
}
diff --git a/src/Movement/Move.h b/src/Movement/Move.h
index 68f1984b..8792305e 100644
--- a/src/Movement/Move.h
+++ b/src/Movement/Move.h
@@ -150,8 +150,8 @@ public:
uint32_t GetStepInterval(size_t axis, uint32_t microstepShift) const; // Get the current step interval for this axis or extruder
#endif
- static int32_t MotorEndPointToMachine(size_t drive, float coord); // Convert a single motor position to number of steps
- static float MotorEndpointToPosition(int32_t endpoint, size_t drive); // Convert number of motor steps to motor position
+ static int32_t MotorMovementToSteps(size_t drive, float coord); // Convert a single motor position to number of steps
+ static float MotorStepsToMovement(size_t drive, int32_t endpoint); // Convert number of motor steps to motor position
protected:
DECLARE_OBJECT_MODEL
diff --git a/src/Movement/StepTimer.cpp b/src/Movement/StepTimer.cpp
index 8b275588..c09bccc7 100644
--- a/src/Movement/StepTimer.cpp
+++ b/src/Movement/StepTimer.cpp
@@ -16,8 +16,8 @@
#if SAM4S || SAME70
// Static data used by step ISR
-volatile uint32_t stepTimerPendingStatus = 0; // for holding status bits that we have read (and therefore cleared) but haven't serviced yet
-volatile uint32_t stepTimerHighWord = 0; // upper 16 bits of step timer
+static volatile uint32_t stepTimerPendingStatus = 0; // for holding status bits that we have read (and therefore cleared) but haven't serviced yet
+static volatile uint32_t stepTimerHighWord = 0; // upper 16 bits of step timer
#endif
namespace StepTimer
@@ -85,6 +85,14 @@ namespace StepTimer
return (lowWord & 0x0000FFFF) | highWord;
}
+#else
+
+ // Get the interrupt clock count. Despite the name, on these processors we don't need to disable interrupts before calling this.
+ uint32_t GetInterruptClocksInterruptsDisabled()
+ {
+ return STEP_TC->TC_CHANNEL[STEP_TC_CHAN].TC_CV;
+ }
+
#endif
// Schedule an interrupt at the specified clock count, or return true if that time is imminent or has passed already.
diff --git a/src/Movement/StepTimer.h b/src/Movement/StepTimer.h
index b82a11c1..3818f3b1 100644
--- a/src/Movement/StepTimer.h
+++ b/src/Movement/StepTimer.h
@@ -19,11 +19,13 @@ namespace StepTimer
void Init();
-#if SAM4S || SAME70 // if the TCs are 16-bit
-
- // Function GetInterruptClocksInterruptsDisabled() is quite long for these processors, so it is moved to StepTimer.cpp and no longer inlined
+ // Function GetInterruptClocksInterruptsDisabled() is quite long for SAM4S and SAME70 processors, so it is moved to StepTimer.cpp and no longer inlined
+ // On other processor we have had trouble with the compiler moving instructions around too much when it is inlined.
+ // So we don't inline it any more.
uint32_t GetInterruptClocksInterruptsDisabled() __attribute__ ((hot)); // Get the interrupt clock count, when we know already that interrupts are disabled
+#if SAM4S || SAME70 // if the TCs are 16-bit
+
// Get the interrupt clock count
static inline uint32_t GetInterruptClocks()
{
@@ -38,13 +40,7 @@ namespace StepTimer
// Get the interrupt clock count
static inline uint32_t GetInterruptClocks()
{
- return STEP_TC->TC_CHANNEL[STEP_TC_CHAN].TC_CV;
- }
-
- // Get the interrupt clock count, when we know that interrupts are already disabled
- static inline uint32_t GetInterruptClocksInterruptsDisabled()
- {
- return STEP_TC->TC_CHANNEL[STEP_TC_CHAN].TC_CV;
+ return GetInterruptClocksInterruptsDisabled(); // no need to disable interrupts on these processors
}
#endif
diff --git a/src/ObjectModel/ObjectModel.cpp b/src/ObjectModel/ObjectModel.cpp
index 44c579b1..d8ead242 100644
--- a/src/ObjectModel/ObjectModel.cpp
+++ b/src/ObjectModel/ObjectModel.cpp
@@ -117,7 +117,7 @@ void ObjectModelTableEntry::ReportItemAsJson(OutputBuffer *buf, const char *filt
break;
case TYPE_OF(const char*):
- buf->EncodeString((const char*)nParam, strlen((const char*)nParam), true, true, false);
+ buf->EncodeString((const char*)nParam, true);
break;
case TYPE_OF(Bitmap32):
diff --git a/src/Pccb/Pins_Pccb.h b/src/Pccb/Pins_Pccb.h
index 23d3d5a7..362ae1c9 100644
--- a/src/Pccb/Pins_Pccb.h
+++ b/src/Pccb/Pins_Pccb.h
@@ -79,7 +79,7 @@ constexpr size_t NUM_SERIAL_CHANNELS = 1; // The number of serial IO channels
#define SERIAL_MAIN_DEVICE SerialUSB
// SerialUSB
-constexpr Pin UsbVBusPin = 47; // Pin used to monitor VBUS on USB port
+constexpr Pin UsbVBusPin = PortCPin(11); // Pin used to monitor VBUS on USB port
#define I2C_IFACE Wire // First and only I2C interface
#define I2C_IRQn WIRE_ISR_ID
@@ -91,10 +91,10 @@ constexpr Pin GlobalTmc22xxEnablePin = 1; // The pin that drives ENN of all in
#ifdef PCCB_X5
-constexpr Pin GlobalTmc2660EnablePin = 52; // The pin that drives ENN of all drivers on the DueX5
-constexpr Pin ENABLE_PINS[NumDirectDrivers] = { 61, 35, 41, 55, 0, 64 };
-constexpr Pin STEP_PINS[NumDirectDrivers] = { 60, 38, 58, 56, 46, 50 };
-constexpr Pin DIRECTION_PINS[NumDirectDrivers] = { 17, 57, 54, 34, 1, 53 };
+constexpr Pin GlobalTmc2660EnablePin = PortCPin(16); // The pin that drives ENN of all drivers on the DueX5
+constexpr Pin ENABLE_PINS[NumDirectDrivers] = { PortBPin(14), PortCPin(25), PortCPin( 5), PortCPin(19), PortAPin( 0), PortCPin(28) };
+constexpr Pin STEP_PINS[NumDirectDrivers] = { PortCPin(24), PortCPin( 2), PortCPin(22), PortCPin(20), PortCPin(10), PortCPin(14) };
+constexpr Pin DIRECTION_PINS[NumDirectDrivers] = { PortAPin(17), PortCPin(21), PortCPin(18), PortCPin(13), PortAPin( 1), PortCPin(17) };
Spi * const SPI_TMC2660 = SPI;
constexpr uint32_t ID_TMC2660_SPI = ID_SPI;
@@ -102,15 +102,15 @@ constexpr IRQn TMC2660_SPI_IRQn = SPI_IRQn;
# define TMC2660_SPI_Handler SPI_Handler
// Pin assignments, using USART1 in SPI mode
-constexpr Pin TMC2660MosiPin = 13; // PA13
-constexpr Pin TMC2660MisoPin = 12; // PA12
-constexpr Pin TMC2660SclkPin = 14; // PA14
+constexpr Pin TMC2660MosiPin = PortAPin(13);
+constexpr Pin TMC2660MisoPin = PortAPin(12);
+constexpr Pin TMC2660SclkPin = PortAPin(14);
#else
-constexpr Pin ENABLE_PINS[NumDirectDrivers] = { NoPin, NoPin, 61, 35, 41, 55, 0, 64 };
-constexpr Pin STEP_PINS[NumDirectDrivers] = { 40, 43, 60, 38, 58, 56, 46, 50 };
-constexpr Pin DIRECTION_PINS[NumDirectDrivers] = { 8, 11, 17, 57, 54, 34, 1, 53 };
+constexpr Pin ENABLE_PINS[NumDirectDrivers] = { NoPin, NoPin, PortBPin(14), PortCPin(25), PortCPin( 5), PortCPin(19), PortAPin( 0), PortCPin(28) };
+constexpr Pin STEP_PINS[NumDirectDrivers] = { PortCPin( 4), PortCPin( 7), PortCPin(24), PortCPin( 2), PortCPin(22), PortCPin(20), PortCPin(10), PortCPin(14) };
+constexpr Pin DIRECTION_PINS[NumDirectDrivers] = { PortAPin( 8), PortAPin(11), PortAPin(17), PortCPin(21), PortCPin(18), PortCPin(13), PortAPin( 1), PortCPin(17) };
Uart * const TMC22xxUarts[MaxSmartDrivers] = { UART0, UART1 };
constexpr uint32_t TMC22xxUartIds[MaxSmartDrivers] = { ID_UART0, ID_UART1 };
@@ -135,13 +135,13 @@ const uint32_t TransferTimeout = 10; // any transfer should complete within
// Endstops
// RepRapFirmware only has a single endstop per axis.
// Gcode defines if it is a max ("high end") or min ("low end") endstop and sets if it is active HIGH or LOW.
-constexpr Pin END_STOP_PINS[NumEndstops] = { 25, 67, 24, 63 };
+constexpr Pin END_STOP_PINS[NumEndstops] = { PortAPin(24), PortAPin(25), PortCPin(31), PortCPin(27) };
// Heaters and thermistors
-constexpr Pin HEAT_ON_PINS[NumHeaters] = { 36, 59 }; // these are actually the LED control pins
-constexpr Pin TEMP_SENSE_PINS[NumThermistorInputs] = { 20, 49 }; // Thermistor pin numbers
-constexpr Pin VssaSensePin = 19;
-constexpr Pin VrefSensePin = 27;
+constexpr Pin HEAT_ON_PINS[NumHeaters] = { PortCPin(0), PortCPin(23) }; // these are actually the LED control pins
+constexpr Pin TEMP_SENSE_PINS[NumThermistorInputs] = { PortAPin(20), PortCPin(13) }; // thermistor pin numbers
+constexpr Pin VssaSensePin = PortAPin(19);
+constexpr Pin VrefSensePin = PortBPin(1);
// Default thermistor parameters - on PCCB we default both thermistors to the same parameters
constexpr float BED_R25 = 100000.0;
@@ -158,14 +158,14 @@ constexpr float THERMISTOR_SERIES_RS = 2200.0;
constexpr size_t MaxSpiTempSensors = 1; //TODO which SPI channels does PCCB route to the DueX?
// Digital pins the 31855s have their select lines tied to
-constexpr Pin SpiTempSensorCsPins[MaxSpiTempSensors] = { 63 }; // SPI0_CS6 if a DueX5 is connected
+constexpr Pin SpiTempSensorCsPins[MaxSpiTempSensors] = { PortCPin(27) }; // SPI0_CS6 if a DueX5 is connected
// Pin that controls the ATX power on/off
constexpr Pin ATX_POWER_PIN = NoPin;
// Analogue pin numbers
constexpr Pin Z_PROBE_PIN = NoPin; // Z probe analog input
-constexpr Pin PowerMonitorVinDetectPin = 48; // Vin monitor
+constexpr Pin PowerMonitorVinDetectPin = PortCPin(12); // Vin monitor
constexpr float PowerMonitorVoltageRange = 11.0 * 3.3; // We use an 11:1 voltage divider
// Digital pin number to turn the IR LED on (high) or off (low), also controls the DIAG LED
@@ -175,24 +175,24 @@ constexpr Pin DiagPin = NoPin;
// Cooling fans
constexpr size_t NUM_FANS = 4;
constexpr size_t NumTachos = 2;
-constexpr Pin COOLING_FAN_PINS[NUM_FANS] = { 16, 39, 15, 37 }; // PWML2, PWML3, TIOA1, PWML1
-constexpr Pin TachoPins[NumTachos] = { 26, 66 };
+constexpr Pin COOLING_FAN_PINS[NUM_FANS] = { PortAPin(16), PortCPin(3), PortAPin(15), PortCPin(1) }; // PWML2, PWML3, TIOA1, PWML1
+constexpr Pin TachoPins[NumTachos] = { PortBPin(0), PortCPin(30) };
// Main LED control
constexpr size_t NumLeds = 2; // number of main LEDs
-constexpr Pin LedOnPins[NumLeds] = { 36, 59 }; // LED control pins
+constexpr Pin LedOnPins[NumLeds] = { PortCPin(0), PortCPin(23) }; // LED control pins
// DotStar LED control (USART0 is SharedSPI,
Usart * const DotStarUsart = USART1;
constexpr uint32_t DotStarUsartId = ID_USART1;
-constexpr Pin DotStarMosiPin = 22;
-constexpr Pin DotStarSclkPin = 23;
+constexpr Pin DotStarMosiPin = PortAPin(22);
+constexpr Pin DotStarSclkPin = PortAPin(23);
constexpr IRQn DotStarUsartIRQn = USART1_IRQn;
const uint32_t DotStarSpiClockFrequency = 100000; // try sending at 100kHz
// SD cards
constexpr size_t NumSdCards = 1;
-constexpr Pin SdCardDetectPins[NumSdCards] = { 44 };
+constexpr Pin SdCardDetectPins[NumSdCards] = { PortCPin(8) };
constexpr Pin SdWriteProtectPins[NumSdCards] = { NoPin };
constexpr Pin SdSpiCSPins[1] = { NoPin };
constexpr uint32_t ExpectedSdCardSpeed = 15000000;
@@ -202,10 +202,10 @@ constexpr uint32_t ExpectedSdCardSpeed = 15000000;
// This is the mapping from logical pins 60+ to firmware pin numbers
constexpr Pin SpecialPinMap[] =
{
- 18, 21, 51, 59, 62, 65 // PA18/AD1, PA21/AD8, PC15/AD11, PC22, PC23, PC29
+ PortAPin(18), PortAPin(21), PortCPin(15), PortCPin(29) // PA18/AD1, PA21/AD8, PC15/AD11, PC29
};
-constexpr int HighestLogicalPin = 65; // highest logical pin number on this electronics
+constexpr int HighestLogicalPin = 63; // highest logical pin number on this electronics
// SAM4S Flash locations (may be expanded in the future)
constexpr uint32_t IAP_FLASH_START = 0x00470000;
diff --git a/src/Platform.cpp b/src/Platform.cpp
index 40cb2273..f149baf8 100644
--- a/src/Platform.cpp
+++ b/src/Platform.cpp
@@ -345,8 +345,8 @@ void Platform::Init()
// AXES
for (size_t axis = 0; axis < MaxAxes; ++axis)
{
- axisMinima[axis] = 0.0;
- axisMaxima[axis] = 200.0;
+ axisMinima[axis] = DefaultAxisMinimum;
+ axisMaxima[axis] = DefaultAxisMaximum;
}
axisMaximaProbed = axisMinimaProbed = 0;
@@ -400,7 +400,7 @@ void Platform::Init()
}
}
- for (size_t endstop = 0; endstop < NumEndstops; ++endstop)
+ for (Pin p : endStopPins)
{
#if defined(DUET_NG) || defined(DUET_06_085) || defined(__RADDS__) || defined(__ALLIGATOR__)
// Enable pullup resistors on endstop inputs here if necessary.
@@ -411,9 +411,9 @@ void Platform::Init()
// Note: if we don't have a DueX board connected, the pullups on endstop inputs 5-9 must always be enabled.
// Also the pullups on endstop inputs 10-11 must always be enabled.
// I don't know whether RADDS and Alligator have hardware pullup resistors or not. I'll assume they might not.
- pinMode(endStopPins[endstop], INPUT_PULLUP); // enable pullup on endstop input
+ pinMode(p, INPUT_PULLUP); // enable pullup on endstop input
#else
- pinMode(endStopPins[endstop], INPUT); // don't enable pullup on endstop input
+ pinMode(p, INPUT); // don't enable pullup on endstop input
#endif
}
@@ -521,15 +521,15 @@ void Platform::Init()
// Enable pullups on all the SPI CS pins. This is required if we are using more than one device on the SPI bus.
// Otherwise, when we try to initialise the first device, the other devices may respond as well because their CS lines are not high.
- for (size_t i = 0; i < MaxSpiTempSensors; ++i)
+ for (Pin p : SpiTempSensorCsPins)
{
- setPullup(SpiTempSensorCsPins[i], true);
+ pinMode(p, INPUT_PULLUP);
}
- for (size_t heater = 0; heater < NumHeaters; heater++)
+ for (Pin p : HEAT_ON_PINS)
{
// pinMode is safe to call when the pin is NoPin, so we don't need to check it here
- pinMode(HEAT_ON_PINS[heater],
+ pinMode(p,
#if ACTIVE_LOW_HEAT_ON
OUTPUT_HIGH
#else
@@ -1415,7 +1415,7 @@ void Platform::Spin()
// The driver often produces a transient open-load error, especially in stealthchop mode, so we require the condition to persist before we report it.
// Also, false open load indications persist when in standstill, if the phase has zero current in that position
- if ((stat & TMC_RR_OLA) != 0)
+ if ((stat & TMC_RR_OLA) != 0 && motorCurrents[nextDriveToPoll] * motorCurrentFraction[nextDriveToPoll] >= MinimumOpenLoadMotorCurrent)
{
if (!openLoadATimer.IsRunning())
{
@@ -1433,7 +1433,7 @@ void Platform::Spin()
}
}
- if ((stat & TMC_RR_OLB) != 0)
+ if ((stat & TMC_RR_OLB) != 0 && motorCurrents[nextDriveToPoll] * motorCurrentFraction[nextDriveToPoll] >= MinimumOpenLoadMotorCurrent)
{
if (!openLoadBTimer.IsRunning())
{
@@ -1906,9 +1906,9 @@ void Platform::SoftwareReset(uint16_t reason, const uint32_t *stk)
if (stk != nullptr)
{
srdBuf[slot].sp = reinterpret_cast<uint32_t>(stk);
- for (size_t i = 0; i < ARRAY_SIZE(srdBuf[slot].stack); ++i)
+ for (uint32_t& stval : srdBuf[slot].stack)
{
- srdBuf[slot].stack[i] = (stk < &_estack) ? *stk : 0xFFFFFFFF;
+ stval = (stk < &_estack) ? *stk : 0xFFFFFFFF;
++stk;
}
}
@@ -2235,9 +2235,9 @@ void Platform::Diagnostics(MessageType mtype)
{
// We saved a stack dump, so print it
scratchString.Clear();
- for (size_t i = 0; i < ARRAY_SIZE(srdBuf[slot].stack); ++i)
+ for (uint32_t stval : srdBuf[slot].stack)
{
- scratchString.catf(" %08" PRIx32, srdBuf[slot].stack[i]);
+ scratchString.catf(" %08" PRIx32, stval);
}
MessageF(mtype, "Stack:%s\n", scratchString.c_str());
}
@@ -2285,7 +2285,7 @@ void Platform::Diagnostics(MessageType mtype)
// Show the motor stall status
for (size_t drive = 0; drive < numSmartDrivers; ++drive)
{
- String<100> driverStatus;
+ String<MediumStringLength> driverStatus;
SmartDrivers::AppendDriverStatus(drive, driverStatus.GetRef());
MessageF(mtype, "Driver %u:%s\n", drive, driverStatus.c_str());
}
diff --git a/src/Tasks.cpp b/src/Tasks.cpp
index 2f739d59..675a7a4d 100644
--- a/src/Tasks.cpp
+++ b/src/Tasks.cpp
@@ -28,7 +28,7 @@ extern char _end;
// The main task currently runs GCodes, so it needs to be large enough to hold the matrices used for auto calibration.
// The timer and idle tasks currently never do I/O, so they can be much smaller.
-constexpr unsigned int MainTaskStackWords = 2040;
+constexpr unsigned int MainTaskStackWords = 1600;
constexpr unsigned int IdleTaskStackWords = 60;
static Task<IdleTaskStackWords> idleTask;
diff --git a/src/Version.h b/src/Version.h
index e22999ec..19c0d8ea 100644
--- a/src/Version.h
+++ b/src/Version.h
@@ -12,7 +12,7 @@
#ifndef VERSION
#ifdef RTOS
# define RTOSVER "(RTOS)"
-# define MAIN_VERSION "2.02RC5"
+# define MAIN_VERSION "2.02RC6"
#else
# define MAIN_VERSION "1.22"
# define RTOSVER
@@ -22,7 +22,7 @@
#endif
#ifndef DATE
-# define DATE "2018-11-28b1"
+# define DATE "2018-12-15b2"
#endif
#define AUTHORS "reprappro, dc42, chrishamm, t3p3, dnewman, printm3d"