diff --git a/configTool/js/main.js b/configTool/js/main.js
index 389b31b..c5ea54a 100644
--- a/configTool/js/main.js
+++ b/configTool/js/main.js
@@ -56,7 +56,8 @@ window.addEventListener('DOMContentLoaded', function() {
acc: document.querySelectorAll("input[name='acc']"),
dec: document.querySelectorAll("input[name='dec']"),
maxSpeed: document.querySelectorAll("input[name='maxSpeed']"),
- fullStepSpeed: document.querySelectorAll("input[name='fullStepSpeed']")
+ fullStepSpeed: document.querySelectorAll("input[name='fullStepSpeed']"),
+ minSpeed: document.querySelectorAll("input[name='minSpeed']")
},
voltageMode: {
KVAL_HOLD: document.querySelectorAll("input[name='KVAL_HOLD']"),
@@ -68,6 +69,7 @@ window.addEventListener('DOMContentLoaded', function() {
FN_SLP_ACC: document.querySelectorAll("input[name='FN_SLP_ACC']"),
FN_SLP_DEC: document.querySelectorAll("input[name='FN_SLP_DEC']"),
STALL_TH: document.querySelectorAll("input[name='STALL_TH']"),
+ lowSpeedOptimizeEnable: document.querySelectorAll("input[name='lowSpeedOptimizeEnable']"),
lowSpeedOptimize: document.querySelectorAll("input[name='lowSpeedOptimize']")
},
servoMode: {
diff --git a/configTool/v1.0/css/styles.css b/configTool/v1.0/css/styles.css
new file mode 100644
index 0000000..e1b98f1
--- /dev/null
+++ b/configTool/v1.0/css/styles.css
@@ -0,0 +1,77 @@
+@charset 'utf-8';
+
+/* base
+--------------------------------------------------- */
+* { margin: 0; padding: 0; }
+html { box-sizing: border-box; }
+img { max-width: 100%; height: auto; }
+h1, h2, h3, h4, h5, h6 { font-size: 100%; font-weight: normal; }
+ul, ol { list-style: none; }
+i, em { font-style: normal; }
+@media screen and (max-width:59.99em) {
+ html { font-size: 56.25%; }
+}
+@media screen and (min-width:60em) {
+ html { font-size: 62.5%; }
+}
+body { font-family: BlinkMacSystemFont, -apple-system, "Helvetica Neue", Arial, "Hiragino Kaku Gothic ProN", "Hiragino Sans", Meiryo, sans-serif; font-size: 1.6rem; line-height: 1; color: #363636; }
+@media (-webkit-min-device-pixel-ratio:2) {
+ body { -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; }
+}
+::-moz-selection { background: #363636; color: #fff; text-shadow: none; }
+::selection { background: #363636; color: #fff; text-shadow: none; }
+
+/* content
+--------------------------------------------------- */
+.container { margin: 8rem auto; width: 92.19%; max-width: 96rem; min-width: 88rem; }
+.line-ponoor { position: relative; width: 100%; height: 0.4rem; border: 0; background-color: #8d3f2b; background-image: linear-gradient(117deg, #8d3f2b 0% 55%, #363636 55% 70%, #e6e6e6 70% 82%, #ff6720 82% 95%, #fbde40 95% 100%); }
+h1 { display: -webkit-flex; display: flex; -webkit-align-items: flex-end; align-items: flex-end; margin-bottom: 6.4rem; font-weight: 600; font-size: 4.8rem; }
+h1 > span { display: inline-block; margin-bottom: 0.5rem; margin-left: 1.6rem; padding: 0.4rem 1.2rem; background-color: #eee; border-radius: 2.4rem; font-size: 1.6rem; }
+.heading-wrap { margin-top: 6.4rem; margin-bottom: 4rem; display: -webkit-flex; display: flex; -webkit-align-items: center; align-items: center; }
+.heading-wrap > h2 { margin-right: 3.2rem; font-weight: 600; font-size: 3.2rem; }
+.file-input input[type="file"] { display: none; }
+.file-input label { display: inline-block; position: relative; cursor: pointer; padding: 1rem 2rem; border-radius: 0.2rem; margin-right: 0.8rem; background-color: #ff6720; color: #fff; font-weight: 600; font-size: 1.4rem; transition: opacity 0.2s ease-out; }
+.file-input label:after { content: "No file selected"; color: #808080; font-size: 1.4rem; height: 2rem; line-height: 2rem; position: absolute; right: -12.4rem; top: calc(50% - 1rem); }
+.file-input label:hover { opacity: 0.8; }
+.file-input label.changed:after { content: ""; }
+.file-input .filename { font-size: 1.4rem; }
+.file-export { margin-top: 8rem; width: 100%; }
+.file-export > input[type="submit"] { width: 28rem; height: 100%; border: 0; outline: none; padding: 2rem 0; background-color: #ff6720; border-radius: 0.2rem; font-weight: 600; font-size: 2rem; color: #fff; text-align: center; cursor: pointer; transition: opacity 0.2s ease-out; }
+.file-export > input[type="submit"]:hover { opacity: 0.8; }
+.input-setting { padding: 0.8rem 1.2rem; border: 1px solid #eee; border-radius: 0.2rem; }
+.input-setting > .label { display: -webkit-flex; display: flex; -webkit-align-items: center; align-items: center; font-weight: 600; }
+.input-setting > .label input { margin-left: 0.8rem; }
+.input-list { border-bottom: 1px solid #eee; }
+.input-list > li { display: -webkit-flex; display: flex; -webkit-align-items: center; align-items: center; }
+.input-list > li > .input-label { width: calc(100% - 66rem); padding-right: 0.5rem; }
+.input-list > li > .input-items { width: 66rem; }
+.input-list > li.heading { padding-bottom: 0.8rem; border-bottom: 1px solid #eee; font-weight: 600; font-size: 1.4rem; }
+.input-list > li:not(.heading) { padding: 1.2rem 0; border-top: 1px solid #eee; }
+.input-label { position: relative; font-weight: 600; }
+.input-label > .hint { border-bottom: 1px dotted rgba(54, 54, 54, 0.6); cursor: pointer; position: relative; }
+.input-label > .hint:hover + .tooltip { display: block; }
+.input-label > .tooltip { display: none; position: absolute; left: 0.8rem; top: 3.2rem; z-index: 9999; max-width: 80%; padding: 1.2rem 1.6rem; color: #fff; background-color: #555; border-radius: 0.2rem; font-size: 1.4rem; line-height: 1.5; }
+.input-label > .tooltip::after { width: 100%; content: ""; display: block; position: absolute; left: 0.8rem; top: -8px; border-top: 8px solid transparent; border-left: 8px solid #555; }
+.input-items { display: -webkit-flex; display: flex; -webkit-align-items: center; align-items: center; }
+.input-items > p, .input-items > select, .input-items > input[type="text"], .input-items > input[type="number"] { margin-right: 0.2rem; }
+.input-items > p, .input-items > select { width: 12rem; }
+.input-items > input[type="text"] { width: 22.8rem; }
+.input-items > input[type="number"] { width: 11rem; }
+.input-items > input[type="text"], .input-items > input[type="number"] { outline: none; padding: 0.5rem 0.2rem 0.5rem 0.6rem; background-color: #fff; border: 0.1rem solid #d3d3d3; border-radius: 0.2rem; font-size: 1.4rem; }
+.input-items > input[type="text"]:focus, .input-items > input[type="number"]:focus { box-shadow: inset 0 0 2px 0 #ff6720; }
+.input-items > input[type="checkbox"] { width: 1.6rem; margin-right: 6.6rem; }
+.input-items > input[disabled="disabled"], .input-items > select[disabled="disabled"], .input-items > p[disabled="disabled"] { display: none; }
+.input-items > input[readonly="readonly"] { outline: 0; background-color: #eee; cursor: not-allowed; }
+.input-items > input[readonly="readonly"]:focus { box-shadow: none; }
+.input-items > .btn { display: -webkit-flex; display: flex; -webkit-align-items: center; align-items: center; margin-left: 1.2rem; font-size: 1.4rem; line-height: 1.6rem; }
+.input-items > .btn > input { margin-right: 0.6rem; }
+.input-items.-sm > input[type="text"], .input-items.-sm > input[type="number"] { width: 4.8rem; }
+.input-list.-motor .input-items > .unit { display: block; font-size: 0.8em; }
+.input-list.-motor .input-items > p, .input-list.-motor .input-items > select, .input-list.-motor .input-items > input[type="text"], .input-list.-motor .input-items > input[type="number"] { margin-right: 0.4rem; }
+.input-list.-motor .input-items > p, .input-list.-motor .input-items > select { width: 7.2rem; }
+.input-list.-motor .input-items > input[type="number"] { width: 6.2rem; }
+.input-list.-motor .input-items > input[type="checkbox"] { width: 1.6rem; margin-right: 6rem; }
+
+/* IE */
+_:-ms-lang(x), .file-input > label { display: none; }
+_:-ms-lang(x), .file-input > input[type="file"] { width: auto; }
diff --git a/configTool/v1.0/index.html b/configTool/v1.0/index.html
new file mode 100644
index 0000000..8b45fa6
--- /dev/null
+++ b/configTool/v1.0/index.html
@@ -0,0 +1,1332 @@
+
+
+
+
+
+
STEP800 configuration tool
+
+
+
+
+
+
+
+
+
STEP800 configuration tool rev 1.0
+
+
+
+ Choose file
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/configTool/v1.0/js/main.js b/configTool/v1.0/js/main.js
new file mode 100644
index 0000000..389b31b
--- /dev/null
+++ b/configTool/v1.0/js/main.js
@@ -0,0 +1,255 @@
+window.addEventListener('DOMContentLoaded', function() {
+ var NUM_MOTOR = 8;
+ var inputElements = {
+ information: {
+ configName: document.querySelector("input[name='configName']"),
+ configVersion: document.querySelectorAll("input[name='configVersion']"),
+ targetProduct: document.querySelector("input[name='targetProduct']")
+ },
+ network: {
+ myIp: document.querySelectorAll("input[name='myIp']"),
+ isMyIpAddId: document.querySelector("input[name='isMyIpAddId']"),
+ destIp: document.querySelectorAll("input[name='destIp']"),
+ dns: document.querySelectorAll("input[name='dns']"),
+ gateway: document.querySelectorAll("input[name='gateway']"),
+ subnet: document.querySelectorAll("input[name='subnet']"),
+ inPort: document.querySelector("input[name='inPort']"),
+ outPort: document.querySelector("input[name='outPort']"),
+ isOutPortAddId: document.querySelector("input[name='isOutPortAddId']"),
+ mac: document.querySelectorAll("input[name='mac']"),
+ isMacAddId: document.querySelector("input[name='isMacAddId']"),
+ bootedMsgEnable: document.querySelector("input[name='bootedMsgEnable']"),
+ canSendMsgBeforeDestIp: document.querySelector("input[name='canSendMsgBeforeDestIp']"),
+ reportError: document.querySelector("input[name='reportError']")
+ },
+ alarmAndReport: {
+ reportBUSY: document.querySelectorAll("input[name='reportBUSY']"),
+ reportHiZ: document.querySelectorAll("input[name='reportHiZ']"),
+ reportHomeSwStatus: document.querySelectorAll("input[name='reportHomeSwStatus']"),
+ // reportLimitSwStatus: document.querySelectorAll("input[name='reportLimitSwStatus']"),
+ reportDir: document.querySelectorAll("input[name='reportDir']"),
+ reportMotorStatus: document.querySelectorAll("input[name='reportMotorStatus']"),
+ reportSwEvn: document.querySelectorAll("input[name='reportSwEvn']"),
+ reportUVLO: document.querySelectorAll("input[name='reportUVLO']"),
+ reportThermalStatus: document.querySelectorAll("input[name='reportThermalStatus']"),
+ reportOCD: document.querySelectorAll("input[name='reportOCD']"),
+ reportStall: document.querySelectorAll("input[name='reportStall']"),
+ OCThreshold: document.querySelectorAll("select[name='OCThreshold']")
+ },
+ driverSettings: {
+ homingAtStartup : document.querySelectorAll("input[name='homingAtStartup']"),
+ homingDirection : document.querySelectorAll("select[name='homingDirection']"),
+ homingSpeed: document.querySelectorAll("input[name='homingSpeed']"),
+ homeSwMode: document.querySelectorAll("input[name='homeSwMode']"),
+ prohibitMotionOnHomeSw: document.querySelectorAll("input[name='prohibitMotionOnHomeSw']"),
+ // limitSwMode: document.querySelectorAll("input[name='limitSwMode']"),
+ // prohibitMotionOnLimitSw: document.querySelectorAll("input[name='prohibitMotionOnLimitSw']"),
+ goUntilTimeout: document.querySelectorAll("input[name='goUntilTimeout']"),
+ releaseSwTimeout: document.querySelectorAll("input[name='releaseSwTimeout']"),
+ stepMode: document.querySelectorAll("select[name='stepMode']"),
+ // isCurrentMode: document.querySelectorAll("input[name='isCurrentMode']"),
+ // slewRate: document.querySelectorAll("select[name='slewRate']"),
+ electromagnetBrakeEnable: document.querySelectorAll("input[name='electromagnetBrakeEnable']"),
+ brakeTransitionDuration: document.querySelectorAll("input[name='brakeTransitionDuration']")
+ },
+ speedProfile: {
+ acc: document.querySelectorAll("input[name='acc']"),
+ dec: document.querySelectorAll("input[name='dec']"),
+ maxSpeed: document.querySelectorAll("input[name='maxSpeed']"),
+ fullStepSpeed: document.querySelectorAll("input[name='fullStepSpeed']")
+ },
+ voltageMode: {
+ KVAL_HOLD: document.querySelectorAll("input[name='KVAL_HOLD']"),
+ KVAL_RUN: document.querySelectorAll("input[name='KVAL_RUN']"),
+ KVAL_ACC: document.querySelectorAll("input[name='KVAL_ACC']"),
+ KVAL_DEC: document.querySelectorAll("input[name='KVAL_DEC']"),
+ INT_SPEED: document.querySelectorAll("input[name='INT_SPEED']"),
+ ST_SLP: document.querySelectorAll("input[name='ST_SLP']"),
+ FN_SLP_ACC: document.querySelectorAll("input[name='FN_SLP_ACC']"),
+ FN_SLP_DEC: document.querySelectorAll("input[name='FN_SLP_DEC']"),
+ STALL_TH: document.querySelectorAll("input[name='STALL_TH']"),
+ lowSpeedOptimize: document.querySelectorAll("input[name='lowSpeedOptimize']")
+ },
+ servoMode: {
+ kP: document.querySelectorAll("input[name='kP']"),
+ kI: document.querySelectorAll("input[name='kI']"),
+ kD: document.querySelectorAll("input[name='kD']")
+ }
+ };
+
+ var targetAllInputs = {
+ alarmAndReport: document.querySelector("input.alarmAndReport[name='targetAll']"),
+ driverSettings: document.querySelector("input.driverSettings[name='targetAll']"),
+ speedProfile: document.querySelector("input.speedProfile[name='targetAll']"),
+ voltageMode: document.querySelector("input.voltageMode[name='targetAll']"),
+ //currentMode: document.querySelector("input.currentMode[name='targetAll']"),
+ servoMode: document.querySelector("input.servoMode[name='targetAll']")
+ }
+ var rowLabelTexts = {
+ alarmAndReport: document.querySelectorAll("div.rowLabel.alarmAndReport p"),
+ driverSettings: document.querySelectorAll("div.rowLabel.driverSettings p"),
+ speedProfile: document.querySelectorAll("div.rowLabel.speedProfile p"),
+ voltageMode: document.querySelectorAll("div.rowLabel.voltageMode p"),
+ //currentMode: document.querySelectorAll("div.rowLabel.currentMode p"),
+ servoMode: document.querySelectorAll("div.rowLabel.servoMode p")
+ }
+
+ var form = document.querySelector("form");
+ var loadInput = document.querySelector("input[name='load']");
+
+ for (catName in targetAllInputs) {
+ targetAllInputs[catName].addEventListener('change', changeTargetAll, false);
+ targetAllInputs[catName].dispatchEvent(new Event('change', { 'bubbles': true }));
+ }
+
+ function changeTargetAll(e) {
+ var catInputs = inputElements[e.target.className];
+
+ for(paramName in catInputs) {
+ var paramInputs = catInputs[paramName];
+ if(e.target.checked) {
+ paramInputs[0].removeAttribute('disabled');
+ for (var i = 0; i < NUM_MOTOR; i ++) {
+ paramInputs[i + 1].setAttribute('disabled', 'disabled');
+ }
+ } else {
+ paramInputs[0].setAttribute('disabled', 'disabled');
+ for (var i = 0; i < NUM_MOTOR; i ++) {
+ paramInputs[i + 1].removeAttribute('disabled');
+ }
+ }
+ }
+ if (e.target.checked) {
+ rowLabelTexts[e.target.className][0].removeAttribute('disabled');
+ for (var i = 0; i < NUM_MOTOR; i ++) {
+ rowLabelTexts[e.target.className][i + 1].setAttribute('disabled', 'disabled');
+ }
+ } else {
+ rowLabelTexts[e.target.className][0].setAttribute('disabled', 'disabled');
+ for (var i = 0; i < NUM_MOTOR; i ++) {
+ rowLabelTexts[e.target.className][i + 1].removeAttribute('disabled');
+ }
+ }
+ }
+
+ form.addEventListener('submit', function(e) {
+ e.stopPropagation();
+ e.preventDefault();
+
+ var configObject = {};
+ for(catName in inputElements) {
+ configObject[catName] = {};
+ for (paramName in inputElements[catName]) {
+ if (catName === 'network' || catName === 'information') {
+ if (0 < inputElements[catName][paramName].length) {
+ configObject[catName][paramName] = [];
+ for (var i = 0; i < inputElements[catName][paramName].length; i++) {
+ configObject[catName][paramName].push(getInputValue(inputElements[catName][paramName][i]));
+ }
+ } else {
+ configObject[catName][paramName] = getInputValue(inputElements[catName][paramName]);
+ }
+ } else {
+ var isTargetAll = targetAllInputs[catName].checked;
+ for (paramName in inputElements[catName]) {
+ configObject[catName][paramName] = [];
+ for (var i = 0; i < NUM_MOTOR; i ++) {
+ if (isTargetAll) {
+ configObject[catName][paramName].push(getInputValue(inputElements[catName][paramName][0]));
+ } else {
+ configObject[catName][paramName].push(getInputValue(inputElements[catName][paramName][i+1]));
+ }
+ }
+ }
+ }
+ }
+ }
+ function getInputValue(elm) {
+ if (elm.tagName === 'INPUT') {
+
+ var type = elm.getAttribute("type");
+ switch (type) {
+ case 'number':
+ return Number(elm.value);
+ break;
+ case 'text':
+ return elm.value;
+ break;
+ case 'checkbox':
+ return elm.checked;
+ break;
+ default:
+ return 0;
+ break;
+ }
+ } else if (elm.tagName === 'SELECT') {
+ return Number(elm.value);
+ }
+ }
+
+
+ var configJson = JSON.stringify(configObject, null, '\t');
+ var configBlob = new Blob([configJson], {type: 'text/plain'});
+ var a = document.createElement('a');
+ a.href = URL.createObjectURL(configBlob);
+ a.download = 'config.txt';
+ a.click();
+ }, false);
+
+ loadInput.addEventListener('change', function(e) {
+ var fileReader = new FileReader();
+ fileReader.readAsText(e.target.files[0]);
+
+ fileReader.onload = function(e) {
+ var jsonObject = JSON.parse(e.target.result);
+
+ for(catName in inputElements) {
+ if (jsonObject[catName] !== undefined) {
+ for (paramName in inputElements[catName]) {
+ if (jsonObject[catName][paramName] !== undefined) {
+ if (catName === 'network' || catName === 'information') {
+ if (0 < inputElements[catName][paramName].length) {
+ for (var i = 0; i < inputElements[catName][paramName].length; i++) {
+ setInputValue(inputElements[catName][paramName][i], jsonObject[catName][paramName][i]);
+ }
+ } else {
+ setInputValue(inputElements[catName][paramName], jsonObject[catName][paramName]);
+ }
+ } else {
+ for (paramName in inputElements[catName]) {
+ for (var i = 0; i < NUM_MOTOR; i ++) {
+ setInputValue(inputElements[catName][paramName][i+1], jsonObject[catName][paramName][i]);
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ function setInputValue(elm, val) {
+
+ if (elm.tagName === 'INPUT') {
+
+ var type = elm.getAttribute('type');
+ switch (type) {
+ case 'number':
+ elm.value = val;
+ break;
+ case 'text':
+ elm.value = val;
+ break;
+ case 'checkbox':
+ elm.checked = val;
+ break;
+ default:
+ return 0;
+ break;
+ }
+ } else if (elm.tagName === 'SELECT') {
+ elm.selectedIndex = val;
+ }
+ }
+ }
+
+ }, false)
+});
\ No newline at end of file
diff --git a/configTool/v1.0/js/styles.js b/configTool/v1.0/js/styles.js
new file mode 100644
index 0000000..54029ae
--- /dev/null
+++ b/configTool/v1.0/js/styles.js
@@ -0,0 +1,54 @@
+// file-input
+const formInputs = document.getElementsByClassName("file");
+const length = formInputs.length;
+for (let i = 0; i < length; i++) {
+ formInputs[i].onchange = function () {
+ const file = this.files[0].name;
+ const label = this.nextElementSibling;
+ if (!label.classList.contains("changed")) {
+ const span = document.createElement("span");
+ span.className = "filename";
+ this.parentNode.appendChild(span);
+ label.classList.add("changed");
+ }
+ label.nextElementSibling.innerHTML = file;
+ };
+}
+
+// mac address hexadecimal -> decimal
+function dec() {
+ let val = document.querySelectorAll("input[name='mac']");
+ val.forEach(function(elem){
+ let hex = elem.value;
+ let decimal = parseInt(hex,16);
+ elem.value = decimal;
+ });
+}
+
+function hex() {
+ let val = document.querySelectorAll("input[name='mac']");
+ val.forEach(function(elem){
+ let decimal = parseInt(elem.value);
+ let hex = decimal.toString(16).toUpperCase();
+ elem.value = hex;
+ });
+}
+
+window.onload = function () {
+ let elmbtn = document.getElementById('btn');
+ elmbtn.onclick = function () {
+ if (this.checked == true) {
+ hex();
+ } else {
+ dec();
+ }
+ }
+
+ let expbtn = document.getElementById('export');
+ expbtn.onclick = function () {
+ if (elmbtn.checked == true) {
+ elmbtn.checked = false;
+ dec();
+ }
+ }
+}
\ No newline at end of file
diff --git a/firmware-platformIO/STEP800_firmware/src/diagnosis.cpp b/firmware-platformIO/STEP800_firmware/src/diagnosis.cpp
index cc12e82..d4b4f73 100644
--- a/firmware-platformIO/STEP800_firmware/src/diagnosis.cpp
+++ b/firmware-platformIO/STEP800_firmware/src/diagnosis.cpp
@@ -283,6 +283,7 @@ void printConfigurations() {
printAllData(F("dec"), dec);
printAllData(F("maxSpeed"), maxSpeed);
printAllData(F("fullStepSpeed"), fullStepSpeed);
+ printAllData("minSpeed", minSpeed);
printHeader(F("Voltage mode"));
printAllData(F("kvalHold"), kvalHold);
@@ -294,7 +295,8 @@ void printConfigurations() {
printAllData(F("accFinalSlope"), accFinalSlope);
printAllData(F("decFinalSlope"), decFinalSlope);
printAllData(F("stallThreshold"), stallThreshold);
- printAllData(F("lowSpeedOptimize"), lowSpeedOptimize);
+ showAllBools("lowSpeedOptimizeEnable", lowSpeedOptimizeEnable);
+ printAllData("lowSpeedOptimizeThreshold", lowSpeedOptimizeThreshold);
printHeader(F("Servo mode"));
printAllData(F("kP"), kP);
diff --git a/firmware-platformIO/STEP800_firmware/src/globals.cpp b/firmware-platformIO/STEP800_firmware/src/globals.cpp
index 9d59fe9..3a8dc26 100644
--- a/firmware-platformIO/STEP800_firmware/src/globals.cpp
+++ b/firmware-platformIO/STEP800_firmware/src/globals.cpp
@@ -119,7 +119,8 @@ uint8_t
microStepMode[NUM_OF_MOTOR]; // STEP_MODE
uint16_t slewRate[NUM_OF_MOTOR]; // GATECFG1
uint8_t slewRateNum[NUM_OF_MOTOR]; // [0]114, [1]220, [2]400, [3]520, [4]790, [5]980.
-float lowSpeedOptimize[NUM_OF_MOTOR];
+bool lowSpeedOptimizeEnable[NUM_OF_MOTOR];
+float lowSpeedOptimizeThreshold[NUM_OF_MOTOR];
bool electromagnetBrakeEnable[NUM_OF_MOTOR];
uint16_t brakeTransitionDuration[NUM_OF_MOTOR];
@@ -127,6 +128,7 @@ float
acc[NUM_OF_MOTOR],
dec[NUM_OF_MOTOR],
maxSpeed[NUM_OF_MOTOR],
+ minSpeed[NUM_OF_MOTOR],
fullStepSpeed[NUM_OF_MOTOR];
// Servo mode
diff --git a/firmware-platformIO/STEP800_firmware/src/globals.h b/firmware-platformIO/STEP800_firmware/src/globals.h
index 9853524..12c6fa2 100644
--- a/firmware-platformIO/STEP800_firmware/src/globals.h
+++ b/firmware-platformIO/STEP800_firmware/src/globals.h
@@ -255,13 +255,15 @@ extern uint8_t
microStepMode[NUM_OF_MOTOR]; // STEP_MODE
extern uint16_t slewRate[NUM_OF_MOTOR]; // GATECFG1
extern uint8_t slewRateNum[NUM_OF_MOTOR]; // [0]114, [1]220, [2]400, [3]520, [4]790, [5]980.
-extern float lowSpeedOptimize[NUM_OF_MOTOR];
+extern float lowSpeedOptimizeThreshold[NUM_OF_MOTOR];
+extern bool lowSpeedOptimizeEnable[NUM_OF_MOTOR];
extern bool electromagnetBrakeEnable[NUM_OF_MOTOR];
extern uint16_t brakeTransitionDuration[NUM_OF_MOTOR];
extern float
acc[NUM_OF_MOTOR],
dec[NUM_OF_MOTOR],
maxSpeed[NUM_OF_MOTOR],
+ minSpeed[NUM_OF_MOTOR],
fullStepSpeed[NUM_OF_MOTOR];
// Servo mode
diff --git a/firmware-platformIO/STEP800_firmware/src/loadConfig.cpp b/firmware-platformIO/STEP800_firmware/src/loadConfig.cpp
index e4e3458..aac5054 100644
--- a/firmware-platformIO/STEP800_firmware/src/loadConfig.cpp
+++ b/firmware-platformIO/STEP800_firmware/src/loadConfig.cpp
@@ -147,11 +147,13 @@ void loadConfig() {
JsonArray speedProfile_dec = speedProfile["dec"];
JsonArray speedProfile_maxSpeed = speedProfile["maxSpeed"];
JsonArray speedProfile_fullStepSpeed = speedProfile["fullStepSpeed"];
+ JsonArray speedProfile_minSpeed = speedProfile["minSpeed"];
for (i = 0; i < NUM_OF_MOTOR; i++) {
acc[i] = speedProfile_acc[i] | 1000.;
dec[i] = speedProfile_dec[i] | 1000.;
maxSpeed[i] = speedProfile_maxSpeed[i] | 650.;
fullStepSpeed[i] = speedProfile_fullStepSpeed[i] | 15610.;
+ minSpeed[i] = speedProfile_minSpeed[i] | 0.;
}
// Voltage mode
@@ -165,6 +167,7 @@ void loadConfig() {
JsonArray voltageMode_FN_SLP_ACC = voltageMode["FN_SLP_ACC"];
JsonArray voltageMode_FN_SLP_DEC = voltageMode["FN_SLP_DEC"];
JsonArray voltageMode_STALL_TH = voltageMode["STALL_TH"];
+ JsonArray voltageMode_lowSpeedOptimizeEnable = voltageMode["lowSpeedOptimizeEnable"];
JsonArray voltageMode_lowSpeedOptimize = voltageMode["lowSpeedOptimize"];
for (i = 0; i < NUM_OF_MOTOR; i++) {
kvalHold[i] = voltageMode_KVAL_HOLD[i] | 0;
@@ -177,7 +180,8 @@ void loadConfig() {
decFinalSlope[i] = voltageMode_FN_SLP_DEC[i] | 0x29;
// stallThreshold[i] = voltageMode_STALL_TH[i] | 0x1F;
stallThreshold[i] = voltageMode_STALL_TH[i] | 0x7F;
- lowSpeedOptimize[i] = voltageMode_lowSpeedOptimize[i] | 20.;
+ lowSpeedOptimizeEnable[i] = voltageMode_lowSpeedOptimizeEnable[i] | false;
+ lowSpeedOptimizeThreshold[i] = voltageMode_lowSpeedOptimize[i] | 20.;
}
// Current mode
diff --git a/firmware-platformIO/STEP800_firmware/src/main.cpp b/firmware-platformIO/STEP800_firmware/src/main.cpp
index 2b44baa..4b32af8 100644
--- a/firmware-platformIO/STEP800_firmware/src/main.cpp
+++ b/firmware-platformIO/STEP800_firmware/src/main.cpp
@@ -33,8 +33,8 @@ const char *firmwareName = "STEP800_PROTO_BLACK";
#else
const char *firmwareName = "STEP800_R1";
#endif
-const uint8_t firmwareVersion[3] = {1,0,0};
-const uint8_t applicableConfigVersion[2] = {1,0};
+const uint8_t firmwareVersion[3] = {1,0,1};
+const uint8_t applicableConfigVersion[2] = {1,1};
// L6470vh
#ifdef PROTOTYPE_BLACK
@@ -357,7 +357,7 @@ void updateServo(uint32_t currentTimeMicros) {
integral[i] += ((error + eZ1[i]) / 2.0f);
if (integral[i] > 1500.0f) integral[i] = 1500.0f;
else if (integral[i] < -1500.0f) integral[i] = -1500.0f;
- if (abs(error) > position_tolerance) {
+ if (fabsf(error) > position_tolerance) {
double diff = error - eZ1[i];
spd = error * kP[i] + integral[i] * kI[i] + diff * kD[i];
diff --git a/firmware-platformIO/STEP800_firmware/src/oscListeners.cpp b/firmware-platformIO/STEP800_firmware/src/oscListeners.cpp
index 1e2ff6d..7fa644a 100644
--- a/firmware-platformIO/STEP800_firmware/src/oscListeners.cpp
+++ b/firmware-platformIO/STEP800_firmware/src/oscListeners.cpp
@@ -52,6 +52,7 @@ void OSCMsgReceive() {
// speed
bMsgRouted |= msgIN.route("/setSpeedProfile", setSpeedProfile);
bMsgRouted |= msgIN.route("/setMaxSpeed", setMaxSpeed);
+ bMsgRouted |= msgIN.route("/setMinSpeed", setMinSpeed);
bMsgRouted |= msgIN.route("/setFullstepSpeed", setFullstepSpeed);
bMsgRouted |= msgIN.route("/getFullstepSpeed", getFullstepSpeed);
bMsgRouted |= msgIN.route("/setAcc", setAcc);
@@ -116,6 +117,7 @@ void OSCMsgReceive() {
bMsgRouted |= msgIN.route("/getStallThreshold", getStallThreshold);
bMsgRouted |= msgIN.route("/setOverCurrentThreshold", setOverCurrentThreshold);
bMsgRouted |= msgIN.route("/getOverCurrentThreshold", getOverCurrentThreshold);
+ bMsgRouted |= msgIN.route("/enableLowSpeedOptimize", enableLowSpeedOptimize);
bMsgRouted |= msgIN.route("/setLowSpeedOptimizeThreshold", setLowSpeedOptimizeThreshold);
bMsgRouted |= msgIN.route("/getLowSpeedOptimizeThreshold", getLowSpeedOptimizeThreshold);
@@ -732,16 +734,18 @@ void getOverCurrentThreshold(OSCMessage& msg, int addrOffset) {
void setLowSpeedOptimizeThreshold(OSCMessage& msg, int addrOffset) {
uint8_t motorID = getInt(msg, 0);
- float _minSpeed = getFloat(msg,1);
+ float _lowSpdOptThreshold = getFloat(msg,1);
if(isCorrectMotorId(motorID)) {
motorID -= MOTOR_ID_FIRST;
- stepper[motorID].setMinSpeed(_minSpeed);
- lowSpeedOptimize[motorID] = _minSpeed;
+ lowSpeedOptimizeThreshold[motorID] = _lowSpdOptThreshold;
+ if (lowSpeedOptimizeEnable[motorID])
+ stepper[motorID].setMinSpeed(_lowSpdOptThreshold);
}
else if (motorID == MOTOR_ID_ALL) {
for (uint8_t i = 0; i < NUM_OF_MOTOR; i++) {
- stepper[i].setMinSpeed(_minSpeed);
- lowSpeedOptimize[i] = _minSpeed;
+ lowSpeedOptimizeThreshold[i] = _lowSpdOptThreshold;
+ if (lowSpeedOptimizeEnable[i])
+ stepper[i].setMinSpeed(_lowSpdOptThreshold);
}
}
}
@@ -762,7 +766,7 @@ void getLowSpeedOptimizeThreshold(uint8_t motorId) {
bool optimizationEnabled = (stepper[motorId].getParam(MIN_SPEED) & (1 << 12)) > 0;
OSCMessage newMes("/lowSpeedOptimizeThreshold");
newMes.add((int32_t)motorId + MOTOR_ID_FIRST);
- newMes.add(stepper[motorId].getMinSpeed());
+ newMes.add(lowSpeedOptimizeEnable[motorId]);
newMes.add(optimizationEnabled);
Udp.beginPacket(destIp, outPort);
newMes.send(Udp);
@@ -771,6 +775,32 @@ void getLowSpeedOptimizeThreshold(uint8_t motorId) {
turnOnTXL();
}
+void enableLowSpeedOptimize(OSCMessage& msg, int addrOffset) {
+ uint8_t motorID = getInt(msg, 0);
+ bool state = getBool(msg, 1);
+ if(isCorrectMotorId(motorID)) {
+ motorID -= MOTOR_ID_FIRST;
+ stepper[motorID].setLoSpdOpt(state);
+ lowSpeedOptimizeEnable[motorID] = state;
+ if (state) {
+ stepper[motorID].setMinSpeed(lowSpeedOptimizeThreshold[motorID]);
+ } else {
+ stepper[motorID].setMinSpeed(minSpeed[motorID]);
+ }
+ }
+ else if (motorID == MOTOR_ID_ALL) {
+ for (uint8_t i = 0; i < NUM_OF_MOTOR; i++) {
+ stepper[i].setLoSpdOpt(state);
+ lowSpeedOptimizeEnable[i] = state;
+ if (state) {
+ stepper[i].setMinSpeed(lowSpeedOptimizeThreshold[i]);
+ } else {
+ stepper[i].setMinSpeed(minSpeed[i]);
+ }
+ }
+ }
+}
+
void setBemfParam(OSCMessage& msg, int addrOffset) {
uint8_t motorID = getInt(msg, 0);
uint16_t intSpeed = constrain(getInt(msg, 1), 0, 0x3FFF);
@@ -1429,7 +1459,26 @@ void setMaxSpeed(OSCMessage& msg, int addrOffset) {
}
}
}
-// MIN_SPEED register is set by setLowSpeedOptimizeThreshold function.
+
+void setMinSpeed(OSCMessage& msg, int addrOffset) {
+ uint8_t motorID = getInt(msg, 0);
+ float _minSpeed = getFloat(msg, 1);
+ if(isCorrectMotorId(motorID)) {
+ motorID -= MOTOR_ID_FIRST;
+ minSpeed[motorID] = _minSpeed;
+ if (!lowSpeedOptimizeEnable[motorID]) {
+ stepper[motorID].setMinSpeed(_minSpeed);
+ }
+ }
+ else if (motorID == MOTOR_ID_ALL) {
+ for (uint8_t i = 0; i < NUM_OF_MOTOR; i++) {
+ minSpeed[i] = _minSpeed;
+ if (!lowSpeedOptimizeEnable[motorID]) {
+ stepper[i].setMinSpeed(_minSpeed);
+ }
+ }
+ }
+}
void setFullstepSpeed(OSCMessage& msg, int addrOffset) {
uint8_t motorID = getInt(msg, 0);
diff --git a/firmware-platformIO/STEP800_firmware/src/oscListeners.h b/firmware-platformIO/STEP800_firmware/src/oscListeners.h
index bab861a..d033a54 100644
--- a/firmware-platformIO/STEP800_firmware/src/oscListeners.h
+++ b/firmware-platformIO/STEP800_firmware/src/oscListeners.h
@@ -72,6 +72,7 @@ void getOverCurrentThreshold(OSCMessage& msg, int addrOffset);
void setLowSpeedOptimizeThreshold(OSCMessage& msg, int addrOffset);
void getLowSpeedOptimizeThreshold(OSCMessage& msg, int addrOffset);
void getLowSpeedOptimizeThreshold(uint8_t motorId);
+void enableLowSpeedOptimize(OSCMessage& msg, int addrOffset);
void setBemfParam(OSCMessage& msg, int addrOffset);
void getBemfParam(OSCMessage& msg, int addrOffset);
void getBemfParam(uint8_t motorId);
@@ -119,6 +120,8 @@ void getKval(uint8_t motorId);
// speed_commands_osc_listener
void setSpeedProfile(OSCMessage& msg, int addrOffset);
void setMaxSpeed(OSCMessage& msg, int addrOffset);
+void setMinSpeed(OSCMessage& msg, int addrOffset);
+void getMinSpeed(OSCMessage& msg, int addrOffset);
void setFullstepSpeed(OSCMessage& msg, int addrOffset);
void getFullstepSpeed(OSCMessage& msg, int addrOffset);
void setAcc(OSCMessage& msg, int addrOffset);
diff --git a/firmware-platformIO/STEP800_firmware/src/utils.cpp b/firmware-platformIO/STEP800_firmware/src/utils.cpp
index e65402f..c2ef366 100644
--- a/firmware-platformIO/STEP800_firmware/src/utils.cpp
+++ b/firmware-platformIO/STEP800_firmware/src/utils.cpp
@@ -75,8 +75,12 @@ void resetMotorDriver(uint8_t deviceID) {
stepper[deviceID].resetDev();
stepper[deviceID].configStepMode(microStepMode[deviceID]);
stepper[deviceID].setMaxSpeed(maxSpeed[deviceID]);
- stepper[deviceID].setLoSpdOpt(true);
- stepper[deviceID].setMinSpeed(lowSpeedOptimize[deviceID]); // Low speed optimization threshold
+ stepper[deviceID].setLoSpdOpt(lowSpeedOptimizeEnable[deviceID]);
+ if (lowSpeedOptimizeEnable[deviceID]) {
+ stepper[deviceID].setMinSpeed(lowSpeedOptimizeThreshold[deviceID]); // Low speed optimization threshold
+ } else {
+ stepper[deviceID].setMinSpeed(minSpeed[deviceID]);
+ }
stepper[deviceID].setFullSpeed(fullStepSpeed[deviceID]);
stepper[deviceID].setAcc(acc[deviceID]);
stepper[deviceID].setDec(dec[deviceID]);