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:
-rw-r--r--.cproject121
-rw-r--r--.settings/language.settings.xml25
-rw-r--r--src/BugList.txt1
-rw-r--r--src/DuetM/Pins_DuetM.h15
-rw-r--r--src/DuetNG/Pins_DuetNG.h13
-rw-r--r--src/Fans/DotStarLed.h2
-rw-r--r--src/GCodes/GCodes2.cpp28
-rw-r--r--src/Movement/BedProbing/Grid.cpp4
-rw-r--r--src/Movement/DDA.cpp208
-rw-r--r--src/Movement/DDA.h46
-rw-r--r--src/Movement/DriveMovement.cpp73
-rw-r--r--src/Movement/DriveMovement.h12
-rw-r--r--src/Movement/Kinematics/CoreXYKinematics.cpp6
-rw-r--r--src/Movement/Kinematics/CoreXYUKinematics.cpp12
-rw-r--r--src/Movement/Kinematics/CoreXYUVKinematics.cpp12
-rw-r--r--src/Movement/Kinematics/Kinematics.cpp5
-rw-r--r--src/Movement/Kinematics/Kinematics.h4
-rw-r--r--src/Movement/Kinematics/LinearDeltaKinematics.cpp88
-rw-r--r--src/Movement/Kinematics/LinearDeltaKinematics.h48
-rw-r--r--src/Movement/Kinematics/RotaryDeltaKinematics.cpp507
-rw-r--r--src/Movement/Kinematics/RotaryDeltaKinematics.h88
-rw-r--r--src/Movement/Kinematics/ScaraKinematics.cpp2
-rw-r--r--src/Movement/Kinematics/ZLeadscrewKinematics.h2
-rw-r--r--src/Movement/Move.cpp16
-rw-r--r--src/Movement/Move.h14
-rw-r--r--src/Pccb/Pins_Pccb.h66
-rw-r--r--src/Platform.cpp36
-rw-r--r--src/Platform.h10
-rw-r--r--src/StepperDrivers/TMC22xx/TMC22xx.cpp65
-rw-r--r--src/StepperDrivers/TMC2660/TMC2660.cpp113
-rw-r--r--src/StepperDrivers/TMC2660/TMC2660.h6
-rw-r--r--src/Version.h4
32 files changed, 1310 insertions, 342 deletions
diff --git a/.cproject b/.cproject
index d042dbc4..a6326278 100644
--- a/.cproject
+++ b/.cproject
@@ -840,6 +840,127 @@
</storageModule>
<storageModule moduleId="org.eclipse.cdt.core.externalSettings"/>
</cconfiguration>
+ <cconfiguration id="cdt.managedbuild.config.gnu.cross.exe.release.516195201.976458850.241502451.170574622.649587786.1798324396.239853003">
+ <storageModule buildSystemId="org.eclipse.cdt.managedbuilder.core.configurationDataProvider" id="cdt.managedbuild.config.gnu.cross.exe.release.516195201.976458850.241502451.170574622.649587786.1798324396.239853003" moduleId="org.eclipse.cdt.core.settings" name="PCCB_X5">
+ <macros>
+ <stringMacro name="LinkFlags2" type="VALUE_TEXT" value="-Wl,--end-group -lm"/>
+ <stringMacro name="LinkFlags1" type="VALUE_TEXT" value="-mthumb -Wl,--cref -Wl,--check-sections -Wl,--gc-sections -Wl,--entry=Reset_Handler -Wl,--unresolved-symbols=report-all -Wl,--warn-common -Wl,--warn-section-align -Wl,--warn-unresolved-symbols -Wl,--start-group"/>
+ <stringMacro name="CoreName" type="VALUE_TEXT" value="CoreNG"/>
+ <stringMacro name="GccPath" type="VALUE_TEXT" value="C:\Program Files (x86)\GNU Tools ARM Embedded\7 2018-q2-update\bin"/>
+ </macros>
+ <externalSettings/>
+ <extensions>
+ <extension id="org.eclipse.cdt.core.ELF" point="org.eclipse.cdt.core.BinaryParser"/>
+ <extension id="org.eclipse.cdt.core.GmakeErrorParser" point="org.eclipse.cdt.core.ErrorParser"/>
+ <extension id="org.eclipse.cdt.core.CWDLocator" point="org.eclipse.cdt.core.ErrorParser"/>
+ <extension id="org.eclipse.cdt.core.GCCErrorParser" point="org.eclipse.cdt.core.ErrorParser"/>
+ <extension id="org.eclipse.cdt.core.GASErrorParser" point="org.eclipse.cdt.core.ErrorParser"/>
+ <extension id="org.eclipse.cdt.core.GLDErrorParser" point="org.eclipse.cdt.core.ErrorParser"/>
+ </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">
+ <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"/>
+ <option id="cdt.managedbuild.option.gnu.cross.prefix.2115296403" name="Prefix" superClass="cdt.managedbuild.option.gnu.cross.prefix" useByScannerDiscovery="false" value="arm-none-eabi-" valueType="string"/>
+ <targetPlatform archList="all" binaryParser="org.eclipse.cdt.core.ELF" id="cdt.managedbuild.targetPlatform.gnu.cross.650998352" isAbstract="false" osList="all" superClass="cdt.managedbuild.targetPlatform.gnu.cross"/>
+ <builder buildPath="${workspace_loc:/RepRapFirmware}/Release" id="cdt.managedbuild.builder.gnu.cross.2109049020" keepEnvironmentInBuildfile="false" managedBuildOn="true" name="Gnu Make Builder" parallelBuildOn="true" parallelizationNumber="optimal" superClass="cdt.managedbuild.builder.gnu.cross"/>
+ <tool id="cdt.managedbuild.tool.gnu.cross.assembler.1562151564" name="Cross GCC Assembler" superClass="cdt.managedbuild.tool.gnu.cross.assembler">
+ <inputType id="cdt.managedbuild.tool.gnu.assembler.input.421833380" superClass="cdt.managedbuild.tool.gnu.assembler.input"/>
+ </tool>
+ <tool commandLinePattern="${COMMAND} ${FLAGS} ${OUTPUT_FLAG} ${OUTPUT_PREFIX}${OUTPUT} ${INPUTS}" id="cdt.managedbuild.tool.gnu.cross.c.compiler.907968158" name="Cross GCC Compiler" superClass="cdt.managedbuild.tool.gnu.cross.c.compiler">
+ <option defaultValue="gnu.c.optimization.level.most" id="gnu.c.compiler.option.optimization.level.1879548421" name="Optimization Level" superClass="gnu.c.compiler.option.optimization.level" useByScannerDiscovery="false" value="gnu.c.optimization.level.more" valueType="enumerated"/>
+ <option id="gnu.c.compiler.option.debugging.level.1798838148" name="Debug Level" superClass="gnu.c.compiler.option.debugging.level" useByScannerDiscovery="false" value="gnu.c.debugging.level.none" valueType="enumerated"/>
+ <option id="gnu.c.compiler.option.misc.verbose.1017329274" name="Verbose (-v)" superClass="gnu.c.compiler.option.misc.verbose" useByScannerDiscovery="false" value="false" valueType="boolean"/>
+ <option id="gnu.c.compiler.option.misc.other.1392314364" name="Other flags" superClass="gnu.c.compiler.option.misc.other" useByScannerDiscovery="false" value="-c -std=gnu99 -mcpu=cortex-m4 -mthumb -ffunction-sections -fdata-sections -nostdlib -Wdouble-promotion -fsingle-precision-constant &quot;-Wa,-ahl=$*.s&quot;" valueType="string"/>
+ <option id="gnu.c.compiler.option.include.paths.712616825" name="Include paths (-I)" superClass="gnu.c.compiler.option.include.paths" useByScannerDiscovery="false" valueType="includePath">
+ <listOptionValue builtIn="false" value="&quot;${workspace_loc:/${CoreName}/cores/arduino}&quot;"/>
+ <listOptionValue builtIn="false" value="&quot;${workspace_loc:/${CoreName}/libraries/Storage}&quot;"/>
+ <listOptionValue builtIn="false" value="&quot;${workspace_loc:/${CoreName}/asf}&quot;"/>
+ <listOptionValue builtIn="false" value="&quot;${workspace_loc:/${CoreName}/asf/common/utils}&quot;"/>
+ <listOptionValue builtIn="false" value="&quot;${workspace_loc:/${CoreName}/asf/common/services/ioport}&quot;"/>
+ <listOptionValue builtIn="false" value="&quot;${workspace_loc:/${CoreName}/asf/sam/drivers}&quot;"/>
+ <listOptionValue builtIn="false" value="&quot;${workspace_loc:/${CoreName}/asf/sam/utils}&quot;"/>
+ <listOptionValue builtIn="false" value="&quot;${workspace_loc:/${CoreName}/asf/sam/utils/cmsis/sam4s/include}&quot;"/>
+ <listOptionValue builtIn="false" value="&quot;${workspace_loc:/${CoreName}/asf/sam/utils/header_files}&quot;"/>
+ <listOptionValue builtIn="false" value="&quot;${workspace_loc:/${CoreName}/asf/sam/utils/preprocessor}&quot;"/>
+ <listOptionValue builtIn="false" value="&quot;${workspace_loc:/${CoreName}/asf/thirdparty/CMSIS/Include}&quot;"/>
+ <listOptionValue builtIn="false" value="&quot;${workspace_loc:/${CoreName}/variants/sam4s}&quot;"/>
+ </option>
+ <option id="gnu.c.compiler.option.preprocessor.def.symbols.1475180073" name="Defined symbols (-D)" superClass="gnu.c.compiler.option.preprocessor.def.symbols" useByScannerDiscovery="false" valueType="definedSymbols">
+ <listOptionValue builtIn="false" value="__SAM4S8C__"/>
+ <listOptionValue builtIn="false" value="RTOS"/>
+ <listOptionValue builtIn="false" value="PCCB"/>
+ <listOptionValue builtIn="false" value="PCCB_X5"/>
+ </option>
+ <inputType id="cdt.managedbuild.tool.gnu.c.compiler.input.1120814753" superClass="cdt.managedbuild.tool.gnu.c.compiler.input"/>
+ </tool>
+ <tool id="cdt.managedbuild.tool.gnu.cross.c.linker.1936542357" name="Cross GCC Linker" superClass="cdt.managedbuild.tool.gnu.cross.c.linker"/>
+ <tool id="cdt.managedbuild.tool.gnu.cross.archiver.1577761657" name="Cross GCC Archiver" superClass="cdt.managedbuild.tool.gnu.cross.archiver"/>
+ <tool command="gcc" commandLinePattern="${COMMAND} ${FLAGS} ${OUTPUT_FLAG} ${OUTPUT_PREFIX}${OUTPUT} ${LinkFlags1} &quot;${workspace_loc}/${CoreName}/SAM4S_RTOS/cores/arduino/syscalls.o&quot; ${INPUTS} ${LinkFlags2}" id="cdt.managedbuild.tool.gnu.cross.cpp.linker.523461887" name="Cross G++ Linker" superClass="cdt.managedbuild.tool.gnu.cross.cpp.linker">
+ <option id="gnu.cpp.link.option.nostdlibs.1674515330" name="No startup or default libs (-nostdlib)" superClass="gnu.cpp.link.option.nostdlibs" useByScannerDiscovery="false" value="false" valueType="boolean"/>
+ <option id="gnu.cpp.link.option.paths.144825348" name="Library search path (-L)" superClass="gnu.cpp.link.option.paths" useByScannerDiscovery="false" valueType="libPaths">
+ <listOptionValue builtIn="false" value="&quot;${workspace_loc:/${CoreName}/SAM4S_RTOS_PCCB/}&quot;"/>
+ <listOptionValue builtIn="false" value="&quot;${workspace_loc:/FreeRTOS/SAM4S}&quot;"/>
+ </option>
+ <option id="gnu.cpp.link.option.libs.1538113275" name="Libraries (-l)" superClass="gnu.cpp.link.option.libs" useByScannerDiscovery="false" valueType="libs">
+ <listOptionValue builtIn="false" value="${CoreName}"/>
+ <listOptionValue builtIn="false" value="FreeRTOS"/>
+ </option>
+ <option id="gnu.cpp.link.option.flags.1106600671" name="Linker flags" superClass="gnu.cpp.link.option.flags" useByScannerDiscovery="false" value="-Os --specs=nano.specs -Wl,--gc-sections -Wl,--fatal-warnings -mcpu=cortex-m4 -T${workspace_loc:/${CoreName}/variants/sam4s/linker_scripts/gcc/flash.ld} -Wl,-Map,${workspace_loc:/${ProjName}/${ConfigName}}/${BuildArtifactFileBaseName}.map" valueType="string"/>
+ <inputType id="cdt.managedbuild.tool.gnu.cpp.linker.input.180173717" superClass="cdt.managedbuild.tool.gnu.cpp.linker.input">
+ <additionalInput kind="additionalinputdependency" paths="$(USER_OBJS)"/>
+ <additionalInput kind="additionalinput" paths="$(LIBS)"/>
+ </inputType>
+ </tool>
+ <tool command="g++" id="cdt.managedbuild.tool.gnu.cross.cpp.compiler.265237939" name="Cross G++ Compiler" superClass="cdt.managedbuild.tool.gnu.cross.cpp.compiler">
+ <option id="gnu.cpp.compiler.option.optimization.level.1022715653" name="Optimization Level" superClass="gnu.cpp.compiler.option.optimization.level" useByScannerDiscovery="false" value="gnu.cpp.compiler.optimization.level.more" valueType="enumerated"/>
+ <option id="gnu.cpp.compiler.option.debugging.level.746816525" name="Debug Level" superClass="gnu.cpp.compiler.option.debugging.level" useByScannerDiscovery="false" value="gnu.cpp.compiler.debugging.level.none" valueType="enumerated"/>
+ <option id="gnu.cpp.compiler.option.other.verbose.628173646" name="Verbose (-v)" superClass="gnu.cpp.compiler.option.other.verbose" useByScannerDiscovery="false" value="false" valueType="boolean"/>
+ <option id="gnu.cpp.compiler.option.other.other.195351069" name="Other flags" superClass="gnu.cpp.compiler.option.other.other" useByScannerDiscovery="false" value="-c -std=gnu++14 -mcpu=cortex-m4 -mthumb -ffunction-sections -fdata-sections -fno-threadsafe-statics -fno-rtti -fno-exceptions -nostdlib -Wdouble-promotion -fsingle-precision-constant &quot;-Wa,-ahl=$*.s&quot;" valueType="string"/>
+ <option id="gnu.cpp.compiler.option.include.paths.1437187820" name="Include paths (-I)" superClass="gnu.cpp.compiler.option.include.paths" useByScannerDiscovery="false" valueType="includePath">
+ <listOptionValue builtIn="false" value="&quot;${workspace_loc:/${CoreName}/cores/arduino}&quot;"/>
+ <listOptionValue builtIn="false" value="&quot;${workspace_loc:/${CoreName}/libraries/Flash}&quot;"/>
+ <listOptionValue builtIn="false" value="&quot;${workspace_loc:/${CoreName}/libraries/SharedSpi}&quot;"/>
+ <listOptionValue builtIn="false" value="&quot;${workspace_loc:/${CoreName}/libraries/Storage}&quot;"/>
+ <listOptionValue builtIn="false" value="&quot;${workspace_loc:/${CoreName}/libraries/Wire}&quot;"/>
+ <listOptionValue builtIn="false" value="&quot;${workspace_loc:/${CoreName}/asf}&quot;"/>
+ <listOptionValue builtIn="false" value="&quot;${workspace_loc:/${CoreName}/asf/common/utils}&quot;"/>
+ <listOptionValue builtIn="false" value="&quot;${workspace_loc:/${CoreName}/asf/common/services/clock}&quot;"/>
+ <listOptionValue builtIn="false" value="&quot;${workspace_loc:/${CoreName}/asf/common/services/ioport}&quot;"/>
+ <listOptionValue builtIn="false" value="&quot;${workspace_loc:/${CoreName}/asf/sam/drivers}&quot;"/>
+ <listOptionValue builtIn="false" value="&quot;${workspace_loc:/${CoreName}/asf/sam/services/flash_efc}&quot;"/>
+ <listOptionValue builtIn="false" value="&quot;${workspace_loc:/${CoreName}/asf/sam/utils}&quot;"/>
+ <listOptionValue builtIn="false" value="&quot;${workspace_loc:/${CoreName}/asf/sam/utils/cmsis/sam4s/include}&quot;"/>
+ <listOptionValue builtIn="false" value="&quot;${workspace_loc:/${CoreName}/asf/sam/utils/header_files}&quot;"/>
+ <listOptionValue builtIn="false" value="&quot;${workspace_loc:/${CoreName}/asf/sam/utils/preprocessor}&quot;"/>
+ <listOptionValue builtIn="false" value="&quot;${workspace_loc:/${CoreName}/asf/thirdparty/CMSIS/Include}&quot;"/>
+ <listOptionValue builtIn="false" value="&quot;${workspace_loc:/${CoreName}/variants/sam4s}&quot;"/>
+ <listOptionValue builtIn="false" value="&quot;${workspace_loc:/${ProjName}/src}&quot;"/>
+ <listOptionValue builtIn="false" value="&quot;${workspace_loc:/${ProjName}/src/Pccb}&quot;"/>
+ <listOptionValue builtIn="false" value="&quot;${workspace_loc:/DuetWiFiSocketServer/src/include}&quot;"/>
+ <listOptionValue builtIn="false" value="&quot;${workspace_loc:/FreeRTOS/src/include}&quot;"/>
+ <listOptionValue builtIn="false" value="&quot;${workspace_loc:/FreeRTOS/src/portable/GCC/ARM_CM3}&quot;"/>
+ </option>
+ <option id="gnu.cpp.compiler.option.preprocessor.def.900153856" name="Defined symbols (-D)" superClass="gnu.cpp.compiler.option.preprocessor.def" useByScannerDiscovery="false" valueType="definedSymbols">
+ <listOptionValue builtIn="false" value="__SAM4S8C__"/>
+ <listOptionValue builtIn="false" value="RTOS"/>
+ <listOptionValue builtIn="false" value="PCCB"/>
+ <listOptionValue builtIn="false" value="PCCB_X5"/>
+ <listOptionValue builtIn="false" value="_XOPEN_SOURCE"/>
+ </option>
+ <inputType id="cdt.managedbuild.tool.gnu.cpp.compiler.input.940275677" superClass="cdt.managedbuild.tool.gnu.cpp.compiler.input"/>
+ </tool>
+ </toolChain>
+ </folderInfo>
+ <sourceEntries>
+ <entry excluding="src/DuetM|src/Display|src/Networking|src/Alligator|src/SAME70_TEST|src/Duet|src/Networking/ESP8266WiFi|src/Networking/LwipEthernet|src/DuetNG|src/RADDS" flags="VALUE_WORKSPACE_PATH|RESOLVED" kind="sourcePath" name=""/>
+ </sourceEntries>
+ </configuration>
+ </storageModule>
+ <storageModule moduleId="org.eclipse.cdt.core.externalSettings"/>
+ </cconfiguration>
</storageModule>
<storageModule moduleId="cdtBuildSystem" version="4.0.0">
<project id="RepRapFirmware.cdt.managedbuild.target.gnu.cross.exe.1494358155" name="Executable" projectType="cdt.managedbuild.target.gnu.cross.exe"/>
diff --git a/.settings/language.settings.xml b/.settings/language.settings.xml
index 93f91cfc..4f109f3e 100644
--- a/.settings/language.settings.xml
+++ b/.settings/language.settings.xml
@@ -5,7 +5,7 @@
<provider copy-of="extension" id="org.eclipse.cdt.ui.UserLanguageSettingsProvider"/>
<provider-reference id="org.eclipse.cdt.core.ReferencedProjectsLanguageSettingsProvider" ref="shared-provider"/>
<provider-reference id="org.eclipse.cdt.managedbuilder.core.MBSLanguageSettingsProvider" ref="shared-provider"/>
- <provider class="org.eclipse.cdt.internal.build.crossgcc.CrossGCCBuiltinSpecsDetector" console="false" env-hash="-102132239664010639" id="org.eclipse.cdt.build.crossgcc.CrossGCCBuiltinSpecsDetector" keep-relative-paths="false" name="CDT Cross GCC Built-in Compiler Settings" parameter="${COMMAND} ${FLAGS} -E -P -v -dD &quot;${INPUTS}&quot;" prefer-non-shared="true">
+ <provider class="org.eclipse.cdt.internal.build.crossgcc.CrossGCCBuiltinSpecsDetector" console="false" env-hash="-284248688145585500" id="org.eclipse.cdt.build.crossgcc.CrossGCCBuiltinSpecsDetector" keep-relative-paths="false" name="CDT Cross GCC Built-in Compiler Settings" parameter="${COMMAND} ${FLAGS} -E -P -v -dD &quot;${INPUTS}&quot;" prefer-non-shared="true">
<language-scope id="org.eclipse.cdt.core.gcc"/>
<language-scope id="org.eclipse.cdt.core.g++"/>
</provider>
@@ -16,7 +16,7 @@
<provider copy-of="extension" id="org.eclipse.cdt.ui.UserLanguageSettingsProvider"/>
<provider-reference id="org.eclipse.cdt.core.ReferencedProjectsLanguageSettingsProvider" ref="shared-provider"/>
<provider-reference id="org.eclipse.cdt.managedbuilder.core.MBSLanguageSettingsProvider" ref="shared-provider"/>
- <provider class="org.eclipse.cdt.internal.build.crossgcc.CrossGCCBuiltinSpecsDetector" console="false" env-hash="-102132239664010639" id="org.eclipse.cdt.build.crossgcc.CrossGCCBuiltinSpecsDetector" keep-relative-paths="false" name="CDT Cross GCC Built-in Compiler Settings" parameter="${COMMAND} ${FLAGS} -E -P -v -dD &quot;${INPUTS}&quot;" prefer-non-shared="true">
+ <provider class="org.eclipse.cdt.internal.build.crossgcc.CrossGCCBuiltinSpecsDetector" console="false" env-hash="-284248688145585500" id="org.eclipse.cdt.build.crossgcc.CrossGCCBuiltinSpecsDetector" keep-relative-paths="false" name="CDT Cross GCC Built-in Compiler Settings" parameter="${COMMAND} ${FLAGS} -E -P -v -dD &quot;${INPUTS}&quot;" prefer-non-shared="true">
<language-scope id="org.eclipse.cdt.core.gcc"/>
<language-scope id="org.eclipse.cdt.core.g++"/>
</provider>
@@ -27,7 +27,7 @@
<provider copy-of="extension" id="org.eclipse.cdt.ui.UserLanguageSettingsProvider"/>
<provider-reference id="org.eclipse.cdt.core.ReferencedProjectsLanguageSettingsProvider" ref="shared-provider"/>
<provider-reference id="org.eclipse.cdt.managedbuilder.core.MBSLanguageSettingsProvider" ref="shared-provider"/>
- <provider class="org.eclipse.cdt.internal.build.crossgcc.CrossGCCBuiltinSpecsDetector" console="false" env-hash="-102132239664010639" id="org.eclipse.cdt.build.crossgcc.CrossGCCBuiltinSpecsDetector" keep-relative-paths="false" name="CDT Cross GCC Built-in Compiler Settings" parameter="${COMMAND} ${FLAGS} -E -P -v -dD &quot;${INPUTS}&quot;" prefer-non-shared="true">
+ <provider class="org.eclipse.cdt.internal.build.crossgcc.CrossGCCBuiltinSpecsDetector" console="false" env-hash="-284248688145585500" id="org.eclipse.cdt.build.crossgcc.CrossGCCBuiltinSpecsDetector" keep-relative-paths="false" name="CDT Cross GCC Built-in Compiler Settings" parameter="${COMMAND} ${FLAGS} -E -P -v -dD &quot;${INPUTS}&quot;" prefer-non-shared="true">
<language-scope id="org.eclipse.cdt.core.gcc"/>
<language-scope id="org.eclipse.cdt.core.g++"/>
</provider>
@@ -38,7 +38,7 @@
<provider copy-of="extension" id="org.eclipse.cdt.ui.UserLanguageSettingsProvider"/>
<provider-reference id="org.eclipse.cdt.core.ReferencedProjectsLanguageSettingsProvider" ref="shared-provider"/>
<provider-reference id="org.eclipse.cdt.managedbuilder.core.MBSLanguageSettingsProvider" ref="shared-provider"/>
- <provider class="org.eclipse.cdt.internal.build.crossgcc.CrossGCCBuiltinSpecsDetector" console="false" env-hash="-102132239664010639" id="org.eclipse.cdt.build.crossgcc.CrossGCCBuiltinSpecsDetector" keep-relative-paths="false" name="CDT Cross GCC Built-in Compiler Settings" parameter="${COMMAND} ${FLAGS} -E -P -v -dD &quot;${INPUTS}&quot;" prefer-non-shared="true">
+ <provider class="org.eclipse.cdt.internal.build.crossgcc.CrossGCCBuiltinSpecsDetector" console="false" env-hash="-284248688145585500" id="org.eclipse.cdt.build.crossgcc.CrossGCCBuiltinSpecsDetector" keep-relative-paths="false" name="CDT Cross GCC Built-in Compiler Settings" parameter="${COMMAND} ${FLAGS} -E -P -v -dD &quot;${INPUTS}&quot;" prefer-non-shared="true">
<language-scope id="org.eclipse.cdt.core.gcc"/>
<language-scope id="org.eclipse.cdt.core.g++"/>
</provider>
@@ -49,7 +49,7 @@
<provider copy-of="extension" id="org.eclipse.cdt.ui.UserLanguageSettingsProvider"/>
<provider-reference id="org.eclipse.cdt.core.ReferencedProjectsLanguageSettingsProvider" ref="shared-provider"/>
<provider-reference id="org.eclipse.cdt.managedbuilder.core.MBSLanguageSettingsProvider" ref="shared-provider"/>
- <provider class="org.eclipse.cdt.internal.build.crossgcc.CrossGCCBuiltinSpecsDetector" console="false" env-hash="-102132239664010639" id="org.eclipse.cdt.build.crossgcc.CrossGCCBuiltinSpecsDetector" keep-relative-paths="false" name="CDT Cross GCC Built-in Compiler Settings" parameter="${COMMAND} ${FLAGS} -E -P -v -dD &quot;${INPUTS}&quot;" prefer-non-shared="true">
+ <provider class="org.eclipse.cdt.internal.build.crossgcc.CrossGCCBuiltinSpecsDetector" console="false" env-hash="-284248688145585500" id="org.eclipse.cdt.build.crossgcc.CrossGCCBuiltinSpecsDetector" keep-relative-paths="false" name="CDT Cross GCC Built-in Compiler Settings" parameter="${COMMAND} ${FLAGS} -E -P -v -dD &quot;${INPUTS}&quot;" prefer-non-shared="true">
<language-scope id="org.eclipse.cdt.core.gcc"/>
<language-scope id="org.eclipse.cdt.core.g++"/>
</provider>
@@ -60,7 +60,7 @@
<provider copy-of="extension" id="org.eclipse.cdt.ui.UserLanguageSettingsProvider"/>
<provider-reference id="org.eclipse.cdt.core.ReferencedProjectsLanguageSettingsProvider" ref="shared-provider"/>
<provider-reference id="org.eclipse.cdt.managedbuilder.core.MBSLanguageSettingsProvider" ref="shared-provider"/>
- <provider class="org.eclipse.cdt.internal.build.crossgcc.CrossGCCBuiltinSpecsDetector" console="false" env-hash="-102132239664010639" id="org.eclipse.cdt.build.crossgcc.CrossGCCBuiltinSpecsDetector" keep-relative-paths="false" name="CDT Cross GCC Built-in Compiler Settings" parameter="${COMMAND} ${FLAGS} -E -P -v -dD &quot;${INPUTS}&quot;" prefer-non-shared="true">
+ <provider class="org.eclipse.cdt.internal.build.crossgcc.CrossGCCBuiltinSpecsDetector" console="false" env-hash="-284248688145585500" id="org.eclipse.cdt.build.crossgcc.CrossGCCBuiltinSpecsDetector" keep-relative-paths="false" name="CDT Cross GCC Built-in Compiler Settings" parameter="${COMMAND} ${FLAGS} -E -P -v -dD &quot;${INPUTS}&quot;" prefer-non-shared="true">
<language-scope id="org.eclipse.cdt.core.gcc"/>
<language-scope id="org.eclipse.cdt.core.g++"/>
</provider>
@@ -71,7 +71,18 @@
<provider copy-of="extension" id="org.eclipse.cdt.ui.UserLanguageSettingsProvider"/>
<provider-reference id="org.eclipse.cdt.core.ReferencedProjectsLanguageSettingsProvider" ref="shared-provider"/>
<provider-reference id="org.eclipse.cdt.managedbuilder.core.MBSLanguageSettingsProvider" ref="shared-provider"/>
- <provider class="org.eclipse.cdt.internal.build.crossgcc.CrossGCCBuiltinSpecsDetector" console="false" env-hash="-102132239664010639" id="org.eclipse.cdt.build.crossgcc.CrossGCCBuiltinSpecsDetector" keep-relative-paths="false" name="CDT Cross GCC Built-in Compiler Settings" parameter="${COMMAND} ${FLAGS} -E -P -v -dD &quot;${INPUTS}&quot;" prefer-non-shared="true">
+ <provider class="org.eclipse.cdt.internal.build.crossgcc.CrossGCCBuiltinSpecsDetector" console="false" env-hash="-284248688145585500" id="org.eclipse.cdt.build.crossgcc.CrossGCCBuiltinSpecsDetector" keep-relative-paths="false" name="CDT Cross GCC Built-in Compiler Settings" parameter="${COMMAND} ${FLAGS} -E -P -v -dD &quot;${INPUTS}&quot;" prefer-non-shared="true">
+ <language-scope id="org.eclipse.cdt.core.gcc"/>
+ <language-scope id="org.eclipse.cdt.core.g++"/>
+ </provider>
+ </extension>
+ </configuration>
+ <configuration id="cdt.managedbuild.config.gnu.cross.exe.release.516195201.976458850.241502451.170574622.649587786.1798324396.239853003" name="PCCB_X5">
+ <extension point="org.eclipse.cdt.core.LanguageSettingsProvider">
+ <provider copy-of="extension" id="org.eclipse.cdt.ui.UserLanguageSettingsProvider"/>
+ <provider-reference id="org.eclipse.cdt.core.ReferencedProjectsLanguageSettingsProvider" ref="shared-provider"/>
+ <provider-reference id="org.eclipse.cdt.managedbuilder.core.MBSLanguageSettingsProvider" ref="shared-provider"/>
+ <provider class="org.eclipse.cdt.internal.build.crossgcc.CrossGCCBuiltinSpecsDetector" console="false" env-hash="-284248688145585500" id="org.eclipse.cdt.build.crossgcc.CrossGCCBuiltinSpecsDetector" keep-relative-paths="false" name="CDT Cross GCC Built-in Compiler Settings" parameter="${COMMAND} ${FLAGS} -E -P -v -dD &quot;${INPUTS}&quot;" prefer-non-shared="true">
<language-scope id="org.eclipse.cdt.core.gcc"/>
<language-scope id="org.eclipse.cdt.core.g++"/>
</provider>
diff --git a/src/BugList.txt b/src/BugList.txt
index 8d62eb94..8bbbc24b 100644
--- a/src/BugList.txt
+++ b/src/BugList.txt
@@ -258,6 +258,7 @@ Bug fixes/investigations for 2.02beta3:
Other:
Planned for 2.02:
+- Still doesn't always find the DueX5, see https://forum.duet3d.com/topic/6239/unstable-after-firmware-upgrade/3. Is the Heat task affecting the timing? Need new I2C driver?
- @wilriker PR for M106 PWM limit
- WiFi continuous auto reconnect in client mode, or extra M552 parameter? See https://forum.duet3d.com/topic/5765/wifi-module-auto-reconnect
- Better dead time measurement during auto tuning. Measure both turn-on and turn-off?
diff --git a/src/DuetM/Pins_DuetM.h b/src/DuetM/Pins_DuetM.h
index f59ec75c..bc489001 100644
--- a/src/DuetM/Pins_DuetM.h
+++ b/src/DuetM/Pins_DuetM.h
@@ -63,18 +63,17 @@ constexpr size_t NUM_SERIAL_CHANNELS = 2; // The number of serial IO channels
// The numbers of entries in each array must correspond with the values of DRIVES, AXES, or HEATERS. Set values to NoPin to flag unavailability.
// Drivers
-constexpr Pin GlobalTmcEnablePin = 1; // The pin that drives ENN of all drivers
+constexpr Pin GlobalTmc22xxEnablePin = 1; // The pin that drives ENN of all drivers
constexpr Pin ENABLE_PINS[DRIVES] = { NoPin, NoPin, NoPin, NoPin, NoPin, 63, 61 };
constexpr Pin STEP_PINS[DRIVES] = { 56, 38, 64, 40, 41, 67, 57 };
constexpr Pin DIRECTION_PINS[DRIVES] = { 54, 8, 30, 33, 42, 18, 60 };
// UART interface to stepper drivers
-Uart * const UART_TMC_DRV = UART0;
-const IRQn UART_TMC_DRV_IRQn = UART0_IRQn;
-const uint32_t ID_UART_TMC_DRV = ID_UART0;
-const uint8_t UART_TMC_DRV_PINS = APINS_UART0;
-
-#define UART_TMC_DRV_Handler UART0_Handler
+Uart * const UART_TMC22xx = UART0;
+const IRQn TMC22xx_UART_IRQn = UART0_IRQn;
+const uint32_t ID_TMC22xx_UART = ID_UART0;
+const uint8_t TMC22xx_UART_PINS = APINS_UART0;
+#define TMC22xx_UART_Handler UART0_Handler
// Define the baud rate used to send/receive data to/from the drivers.
// If we assume a worst case clock frequency of 8MHz then the maximum baud rate is 8MHz/16 = 500kbaud.
@@ -85,7 +84,7 @@ const uint8_t UART_TMC_DRV_PINS = APINS_UART0;
const uint32_t DriversBaudRate = 200000;
const uint32_t TransferTimeout = 10; // any transfer should complete within 10 ticks @ 1ms/tick
-constexpr Pin DriverMuxPins[3] = { 50, 52, 53 }; // Pins that control the UART multiplexer, LSB first
+constexpr Pin TMC22xxMuxPins[3] = { 50, 52, 53 }; // Pins that control the UART multiplexer, LSB first
// Endstops
// RepRapFirmware only has a single endstop per axis.
diff --git a/src/DuetNG/Pins_DuetNG.h b/src/DuetNG/Pins_DuetNG.h
index 8d4f7334..358c8301 100644
--- a/src/DuetNG/Pins_DuetNG.h
+++ b/src/DuetNG/Pins_DuetNG.h
@@ -17,6 +17,7 @@ constexpr size_t NumFirmwareUpdateModules = 4; // 3 modules, plus one for manua
#define HAS_CPU_TEMP_SENSOR 1
#define HAS_HIGH_SPEED_SD 1
#define SUPPORT_TMC2660 1
+#define TMC2660_USES_USART 1
#define HAS_VOLTAGE_MONITOR 1
#define HAS_VREF_MONITOR 0
#define ACTIVE_LOW_HEAT_ON 1
@@ -61,11 +62,21 @@ constexpr Pin AdditionalIoExpansionStart = 220; // Pin numbers 220-235 are on t
// 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
-constexpr Pin GlobalTmcEnablePin = 38; // The pin that drives ENN of all TMC2660 drivers on production boards (on pre-production boards they are grounded)
+constexpr Pin GlobalTmc2660EnablePin = 38; // The pin that drives ENN of all TMC2660 drivers on production boards (on pre-production boards they are grounded)
constexpr Pin ENABLE_PINS[DRIVES] = { 78, 41, 42, 49, 57, 87, 88, 89, 90, 31, 82, 60 };
constexpr Pin STEP_PINS[DRIVES] = { 70, 71, 72, 69, 68, 66, 65, 64, 67, 91, 84, 85 };
constexpr Pin DIRECTION_PINS[DRIVES] = { 75, 76, 77, 01, 73, 92, 86, 80, 81, 32, 83, 25 };
+// Pin assignments etc. using USART1 in SPI mode
+Usart * const USART_TMC2660 = USART1;
+constexpr uint32_t ID_TMC2660_SPI = ID_USART1;
+constexpr IRQn TMC2660_SPI_IRQn = USART1_IRQn;
+# define TMC2660_SPI_Handler USART1_Handler
+
+constexpr Pin TMC2660MosiPin = 22; // PA13
+constexpr Pin TMC2660MisoPin = 21; // PA22
+constexpr Pin TMC2660SclkPin = 23; // PA23
+
constexpr Pin DueX_SG = 96; // DueX stallguard detect pin = PE0 (was E2_STOP)
constexpr Pin DueX_INT = 17; // DueX interrupt pin = PA17 (was E6_STOP)
diff --git a/src/Fans/DotStarLed.h b/src/Fans/DotStarLed.h
index 838a33c6..902918ec 100644
--- a/src/Fans/DotStarLed.h
+++ b/src/Fans/DotStarLed.h
@@ -8,7 +8,7 @@
#ifndef SRC_FANS_DOTSTARLED_H_
#define SRC_FANS_DOTSTARLED_H_
-#include "ReprapFirmware.h"
+#include "RepRapFirmware.h"
#include "GCodes/GCodeResult.h"
class GCodeBuffer;
diff --git a/src/GCodes/GCodes2.cpp b/src/GCodes/GCodes2.cpp
index 52825318..d2a685cc 100644
--- a/src/GCodes/GCodes2.cpp
+++ b/src/GCodes/GCodes2.cpp
@@ -1919,28 +1919,31 @@ bool GCodes::HandleMcode(GCodeBuffer& gb, const StringRef& reply)
case 204: // Set max travel and printing accelerations
{
+ Move& move = reprap.GetMove();
bool seen = false;
if (gb.Seen('S'))
{
// For backwards compatibility with old versions of Marlin (e.g. for Cura and the Prusa fork of slic3r), set both accelerations
const float acc = gb.GetFValue();
- platform.SetMaxPrintingAcceleration(acc);
- platform.SetMaxTravelAcceleration(acc);
+ move.SetMaxPrintingAcceleration(acc);
+ move.SetMaxTravelAcceleration(acc);
seen = true;
}
if (gb.Seen('P'))
{
- platform.SetMaxPrintingAcceleration(gb.GetFValue());
+ move.SetMaxPrintingAcceleration(gb.GetFValue());
seen = true;
}
if (gb.Seen('T'))
{
- platform.SetMaxTravelAcceleration(gb.GetFValue());
+ move.SetMaxTravelAcceleration(gb.GetFValue());
seen = true;
}
if (!seen)
{
- reply.printf("Maximum printing acceleration %.1f, maximum travel acceleration %.1f", (double)platform.GetMaxPrintingAcceleration(), (double)platform.GetMaxTravelAcceleration());
+ reply.printf("Maximum printing acceleration %.1f, maximum travel acceleration %.1f%s",
+ (double)move.GetMaxPrintingAcceleration(), (double)move.GetMaxTravelAcceleration(),
+ (move.IsDRCenabled()) ? " (both currently ignored because DRC is enabled)" : "");
}
}
break;
@@ -3618,8 +3621,19 @@ bool GCodes::HandleMcode(GCodeBuffer& gb, const StringRef& reply)
break;
#endif
- case 593: // Configure filament properties
- // TODO: We may need this code later to restrict specific filaments to certain tools or to reset filament counters.
+ case 593: // Configure dynamic ringing cancellation
+ if (gb.Seen('F'))
+ {
+ reprap.GetMove().SetDRCfreq(gb.GetFValue());
+ }
+ else if (reprap.GetMove().IsDRCenabled())
+ {
+ reply.printf("Dynamic ringing cancellation at %.1fHz", (double)reprap.GetMove().GetDRCfreq());
+ }
+ else
+ {
+ reply.copy("Dynamic ringing cancellation is disabled");
+ }
break;
case 665: // Set delta configuration
diff --git a/src/Movement/BedProbing/Grid.cpp b/src/Movement/BedProbing/Grid.cpp
index 379a4a60..3f598706 100644
--- a/src/Movement/BedProbing/Grid.cpp
+++ b/src/Movement/BedProbing/Grid.cpp
@@ -247,10 +247,10 @@ void HeightMap::SetGridHeight(size_t xIndex, size_t yIndex, float height)
// Note that deltaX and deltaY may be negative
unsigned int HeightMap::GetMinimumSegments(float deltaX, float deltaY) const
{
- const float xDistance = fabs(deltaX);
+ const float xDistance = fabsf(deltaX);
unsigned int xSegments = (xDistance > 0.0) ? (unsigned int)(xDistance * def.recipXspacing + 0.4) : 1;
- const float yDistance = fabs(deltaY);
+ const float yDistance = fabsf(deltaY);
unsigned int ySegments = (yDistance > 0.0) ? (unsigned int)(yDistance * def.recipYspacing + 0.4) : 1;
return max<unsigned int>(xSegments, ySegments);
diff --git a/src/Movement/DDA.cpp b/src/Movement/DDA.cpp
index d26d60fe..8ea28469 100644
--- a/src/Movement/DDA.cpp
+++ b/src/Movement/DDA.cpp
@@ -195,13 +195,13 @@ void DDA::DebugPrint() const
DebugPrintVector(" end", endCoordinates, numAxes);
}
- debugPrintf(" d=%f", (double)totalDistance);
+ debugPrintf(" s=%f", (double)totalDistance);
DebugPrintVector(" vec", directionVector, 5);
debugPrintf("\n"
- "a=%f reqv=%f startv=%f topv=%f endv=%f daccel=%f ddecel=%f\n"
- "cks=%" PRIu32 " sstcda=%" PRIu32 " tstcdapdsc=%" PRIu32 " exac=%" PRIi32 "\n",
- (double)acceleration, (double)requestedSpeed, (double)startSpeed, (double)topSpeed, (double)endSpeed, (double)accelDistance, (double)decelDistance,
- clocksNeeded, startSpeedTimesCdivA, topSpeedTimesCdivAPlusDecelStartClocks, extraAccelerationClocks);
+ "a=%f d=%f reqv=%f startv=%f topv=%f endv=%f sa=%f sd=%f\n"
+ "cks=%" PRIu32 " sstcda=%" PRIu32 " tstcddpdsc=%" PRIu32 " exac=%" PRIi32 "\n",
+ (double)acceleration, (double)deceleration, (double)requestedSpeed, (double)startSpeed, (double)topSpeed, (double)endSpeed, (double)accelDistance, (double)decelDistance,
+ clocksNeeded, startSpeedTimesCdivA, topSpeedTimesCdivDPlusDecelStartClocks, extraAccelerationClocks);
}
// Print the DDA and active DMs
@@ -439,7 +439,7 @@ bool DDA::Init(GCodes::RawMove &nextMove, bool doMotorMapping)
totalDistance = 0.0;
for (size_t d = 0; d < DRIVES; d++)
{
- totalDistance += fabs(directionVector[d]);
+ totalDistance += fabsf(directionVector[d]);
}
if (totalDistance > 0.0) // should always be true
{
@@ -451,11 +451,12 @@ bool DDA::Init(GCodes::RawMove &nextMove, bool doMotorMapping)
float normalisedDirectionVector[DRIVES]; // Used to hold a unit-length vector in the direction of motion
memcpy(normalisedDirectionVector, directionVector, sizeof(normalisedDirectionVector));
Absolute(normalisedDirectionVector, DRIVES);
- acceleration = VectorBoxIntersection(normalisedDirectionVector, accelerations, DRIVES);
- if (xyMoving)
+ acceleration = maxAcceleration = VectorBoxIntersection(normalisedDirectionVector, accelerations, DRIVES);
+ if (xyMoving && !move.IsDRCenabled()) // apply M204 acceleration limits to XY moves
{
- acceleration = min<float>(acceleration, (isPrintingMove) ? reprap.GetPlatform().GetMaxPrintingAcceleration() : reprap.GetPlatform().GetMaxTravelAcceleration());
+ acceleration = min<float>(acceleration, (isPrintingMove) ? move.GetMaxPrintingAcceleration() : move.GetMaxTravelAcceleration());
}
+ deceleration = acceleration;
// 6. Set the speed to the smaller of the requested and maximum speed.
// Also enforce a minimum speed of 0.5mm/sec. We need a minimum speed to avoid overflow in the movement calculations.
@@ -484,7 +485,7 @@ bool DDA::Init(GCodes::RawMove &nextMove, bool doMotorMapping)
requestedSpeed = min<float>(max<float>(reqSpeed, MinimumMovementSpeed), VectorBoxIntersection(normalisedDirectionVector, reprap.GetPlatform().MaxFeedrates(), DRIVES));
// On a Cartesian printer, it is OK to limit the X and Y speeds and accelerations independently, and in consequence to allow greater values
- // for diagonal moves. On a delta, this is not OK and any movement in the XY plane should be limited to the X/Y axis values, which we assume to be equal.
+ // for diagonal moves. On other architectures, this is not OK and any movement in the XY plane should be limited to the X/Y axis values, which we assume to be equal.
if (doMotorMapping)
{
k.LimitSpeedAndAcceleration(*this, normalisedDirectionVector); // give the kinematics the chance to further restrict the speed and acceleration
@@ -502,7 +503,7 @@ bool DDA::Init(GCodes::RawMove &nextMove, bool doMotorMapping)
{
// Try to meld this move to the previous move to avoid stop/start
// Assuming that this move ends with zero speed, calculate the maximum possible starting speed: u^2 = v^2 - 2as
- prev->targetNextSpeed = min<float>(sqrtf(acceleration * totalDistance * 2.0), requestedSpeed);
+ prev->targetNextSpeed = min<float>(sqrtf(deceleration * totalDistance * 2.0), requestedSpeed);
DoLookahead(prev);
startSpeed = prev->endSpeed;
}
@@ -579,7 +580,7 @@ bool DDA::Init(const float_t adjustments[DRIVES])
float normalisedDirectionVector[DRIVES]; // Used to hold a unit-length vector in the direction of motion
memcpy(normalisedDirectionVector, directionVector, sizeof(normalisedDirectionVector));
Absolute(normalisedDirectionVector, DRIVES);
- acceleration = VectorBoxIntersection(normalisedDirectionVector, accelerations, DRIVES);
+ acceleration = deceleration = VectorBoxIntersection(normalisedDirectionVector, accelerations, DRIVES);
// 6. Set the speed to the smaller of the requested and maximum speed.
requestedSpeed = VectorBoxIntersection(normalisedDirectionVector, maxSpeeds, DRIVES);
@@ -594,14 +595,22 @@ bool DDA::Init(const float_t adjustments[DRIVES])
// Return true if this move is or might have been intended to be a deceleration-only move
// A move planned as a deceleration-only move may have a short acceleration segment at the start because of rounding error
-// We declare this inline because it is only used once, in DDA::DoLookahead
inline bool DDA::IsDecelerationMove() const
{
return decelDistance == totalDistance // the simple case - is a deceleration-only move
|| (topSpeed < requestedSpeed // can't have been intended as deceleration-only if it reaches the requested speed
&& decelDistance > 0.98 * totalDistance // rounding error can only go so far
- && prev->state == DDA::provisional // if we can't adjust the previous move then we don't care (and its figures may not be reliable if it has been recycled already)
- && prev->decelDistance > 0.0); // if the previous move has no deceleration phase then no point in adjus6ting it
+ );
+}
+
+// Return true if this move is or might have been intended to be a deceleration-only move
+// A move planned as a deceleration-only move may have a short acceleration segment at the start because of rounding error
+inline bool DDA::IsAccelerationMove() const
+{
+ return accelDistance == totalDistance // the simple case - is an acceleration-only move
+ || (topSpeed < requestedSpeed // can't have been intended as deceleration-only if it reaches the requested speed
+ && accelDistance > 0.98 * totalDistance // rounding error can only go so far
+ );
}
// Return true if there is no reason to delay preparing this move
@@ -637,21 +646,24 @@ pre(state == provisional)
// We have been asked to adjust the end speed of this move to match the next move starting at targetNextSpeed
if (laDDA->targetNextSpeed > laDDA->requestedSpeed)
{
- laDDA->targetNextSpeed = laDDA->requestedSpeed; // don't try for an end speed higher than our requested speed
+ laDDA->targetNextSpeed = laDDA->requestedSpeed; // don't try for an end speed higher than our requested speed
}
if (laDDA->topSpeed >= laDDA->requestedSpeed)
{
// This move already reaches its top speed, so we just need to adjust the deceleration part
- laDDA->MatchSpeeds(); // adjust it if necessary
+ laDDA->MatchSpeeds(); // adjust it if necessary
goingUp = false;
}
- else if (laDDA->IsDecelerationMove())
+ else if ( laDDA->IsDecelerationMove()
+ && laDDA->prev->state == DDA::provisional // if we can't adjust the previous move then we don't care (and its figures may not be reliable if it has been recycled already)
+ && laDDA->prev->decelDistance > 0.0 // if the previous move has no deceleration phase then no point in adjus6ting it
+ )
{
// This is a deceleration-only move, so we may have to adjust the previous move as well to get optimum behaviour
if (laDDA->prev->state == provisional && laDDA->prev->isPrintingMove == laDDA->isPrintingMove && laDDA->prev->xyMoving == laDDA->xyMoving)
{
laDDA->MatchSpeeds();
- const float maxStartSpeed = sqrtf(fsquare(laDDA->targetNextSpeed) + (2 * laDDA->acceleration * laDDA->totalDistance));
+ const float maxStartSpeed = sqrtf(fsquare(laDDA->targetNextSpeed) + (2 * laDDA->deceleration * laDDA->totalDistance));
laDDA->prev->targetNextSpeed = min<float>(maxStartSpeed, laDDA->requestedSpeed);
// leave 'recurse' true
}
@@ -659,7 +671,7 @@ pre(state == provisional)
{
// This move is a deceleration-only move but we can't adjust the previous one
laDDA->hadLookaheadUnderrun = true;
- const float maxReachableSpeed = sqrtf(fsquare(laDDA->startSpeed) + (2 * laDDA->acceleration * laDDA->totalDistance));
+ const float maxReachableSpeed = sqrtf(fsquare(laDDA->startSpeed) + (2 * laDDA->deceleration * laDDA->totalDistance));
if (laDDA->targetNextSpeed > maxReachableSpeed)
{
laDDA->targetNextSpeed = maxReachableSpeed;
@@ -843,62 +855,71 @@ float DDA::AdvanceBabyStepping(float amount)
// This may cause a move that we intended to be a deceleration-only move to have a tiny acceleration segment at the start
void DDA::RecalculateMove()
{
- const float accelDiff = fsquare(requestedSpeed) - fsquare(startSpeed);
- const float decelDiff = fsquare(requestedSpeed) - fsquare(endSpeed);
- if (accelDiff + decelDiff >= acceleration * totalDistance * 2)
+ const float twoA = 2 * acceleration;
+ const float twoD = 2 * deceleration;
+ accelDistance = (fsquare(requestedSpeed) - fsquare(startSpeed))/twoA;
+ decelDistance = (fsquare(requestedSpeed) - fsquare(endSpeed))/twoD;
+ if (accelDistance + decelDistance < totalDistance)
+ {
+ // This move reaches its top speed
+ topSpeed = requestedSpeed;
+ }
+ else
{
// This move has no steady-speed phase, so it's accelerate-decelerate or accelerate-only or decelerate-only move.
- // If V is the peak speed, then (V^2 - u^2)/2a + (V^2 - v^2)/2a = distance.
- // So (2V^2 - u^2 - v^2) = 2a * distance
- // So V^2 = a * distance + 0.5(u^2 + v^2)
- const float vsquared = (acceleration * totalDistance) + 0.5 * (fsquare(startSpeed) + fsquare(endSpeed));
+ // If V is the peak speed, then (V^2 - u^2)/2a + (V^2 - v^2)/2d = dist
+ // So V^2(2a + 2d) = 2a.2d.dist + 2a.v^2 + 2d.u^2
+ // So V^2 = (2a.2d.dist + 2a.v^2 + 2d.u^2)/(2a + 2d)
+ const float vsquared = ((twoA * twoD * totalDistance) + (twoA * fsquare(endSpeed)) + twoD * fsquare(startSpeed))/(twoA + twoD);
if (vsquared > fsquare(startSpeed) && vsquared > fsquare(endSpeed))
{
// It's an accelerate-decelerate move. Calculate accelerate distance from: V^2 = u^2 + 2as.
- accelDistance = (vsquared - fsquare(startSpeed))/(2 * acceleration);
- decelDistance = totalDistance - accelDistance;
+ accelDistance = (vsquared - fsquare(startSpeed))/twoA;
+ decelDistance = (vsquared - fsquare(endSpeed))/twoD;
topSpeed = sqrtf(vsquared);
}
else
{
// It's an accelerate-only or decelerate-only move.
- // Due to rounding errors and babystepping adjustments, we may have to adjust the acceleration slightly.
- float newAcceleration;
+ // Due to rounding errors and babystepping adjustments, we may have to adjust the acceleration or deceleration slightly.
if (startSpeed < endSpeed)
{
accelDistance = totalDistance;
decelDistance = 0.0;
topSpeed = endSpeed;
- newAcceleration = (fsquare(endSpeed) - fsquare(startSpeed))/(2 * totalDistance);
+ const float newAcceleration = (fsquare(endSpeed) - fsquare(startSpeed))/(2 * totalDistance);
+ if (newAcceleration > 1.02 * acceleration)
+ {
+ // The acceleration increase is greater than we expect from rounding error, so record an error
+ reprap.GetMove().RecordLookaheadError();
+ if (reprap.Debug(moduleMove))
+ {
+ debugPrintf("DDA.cpp(%d) na=%.3f", __LINE__, (double)newAcceleration);
+ DebugPrint();
+ }
+ }
+ acceleration = newAcceleration;
}
else
{
accelDistance = 0.0;
decelDistance = totalDistance;
topSpeed = startSpeed;
- newAcceleration = (fsquare(startSpeed) - fsquare(endSpeed))/(2 * totalDistance);
- }
-
- if (newAcceleration > 1.02 * acceleration)
- {
- // The acceleration increase is greater than we expect from rounding error, so record an error
- reprap.GetMove().RecordLookaheadError();
- if (reprap.Debug(moduleMove))
+ const float newDeceleration = (fsquare(startSpeed) - fsquare(endSpeed))/(2 * totalDistance);
+ if (newDeceleration > 1.02 * deceleration)
{
- debugPrintf("DDA.cpp(%d) na=%.3f", __LINE__, (double)newAcceleration);
- DebugPrint();
+ // The deceleration increase is greater than we expect from rounding error, so record an error
+ reprap.GetMove().RecordLookaheadError();
+ if (reprap.Debug(moduleMove))
+ {
+ debugPrintf("DDA.cpp(%d) nd=%.3f", __LINE__, (double)newDeceleration);
+ DebugPrint();
+ }
}
+ deceleration = newDeceleration;
}
- acceleration = newAcceleration;
}
}
- else
- {
- // This move reaches its top speed
- topSpeed = requestedSpeed;
- accelDistance = accelDiff/(2 * acceleration);
- decelDistance = decelDiff/(2 * acceleration);
- }
if (canPauseAfter && endSpeed != 0.0)
{
@@ -914,7 +935,7 @@ void DDA::RecalculateMove()
}
// We need to set the number of clocks needed here because we use it before the move has been frozen
- const float totalTime = (2 * topSpeed - startSpeed - endSpeed)/acceleration + (totalDistance - accelDistance - decelDistance)/topSpeed;
+ const float totalTime = (topSpeed - startSpeed)/acceleration + (topSpeed - endSpeed)/deceleration + (totalDistance - accelDistance - decelDistance)/topSpeed;
clocksNeeded = (uint32_t)(totalTime * StepClockRate);
}
@@ -1018,10 +1039,85 @@ pre(disableDeltaMapping || drive < MaxAxes)
}
}
+// Adjust the acceleration and deceleration to reduce ringing
+// This is only called once, so inlined for speed
+inline void DDA::AdjustAcceleration()
+{
+ // Try to reduce the acceleration/deceleration of the move to cancel ringing
+ const float idealPeriod = reprap.GetMove().GetDRCperiod();
+
+ const float accTime = (topSpeed - startSpeed)/acceleration;
+ const bool adjustAcceleration =
+ (accTime < idealPeriod && accTime > 0.2 * idealPeriod && ((prev->state != DDAState::frozen && prev->state != DDAState::executing) || !prev->IsAccelerationMove()));
+ if (adjustAcceleration)
+ {
+ acceleration = (topSpeed - startSpeed)/idealPeriod;
+ accelDistance = (fsquare(topSpeed) - fsquare(startSpeed))/(2 *acceleration);
+ }
+
+ const float decelTime = (topSpeed - endSpeed)/deceleration;
+ const float adjustDeceleration =
+ (decelTime < idealPeriod && decelTime > 0.2 * idealPeriod && (next->state != DDAState::provisional || !next->IsDecelerationMove()));
+ if (adjustDeceleration)
+ {
+ deceleration = (topSpeed - endSpeed)/idealPeriod;
+ decelDistance = (fsquare(topSpeed) - fsquare(endSpeed))/(2 * deceleration);
+ }
+
+ if (adjustAcceleration || adjustDeceleration)
+ {
+ if (accelDistance + decelDistance > totalDistance)
+ {
+ // We can't keep this as a trapezoidal move
+ const float twiceTotalDistance = 2 * totalDistance;
+ if (adjustAcceleration && adjustDeceleration && (startSpeed + endSpeed) * idealPeriod < totalDistance)
+ {
+ // Change it into an accelerate-decelerate move with equal acceleration and deceleration times
+ acceleration = (twiceTotalDistance - (3 * startSpeed + endSpeed) * idealPeriod)/(2 * fsquare(idealPeriod));
+ deceleration = (twiceTotalDistance - (startSpeed + 3 * endSpeed) * idealPeriod)/(2 * fsquare(idealPeriod));
+ topSpeed = (totalDistance/idealPeriod) - (startSpeed + endSpeed)/2;
+ accelDistance = startSpeed * idealPeriod + (acceleration * fsquare(idealPeriod))/2;
+ decelDistance = endSpeed * idealPeriod + (deceleration * fsquare(idealPeriod))/2;
+ }
+ else if (startSpeed < endSpeed)
+ {
+ // Change it into an accelerate-only move, accelerating as slowly as we can
+ acceleration = (fsquare(endSpeed) - fsquare(startSpeed))/twiceTotalDistance;
+ topSpeed = endSpeed;
+ accelDistance = totalDistance;
+ decelDistance = 0.0;
+ }
+ else
+ {
+ // Change it into a decelerate-only move, decelerating as slowly as we can
+ deceleration = (fsquare(startSpeed) - fsquare(endSpeed))/twiceTotalDistance;
+ topSpeed = startSpeed;
+ accelDistance = 0.0;
+ decelDistance = totalDistance;
+ }
+ }
+ const float totalTime = (topSpeed - startSpeed)/acceleration + (topSpeed - endSpeed)/deceleration + (totalDistance - accelDistance - decelDistance)/topSpeed;
+ clocksNeeded = (uint32_t)(totalTime * StepClockRate);
+ if (reprap.Debug(moduleMove))
+ {
+ debugPrintf("New a=%f d=%f\n", (double)acceleration, (double)deceleration);
+ }
+ }
+}
+
// Prepare this DDA for execution.
// This must not be called with interrupts disabled, because it calls Platform::EnableDrive.
void DDA::Prepare(uint8_t simMode)
{
+ if ( xyMoving
+ && reprap.GetMove().IsDRCenabled()
+ && topSpeed > startSpeed && topSpeed > endSpeed
+ && (fabsf(directionVector[X_AXIS]) > 0.5 || fabsf(directionVector[Y_AXIS]) > 0.5)
+ )
+ {
+ AdjustAcceleration();
+ }
+
PrepParams params;
params.decelStartDistance = totalDistance - decelDistance;
@@ -1046,8 +1142,8 @@ void DDA::Prepare(uint8_t simMode)
const float decelStartTime = accelStopTime + (params.decelStartDistance - accelDistance)/topSpeed;
startSpeedTimesCdivA = (uint32_t)roundU32((startSpeed * StepClockRate)/acceleration);
- params.topSpeedTimesCdivA = (uint32_t)roundU32((topSpeed * StepClockRate)/acceleration);
- topSpeedTimesCdivAPlusDecelStartClocks = params.topSpeedTimesCdivA + (uint32_t)roundU32(decelStartTime * StepClockRate);
+ params.topSpeedTimesCdivD = (uint32_t)roundU32((topSpeed * StepClockRate)/deceleration);
+ topSpeedTimesCdivDPlusDecelStartClocks = params.topSpeedTimesCdivD + (uint32_t)roundU32(decelStartTime * StepClockRate);
extraAccelerationClocks = roundS32((accelStopTime - (accelDistance/topSpeed)) * StepClockRate);
params.compFactor = (topSpeed - startSpeed)/topSpeed;
@@ -1094,7 +1190,7 @@ void DDA::Prepare(uint8_t simMode)
&& ( pdm->totalSteps > 1000000
|| pdm->reverseStartStep < pdm->mp.cart.decelStartStep
|| (pdm->reverseStartStep <= pdm->totalSteps
- && pdm->mp.cart.fourMaxStepDistanceMinusTwoDistanceToStopTimesCsquaredDivA > (int64_t)(pdm->mp.cart.twoCsquaredTimesMmPerStepDivA * pdm->reverseStartStep))
+ && pdm->mp.cart.fourMaxStepDistanceMinusTwoDistanceToStopTimesCsquaredDivD > (int64_t)(pdm->mp.cart.twoCsquaredTimesMmPerStepDivD * pdm->reverseStartStep))
)
)
{
@@ -1735,6 +1831,10 @@ void DDA::LimitSpeedAndAcceleration(float maxSpeed, float maxAcceleration)
{
acceleration = maxAcceleration;
}
+ if (deceleration > maxAcceleration)
+ {
+ deceleration = maxAcceleration;
+ }
}
// End
diff --git a/src/Movement/DDA.h b/src/Movement/DDA.h
index 4747d430..b0cc4cc1 100644
--- a/src/Movement/DDA.h
+++ b/src/Movement/DDA.h
@@ -140,9 +140,11 @@ private:
void RemoveDM(size_t drive);
void ReleaseDMs();
bool IsDecelerationMove() const; // return true if this move is or have been might have been intended to be a deceleration-only move
+ bool IsAccelerationMove() const; // return true if this move is or have been might have been intended to be an acceleration-only move
void DebugPrintVector(const char *name, const float *vec, size_t len) const;
void CheckEndstops(Platform& platform);
float NormaliseXYZ(); // Make the direction vector unit-normal in XYZ
+ void AdjustAcceleration(); // Adjust the acceleration and deceleration to reduce ringing
static void DoLookahead(DDA *laDDA) __attribute__ ((hot)); // Try to smooth out moves in the queue
static float Normalise(float v[], size_t dim1, size_t dim2); // Normalise a vector of dim1 dimensions to unit length in the first dim1 dimensions
@@ -175,6 +177,10 @@ private:
uint16_t flags; // so that we can print all the flags at once for debugging
};
+#if SUPPORT_IOBITS
+ IoBits_t ioBits; // port state required during this move (here because it is currently 16 bits)
+#endif
+
EndstopChecks endStopsToCheck; // Which endstops we are checking on this move
AxesBitmap xAxes; // Which axes are behaving as X axes
AxesBitmap yAxes; // Which axes are behaving as Y axes
@@ -186,12 +192,10 @@ private:
float directionVector[DRIVES]; // The normalised direction vector - first 3 are XYZ Cartesian coordinates even on a delta
float totalDistance; // How long is the move in hypercuboid space
float acceleration; // The acceleration to use
+ float deceleration; // The deceleration to use
float requestedSpeed; // The speed that the user asked for
float virtualExtruderPosition; // the virtual extruder position at the end of this move, used for pause/resume
- // These are used only in delta calculations
- int32_t cKc; // The Z movement fraction multiplied by Kc and converted to integer
-
// These vary depending on how we connect the move with its predecessor and successor, but remain constant while the move is being executed
float startSpeed;
float endSpeed;
@@ -199,21 +203,31 @@ private:
float accelDistance;
float decelDistance;
- // This is a temporary, used to keep track of the lookahead to avoid making recursive calls
- float targetNextSpeed; // The speed that the next move would like to start at
-
- // These are calculated from the above and used in the ISR, so they are set up by Prepare()
- uint32_t clocksNeeded; // in clocks
- uint32_t moveStartTime; // clock count at which the move was started
- uint32_t startSpeedTimesCdivA; // the number of clocks it would have taken to reach the start speed from rest
- uint32_t topSpeedTimesCdivAPlusDecelStartClocks;
- int32_t extraAccelerationClocks; // the additional number of clocks needed because we started the move at less than topSpeed. Negative after ReduceHomingSpeed has been called.
-
float proportionLeft; // what proportion of the extrusion in the G1 or G0 move of which this is a part remains to be done after this segment is complete
+ uint32_t clocksNeeded;
-#if SUPPORT_IOBITS
- IoBits_t ioBits; // port state required during this move
-#endif
+ union
+ {
+ // Values that are needed only before Prepare is called
+ struct
+ {
+ float targetNextSpeed; // The speed that the next move would like to start at, used to keep track of the lookahead without making recursive calls
+ float maxAcceleration; // the maximum allowed acceleration for this move according to the limits set by M201
+ };
+
+ // Values that are not set or accessed before Prepare is called
+ struct
+ {
+ // These are calculated from the above and used in the ISR, so they are set up by Prepare()
+ uint32_t moveStartTime; // clock count at which the move was started
+ uint32_t startSpeedTimesCdivA; // the number of clocks it would have taken to reach the start speed from rest
+ uint32_t topSpeedTimesCdivDPlusDecelStartClocks;
+ int32_t extraAccelerationClocks; // the additional number of clocks needed because we started the move at less than topSpeed. Negative after ReduceHomingSpeed has been called.
+
+ // These are used only in delta calculations
+ int32_t cKc; // The Z movement fraction multiplied by Kc and converted to integer
+ };
+ };
#if DDA_LOG_PROBE_CHANGES
static bool probeTriggered;
diff --git a/src/Movement/DriveMovement.cpp b/src/Movement/DriveMovement.cpp
index f510d0a2..7ebbc6c5 100644
--- a/src/Movement/DriveMovement.cpp
+++ b/src/Movement/DriveMovement.cpp
@@ -59,6 +59,7 @@ void DriveMovement::PrepareCartesianAxis(const DDA& dda, const PrepParams& param
{
const float stepsPerMm = (float)totalSteps/dda.totalDistance;
mp.cart.twoCsquaredTimesMmPerStepDivA = roundU64((double)(StepClockRateSquared * 2)/((double)stepsPerMm * (double)dda.acceleration));
+ mp.cart.twoCsquaredTimesMmPerStepDivD = roundU64((double)(StepClockRateSquared * 2)/((double)stepsPerMm * (double)dda.deceleration));
// Acceleration phase parameters
mp.cart.accelStopStep = (uint32_t)(dda.accelDistance * stepsPerMm) + 1;
@@ -72,18 +73,18 @@ void DriveMovement::PrepareCartesianAxis(const DDA& dda, const PrepParams& param
if (dda.decelDistance * stepsPerMm < 0.5)
{
mp.cart.decelStartStep = totalSteps + 1;
- twoDistanceToStopTimesCsquaredDivA = 0;
+ twoDistanceToStopTimesCsquaredDivD = 0;
}
else
{
mp.cart.decelStartStep = (uint32_t)(params.decelStartDistance * stepsPerMm) + 1;
- const uint64_t initialDecelSpeedTimesCdivASquared = isquare64(params.topSpeedTimesCdivA);
- twoDistanceToStopTimesCsquaredDivA = initialDecelSpeedTimesCdivASquared + roundU64((params.decelStartDistance * (StepClockRateSquared * 2))/dda.acceleration);
+ const uint64_t initialDecelSpeedTimesCdivDSquared = isquare64(params.topSpeedTimesCdivD);
+ twoDistanceToStopTimesCsquaredDivD = initialDecelSpeedTimesCdivDSquared + roundU64((params.decelStartDistance * (StepClockRateSquared * 2))/dda.deceleration);
}
// No reverse phase
reverseStartStep = totalSteps + 1;
- mp.cart.fourMaxStepDistanceMinusTwoDistanceToStopTimesCsquaredDivA = 0;
+ mp.cart.fourMaxStepDistanceMinusTwoDistanceToStopTimesCsquaredDivD = 0;
}
// Prepare this DM for a Delta axis move
@@ -99,6 +100,7 @@ void DriveMovement::PrepareDeltaAxis(const DDA& dda, const PrepParams& params)
mp.delta.minusAaPlusBbTimesKs = -roundS32(aAplusbB * stepsPerMm * DriveMovement::K2);
mp.delta.dSquaredMinusAsquaredMinusBsquaredTimesKsquaredSsquared = roundS64(dSquaredMinusAsquaredMinusBsquared * fsquare(stepsPerMm * DriveMovement::K2));
mp.delta.twoCsquaredTimesMmPerStepDivA = roundU64((double)(2 * StepClockRateSquared)/((double)stepsPerMm * (double)dda.acceleration));
+ mp.delta.twoCsquaredTimesMmPerStepDivD = roundU64((double)(2 * StepClockRateSquared)/((double)stepsPerMm * (double)dda.deceleration));
// Calculate the distance at which we need to reverse direction.
if (params.a2plusb2 <= 0.0)
@@ -159,12 +161,12 @@ void DriveMovement::PrepareDeltaAxis(const DDA& dda, const PrepParams& params)
if (dda.decelDistance * stepsPerMm < 0.5)
{
mp.delta.decelStartDsK = 0xFFFFFFFF;
- twoDistanceToStopTimesCsquaredDivA = 0;
+ twoDistanceToStopTimesCsquaredDivD = 0;
}
else
{
mp.delta.decelStartDsK = roundU32(params.decelStartDistance * stepsPerMm * K2);
- twoDistanceToStopTimesCsquaredDivA = isquare64(params.topSpeedTimesCdivA) + roundU64((params.decelStartDistance * (StepClockRateSquared * 2))/dda.acceleration);
+ twoDistanceToStopTimesCsquaredDivD = isquare64(params.topSpeedTimesCdivD) + roundU64((params.decelStartDistance * (StepClockRateSquared * 2))/dda.deceleration);
}
}
@@ -224,6 +226,7 @@ void DriveMovement::PrepareExtruder(const DDA& dda, const PrepParams& params, fl
}
mp.cart.twoCsquaredTimesMmPerStepDivA = roundU64((double)(StepClockRateSquared * 2)/((double)stepsPerMm * (double)dda.acceleration));
+ mp.cart.twoCsquaredTimesMmPerStepDivD = roundU64((double)(StepClockRateSquared * 2)/((double)stepsPerMm * (double)dda.deceleration));
// Constant speed phase parameters
mp.cart.mmPerStepTimesCKdivtopSpeed = (uint32_t)((float)((uint64_t)StepClockRate * K1)/(stepsPerMm * dda.topSpeed));
@@ -234,28 +237,28 @@ void DriveMovement::PrepareExtruder(const DDA& dda, const PrepParams& params, fl
{
totalSteps = (uint32_t)max<int32_t>(netSteps, 0);
mp.cart.decelStartStep = reverseStartStep = netSteps + 1;
- mp.cart.fourMaxStepDistanceMinusTwoDistanceToStopTimesCsquaredDivA = 0;
- twoDistanceToStopTimesCsquaredDivA = 0;
+ mp.cart.fourMaxStepDistanceMinusTwoDistanceToStopTimesCsquaredDivD = 0;
+ twoDistanceToStopTimesCsquaredDivD = 0;
}
else
{
mp.cart.decelStartStep = (uint32_t)((params.decelStartDistance + accelCompensationDistance) * stepsPerMm) + 1;
- const int32_t initialDecelSpeedTimesCdivA = (int32_t)params.topSpeedTimesCdivA - (int32_t)mp.cart.compensationClocks; // signed because it may be negative and we square it
- const uint64_t initialDecelSpeedTimesCdivASquared = isquare64(initialDecelSpeedTimesCdivA);
- twoDistanceToStopTimesCsquaredDivA =
- initialDecelSpeedTimesCdivASquared + roundU64(((params.decelStartDistance + accelCompensationDistance) * (float)(StepClockRateSquared * 2))/dda.acceleration);
+ 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 =
+ initialDecelSpeedTimesCdivDSquared + roundU64(((params.decelStartDistance + accelCompensationDistance) * (float)(StepClockRateSquared * 2))/dda.deceleration);
// See whether there is a reverse phase
- const float compensationSpeedChange = dda.acceleration * compensationTime;
+ const float compensationSpeedChange = dda.deceleration * compensationTime;
const uint32_t stepsBeforeReverse = (compensationSpeedChange > dda.topSpeed)
? mp.cart.decelStartStep - 1
- : twoDistanceToStopTimesCsquaredDivA/mp.cart.twoCsquaredTimesMmPerStepDivA;
+ : twoDistanceToStopTimesCsquaredDivD/mp.cart.twoCsquaredTimesMmPerStepDivD;
if (dda.endSpeed < compensationSpeedChange && (int32_t)stepsBeforeReverse > netSteps)
{
reverseStartStep = stepsBeforeReverse + 1;
totalSteps = (uint32_t)((int32_t)(2 * stepsBeforeReverse) - netSteps);
- mp.cart.fourMaxStepDistanceMinusTwoDistanceToStopTimesCsquaredDivA =
- (int64_t)((2 * stepsBeforeReverse) * mp.cart.twoCsquaredTimesMmPerStepDivA) - (int64_t)twoDistanceToStopTimesCsquaredDivA;
+ mp.cart.fourMaxStepDistanceMinusTwoDistanceToStopTimesCsquaredDivD =
+ (int64_t)((2 * stepsBeforeReverse) * mp.cart.twoCsquaredTimesMmPerStepDivD) - (int64_t)twoDistanceToStopTimesCsquaredDivD;
}
else
{
@@ -266,7 +269,7 @@ void DriveMovement::PrepareExtruder(const DDA& dda, const PrepParams& params, fl
}
reverseStartStep = netSteps + 1;
totalSteps = (uint32_t)max<int32_t>(netSteps, 0);
- mp.cart.fourMaxStepDistanceMinusTwoDistanceToStopTimesCsquaredDivA = 0;
+ mp.cart.fourMaxStepDistanceMinusTwoDistanceToStopTimesCsquaredDivD = 0;
}
}
}
@@ -278,22 +281,22 @@ void DriveMovement::DebugPrint(char c, bool isDeltaMovement) const
debugPrintf("DM%c%s dir=%c steps=%" PRIu32 " next=%" PRIu32 " rev=%" PRIu32 " interval=%" PRIu32
" 2dtstc2diva=%" PRIu64 "\n",
c, (state == DMState::stepError) ? " ERR:" : ":", (direction) ? 'F' : 'B', totalSteps, nextStep, reverseStartStep, stepInterval,
- twoDistanceToStopTimesCsquaredDivA);
+ twoDistanceToStopTimesCsquaredDivD);
if (isDeltaMovement)
{
debugPrintf("hmz0sK=%" PRIi32 " minusAaPlusBbTimesKs=%" PRIi32 " dSquaredMinusAsquaredMinusBsquared=%" PRId64 "\n"
- "2c2mmsda=%" PRIu64 " asdsk=%" PRIu32 " dsdsk=%" PRIu32 " mmstcdts=%" PRIu32 "\n",
+ "2c2mmsda=%" PRIu64 "2c2mmsdd=%" PRIu64 " asdsk=%" PRIu32 " dsdsk=%" PRIu32 " mmstcdts=%" PRIu32 "\n",
mp.delta.hmz0sK, mp.delta.minusAaPlusBbTimesKs, mp.delta.dSquaredMinusAsquaredMinusBsquaredTimesKsquaredSsquared,
- mp.delta.twoCsquaredTimesMmPerStepDivA, mp.delta.accelStopDsK, mp.delta.decelStartDsK, mp.delta.mmPerStepTimesCKdivtopSpeed
+ mp.delta.twoCsquaredTimesMmPerStepDivA, mp.delta.twoCsquaredTimesMmPerStepDivD, mp.delta.accelStopDsK, mp.delta.decelStartDsK, mp.delta.mmPerStepTimesCKdivtopSpeed
);
}
else
{
- debugPrintf("accelStopStep=%" PRIu32 " decelStartStep=%" PRIu32 " 2CsqtMmPerStepDivA=%" PRIu64 "\n"
+ debugPrintf("accelStopStep=%" PRIu32 " decelStartStep=%" PRIu32 " 2c2mmsda=%" PRIu64 " 2c2mmsdd=%" PRIu64 "\n"
"mmPerStepTimesCdivtopSpeed=%" PRIu32 " fmsdmtstdca2=%" PRId64 " cc=%" PRIu32 " acc=%" PRIu32 "\n",
- mp.cart.accelStopStep, mp.cart.decelStartStep, mp.cart.twoCsquaredTimesMmPerStepDivA,
- mp.cart.mmPerStepTimesCKdivtopSpeed, mp.cart.fourMaxStepDistanceMinusTwoDistanceToStopTimesCsquaredDivA, mp.cart.compensationClocks, mp.cart.accelCompensationClocks
+ mp.cart.accelStopStep, mp.cart.decelStartStep, mp.cart.twoCsquaredTimesMmPerStepDivA, mp.cart.twoCsquaredTimesMmPerStepDivD,
+ mp.cart.mmPerStepTimesCKdivtopSpeed, mp.cart.fourMaxStepDistanceMinusTwoDistanceToStopTimesCsquaredDivD, mp.cart.compensationClocks, mp.cart.accelCompensationClocks
);
}
}
@@ -353,12 +356,12 @@ pre(nextStep < totalSteps; stepsTillRecalc == 0)
else if (nextCalcStep < reverseStartStep)
{
// deceleration phase, not reversed yet
- const uint64_t temp = mp.cart.twoCsquaredTimesMmPerStepDivA * nextCalcStep;
- const uint32_t adjustedTopSpeedTimesCdivAPlusDecelStartClocks = dda.topSpeedTimesCdivAPlusDecelStartClocks - mp.cart.compensationClocks;
+ const uint64_t temp = mp.cart.twoCsquaredTimesMmPerStepDivD * nextCalcStep;
+ const uint32_t adjustedTopSpeedTimesCdivDPlusDecelStartClocks = dda.topSpeedTimesCdivDPlusDecelStartClocks - mp.cart.compensationClocks;
// Allow for possible rounding error when the end speed is zero or very small
- nextCalcStepTime = (temp < twoDistanceToStopTimesCsquaredDivA)
- ? adjustedTopSpeedTimesCdivAPlusDecelStartClocks - isqrt64(twoDistanceToStopTimesCsquaredDivA - temp)
- : adjustedTopSpeedTimesCdivAPlusDecelStartClocks;
+ nextCalcStepTime = (temp < twoDistanceToStopTimesCsquaredDivD)
+ ? adjustedTopSpeedTimesCdivDPlusDecelStartClocks - isqrt64(twoDistanceToStopTimesCsquaredDivD - temp)
+ : adjustedTopSpeedTimesCdivDPlusDecelStartClocks;
}
else
{
@@ -371,9 +374,9 @@ pre(nextStep < totalSteps; stepsTillRecalc == 0)
reprap.GetPlatform().SetDirection(drive, direction);
}
}
- const uint32_t adjustedTopSpeedTimesCdivAPlusDecelStartClocks = dda.topSpeedTimesCdivAPlusDecelStartClocks - mp.cart.compensationClocks;
- nextCalcStepTime = adjustedTopSpeedTimesCdivAPlusDecelStartClocks
- + isqrt64((int64_t)(mp.cart.twoCsquaredTimesMmPerStepDivA * nextCalcStep) - mp.cart.fourMaxStepDistanceMinusTwoDistanceToStopTimesCsquaredDivA);
+ const uint32_t adjustedTopSpeedTimesCdivDPlusDecelStartClocks = dda.topSpeedTimesCdivDPlusDecelStartClocks - mp.cart.compensationClocks;
+ nextCalcStepTime = adjustedTopSpeedTimesCdivDPlusDecelStartClocks
+ + isqrt64((int64_t)(mp.cart.twoCsquaredTimesMmPerStepDivD * nextCalcStep) - mp.cart.fourMaxStepDistanceMinusTwoDistanceToStopTimesCsquaredDivD);
}
// When crossing between movement phases with high microstepping, due to rounding errors the next step may appear to be due before the last one
@@ -491,11 +494,11 @@ pre(nextStep < totalSteps; stepsTillRecalc == 0)
}
else
{
- const uint64_t temp = (mp.delta.twoCsquaredTimesMmPerStepDivA * (uint32_t)dsK)/K2;
+ const uint64_t temp = (mp.delta.twoCsquaredTimesMmPerStepDivD * (uint32_t)dsK)/K2;
// Because of possible rounding error when the end speed is zero or very small, we need to check that the square root will work OK
- nextCalcStepTime = (temp < twoDistanceToStopTimesCsquaredDivA)
- ? dda.topSpeedTimesCdivAPlusDecelStartClocks - isqrt64(twoDistanceToStopTimesCsquaredDivA - temp)
- : dda.topSpeedTimesCdivAPlusDecelStartClocks;
+ nextCalcStepTime = (temp < twoDistanceToStopTimesCsquaredDivD)
+ ? dda.topSpeedTimesCdivDPlusDecelStartClocks - isqrt64(twoDistanceToStopTimesCsquaredDivD - temp)
+ : dda.topSpeedTimesCdivDPlusDecelStartClocks;
}
// When crossing between movement phases with high microstepping, due to rounding errors the next step may appear to be due before the last one.
diff --git a/src/Movement/DriveMovement.h b/src/Movement/DriveMovement.h
index 8deb5b14..d5df4602 100644
--- a/src/Movement/DriveMovement.h
+++ b/src/Movement/DriveMovement.h
@@ -93,7 +93,7 @@ struct PrepParams
{
// Parameters used for all types of motion
float decelStartDistance;
- uint32_t topSpeedTimesCdivA;
+ uint32_t topSpeedTimesCdivD;
// Parameters used only for extruders
float compFactor;
@@ -171,18 +171,19 @@ private:
uint32_t stepInterval; // how many clocks between steps
// The following only needs to be stored per-drive if we are supporting pressure advance
- uint64_t twoDistanceToStopTimesCsquaredDivA;
+ uint64_t twoDistanceToStopTimesCsquaredDivD;
// Parameters unique to a style of move (Cartesian, delta or extruder). Currently, extruders and Cartesian moves use the same parameters.
union MoveParams
{
struct CartesianParameters // Parameters for Cartesian and extruder movement, including extruder pressure advance
{
- // The following don't depend on how the move is executed, so they could be set up in Init()
+ // The following don't depend on how the move is executed, so they could be set up in Init() if we use fixed acceleration/deceleration
uint64_t twoCsquaredTimesMmPerStepDivA; // 2 * clock^2 * mmPerStepInHyperCuboidSpace / acceleration
+ uint64_t twoCsquaredTimesMmPerStepDivD; // 2 * clock^2 * mmPerStepInHyperCuboidSpace / deceleration
// The following depend on how the move is executed, so they must be set up in Prepare()
- int64_t fourMaxStepDistanceMinusTwoDistanceToStopTimesCsquaredDivA; // this one can be negative
+ int64_t fourMaxStepDistanceMinusTwoDistanceToStopTimesCsquaredDivD; // this one can be negative
uint32_t accelStopStep; // the first step number at which we are no longer accelerating
uint32_t decelStartStep; // the first step number at which we are decelerating
uint32_t mmPerStepTimesCKdivtopSpeed; // mmPerStepInHyperCuboidSpace * clock / topSpeed
@@ -192,8 +193,9 @@ private:
struct DeltaParameters // Parameters for delta movement
{
- // The following don't depend on how the move is executed, so they can be set up in Init
+ // The following don't depend on how the move is executed, so they could be set up in Init() if we use fixed acceleration/deceleration
uint64_t twoCsquaredTimesMmPerStepDivA; // this could be stored in the DDA if all towers use the same steps/mm
+ uint64_t twoCsquaredTimesMmPerStepDivD; // 2 * clock^2 * mmPerStepInHyperCuboidSpace / deceleration
int64_t dSquaredMinusAsquaredMinusBsquaredTimesKsquaredSsquared;
int32_t hmz0sK; // the starting step position less the starting Z height, multiplied by the Z movement fraction and K (can go negative)
int32_t minusAaPlusBbTimesKs;
diff --git a/src/Movement/Kinematics/CoreXYKinematics.cpp b/src/Movement/Kinematics/CoreXYKinematics.cpp
index 86d32a33..09a5f24d 100644
--- a/src/Movement/Kinematics/CoreXYKinematics.cpp
+++ b/src/Movement/Kinematics/CoreXYKinematics.cpp
@@ -62,7 +62,7 @@ void CoreXYKinematics::LimitSpeedAndAcceleration(DDA& dda, const float *normalis
{
const float vecX = normalisedDirectionVector[0];
const float vecY = normalisedDirectionVector[1];
- const float vecMax = max<float>(fabs(vecX + vecY), fabs(vecX - vecY)); // pick the case for the motor that is working hardest
+ const float vecMax = max<float>(fabsf(vecX + vecY), fabsf(vecX - vecY)); // pick the case for the motor that is working hardest
if (vecMax > 0.01) // avoid division by zero or near-zero
{
const Platform& platform = reprap.GetPlatform();
@@ -70,8 +70,8 @@ void CoreXYKinematics::LimitSpeedAndAcceleration(DDA& dda, const float *normalis
const float aY = platform.Acceleration(1);
const float vX = platform.MaxFeedrate(0);
const float vY = platform.MaxFeedrate(1);
- const float aMax = (fabs(vecX) + fabs(vecY)) * aX * aY/(vecMax * (fabs(vecX) * aY + fabs(vecY) * aX));
- const float vMax = (fabs(vecX) + fabs(vecY)) * vX * vY/(vecMax * (fabs(vecX) * vY + fabs(vecY) * vX));
+ const float aMax = (fabsf(vecX) + fabsf(vecY)) * aX * aY/(vecMax * (fabsf(vecX) * aY + fabsf(vecY) * aX));
+ const float vMax = (fabsf(vecX) + fabsf(vecY)) * vX * vY/(vecMax * (fabsf(vecX) * vY + fabsf(vecY) * vX));
dda.LimitSpeedAndAcceleration(vMax, aMax);
}
}
diff --git a/src/Movement/Kinematics/CoreXYUKinematics.cpp b/src/Movement/Kinematics/CoreXYUKinematics.cpp
index 0b2f3981..3f2db5cb 100644
--- a/src/Movement/Kinematics/CoreXYUKinematics.cpp
+++ b/src/Movement/Kinematics/CoreXYUKinematics.cpp
@@ -106,7 +106,7 @@ void CoreXYUKinematics::LimitSpeedAndAcceleration(DDA& dda, const float *normali
const float vecY = normalisedDirectionVector[1];
// Limit the XY motor accelerations
- const float vecMaxXY = max<float>(fabs(vecX + vecY), fabs(vecX - vecY)); // pick the case for the motor that is working hardest
+ const float vecMaxXY = max<float>(fabsf(vecX + vecY), fabsf(vecX - vecY)); // pick the case for the motor that is working hardest
if (vecMaxXY > 0.01) // avoid division by zero or near-zero
{
const Platform& platform = reprap.GetPlatform();
@@ -114,14 +114,14 @@ void CoreXYUKinematics::LimitSpeedAndAcceleration(DDA& dda, const float *normali
const float aY = platform.Acceleration(1);
const float vX = platform.MaxFeedrate(0);
const float vY = platform.MaxFeedrate(1);
- const float aMax = (fabs(vecX) + fabs(vecY)) * aX * aY/(vecMaxXY * (fabs(vecX) * aY + fabs(vecY) * aX));
- const float vMax = (fabs(vecX) + fabs(vecY)) * vX * vY/(vecMaxXY * (fabs(vecX) * vY + fabs(vecY) * vX));
+ const float aMax = (fabsf(vecX) + fabsf(vecY)) * aX * aY/(vecMaxXY * (fabsf(vecX) * aY + fabsf(vecY) * aX));
+ const float vMax = (fabsf(vecX) + fabsf(vecY)) * vX * vY/(vecMaxXY * (fabsf(vecX) * vY + fabsf(vecY) * vX));
dda.LimitSpeedAndAcceleration(vMax, aMax);
}
// Limit the UV motor accelerations
const float vecU = normalisedDirectionVector[3];
- const float vecMaxUV = max<float>(fabs(vecU + vecY), fabs(vecU - vecY)); // pick the case for the motor that is working hardest
+ const float vecMaxUV = max<float>(fabsf(vecU + vecY), fabsf(vecU - vecY)); // pick the case for the motor that is working hardest
if (vecMaxUV > 0.01) // avoid division by zero or near-zero
{
const Platform& platform = reprap.GetPlatform();
@@ -129,8 +129,8 @@ void CoreXYUKinematics::LimitSpeedAndAcceleration(DDA& dda, const float *normali
const float aY = platform.Acceleration(1);
const float vU = platform.MaxFeedrate(3);
const float vY = platform.MaxFeedrate(1);
- const float aMax = (fabs(vecU) + fabs(vecY)) * aU * aY/(vecMaxUV * (fabs(vecU) * aY + fabs(vecY) * aU));
- const float vMax = (fabs(vecU) + fabs(vecY)) * vU * vY/(vecMaxUV * (fabs(vecU) * vY + fabs(vecY) * vU));
+ const float aMax = (fabsf(vecU) + fabsf(vecY)) * aU * aY/(vecMaxUV * (fabsf(vecU) * aY + fabsf(vecY) * aU));
+ const float vMax = (fabsf(vecU) + fabsf(vecY)) * vU * vY/(vecMaxUV * (fabsf(vecU) * vY + fabsf(vecY) * vU));
dda.LimitSpeedAndAcceleration(vMax, aMax);
}
}
diff --git a/src/Movement/Kinematics/CoreXYUVKinematics.cpp b/src/Movement/Kinematics/CoreXYUVKinematics.cpp
index 6d2ea68c..69c24311 100644
--- a/src/Movement/Kinematics/CoreXYUVKinematics.cpp
+++ b/src/Movement/Kinematics/CoreXYUVKinematics.cpp
@@ -105,7 +105,7 @@ void CoreXYUVKinematics::LimitSpeedAndAcceleration(DDA& dda, const float *normal
const float vecY = normalisedDirectionVector[1];
// Limit the XY motor accelerations
- const float vecMaxXY = max<float>(fabs(vecX + vecY), fabs(vecX - vecY)); // pick the case for the motor that is working hardest
+ const float vecMaxXY = max<float>(fabsf(vecX + vecY), fabsf(vecX - vecY)); // pick the case for the motor that is working hardest
if (vecMaxXY > 0.01) // avoid division by zero or near-zero
{
const Platform& platform = reprap.GetPlatform();
@@ -113,15 +113,15 @@ void CoreXYUVKinematics::LimitSpeedAndAcceleration(DDA& dda, const float *normal
const float aY = platform.Acceleration(1);
const float vX = platform.MaxFeedrate(0);
const float vY = platform.MaxFeedrate(1);
- const float aMax = (fabs(vecX) + fabs(vecY)) * aX * aY/(vecMaxXY * (fabs(vecX) * aY + fabs(vecY) * aX));
- const float vMax = (fabs(vecX) + fabs(vecY)) * vX * vY/(vecMaxXY * (fabs(vecX) * vY + fabs(vecY) * vX));
+ const float aMax = (fabsf(vecX) + fabsf(vecY)) * aX * aY/(vecMaxXY * (fabsf(vecX) * aY + fabsf(vecY) * aX));
+ const float vMax = (fabsf(vecX) + fabsf(vecY)) * vX * vY/(vecMaxXY * (fabsf(vecX) * vY + fabsf(vecY) * vX));
dda.LimitSpeedAndAcceleration(vMax, aMax);
}
// Limit the UV motor accelerations
const float vecU = normalisedDirectionVector[3];
const float vecV = normalisedDirectionVector[4];
- const float vecMaxUV = max<float>(fabs(vecU + vecV), fabs(vecU - vecV)); // pick the case for the motor that is working hardest
+ const float vecMaxUV = max<float>(fabsf(vecU + vecV), fabsf(vecU - vecV)); // pick the case for the motor that is working hardest
if (vecMaxUV > 0.01) // avoid division by zero or near-zero
{
const Platform& platform = reprap.GetPlatform();
@@ -129,8 +129,8 @@ void CoreXYUVKinematics::LimitSpeedAndAcceleration(DDA& dda, const float *normal
const float aV = platform.Acceleration(4);
const float vU = platform.MaxFeedrate(3);
const float vV = platform.MaxFeedrate(4);
- const float aMax = (fabs(vecU) + fabs(vecV)) * aU * aV/(vecMaxUV * (fabs(vecU) * aV + fabs(vecV) * aU));
- const float vMax = (fabs(vecU) + fabs(vecV)) * vU * vV/(vecMaxUV * (fabs(vecU) * vV + fabs(vecV) * vU));
+ const float aMax = (fabsf(vecU) + fabsf(vecV)) * aU * aV/(vecMaxUV * (fabsf(vecU) * aV + fabsf(vecV) * aU));
+ const float vMax = (fabsf(vecU) + fabsf(vecV)) * vU * vV/(vecMaxUV * (fabsf(vecU) * vV + fabsf(vecV) * vU));
dda.LimitSpeedAndAcceleration(vMax, aMax);
}
}
diff --git a/src/Movement/Kinematics/Kinematics.cpp b/src/Movement/Kinematics/Kinematics.cpp
index 51c4d1fe..145c466a 100644
--- a/src/Movement/Kinematics/Kinematics.cpp
+++ b/src/Movement/Kinematics/Kinematics.cpp
@@ -15,6 +15,7 @@
#include "HangprinterKinematics.h"
#include "PolarKinematics.h"
#include "CoreXYUVKinematics.h"
+#include "RotaryDeltaKinematics.h"
#include "RepRap.h"
#include "Platform.h"
#include "GCodes/GCodeBuffer.h"
@@ -142,8 +143,10 @@ const char* Kinematics::GetHomingFileName(AxesBitmap toBeHomed, AxesBitmap alrea
{
switch (k)
{
+ case KinematicsType::linearDeltaPlusZ: // not implemented yet
default:
return nullptr;
+
case KinematicsType::cartesian:
return new CartesianKinematics();
case KinematicsType::linearDelta:
@@ -162,6 +165,8 @@ const char* Kinematics::GetHomingFileName(AxesBitmap toBeHomed, AxesBitmap alrea
return new PolarKinematics();
case KinematicsType::coreXYUV:
return new CoreXYUVKinematics();
+ case KinematicsType::rotaryDelta:
+ return new RotaryDeltaKinematics();
}
}
diff --git a/src/Movement/Kinematics/Kinematics.h b/src/Movement/Kinematics/Kinematics.h
index f9ebe5d9..2275788b 100644
--- a/src/Movement/Kinematics/Kinematics.h
+++ b/src/Movement/Kinematics/Kinematics.h
@@ -29,8 +29,8 @@ enum class KinematicsType : uint8_t
hangprinter,
polar,
coreXYUV,
-// linearDeltaPlusZ, // reserved for @sga, see https://forum.duet3d.com/topic/5775/aditional-carterian-z-axis-on-delta-printer
-// rotaryDelta, // not yet implemented
+ linearDeltaPlusZ, // reserved for @sga, see https://forum.duet3d.com/topic/5775/aditional-carterian-z-axis-on-delta-printer
+ rotaryDelta, // not yet implemented
unknown // this one must be last!
};
diff --git a/src/Movement/Kinematics/LinearDeltaKinematics.cpp b/src/Movement/Kinematics/LinearDeltaKinematics.cpp
index e2eedfb4..c5c69b26 100644
--- a/src/Movement/Kinematics/LinearDeltaKinematics.cpp
+++ b/src/Movement/Kinematics/LinearDeltaKinematics.cpp
@@ -26,11 +26,11 @@ const char *LinearDeltaKinematics::GetName(bool forStatusReport) const
void LinearDeltaKinematics::Init()
{
- diagonal = defaultDiagonal;
- radius = defaultDeltaRadius;
+ diagonal = DefaultDiagonal;
+ radius = DefaultDeltaRadius;
xTilt = yTilt = 0.0;
- printRadius = defaultPrintRadius;
- homedHeight = defaultDeltaHomedHeight;
+ printRadius = DefaultPrintRadius;
+ homedHeight = DefaultDeltaHomedHeight;
doneAutoCalibration = false;
for (size_t axis = 0; axis < DELTA_AXES; ++axis)
@@ -68,7 +68,7 @@ void LinearDeltaKinematics::Recalc()
// Calculate the base carriage height when the printer is homed, i.e. the carriages are at the endstops less the corrections
const float tempHeight = diagonal; // any sensible height will do here
float machinePos[DELTA_AXES];
- InverseTransform(tempHeight, tempHeight, tempHeight, machinePos);
+ ForwardTransform(tempHeight, tempHeight, tempHeight, machinePos);
homedCarriageHeight = homedHeight + tempHeight - machinePos[Z_AXIS];
printRadiusSquared = fsquare(printRadius);
}
@@ -87,7 +87,6 @@ void LinearDeltaKinematics::NormaliseEndstopAdjustments()
// Calculate the motor position for a single tower from a Cartesian coordinate.
float LinearDeltaKinematics::Transform(const float machinePos[], size_t axis) const
{
- //TODO find a way of returning error if we can't transform the position
if (axis < DELTA_AXES)
{
return sqrtf(D2 - fsquare(machinePos[X_AXIS] - towerX[axis]) - fsquare(machinePos[Y_AXIS] - towerY[axis]))
@@ -102,7 +101,7 @@ float LinearDeltaKinematics::Transform(const float machinePos[], size_t axis) co
}
// Calculate the Cartesian coordinates from the motor coordinates
-void LinearDeltaKinematics::InverseTransform(float Ha, float Hb, float Hc, float machinePos[DELTA_AXES]) const
+void LinearDeltaKinematics::ForwardTransform(float Ha, float Hb, float Hc, float machinePos[DELTA_AXES]) const
{
const float Fa = coreFa + fsquare(Ha);
const float Fb = coreFb + fsquare(Hb);
@@ -129,10 +128,18 @@ void LinearDeltaKinematics::InverseTransform(float Ha, float Hb, float Hc, float
// Convert Cartesian coordinates to motor steps
bool LinearDeltaKinematics::CartesianToMotorSteps(const float machinePos[], const float stepsPerMm[], size_t numVisibleAxes, size_t numTotalAxes, int32_t motorPos[], bool isCoordinated) const
{
- //TODO return false if we can't transform the position
+ bool ok = true;
for (size_t axis = 0; axis < min<size_t>(numVisibleAxes, DELTA_AXES); ++axis)
{
- motorPos[axis] = lrintf(Transform(machinePos, axis) * stepsPerMm[axis]);
+ const float pos = Transform(machinePos, axis);
+ if (isnan(pos) || isinf(pos))
+ {
+ ok = false;
+ }
+ else
+ {
+ motorPos[axis] = lrintf(pos * stepsPerMm[axis]);
+ }
}
// Transform any additional axes linearly
@@ -140,13 +147,13 @@ bool LinearDeltaKinematics::CartesianToMotorSteps(const float machinePos[], cons
{
motorPos[axis] = lrintf(machinePos[axis] * stepsPerMm[axis]);
}
- return true;
+ return ok;
}
// Convert motor coordinates to machine coordinates. Used after homing and after individual motor moves.
void LinearDeltaKinematics::MotorStepsToCartesian(const int32_t motorPos[], const float stepsPerMm[], size_t numVisibleAxes, size_t numTotalAxes, float machinePos[]) const
{
- InverseTransform(motorPos[DELTA_A_AXIS]/stepsPerMm[DELTA_A_AXIS], motorPos[DELTA_B_AXIS]/stepsPerMm[DELTA_B_AXIS], motorPos[DELTA_C_AXIS]/stepsPerMm[DELTA_C_AXIS], machinePos);
+ ForwardTransform(motorPos[DELTA_A_AXIS]/stepsPerMm[DELTA_A_AXIS], motorPos[DELTA_B_AXIS]/stepsPerMm[DELTA_B_AXIS], motorPos[DELTA_C_AXIS]/stepsPerMm[DELTA_C_AXIS], machinePos);
// Convert any additional axes linearly
for (size_t drive = DELTA_AXES; drive < numVisibleAxes; ++drive)
@@ -357,7 +364,7 @@ bool LinearDeltaKinematics::DoAutoCalibration(size_t numFactors, const RandomPro
probeMotorPositions(i, axis) += solution[axis];
}
float newPosition[DELTA_AXES];
- InverseTransform(probeMotorPositions(i, DELTA_A_AXIS), probeMotorPositions(i, DELTA_B_AXIS), probeMotorPositions(i, DELTA_C_AXIS), newPosition);
+ ForwardTransform(probeMotorPositions(i, DELTA_A_AXIS), probeMotorPositions(i, DELTA_B_AXIS), probeMotorPositions(i, DELTA_C_AXIS), newPosition);
corrections[i] = newPosition[Z_AXIS];
expectedResiduals[i] = probePoints.GetZHeight(i) + newPosition[Z_AXIS];
sumOfSquares += fcsquare(expectedResiduals[i]);
@@ -458,7 +465,7 @@ floatc_t LinearDeltaKinematics::ComputeDerivative(unsigned int deriv, float ha,
}
float newPos[DELTA_AXES];
- hiParams.InverseTransform((deriv == 0) ? ha + perturb : ha, (deriv == 1) ? hb + perturb : hb, (deriv == 2) ? hc + perturb : hc, newPos);
+ hiParams.ForwardTransform((deriv == 0) ? ha + perturb : ha, (deriv == 1) ? hb + perturb : hb, (deriv == 2) ? hc + perturb : hc, newPos);
if (deriv == 7)
{
return -newPos[X_AXIS]/printRadius;
@@ -469,7 +476,7 @@ floatc_t LinearDeltaKinematics::ComputeDerivative(unsigned int deriv, float ha,
}
const float zHi = newPos[Z_AXIS];
- loParams.InverseTransform((deriv == 0) ? ha - perturb : ha, (deriv == 1) ? hb - perturb : hb, (deriv == 2) ? hc - perturb : hc, newPos);
+ loParams.ForwardTransform((deriv == 0) ? ha - perturb : ha, (deriv == 1) ? hb - perturb : hb, (deriv == 2) ? hc - perturb : hc, newPos);
const float zLo = newPos[Z_AXIS];
return ((floatc_t)zHi - (floatc_t)zLo)/(floatc_t)(2 * perturb);
@@ -583,16 +590,9 @@ bool LinearDeltaKinematics::Configure(unsigned int mCode, GCodeBuffer& gb, const
case 665:
{
bool seen = false;
- if (gb.Seen('L'))
- {
- diagonal = gb.GetFValue();
- seen = true;
- }
- if (gb.Seen('R'))
- {
- radius = gb.GetFValue();
- seen = true;
- }
+ gb.TryGetFValue('L', diagonal, seen);
+ gb.TryGetFValue('R', radius, seen);
+
if (gb.Seen('B'))
{
printRadius = gb.GetFValue();
@@ -604,24 +604,9 @@ bool LinearDeltaKinematics::Configure(unsigned int mCode, GCodeBuffer& gb, const
p.SetAxisMaximum(Y_AXIS, printRadius, false);
seen = true;
}
- if (gb.Seen('X'))
- {
- // X tower position correction
- angleCorrections[DELTA_A_AXIS] = gb.GetFValue();
- seen = true;
- }
- if (gb.Seen('Y'))
- {
- // Y tower position correction
- angleCorrections[DELTA_B_AXIS] = gb.GetFValue();
- seen = true;
- }
- if (gb.Seen('Z'))
- {
- // Z tower position correction
- angleCorrections[DELTA_C_AXIS] = gb.GetFValue();
- seen = true;
- }
+ gb.TryGetFValue('X', angleCorrections[DELTA_A_AXIS], seen);
+ gb.TryGetFValue('Y', angleCorrections[DELTA_B_AXIS], seen);
+ gb.TryGetFValue('Z', angleCorrections[DELTA_C_AXIS], seen);
if (gb.Seen('H'))
{
@@ -649,21 +634,10 @@ bool LinearDeltaKinematics::Configure(unsigned int mCode, GCodeBuffer& gb, const
case 666:
{
bool seen = false;
- if (gb.Seen('X'))
- {
- endstopAdjustments[X_AXIS] = gb.GetFValue();
- seen = true;
- }
- if (gb.Seen('Y'))
- {
- endstopAdjustments[Y_AXIS] = gb.GetFValue();
- seen = true;
- }
- if (gb.Seen('Z'))
- {
- endstopAdjustments[Z_AXIS] = gb.GetFValue();
- seen = true;
- }
+ gb.TryGetFValue('X', endstopAdjustments[DELTA_A_AXIS], seen);
+ gb.TryGetFValue('Y', endstopAdjustments[DELTA_B_AXIS], seen);
+ gb.TryGetFValue('Z', endstopAdjustments[DELTA_C_AXIS], seen);
+
if (gb.Seen('A'))
{
xTilt = gb.GetFValue() * 0.01;
diff --git a/src/Movement/Kinematics/LinearDeltaKinematics.h b/src/Movement/Kinematics/LinearDeltaKinematics.h
index c183587a..a17ee520 100644
--- a/src/Movement/Kinematics/LinearDeltaKinematics.h
+++ b/src/Movement/Kinematics/LinearDeltaKinematics.h
@@ -12,9 +12,6 @@
#include "Kinematics.h"
constexpr size_t DELTA_AXES = 3;
-constexpr size_t DELTA_A_AXIS = 0;
-constexpr size_t DELTA_B_AXIS = 1;
-constexpr size_t DELTA_C_AXIS = 2;
// Class to hold the parameter for a delta machine.
class LinearDeltaKinematics : public Kinematics
@@ -60,37 +57,42 @@ private:
void Recalc();
void NormaliseEndstopAdjustments(); // Make the average of the endstop adjustments zero
float Transform(const float headPos[], size_t axis) const; // Calculate the motor position for a single tower from a Cartesian coordinate
- void InverseTransform(float Ha, float Hb, float Hc, float headPos[]) const; // Calculate the Cartesian position from the motor positions
+ void ForwardTransform(float Ha, float Hb, float Hc, float headPos[]) const; // Calculate the Cartesian position from the motor positions
floatc_t ComputeDerivative(unsigned int deriv, float ha, float hb, float hc) const; // Compute the derivative of height with respect to a parameter at a set of motor endpoints
void Adjust(size_t numFactors, const floatc_t v[]); // Perform 3-, 4-, 6- or 7-factor adjustment
void PrintParameters(const StringRef& reply) const; // Print all the parameters for debugging
- // Delta parameter defaults
- const float defaultDiagonal = 215.0;
- const float defaultDeltaRadius = 105.6;
- const float defaultPrintRadius = 80.0; // mm
- const float defaultDeltaHomedHeight = 240.0; // mm
+ // Axis names used internally
+ static constexpr size_t DELTA_A_AXIS = 0;
+ static constexpr size_t DELTA_B_AXIS = 1;
+ static constexpr size_t DELTA_C_AXIS = 2;
+
+ // Delta parameter defaults in mm
+ static constexpr float DefaultDiagonal = 215.0;
+ static constexpr float DefaultDeltaRadius = 105.6;
+ static constexpr float DefaultPrintRadius = 80.0;
+ static constexpr float DefaultDeltaHomedHeight = 240.0;
// Core parameters
- float diagonal; // The diagonal rod length, all 3 are assumed to be the same length
- float radius; // The nominal delta radius, before any fine tuning of tower positions
- float angleCorrections[DELTA_AXES]; // Tower position corrections
- float endstopAdjustments[DELTA_AXES]; // How much above or below the ideal position each endstop is
- float printRadius;
- float homedHeight;
- float xTilt, yTilt; // How much we need to raise Z for each unit of movement in the +X and +Y directions
+ float diagonal; // The diagonal rod length, all 3 are assumed to be the same length
+ float radius; // The nominal delta radius, before any fine tuning of tower positions
+ float angleCorrections[DELTA_AXES]; // Tower position corrections
+ float endstopAdjustments[DELTA_AXES]; // How much above or below the ideal position each endstop is
+ float printRadius;
+ float homedHeight;
+ float xTilt, yTilt; // How much we need to raise Z for each unit of movement in the +X and +Y directions
- // Derived values
- float towerX[DELTA_AXES]; // The X coordinate of each tower
- float towerY[DELTA_AXES]; // The Y coordinate of each tower
- float printRadiusSquared;
- float homedCarriageHeight;
+ // Derived values
+ float towerX[DELTA_AXES]; // The X coordinate of each tower
+ float towerY[DELTA_AXES]; // The Y coordinate of each tower
+ float printRadiusSquared;
+ float homedCarriageHeight;
float Xbc, Xca, Xab, Ybc, Yca, Yab;
float coreFa, coreFb, coreFc;
- float Q, Q2, D2;
+ float Q, Q2, D2;
- bool doneAutoCalibration; // True if we have done auto calibration
+ bool doneAutoCalibration; // True if we have done auto calibration
};
#endif /* LINEARDELTAKINEMATICS_H_ */
diff --git a/src/Movement/Kinematics/RotaryDeltaKinematics.cpp b/src/Movement/Kinematics/RotaryDeltaKinematics.cpp
new file mode 100644
index 00000000..3b59d215
--- /dev/null
+++ b/src/Movement/Kinematics/RotaryDeltaKinematics.cpp
@@ -0,0 +1,507 @@
+/*
+ * RotaryDeltaKinematics.cpp
+ *
+ * Created on: 1 Aug 2018
+ * Author: David
+ */
+
+#include "RotaryDeltaKinematics.h"
+#include "RepRap.h"
+#include "Platform.h"
+#include "Movement/DDA.h"
+#include "GCodes/GCodeBuffer.h"
+
+const float RotaryDeltaKinematics::NormalTowerAngles[DELTA_AXES] = { -150.0, -30.0, 90.0 };
+
+// Constructor
+RotaryDeltaKinematics::RotaryDeltaKinematics() : Kinematics(KinematicsType::rotaryDelta, DefaultSegmentsPerSecond, DefaultMinSegmentSize, false)
+{
+ Init();
+}
+
+// Initialise parameters to defaults
+void RotaryDeltaKinematics::Init()
+{
+ radius = DefaultDeltaRadius;
+ printRadius = DefaultPrintRadius;
+ minArmAngle = DefaultMinArmAngle;
+ maxArmAngle = DefaultMaxArmAngle;
+
+ for (size_t axis = 0; axis < DELTA_AXES; ++axis)
+ {
+ armLengths[axis] = DefaultArmLength;
+ rodLengths[axis] = DefaultRodLength;
+ bearingHeights[axis] = DefaultBearingHeight;
+ angleCorrections[axis] = 0.0;
+ endstopAdjustments[axis] = 0.0;
+ }
+
+ Recalc();
+}
+
+// Compute the derived parameters from the primary parameters
+void RotaryDeltaKinematics::Recalc()
+{
+ printRadiusSquared = fsquare(printRadius);
+ for (size_t axis = 0; axis < DELTA_AXES; ++axis)
+ {
+ const float angle = (NormalTowerAngles[axis] + angleCorrections[axis]) * DegreesToRadians;
+ armAngleSines[axis] = sinf(angle);
+ armAngleCosines[axis] = cosf(angle);
+ twiceU[axis] = armLengths[axis] * 2;
+ rodSquared[axis] = fsquare(rodLengths[axis]);
+ rodSquaredMinusArmSquared[axis] = rodSquared[axis] - fsquare(armLengths[axis]);
+ }
+}
+
+// Return the name of the current kinematics.
+// If 'forStatusReport' is true then the string must be the one for that kinematics expected by DuetWebControl and PanelDue.
+// Otherwise it should be in a format suitable for printing.
+const char *RotaryDeltaKinematics::GetName(bool forStatusReport) const
+{
+ return "Rotary delta";
+}
+
+// Set or report the parameters from a M665, M666 or M669 command
+// If 'mCode' is an M-code used to set parameters for the current kinematics (which should only ever be 665, 666, 667 or 669)
+// then search for parameters used to configure the current kinematics. If any are found, perform appropriate actions,
+// and return true if the changes affect the geometry.
+// If errors were discovered while processing parameters, put an appropriate error message in 'reply' and set 'error' to true.
+// If no relevant parameters are found, print the existing ones to 'reply' and return false.
+// If 'mCode' does not apply to this kinematics, call the base class version of this function, which will print a suitable error message.
+bool RotaryDeltaKinematics::Configure(unsigned int mCode, GCodeBuffer& gb, const StringRef& reply, bool& error)
+{
+ switch(mCode)
+ {
+ case 669:
+ {
+ bool seen = false;
+ size_t numValues = 3;
+ if (gb.TryGetFloatArray('L', numValues, armLengths, reply, seen, true))
+ {
+ error = true;
+ return true;
+ }
+
+ numValues = 3;
+ if (gb.TryGetFloatArray('R', numValues, rodLengths, reply, seen, true))
+ {
+ error = true;
+ return true;
+ }
+
+ numValues = 3;
+ if (gb.TryGetFloatArray('H', numValues, bearingHeights, reply, seen, true))
+ {
+ error = true;
+ return true;
+ }
+
+ numValues = 2;
+ if (gb.TryGetFloatArray('A', numValues, minMaxArmAngles, reply, seen, false))
+ {
+ error = true;
+ return true;
+ }
+
+ gb.TryGetFValue('R', radius, seen);
+ if (gb.Seen('B'))
+ {
+ printRadius = gb.GetFValue();
+ // Set the axis limits so that DWC reports them correctly (they are not otherwise used for deltas, except Z min)
+ Platform& p = reprap.GetPlatform();
+ p.SetAxisMinimum(X_AXIS, -printRadius, false);
+ p.SetAxisMinimum(Y_AXIS, -printRadius, false);
+ p.SetAxisMaximum(X_AXIS, printRadius, false);
+ p.SetAxisMaximum(Y_AXIS, printRadius, false);
+ seen = true;
+ }
+
+ gb.TryGetFValue('X', angleCorrections[DELTA_A_AXIS], seen);
+ gb.TryGetFValue('Y', angleCorrections[DELTA_B_AXIS], seen);
+ gb.TryGetFValue('Z', angleCorrections[DELTA_C_AXIS], seen);
+
+ if (seen)
+ {
+ Recalc();
+ }
+ else
+ {
+ reply.printf("Arms (%.3f,%.2f,%.3f)mm, rods (%.3f,%.3f,%.3f)mm, bearingHeights (%.3f,%.2f,%.3f)mm"
+ ", arm movement %.1f to %.1f" DEGREE_SYMBOL
+ ", delta radius %.3f, bed radius %.1f"
+ ", angle corrections (%.3f,%.3f,%.3f)" DEGREE_SYMBOL ,
+ (double)armLengths[DELTA_A_AXIS], (double)armLengths[DELTA_B_AXIS], (double)armLengths[DELTA_C_AXIS],
+ (double)rodLengths[DELTA_A_AXIS], (double)rodLengths[DELTA_B_AXIS], (double)rodLengths[DELTA_C_AXIS],
+ (double)bearingHeights[DELTA_A_AXIS], (double)bearingHeights[DELTA_B_AXIS], (double)bearingHeights[DELTA_C_AXIS],
+ (double)minArmAngle, (double)maxArmAngle,
+ (double)radius, (double)printRadius,
+ (double)angleCorrections[DELTA_A_AXIS], (double)angleCorrections[DELTA_B_AXIS], (double)angleCorrections[DELTA_C_AXIS]);
+ }
+ return seen;
+ }
+
+ case 666:
+ {
+ bool seen = false;
+ gb.TryGetFValue('X', endstopAdjustments[DELTA_A_AXIS], seen);
+ gb.TryGetFValue('Y', endstopAdjustments[DELTA_B_AXIS], seen);
+ gb.TryGetFValue('Z', endstopAdjustments[DELTA_C_AXIS], seen);
+
+ if (!seen)
+ {
+ reply.printf("Endstop adjustments X%.2f Y%.2f Z%.2f" DEGREE_SYMBOL,
+ (double)endstopAdjustments[X_AXIS], (double)endstopAdjustments[Y_AXIS], (double)endstopAdjustments[Z_AXIS]);
+ }
+ return seen;
+ }
+
+ default:
+ return Kinematics::Configure(mCode, gb, reply, error);
+ }
+}
+
+// Convert Cartesian coordinates to motor positions measured in steps from reference position
+// 'machinePos' is a set of axis and extruder positions to convert
+// 'stepsPerMm' is as configured in M92. On a Scara or polar machine this would actually be steps per degree.
+// 'numAxes' is the number of machine axes to convert, which will always be at least 3
+// 'motorPos' is the output vector of motor positions
+// Return true if successful, false if we were unable to convert
+bool RotaryDeltaKinematics::CartesianToMotorSteps(const float machinePos[], const float stepsPerMm[], size_t numVisibleAxes, size_t numTotalAxes, int32_t motorPos[], bool isCoordinated) const
+{
+ bool ok = true;
+ for (size_t axis = 0; axis < min<size_t>(numVisibleAxes, DELTA_AXES); ++axis)
+ {
+ const float pos = Transform(machinePos, axis);
+ if (isnan(pos) || isinf(pos))
+ {
+ ok = false;
+ }
+ else
+ {
+ motorPos[axis] = lrintf(pos * stepsPerMm[axis]);
+ }
+ }
+
+ // TEMP DEBUG
+ if (reprap.Debug(moduleMove))
+ {
+ debugPrintf("Transformed %.2f,%.2f,%.2f mm to %" PRIi32 ",%" PRIi32 ",%" PRIi32 "steps\n",
+ (double)machinePos[0], (double)machinePos[1], (double)machinePos[2],
+ motorPos[0], motorPos[1], motorPos[2]);
+ }
+
+ // Transform any additional axes linearly
+ for (size_t axis = DELTA_AXES; axis < numVisibleAxes; ++axis)
+ {
+ motorPos[axis] = lrintf(machinePos[axis] * stepsPerMm[axis]);
+ }
+ return ok;
+}
+
+// Convert motor positions (measured in steps from reference position) to Cartesian coordinates
+// 'motorPos' is the input vector of motor positions
+// 'stepsPerMm' is as configured in M92. On a Scara or polar machine this would actually be steps per degree.
+// 'numDrives' is the number of machine drives to convert, which will always be at least 3
+// 'machinePos' is the output set of converted axis and extruder positions
+void RotaryDeltaKinematics::MotorStepsToCartesian(const int32_t motorPos[], const float stepsPerMm[], size_t numVisibleAxes, size_t numTotalAxes, float machinePos[]) const
+{
+ ForwardTransform(motorPos[DELTA_A_AXIS]/stepsPerMm[DELTA_A_AXIS], motorPos[DELTA_B_AXIS]/stepsPerMm[DELTA_B_AXIS], motorPos[DELTA_C_AXIS]/stepsPerMm[DELTA_C_AXIS], machinePos);
+
+ // Convert any additional axes linearly
+ for (size_t drive = DELTA_AXES; drive < numVisibleAxes; ++drive)
+ {
+ machinePos[drive] = motorPos[drive]/stepsPerMm[drive];
+ }
+}
+
+// Perform auto calibration. Caller already owns the movement lock.
+// Return true if an error occurred.
+bool RotaryDeltaKinematics::DoAutoCalibration(size_t numFactors, const RandomProbePointSet& probePoints, const StringRef& reply)
+{
+ return true; // auto calibration not implemented yet
+}
+
+// Write the parameters that are set by auto calibration to a file, returning true if success
+bool RotaryDeltaKinematics::WriteCalibrationParameters(FileStore *f) const
+{
+ return true; // auto calibration not implemented yet
+}
+
+// Return true if the specified XY position is reachable by the print head reference point.
+bool RotaryDeltaKinematics::IsReachable(float x, float y, bool isCoordinated) const
+{
+ return fsquare(x) + fsquare(y) < printRadiusSquared;
+}
+
+// Limit the Cartesian position that the user wants to move to returning true if we adjusted the position
+bool RotaryDeltaKinematics::LimitPosition(float coords[], size_t numVisibleAxes, AxesBitmap axesHomed, bool isCoordinated) const
+{
+ const AxesBitmap allAxes = MakeBitmap<AxesBitmap>(X_AXIS) | MakeBitmap<AxesBitmap>(Y_AXIS) | MakeBitmap<AxesBitmap>(Z_AXIS);
+ bool limited = false;
+ if ((axesHomed & allAxes) == allAxes)
+ {
+ // If axes have been homed on a delta printer and this isn't a homing move, check for movements outside limits.
+ // Skip this check if axes have not been homed, so that extruder-only moves are allowed before homing
+ // Constrain the move to be within the build radius
+ const float diagonalSquared = fsquare(coords[X_AXIS]) + fsquare(coords[Y_AXIS]);
+ if (diagonalSquared > printRadiusSquared)
+ {
+ const float factor = sqrtf(printRadiusSquared / diagonalSquared);
+ coords[X_AXIS] *= factor;
+ coords[Y_AXIS] *= factor;
+ limited = true;
+ }
+
+ if (coords[Z_AXIS] < reprap.GetPlatform().AxisMinimum(Z_AXIS))
+ {
+ coords[Z_AXIS] = reprap.GetPlatform().AxisMinimum(Z_AXIS);
+ limited = true;
+ }
+ else if (coords[Z_AXIS] > reprap.GetPlatform().AxisMaximum(Z_AXIS))
+ {
+ coords[Z_AXIS] = reprap.GetPlatform().AxisMaximum(Z_AXIS);
+ limited = true;
+ }
+ }
+
+ // Limit any additional axes according to the M208 limits
+ if (LimitPositionFromAxis(coords, Z_AXIS + 1, numVisibleAxes, axesHomed))
+ {
+ limited = true;
+ }
+
+ return limited;
+}
+
+// Return the initial Cartesian coordinates we assume after switching to this kinematics
+void RotaryDeltaKinematics::GetAssumedInitialPosition(size_t numAxes, float positions[]) const
+{
+ ForwardTransform(0.0, 0.0, 0.0, positions); // assume that the arms are horizontal
+ for (size_t i = DELTA_AXES; i < numAxes; ++i)
+ {
+ positions[i] = 0.0; // set additional axes to zero
+ }
+}
+
+// Return the axes that we can assume are homed after executing a G92 command to set the specified axis coordinates
+AxesBitmap RotaryDeltaKinematics::AxesAssumedHomed(AxesBitmap g92Axes) const
+{
+ // If all of X, Y and Z have been specified then we know the positions of all 3 tower motors, otherwise we don't
+ constexpr AxesBitmap xyzAxes = MakeBitmap<AxesBitmap>(X_AXIS) | MakeBitmap<AxesBitmap>(Y_AXIS) | MakeBitmap<AxesBitmap>(Z_AXIS);
+ if ((g92Axes & xyzAxes) != xyzAxes)
+ {
+ g92Axes &= ~xyzAxes;
+ }
+ return g92Axes;
+}
+
+// Return the set of axes that must be homed prior to regular movement of the specified axes
+AxesBitmap RotaryDeltaKinematics::MustBeHomedAxes(AxesBitmap axesMoving, bool disallowMovesBeforeHoming) const
+{
+ constexpr AxesBitmap xyzAxes = MakeBitmap<AxesBitmap>(X_AXIS) | MakeBitmap<AxesBitmap>(Y_AXIS) | MakeBitmap<AxesBitmap>(Z_AXIS);
+ if ((axesMoving & xyzAxes) != 0)
+ {
+ axesMoving |= xyzAxes;
+ }
+ return axesMoving;
+}
+
+// This function is called when a request is made to home the axes in 'toBeHomed' and the axes in 'alreadyHomed' have already been homed.
+// If we can proceed with homing some axes, return the name of the homing file to be called.
+// If we can't proceed because other axes need to be homed first, return nullptr and pass those axes back in 'mustBeHomedFirst'.
+const char* RotaryDeltaKinematics::GetHomingFileName(AxesBitmap toBeHomed, AxesBitmap alreadyHomed, size_t numVisibleAxes, AxesBitmap& mustHomeFirst) const
+{
+ // If homing X, Y or Z we must home all the towers
+ if ((toBeHomed & LowestNBits<AxesBitmap>(DELTA_AXES)) != 0)
+ {
+ return "homedelta.g";
+ }
+
+ // Return the homing file for the lowest axis that we have been asked to home
+ for (size_t axis = DELTA_AXES; axis < numVisibleAxes; ++axis)
+ {
+ if (IsBitSet(toBeHomed, axis))
+ {
+ return StandardHomingFileNames[axis];
+ }
+ }
+
+ mustHomeFirst = 0;
+ return nullptr;
+}
+
+// This function is called from the step ISR when an endstop switch is triggered during homing.
+// Return true if the entire homing move should be terminated, false if only the motor associated with the endstop switch should be stopped.
+bool RotaryDeltaKinematics::QueryTerminateHomingMove(size_t axis) const
+{
+ return false;
+}
+
+// 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.
+void RotaryDeltaKinematics::OnHomingSwitchTriggered(size_t axis, bool highEnd, const float stepsPerMm[], DDA& dda) const
+{
+ if (axis < DELTA_AXES)
+ {
+ if (highEnd)
+ {
+ const float hitPoint = maxArmAngle + endstopAdjustments[axis];
+ dda.SetDriveCoordinate(lrintf(hitPoint * stepsPerMm[axis]), axis);
+ }
+ }
+ else
+ {
+ // Assume that any additional axes are linear
+ const float hitPoint = (highEnd) ? reprap.GetPlatform().AxisMaximum(axis) : reprap.GetPlatform().AxisMinimum(axis);
+ dda.SetDriveCoordinate(lrintf(hitPoint * stepsPerMm[axis]), axis);
+ }
+}
+
+// Write any calibration data that we need to resume a print after power fail, returning true if successful
+bool RotaryDeltaKinematics::WriteResumeSettings(FileStore *f) const
+{
+// return !doneAutoCalibration || WriteCalibrationParameters(f);
+ return true; // auto calibration not implemented yet
+}
+
+// Limit the speed and acceleration of a move to values that the mechanics can handle.
+// The speeds in Cartesian space have already been limited.
+void RotaryDeltaKinematics::LimitSpeedAndAcceleration(DDA& dda, const float *normalisedDirectionVector) const
+{
+ // Limit the speed in the XY plane to the lower of the X and Y maximum speeds, and similarly for the acceleration
+ const float xyFactor = sqrtf(fsquare(normalisedDirectionVector[X_AXIS]) + fsquare(normalisedDirectionVector[Y_AXIS]));
+ if (xyFactor > 0.01)
+ {
+ const Platform& platform = reprap.GetPlatform();
+ const float maxSpeed = min<float>(platform.MaxFeedrate(X_AXIS), platform.MaxFeedrate(Y_AXIS));
+ const float maxAcceleration = min<float>(platform.Acceleration(X_AXIS), platform.Acceleration(Y_AXIS));
+ dda.LimitSpeedAndAcceleration(maxSpeed/xyFactor, maxAcceleration/xyFactor);
+ }
+}
+
+// Calculate the motor position for a single tower from a Cartesian coordinate.
+// If we first transform the XY coordinates so that +X is along the direction of the arm, then we need to solve this equation:
+// L^2 = (U cos(theta) + (R - x))^2 + y^2 + (U sin(theta) + (H - z))^2
+// Expanding this and using cos^2(theta) + sin^2(theta) = 1 we get:
+// L^2 = U^2 + (H - z)^2 + (R - x)^2 + y^2 + 2U(R - x)cos(theta) + 2U(H - z)sin(theta)
+// This is of the form:
+// a cos(theta) + b sin(theta) = c
+// where:
+// a = 2U(r - x), b = 2U(H - z), c = L^2 - U^2 - (H - z)^2 - (R - x)^2 - y^2
+// We can rearrange, square and use sin^2 + cos^2 = 1 again to get this:
+// (a^2 + b^2)sin^2(theta) - 2bc sin(theta) + (c^2 - a^2) = 0
+// which has solutions:
+// sin(theta) = (bc +/- a sqrt(a^2 + b^2 - c^2))/(a^2 + b^2)
+float RotaryDeltaKinematics::Transform(const float machinePos[], size_t axis) const
+{
+ if (axis < DELTA_AXES)
+ {
+ // 1. Transform the X and Y coordinates so that +X is along the arm and +Y is 90deg anticlockwise from +X
+ const float x = machinePos[X_AXIS] * armAngleCosines[axis] + machinePos[Y_AXIS] * armAngleSines[axis];
+ const float y = machinePos[Y_AXIS] * armAngleCosines[axis] - machinePos[X_AXIS] * armAngleSines[axis];
+
+ // 2. Calculate a, b and c
+ const float rMinusX = radius - x;
+ const float hMinusZ = bearingHeights[axis] - machinePos[Z_AXIS];
+ const float a = twiceU[axis] * rMinusX;
+ const float b = twiceU[axis] * hMinusZ;
+ const float c = rodSquaredMinusArmSquared[axis] - (fsquare(hMinusZ) + fsquare(rMinusX) + fsquare(y));
+
+ // 3. Solve the quadratic equation, taking the lower root
+ const float sinTheta = (b * c - a * sqrtf(fsquare(a) + fsquare(b) - fsquare(c)))/(fsquare(a) + fsquare(b));
+
+ // 4. Take the arc sine and convert to degrees
+ return asinf(sinTheta) * RadiansToDegrees;
+ }
+ else
+ {
+ return machinePos[axis]; // any additional axes must be linear
+ }
+}
+
+// Calculate the Cartesian coordinates from the motor coordinates. We do this by trilateration.
+void RotaryDeltaKinematics::ForwardTransform(float Ha, float Hb, float Hc, float machinePos[DELTA_AXES]) const
+{
+ // Calculate the Cartesian coordinates of the joints at the moving ends of the arms
+ const float angleA = Ha * DegreesToRadians;
+ const float posAX = (radius + (armLengths[DELTA_A_AXIS] * cosf(angleA))) * armAngleCosines[DELTA_A_AXIS];
+ const float posAY = (radius + (armLengths[DELTA_A_AXIS] * cosf(angleA))) * armAngleSines[DELTA_A_AXIS];
+ const float posAZ = bearingHeights[DELTA_A_AXIS] + sinf(angleA);
+
+ const float angleB = Hb * DegreesToRadians;
+ const float posBX = (radius + (armLengths[DELTA_B_AXIS] * cosf(angleB))) * armAngleCosines[DELTA_B_AXIS];
+ const float posBY = (radius + (armLengths[DELTA_B_AXIS] * cosf(angleB))) * armAngleSines[DELTA_B_AXIS];
+ const float posBZ = bearingHeights[DELTA_B_AXIS] + sinf(angleB);
+
+ const float angleC = Hc * DegreesToRadians;
+ const float posCX = (radius + (armLengths[DELTA_C_AXIS] * cosf(angleC))) * armAngleCosines[DELTA_C_AXIS];
+ const float posCY = (radius + (armLengths[DELTA_C_AXIS] * cosf(angleC))) * armAngleSines[DELTA_C_AXIS];
+ const float posCZ = bearingHeights[DELTA_C_AXIS] + sinf(angleC);
+
+ // Calculate some intermediate values that we will use more than once
+ const float Da2 = fsquare(posAX) + fsquare(posAY) + fsquare(posAZ);
+ const float Db2 = fsquare(posBX) + fsquare(posBY) + fsquare(posBZ);
+ const float Dc2 = fsquare(posCX) + fsquare(posCY) + fsquare(posCZ);
+
+ const float Xab = posAX - posBX;
+ const float Xbc = posBX - posCX;
+ const float Xca = posCX - posAX;
+
+ const float Yab = posAY - posBY;
+ const float Ybc = posBY - posCY;
+ const float Yca = posCY - posAY;
+
+ const float Zca = posCZ - posAZ;
+
+ // Calculate PQRST such that x = (Qz + S)/P, y = (Rz + T)/P.
+ const float P = ( posBX * Yca
+ - posAX * posCY
+ + posAY * posCX
+ - posBY * Xca
+ ) * 2;
+
+ const float Q = ( posBY * Zca
+ - posAY * posCZ
+ + posAZ * posCY
+ - posBZ * Yca
+ ) * 2;
+
+ const float R = - ( posBX * Zca
+ + posAX * posCZ
+ + posAZ * posCX
+ - posBZ * Xca
+ ) * 2;
+
+ const float P2 = fsquare(P);
+ const float U = (posAZ * P2) + (posAX * Q * P) + (posAY * R * P);
+ const float A = (P2 + fsquare(Q) + fsquare(R)) * 2;
+
+ const float S = - Yab * (rodSquared[DELTA_C_AXIS] - Dc2)
+ - Yca * (rodSquared[DELTA_B_AXIS] - Db2)
+ - Ybc * (rodSquared[DELTA_A_AXIS] - Da2);
+ const float T = - Xab * (rodSquared[DELTA_C_AXIS] - Dc2)
+ + Xca * (rodSquared[DELTA_B_AXIS] - Db2)
+ + Xbc * (rodSquared[DELTA_A_AXIS] - Da2);
+
+ // Calculate quadratic equation coefficients
+ const float halfB = (S * Q) - (R * T) - U;
+ const float C = fsquare(S) + fsquare(T) + (posAY * T - posAX * S) * P * 2 + (Da2 - rodSquared[DELTA_A_AXIS]) * P2;
+
+ // Solve the quadratic equation for z
+ const float z = (- halfB - sqrtf(fsquare(halfB) - A * C))/A;
+
+ // Substitute back for X and Y
+ machinePos[X_AXIS] = (Q * z + S)/P;
+ machinePos[Y_AXIS] = (R * z + T)/P;
+ machinePos[Z_AXIS] = z;
+
+ if (reprap.Debug(moduleMove))
+ {
+ debugPrintf("Trilaterated (%.2f, %.2f, %.2f)" DEGREE_SYMBOL " to X=%.2f Y=%.2f Z=%.2f\n",
+ (double)Ha, (double)Hb, (double)Hc,
+ (double)machinePos[X_AXIS], (double)machinePos[Y_AXIS], (double)machinePos[Z_AXIS]);
+ }
+}
+
+// End
diff --git a/src/Movement/Kinematics/RotaryDeltaKinematics.h b/src/Movement/Kinematics/RotaryDeltaKinematics.h
new file mode 100644
index 00000000..0630e9f2
--- /dev/null
+++ b/src/Movement/Kinematics/RotaryDeltaKinematics.h
@@ -0,0 +1,88 @@
+/*
+ * RotaryDeltaKinematics.h
+ *
+ * Created on: 1 Aug 2018
+ * Author: David
+ */
+
+#ifndef SRC_MOVEMENT_KINEMATICS_ROTARYDELTAKINEMATICS_H_
+#define SRC_MOVEMENT_KINEMATICS_ROTARYDELTAKINEMATICS_H_
+
+#include "Kinematics.h"
+
+class RotaryDeltaKinematics : public Kinematics
+{
+public:
+ // Constructors
+ RotaryDeltaKinematics();
+
+ // Overridden base class functions. See Kinematics.h for descriptions.
+ const char *GetName(bool forStatusReport) const override;
+ bool Configure(unsigned int mCode, GCodeBuffer& gb, const StringRef& reply, bool& error) override;
+ bool CartesianToMotorSteps(const float machinePos[], const float stepsPerMm[], size_t numVisibleAxes, size_t numTotalAxes, int32_t motorPos[], bool isCoordinated) const override;
+ void MotorStepsToCartesian(const int32_t motorPos[], const float stepsPerMm[], size_t numVisibleAxes, size_t numTotalAxes, float machinePos[]) const override;
+ bool SupportsAutoCalibration() const override { return false; } // TODO support autocalibration
+ bool DoAutoCalibration(size_t numFactors, const RandomProbePointSet& probePoints, const StringRef& reply) override;
+ void SetCalibrationDefaults() override { Init(); }
+ bool WriteCalibrationParameters(FileStore *f) const override;
+ bool IsReachable(float x, float y, bool isCoordinated) const override;
+ bool LimitPosition(float coords[], size_t numVisibleAxes, AxesBitmap axesHomed, bool isCoordinated) const override;
+ void GetAssumedInitialPosition(size_t numAxes, float positions[]) const override;
+ AxesBitmap AxesToHomeBeforeProbing() const override { return MakeBitmap<AxesBitmap>(X_AXIS) | MakeBitmap<AxesBitmap>(Y_AXIS) | MakeBitmap<AxesBitmap>(Z_AXIS); }
+ size_t NumHomingButtons(size_t numVisibleAxes) const override { return 0; }
+ HomingMode GetHomingMode() const override { return homeIndividualMotors; }
+ AxesBitmap AxesAssumedHomed(AxesBitmap g92Axes) const override;
+ AxesBitmap MustBeHomedAxes(AxesBitmap axesMoving, bool disallowMovesBeforeHoming) const override;
+ const char* GetHomingFileName(AxesBitmap toBeHomed, AxesBitmap alreadyHomed, size_t numVisibleAxes, AxesBitmap& mustHomeFirst) const override;
+ bool QueryTerminateHomingMove(size_t axis) const override;
+ void OnHomingSwitchTriggered(size_t axis, bool highEnd, const float stepsPerMm[], DDA& dda) const override;
+ bool WriteResumeSettings(FileStore *f) const override;
+ void LimitSpeedAndAcceleration(DDA& dda, const float *normalisedDirectionVector) const override;
+
+private:
+ void Init();
+ void Recalc();
+ float Transform(const float headPos[], size_t axis) const; // Calculate the motor position for a single tower from a Cartesian coordinate
+ void ForwardTransform(float Ha, float Hb, float Hc, float headPos[]) const; // Calculate the Cartesian position from the motor positions
+
+ // Axis names used internally
+ static constexpr size_t DELTA_AXES = 3;
+ static constexpr size_t DELTA_A_AXIS = 0;
+ static constexpr size_t DELTA_B_AXIS = 1;
+ static constexpr size_t DELTA_C_AXIS = 2;
+
+ // Delta mechanism parameter defaults
+ static constexpr float DefaultSegmentsPerSecond = 100.0;
+ static constexpr float DefaultMinSegmentSize = 0.2;
+ static constexpr float DefaultArmLength = 100.0;
+ static constexpr float DefaultRodLength = 200.0;
+ static constexpr float DefaultDeltaRadius = 50.0;
+ static constexpr float DefaultPrintRadius = 80.0;
+ static constexpr float DefaultBearingHeight = 250.0;
+ static constexpr float DefaultMinArmAngle = -45.0;
+ static constexpr float DefaultMaxArmAngle = 45.0;
+
+ static const float NormalTowerAngles[DELTA_AXES];
+
+ // Core parameters
+ float radius; // The nominal delta radius, before any fine tuning of tower positions
+ float bearingHeights[DELTA_AXES];
+ float armLengths[DELTA_AXES];
+ float rodLengths[DELTA_AXES];
+ float angleCorrections[DELTA_AXES]; // Tower position corrections
+ float endstopAdjustments[DELTA_AXES]; // How much above or below the ideal position each endstop is
+ float minMaxArmAngles[2];
+ float& minArmAngle = minMaxArmAngles[0];
+ float& maxArmAngle = minMaxArmAngles[1];
+ float printRadius;
+
+ // Derived values
+ float armAngleCosines[DELTA_AXES];
+ float armAngleSines[DELTA_AXES];
+ float twiceU[DELTA_AXES];
+ float rodSquared[DELTA_AXES];
+ float rodSquaredMinusArmSquared[DELTA_AXES];
+ float printRadiusSquared;
+};
+
+#endif /* SRC_MOVEMENT_KINEMATICS_ROTARYDELTAKINEMATICS_H_ */
diff --git a/src/Movement/Kinematics/ScaraKinematics.cpp b/src/Movement/Kinematics/ScaraKinematics.cpp
index 8b99645d..ff85c5e2 100644
--- a/src/Movement/Kinematics/ScaraKinematics.cpp
+++ b/src/Movement/Kinematics/ScaraKinematics.cpp
@@ -469,7 +469,7 @@ void ScaraKinematics::Recalc()
}
else
{
- const float minAngle = min<float>(fabs(psiLimits[0]), fabs(psiLimits[1])) * DegreesToRadians;
+ const float minAngle = min<float>(fabsf(psiLimits[0]), fabsf(psiLimits[1])) * DegreesToRadians;
maxRadius = sqrtf(proximalArmLengthSquared + distalArmLengthSquared + (twoPd * cosf(minAngle)));
}
maxRadius *= 0.995;
diff --git a/src/Movement/Kinematics/ZLeadscrewKinematics.h b/src/Movement/Kinematics/ZLeadscrewKinematics.h
index 21e82041..78f1147a 100644
--- a/src/Movement/Kinematics/ZLeadscrewKinematics.h
+++ b/src/Movement/Kinematics/ZLeadscrewKinematics.h
@@ -26,7 +26,7 @@ public:
private:
void AppendCorrections(const floatc_t corrections[], const StringRef& reply) const;
- static const unsigned int MaxLeadscrews = 4;
+ static const unsigned int MaxLeadscrews = 8; // some Folgertech FT5 printers have 8 bed adjusting screws
unsigned int numLeadscrews;
float leadscrewX[MaxLeadscrews], leadscrewY[MaxLeadscrews];
diff --git a/src/Movement/Move.cpp b/src/Movement/Move.cpp
index 89b4ef81..f3d9807b 100644
--- a/src/Movement/Move.cpp
+++ b/src/Movement/Move.cpp
@@ -73,6 +73,8 @@ void Move::Init()
currentDda = nullptr;
stepErrors = 0;
numLookaheadUnderruns = numPrepareUnderruns = numLookaheadErrors = 0;
+ maxPrintingAcceleration = maxTravelAcceleration = 10000.0;
+ drcEnabled = false; // disable dynamic ringing cancellation
// Clear the transforms
SetIdentityTransform();
@@ -1284,6 +1286,20 @@ bool Move::WriteResumeSettings(FileStore *f) const
return kinematics->WriteResumeSettings(f) && (!usingMesh || f->Write("G29 S1\n"));
}
+// Set the DRC frequency or disable DRC
+void Move::SetDRCfreq(float f)
+{
+ if (f >= 4.0 && f <= 10000.0)
+ {
+ drcPeriod = 1.0/f;
+ drcEnabled = true;
+ }
+ else
+ {
+ drcEnabled = false;
+ }
+}
+
// For debugging
void Move::PrintCurrentDda() const
{
diff --git a/src/Movement/Move.h b/src/Movement/Move.h
index 2fefc201..e8a6bb32 100644
--- a/src/Movement/Move.h
+++ b/src/Movement/Move.h
@@ -71,6 +71,15 @@ public:
unsigned int GetNumProbePoints() const; // Return the number of currently used probe points
float PushBabyStepping(float amount); // Try to push some babystepping through the lookahead queue
+ float GetMaxPrintingAcceleration() const { return maxPrintingAcceleration; }
+ void SetMaxPrintingAcceleration(float acc) { maxPrintingAcceleration = acc; }
+ float GetMaxTravelAcceleration() const { return maxTravelAcceleration; }
+ void SetMaxTravelAcceleration(float acc) { maxTravelAcceleration = acc; }
+ float GetDRCfreq() const { return 1.0/drcPeriod; }
+ float GetDRCperiod() const { return drcPeriod; }
+ float IsDRCenabled() const { return drcEnabled; }
+ void SetDRCfreq(float f);
+
void Diagnostics(MessageType mtype); // Report useful stuff
void RecordLookaheadError() { ++numLookaheadErrors; } // Record a lookahead error
@@ -165,6 +174,11 @@ private:
bool active; // Are we live and running?
uint8_t simulationMode; // Are we simulating, or really printing?
MoveState moveState; // whether the idle timer is active
+ bool drcEnabled;
+
+ float maxPrintingAcceleration;
+ float maxTravelAcceleration;
+ float drcPeriod; // the period of ringing that we don't want to excite
unsigned int numLookaheadUnderruns; // How many times we have run out of moves to adjust during lookahead
unsigned int numPrepareUnderruns; // How many times we wanted a new move but there were only un-prepared moves in the queue
diff --git a/src/Pccb/Pins_Pccb.h b/src/Pccb/Pins_Pccb.h
index c361156b..db2ce2b4 100644
--- a/src/Pccb/Pins_Pccb.h
+++ b/src/Pccb/Pins_Pccb.h
@@ -8,7 +8,12 @@
#ifndef SRC_DUETM_PINS_DUETM_H_
#define SRC_DUETM_PINS_DUETM_H_
-#define FIRMWARE_NAME "RepRapFirmware for PCCB"
+#ifdef PCCB_X5
+# define FIRMWARE_NAME "RepRapFirmware for PCCB+DueX5"
+#else
+# define FIRMWARE_NAME "RepRapFirmware for PCCB"
+#endif
+
#define DEFAULT_BOARD_TYPE BoardType::PCCB_10
constexpr size_t NumFirmwareUpdateModules = 1; // 1 module
#define IAP_FIRMWARE_FILE "PccbFirmware.bin"
@@ -21,8 +26,15 @@ constexpr size_t NumFirmwareUpdateModules = 1; // 1 module
#define HAS_CPU_TEMP_SENSOR 1
#define HAS_HIGH_SPEED_SD 1 // SD card socket is optional
-#define SUPPORT_TMC22xx 1
-#define TMC22xx_HAS_MUX 0
+
+#ifdef PCCB_X5
+# define SUPPORT_TMC2660 1
+# define TMC2660_USES_USART 0
+#else
+# define SUPPORT_TMC22xx 1
+# define TMC22xx_HAS_MUX 0
+#endif
+
#define HAS_VOLTAGE_MONITOR 1
#define HAS_VREF_MONITOR 1
#define ACTIVE_LOW_HEAT_ON 1 // although we have no heaters, this matters because we treat the LEDs as heaters
@@ -38,9 +50,19 @@ constexpr size_t NumFirmwareUpdateModules = 1; // 1 module
// The physical capabilities of the machine
+#ifdef PCCB_X5
+
+constexpr size_t DRIVES = 6; // The maximum number of drives supported by the electronics
+constexpr size_t MaxSmartDrivers = 5; // The maximum number of smart drivers
+# define DRIVES_(a,b,c,d,e,f,g,h,i,j,k,l) { a,b,c,d,e,f }
+
+#else
+
constexpr size_t DRIVES = 8; // The maximum number of drives supported by the electronics
constexpr size_t MaxSmartDrivers = 2; // The maximum number of smart drivers
-#define DRIVES_(a,b,c,d,e,f,g,h,i,j,k,l) { a,b,c,d,e,f,g,h }
+# define DRIVES_(a,b,c,d,e,f,g,h,i,j,k,l) { a,b,c,d,e,f,g,h }
+
+#endif
constexpr size_t Heaters = 2; // The number of heaters in the machine. PCCB has no heaters, but we pretend that the LED pins are heaters.
constexpr size_t NumExtraHeaterProtections = 4; // The number of extra heater protection instances
@@ -63,15 +85,37 @@ constexpr size_t NUM_SERIAL_CHANNELS = 1; // The number of serial IO channels
// The numbers of entries in each array must correspond with the values of DRIVES, AXES, or HEATERS. Set values to NoPin to flag unavailability.
// Drivers
-constexpr Pin GlobalTmcEnablePin = 1; // The pin that drives ENN of all drivers
+constexpr Pin GlobalTmc22xxEnablePin = 1; // The pin that drives ENN of all internal drivers
+
+#ifdef PCCB_X5
+
+constexpr Pin GlobalTmc2660EnablePin = 52; // The pin that drives ENN of all drivers on the DueX5
+constexpr Pin ENABLE_PINS[DRIVES] = { 61, 35, 41, 55, 0, 64 };
+constexpr Pin STEP_PINS[DRIVES] = { 60, 38, 58, 56, 46, 50 };
+constexpr Pin DIRECTION_PINS[DRIVES] = { 17, 57, 54, 34, 1, 53 };
+
+Spi * const SPI_TMC2660 = SPI;
+constexpr uint32_t ID_TMC2660_SPI = ID_SPI;
+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
+
+#else
+
constexpr Pin ENABLE_PINS[DRIVES] = { NoPin, NoPin, 61, 35, 41, 55, 0, 64 };
constexpr Pin STEP_PINS[DRIVES] = { 40, 43, 60, 38, 58, 56, 46, 50 };
constexpr Pin DIRECTION_PINS[DRIVES] = { 8, 11, 17, 57, 54, 34, 1, 53 };
-Uart * const DriverUarts[MaxSmartDrivers] = { UART0, UART1 };
-constexpr uint32_t DriverUartIds[MaxSmartDrivers] = { ID_UART0, ID_UART1 };
-constexpr IRQn DriverUartIRQns[MaxSmartDrivers] = { UART0_IRQn, UART1_IRQn };
-constexpr Pin DriverUartPins[MaxSmartDrivers] = { APINS_UART0, APINS_UART1 };
+Uart * const TMC22xxUarts[MaxSmartDrivers] = { UART0, UART1 };
+constexpr uint32_t TMC22xxUartIds[MaxSmartDrivers] = { ID_UART0, ID_UART1 };
+constexpr IRQn TMC22xxUartIRQns[MaxSmartDrivers] = { UART0_IRQn, UART1_IRQn };
+constexpr Pin TMC22xxUartPins[MaxSmartDrivers] = { APINS_UART0, APINS_UART1 };
+
+#endif
// Define the baud rate used to send/receive data to/from the drivers.
// If we assume a worst case clock frequency of 8MHz then the maximum baud rate is 8MHz/16 = 500kbaud.
@@ -89,7 +133,11 @@ 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.
+#ifdef PCCB_X5
+constexpr Pin END_STOP_PINS[DRIVES] = { 24, 25, 67, 63, NoPin, NoPin };
+#else
constexpr Pin END_STOP_PINS[DRIVES] = { 24, 25, 67, 63, NoPin, NoPin, NoPin, NoPin };
+#endif
// Heaters and thermistors
constexpr Pin HEAT_ON_PINS[Heaters] = { 36, 59 }; // these are actually the LED control pins
diff --git a/src/Platform.cpp b/src/Platform.cpp
index db9d8166..44f60c37 100644
--- a/src/Platform.cpp
+++ b/src/Platform.cpp
@@ -199,6 +199,9 @@ void Platform::Init()
SetBoardType(BoardType::Auto);
#ifdef PCCB
+ // Make sure the on-board TMC22xx drivers are disabled
+ pinMode(GlobalTmc22xxEnablePin, OUTPUT_HIGH);
+
// Ensure that the main LEDs are turned off.
// The main LED output is active, just like a heater on the Duet 2 series.
// The secondary LED control dims the LED via the external controller when the output is high. So both outputs must be initialised high.
@@ -324,7 +327,6 @@ void Platform::Init()
ARRAY_INIT(accelerations, ACCELERATIONS);
ARRAY_INIT(driveStepsPerUnit, DRIVE_STEPS_PER_UNIT);
ARRAY_INIT(instantDvs, INSTANT_DVS);
- maxPrintingAcceleration = maxTravelAcceleration = 10000.0;
// Z PROBE
zProbeType = ZProbeType::none; // default is to use no Z probe
@@ -1880,23 +1882,29 @@ void Platform::InitialiseInterrupts()
NVIC_SetPriority(SysTick_IRQn, NvicPrioritySystick); // set priority for tick interrupts
#endif
- // Set UART interrupt priorities
-#ifdef PCCB
- NVIC_SetPriority(DriverUartIRQns[0], NvicPriorityDriversSerialTMC);
- NVIC_SetPriority(DriverUartIRQns[1], NvicPriorityDriversSerialTMC);
-#else
-# if SAM4E || SAME70
- NVIC_SetPriority(UART0_IRQn, NvicPriorityPanelDueUart); // set priority for UART interrupt
+ // Set PanelDue UART interrupt priority
+#ifdef SERIAL_AUX_DEVICE
+ SERIAL_AUX_DEVICE.setInterruptPriority(NvicPriorityPanelDueUart);
+#endif
+#ifdef SERIAL_AUX2_DEVICE
+ SERIAL_AUX2_DEVICE.setInterruptPriority(NvicPriorityPanelDueUart);
+#endif
+
+#if HAS_WIFI_NETWORKING
NVIC_SetPriority(UART1_IRQn, NvicPriorityWiFiUart); // set priority for WiFi UART interrupt
-# elif SAM4S
- NVIC_SetPriority(UART1_IRQn, NvicPriorityPanelDueUart); // set priority for UART interrupt
+#endif
+
+#if SUPPORT_TMC22xx
+# if TMC22xx_HAS_MUX
+ NVIC_SetPriority(TMC22xx_UART_IRQn, NvicPriorityDriversSerialTMC); // set priority for TMC2660 SPI interrupt
# else
- NVIC_SetPriority(UART_IRQn, NvicPriorityPanelDueUart); // set priority for UART interrupt
+ NVIC_SetPriority(TMC22xxUartIRQns[0], NvicPriorityDriversSerialTMC);
+ NVIC_SetPriority(TMC22xxUartIRQns[1], NvicPriorityDriversSerialTMC);
# endif
+#endif
-# if HAS_SMART_DRIVERS
- NVIC_SetPriority(UART_TMC_DRV_IRQn, NvicPriorityDriversSerialTMC);
-# endif
+#if SUPPORT_TMC2660
+ NVIC_SetPriority(TMC2660_SPI_IRQn, NvicPriorityDriversSerialTMC); // set priority for TMC2660 SPI interrupt
#endif
// Timer interrupt for stepper motors
diff --git a/src/Platform.h b/src/Platform.h
index 08ef818b..779215e6 100644
--- a/src/Platform.h
+++ b/src/Platform.h
@@ -426,14 +426,6 @@ public:
float Acceleration(size_t axisOrExtruder) const;
const float* Accelerations() const;
void SetAcceleration(size_t axisOrExtruder, float value);
- float GetMaxPrintingAcceleration() const
- { return maxPrintingAcceleration; }
- void SetMaxPrintingAcceleration(float acc)
- { maxPrintingAcceleration = acc; }
- float GetMaxTravelAcceleration() const
- { return maxTravelAcceleration; }
- void SetMaxTravelAcceleration(float acc)
- { maxTravelAcceleration = acc; }
float MaxFeedrate(size_t axisOrExtruder) const;
const float* MaxFeedrates() const;
void SetMaxFeedrate(size_t axisOrExtruder, float value);
@@ -738,8 +730,6 @@ private:
Pin endStopPins[DRIVES];
float maxFeedrates[DRIVES];
float accelerations[DRIVES];
- float maxPrintingAcceleration;
- float maxTravelAcceleration;
float driveStepsPerUnit[DRIVES];
float instantDvs[DRIVES];
float pressureAdvance[MaxExtruders];
diff --git a/src/StepperDrivers/TMC22xx/TMC22xx.cpp b/src/StepperDrivers/TMC22xx/TMC22xx.cpp
index 97b2b06c..7cc0e9c7 100644
--- a/src/StepperDrivers/TMC22xx/TMC22xx.cpp
+++ b/src/StepperDrivers/TMC22xx/TMC22xx.cpp
@@ -5,7 +5,7 @@
* Author: David
*/
-#include "ReprapFirmware.h"
+#include "RepRapFirmware.h"
#if SUPPORT_TMC22xx
@@ -346,7 +346,7 @@ private:
// Static data members of class TmcDriverState
#if TMC22xx_HAS_MUX
-Uart * const TmcDriverState::uart = UART_TMC_DRV;
+Uart * const TmcDriverState::uart = UART_TMC22xx;
#endif
TmcDriverState * volatile TmcDriverState::currentDriver = nullptr; // volatile because the ISR changes it
@@ -471,7 +471,7 @@ pre(!driversPowered)
}
#if !TMC22xx_HAS_MUX
- uart = DriverUarts[p_driverNumber];
+ uart = TMC22xxUarts[p_driverNumber];
#endif
enabled = false;
@@ -715,27 +715,27 @@ inline void TmcDriverState::SetUartMux()
{
if ((driverNumber & 0x01) != 0)
{
- fastDigitalWriteHigh(DriverMuxPins[0]);
+ fastDigitalWriteHigh(TMC22xxMuxPins[0]);
}
else
{
- fastDigitalWriteLow(DriverMuxPins[0]);
+ fastDigitalWriteLow(TMC22xxMuxPins[0]);
}
if ((driverNumber & 0x02) != 0)
{
- fastDigitalWriteHigh(DriverMuxPins[1]);
+ fastDigitalWriteHigh(TMC22xxMuxPins[1]);
}
else
{
- fastDigitalWriteLow(DriverMuxPins[1]);
+ fastDigitalWriteLow(TMC22xxMuxPins[1]);
}
if ((driverNumber & 0x04) != 0)
{
- fastDigitalWriteHigh(DriverMuxPins[2]);
+ fastDigitalWriteHigh(TMC22xxMuxPins[2]);
}
else
{
- fastDigitalWriteLow(DriverMuxPins[2]);
+ fastDigitalWriteLow(TMC22xxMuxPins[2]);
}
}
@@ -816,11 +816,16 @@ inline void TmcDriverState::UartTmcHandler()
#if TMC22xx_HAS_MUX
+#ifndef TMC22xx_UART_Handler
+# error TMC handler name not defined
+#endif
+
// ISR for the single UART
-extern "C" void UART_TMC_DRV_Handler() __attribute__ ((hot));
-void UART_TMC_DRV_Handler()
+extern "C" void TMC22xx_UART_Handler() __attribute__ ((hot));
+
+void TMC22xx_UART_Handler()
{
- UART_TMC_DRV->UART_IDR = UART_IDR_ENDRX; // disable the interrupt
+ UART_TMC22xx->UART_IDR = UART_IDR_ENDRX; // disable the interrupt
TmcDriverState *driver = TmcDriverState::currentDriver; // capture volatile variable
if (driver != nullptr)
{
@@ -856,27 +861,27 @@ namespace SmartDrivers
numTmc22xxDrivers = min<size_t>(numTmcDrivers, MaxSmartDrivers);
// Make sure the ENN pins are high
- pinMode(GlobalTmcEnablePin, OUTPUT_HIGH);
+ pinMode(GlobalTmc22xxEnablePin, OUTPUT_HIGH);
#if TMC22xx_HAS_MUX
// Set up- the single UART that communicates with all TMC22xx drivers
- ConfigurePin(GetPinDescription(UART_TMC_DRV_PINS)); // the pins are already set up for UART use in the pins table
+ ConfigurePin(GetPinDescription(TMC22xx_UART_PINS)); // the pins are already set up for UART use in the pins table
// Enable the clock to the UART
- pmc_enable_periph_clk(ID_UART_TMC_DRV);
+ pmc_enable_periph_clk(ID_TMC22xx_UART);
// Set the UART baud rate, 8 bits, 2 stop bits, no parity
- UART_TMC_DRV->UART_IDR = ~0u;
- UART_TMC_DRV->UART_CR = UART_CR_RSTRX | UART_CR_RSTTX | UART_CR_RXDIS | UART_CR_TXDIS;
- UART_TMC_DRV->UART_MR = UART_MR_CHMODE_NORMAL | UART_MR_PAR_NO;
- UART_TMC_DRV->UART_BRGR = VARIANT_MCK/(16 * DriversBaudRate); // set baud rate
- UART_TMC_DRV->UART_CR = UART_CR_RSTRX | UART_CR_RSTTX | UART_CR_RXDIS | UART_CR_TXDIS | UART_CR_RSTSTA;
- NVIC_EnableIRQ(UART_TMC_DRV_IRQn);
+ UART_TMC22xx->UART_IDR = ~0u;
+ UART_TMC22xx->UART_CR = UART_CR_RSTRX | UART_CR_RSTTX | UART_CR_RXDIS | UART_CR_TXDIS;
+ UART_TMC22xx->UART_MR = UART_MR_CHMODE_NORMAL | UART_MR_PAR_NO;
+ UART_TMC22xx->UART_BRGR = VARIANT_MCK/(16 * DriversBaudRate); // set baud rate
+ UART_TMC22xx->UART_CR = UART_CR_RSTRX | UART_CR_RSTTX | UART_CR_RXDIS | UART_CR_TXDIS | UART_CR_RSTSTA;
+ NVIC_EnableIRQ(TMC22xx_UART_IRQn);
// Set up the multiplexer control pins as outputs
- pinMode(DriverMuxPins[0], OUTPUT_LOW);
- pinMode(DriverMuxPins[1], OUTPUT_LOW);
- pinMode(DriverMuxPins[2], OUTPUT_LOW);
+ pinMode(TMC22xxMuxPins[0], OUTPUT_LOW);
+ pinMode(TMC22xxMuxPins[1], OUTPUT_LOW);
+ pinMode(TMC22xxMuxPins[2], OUTPUT_LOW);
#endif
driversState = DriversState::noPower;
@@ -885,19 +890,19 @@ namespace SmartDrivers
#if !TMC22xx_HAS_MUX
// Initialise the UART that controls this driver
// The pins are already set up for UART use in the pins table
- ConfigurePin(GetPinDescription(DriverUartPins[drive]));
+ ConfigurePin(GetPinDescription(TMC22xxUartPins[drive]));
// Enable the clock to the UART
- pmc_enable_periph_clk(DriverUartIds[drive]);
+ pmc_enable_periph_clk(TMC22xxUartIds[drive]);
// Set the UART baud rate, 8 bits, 2 stop bits, no parity
- Uart * const uart = DriverUarts[drive];
+ Uart * const uart = TMC22xxUarts[drive];
uart->UART_IDR = ~0u;
uart->UART_CR = UART_CR_RSTRX | UART_CR_RSTTX | UART_CR_RXDIS | UART_CR_TXDIS;
uart->UART_MR = UART_MR_CHMODE_NORMAL | UART_MR_PAR_NO;
uart->UART_BRGR = VARIANT_MCK/(16 * DriversBaudRate); // set baud rate
uart->UART_CR = UART_CR_RSTRX | UART_CR_RSTTX | UART_CR_RXDIS | UART_CR_TXDIS | UART_CR_RSTSTA;
- NVIC_EnableIRQ(DriverUartIRQns[drive]);
+ NVIC_EnableIRQ(TMC22xxUartIRQns[drive]);
#endif
driverStates[drive].Init(drive, driverSelectPins[drive]); // axes are mapped straight through to drivers initially
}
@@ -1045,7 +1050,7 @@ namespace SmartDrivers
if (allInitialised)
{
- digitalWrite(GlobalTmcEnablePin, LOW);
+ digitalWrite(GlobalTmc22xxEnablePin, LOW);
driversState = DriversState::ready;
}
}
@@ -1053,7 +1058,7 @@ namespace SmartDrivers
else
{
// We had power but we lost it
- digitalWrite(GlobalTmcEnablePin, HIGH); // disable the drivers
+ digitalWrite(GlobalTmc22xxEnablePin, HIGH); // disable the drivers
if (TmcDriverState::currentDriver == nullptr)
{
TmcDriverState::currentDriver->AbortTransfer();
diff --git a/src/StepperDrivers/TMC2660/TMC2660.cpp b/src/StepperDrivers/TMC2660/TMC2660.cpp
index f99961ea..5390d56f 100644
--- a/src/StepperDrivers/TMC2660/TMC2660.cpp
+++ b/src/StepperDrivers/TMC2660/TMC2660.cpp
@@ -5,7 +5,7 @@
* Author: David
*/
-#include "ReprapFirmware.h"
+#include "RepRapFirmware.h"
#if SUPPORT_TMC2660
@@ -26,12 +26,6 @@ static size_t numTmc2660Drivers;
static bool driversPowered = false;
-// Pin assignments, using USART1 in SPI mode
-const Pin DriversClockPin = 15; // PB15/TIOA1
-const Pin DriversMosiPin = 22; // PA13
-const Pin DriversMisoPin = 21; // PA22
-const Pin DriversSclkPin = 23; // PA23
-
const int ChopperControlRegisterMode = 999; // mode passed to get/set microstepping to indicate we want the chopper control register
// The SPI clock speed is a compromise:
@@ -228,8 +222,13 @@ private:
// State structures for all drivers
static TmcDriverState driverStates[MaxSmartDrivers];
-// PDC address for the USART
-static Pdc * const usartPdc = usart_get_pdc_base(USART_TMC_DRV);
+// PDC address
+static Pdc * const spiPdc =
+#if TMC2660_USES_USART
+ usart_get_pdc_base(USART_TMC2660);
+#else
+ spi_get_pdc_base(SPI_TMC2660);
+#endif
// Words to send and receive driver SPI data from/to
volatile static uint32_t spiDataOut = 0; // volatile because we care about when it is written
@@ -242,18 +241,18 @@ static TmcDriverState * volatile currentDriver = nullptr; // volatile because th
/*static*/ inline void TmcDriverState::SetupDMA(uint32_t outVal)
{
// Faster code, not using the ASF
- usartPdc->PERIPH_PTCR = (PERIPH_PTCR_RXTDIS | PERIPH_PTCR_TXTDIS); // disable the PDC
+ spiPdc->PERIPH_PTCR = (PERIPH_PTCR_RXTDIS | PERIPH_PTCR_TXTDIS); // disable the PDC
// SPI sends data MSB first, but the firmware uses little-endian mode, so we need to reverse the byte order
spiDataOut = cpu_to_be32(outVal << 8);
- usartPdc->PERIPH_TPR = reinterpret_cast<uint32_t>(&spiDataOut);
- usartPdc->PERIPH_TCR = 3;
+ spiPdc->PERIPH_TPR = reinterpret_cast<uint32_t>(&spiDataOut);
+ spiPdc->PERIPH_TCR = 3;
- usartPdc->PERIPH_RPR = reinterpret_cast<uint32_t>(&spiDataIn);
- usartPdc->PERIPH_RCR = 3;
+ spiPdc->PERIPH_RPR = reinterpret_cast<uint32_t>(&spiDataIn);
+ spiPdc->PERIPH_RCR = 3;
- usartPdc->PERIPH_PTCR = (PERIPH_PTCR_RXTEN | PERIPH_PTCR_TXTEN); // enable the PDC
+ spiPdc->PERIPH_PTCR = (PERIPH_PTCR_RXTEN | PERIPH_PTCR_TXTEN); // enable the PDC
}
// Initialise the state of the driver and its CS pin
@@ -561,18 +560,37 @@ inline void TmcDriverState::StartTransfer()
// Kick off a transfer for that register
const irqflags_t flags = cpu_irq_save(); // avoid race condition
- USART_TMC_DRV->US_CR = US_CR_RSTRX | US_CR_RSTTX; // reset transmitter and receiver
+
+#if TMC2660_USES_USART
+ USART_TMC2660->US_CR = US_CR_RSTRX | US_CR_RSTTX; // reset transmitter and receiver
+#else
+ SPI_TMC2660->SPI_CR = SPI_CR_SPIDIS; // disable the SPI
+ (void)SPI_TMC2660->SPI_RDR; // clear the receive buffer
+#endif
+
fastDigitalWriteLow(pin); // set CS low
SetupDMA(regVal); // set up the PDC
- USART_TMC_DRV->US_IER = US_IER_ENDRX; // enable end-of-transfer interrupt
- USART_TMC_DRV->US_CR = US_CR_RXEN | US_CR_TXEN; // enable transmitter and receiver
+
+#if TMC2660_USES_USART
+ USART_TMC2660->US_IER = US_IER_ENDRX; // enable end-of-transfer interrupt
+ USART_TMC2660->US_CR = US_CR_RXEN | US_CR_TXEN; // enable transmitter and receiver
+#else
+ SPI_TMC2660->SPI_IER = SPI_IER_ENDRX; // enable end-of-transfer interrupt
+ SPI_TMC2660->SPI_CR = SPI_CR_SPIEN; // enable SPI
+#endif
+
cpu_irq_restore(flags);
}
// ISR for the USART
-extern "C" void USART_TMC_DRV_Handler(void) __attribute__ ((hot));
-void USART_TMC_DRV_Handler(void)
+#ifndef TMC2660_SPI_Handler
+# error TMC handler name not defined
+#endif
+
+extern "C" void TMC2660_SPI_Handler(void) __attribute__ ((hot));
+
+void TMC2660_SPI_Handler(void)
{
TmcDriverState *driver = currentDriver; // capture volatile variable
if (driver != nullptr)
@@ -592,7 +610,13 @@ void USART_TMC_DRV_Handler(void)
}
// Driver power is down or there is no current driver, so stop polling
- USART_TMC_DRV->US_IDR = US_IDR_ENDRX;
+
+#if TMC2660_USES_USART
+ USART_TMC2660->US_IDR = US_IDR_ENDRX;
+#else
+ SPI_TMC2660->SPI_IDR = SPI_IDR_ENDRX;
+#endif
+
currentDriver = nullptr; // signal that we are not waiting for an interrupt
}
@@ -607,32 +631,49 @@ namespace SmartDrivers
numTmc2660Drivers = min<size_t>(numTmcDrivers, MaxSmartDrivers);
// Make sure the ENN pins are high
- pinMode(GlobalTmcEnablePin, OUTPUT_HIGH);
+ pinMode(GlobalTmc2660EnablePin, OUTPUT_HIGH);
// The pins are already set up for SPI in the pins table
- ConfigurePin(GetPinDescription(DriversMosiPin));
- ConfigurePin(GetPinDescription(DriversMisoPin));
- ConfigurePin(GetPinDescription(DriversSclkPin));
+ ConfigurePin(GetPinDescription(TMC2660MosiPin));
+ ConfigurePin(GetPinDescription(TMC2660MisoPin));
+ ConfigurePin(GetPinDescription(TMC2660SclkPin));
- // Enable the clock to the USART
- pmc_enable_periph_clk(ID_USART_TMC_DRV);
+ // Enable the clock to the USART or SPI
+ pmc_enable_periph_clk(ID_TMC2660_SPI);
+#if TMC2660_USES_USART
// Set USART_EXT_DRV in SPI mode, with data changing on the falling edge of the clock and captured on the rising edge
- USART_TMC_DRV->US_IDR = ~0u;
- USART_TMC_DRV->US_CR = US_CR_RSTRX | US_CR_RSTTX | US_CR_RXDIS | US_CR_TXDIS;
- USART_TMC_DRV->US_MR = US_MR_USART_MODE_SPI_MASTER
+ USART_TMC2660->US_IDR = ~0u;
+ USART_TMC2660->US_CR = US_CR_RSTRX | US_CR_RSTTX | US_CR_RXDIS | US_CR_TXDIS;
+ USART_TMC2660->US_MR = US_MR_USART_MODE_SPI_MASTER
| US_MR_USCLKS_MCK
| US_MR_CHRL_8_BIT
| US_MR_CHMODE_NORMAL
| US_MR_CPOL
| US_MR_CLKO;
- USART_TMC_DRV->US_BRGR = VARIANT_MCK/DriversSpiClockFrequency; // set SPI clock frequency
- USART_TMC_DRV->US_CR = US_CR_RSTRX | US_CR_RSTTX | US_CR_RXDIS | US_CR_TXDIS | US_CR_RSTSTA;
+ USART_TMC2660->US_BRGR = VARIANT_MCK/DriversSpiClockFrequency; // set SPI clock frequency
+ USART_TMC2660->US_CR = US_CR_RSTRX | US_CR_RSTTX | US_CR_RXDIS | US_CR_TXDIS | US_CR_RSTSTA;
// We need a few microseconds of delay here for the USART to sort itself out before we send any data,
// otherwise the processor generates two short reset pulses on its own NRST pin, and resets itself.
// 2016-07-07: removed this delay, because we no longer send commands to the TMC2660 drivers immediately.
//delay(10);
+#else
+ // Set up the SPI interface with data changing on the falling edge of the clock and captured on the rising edge
+ spi_reset(SPI_TMC2660); // this clears the transmit and receive registers and puts the SPI into slave mode
+ SPI_TMC2660->SPI_MR = SPI_MR_MSTR // master mode
+ | SPI_MR_MODFDIS // disable fault detection
+ | SPI_MR_PCS(0); // fixed peripheral select
+
+ // Set SPI mode, clock frequency, CS active after transfer, delay between transfers
+ const uint16_t baud_div = (uint16_t)spi_calc_baudrate_div(DriversSpiClockFrequency, SystemCoreClock);
+ const uint32_t csr = SPI_CSR_SCBR(baud_div) // Baud rate
+ | SPI_CSR_BITS_8_BIT // Transfer bit width
+ | SPI_CSR_DLYBCT(0) // Transfer delay
+ | SPI_CSR_CSAAT // Keep CS low after transfer in case we are slow in writing the next byte
+ | SPI_CSR_CPOL; // clock high between transfers
+ SPI_TMC2660->SPI_CSR[0] = csr;
+#endif
driversPowered = false;
for (size_t driver = 0; driver < numTmc2660Drivers; ++driver)
@@ -739,7 +780,7 @@ namespace SmartDrivers
if (!wasPowered)
{
// Power to the drivers has been provided or restored, so we need to enable and re-initialise them
- digitalWrite(GlobalTmcEnablePin, LOW);
+ digitalWrite(GlobalTmc2660EnablePin, LOW);
delayMicroseconds(10);
for (size_t driver = 0; driver < numTmc2660Drivers; ++driver)
@@ -750,20 +791,20 @@ namespace SmartDrivers
if (currentDriver == nullptr && numTmc2660Drivers != 0)
{
// Kick off the first transfer
- NVIC_EnableIRQ(UART_TMC_DRV_IRQn);
+ NVIC_EnableIRQ(TMC2660_SPI_IRQn);
driverStates[0].StartTransfer();
}
}
else if (wasPowered)
{
- digitalWrite(GlobalTmcEnablePin, HIGH); // disable the drivers
+ digitalWrite(GlobalTmc2660EnablePin, HIGH); // disable the drivers
}
}
// This is called from the tick ISR, possibly while Spin (with powered either true or false) is being executed
void TurnDriversOff()
{
- digitalWrite(GlobalTmcEnablePin, HIGH); // disable the drivers
+ digitalWrite(GlobalTmc2660EnablePin, HIGH); // disable the drivers
driversPowered = false;
}
diff --git a/src/StepperDrivers/TMC2660/TMC2660.h b/src/StepperDrivers/TMC2660/TMC2660.h
index ceed9734..37721e0d 100644
--- a/src/StepperDrivers/TMC2660/TMC2660.h
+++ b/src/StepperDrivers/TMC2660/TMC2660.h
@@ -16,12 +16,6 @@
#include "MessageType.h"
#include "Libraries/General/StringRef.h"
-// The Platform class needs to know which USART we are using when assigning interrupt priorities
-#define USART_TMC_DRV USART1
-#define UART_TMC_DRV_IRQn USART1_IRQn
-#define ID_USART_TMC_DRV ID_USART1
-#define USART_TMC_DRV_Handler USART1_Handler
-
// TMC2660 Read response. The microstep counter can also be read, but we don't include that here.
const uint32_t TMC_RR_SG = 1 << 0; // stall detected
const uint32_t TMC_RR_OT = 1 << 1; // over temperature shutdown
diff --git a/src/Version.h b/src/Version.h
index b529899b..57dc01e5 100644
--- a/src/Version.h
+++ b/src/Version.h
@@ -12,7 +12,7 @@
#ifndef VERSION
#ifdef RTOS
# define RTOSVER "(RTOS)"
-# define MAIN_VERSION "2.01"
+# define MAIN_VERSION "2.02alpha1"
#else
# define MAIN_VERSION "1.22"
# define RTOSVER
@@ -22,7 +22,7 @@
#endif
#ifndef DATE
-# define DATE "2018-07-26b2"
+# define DATE "2018-08-02b1"
#endif
#define AUTHORS "reprappro, dc42, chrishamm, t3p3, dnewman"