Fix design on standard view (#3)
* Move notes above the fields * Adding documentation * Add documentation * Fix design issue on standard view
This commit is contained in:
committed by
GitHub
parent
1401aa8252
commit
a2751b96d6
@@ -1,6 +1,23 @@
|
||||
# OctoPrint-CalibrationTools
|
||||
|
||||
**TODO:** Describe what your plugin does.
|
||||
A set of tools to help users with calibration process.
|
||||
Supported tunings:
|
||||
|
||||
- E Steps - calibrating number of steps/mm for E extruder;
|
||||
- XYZ Steps - calibrating number of steps/mm for axes X, Y and Z;
|
||||
- PID Auto-tune - calibration Proportional gain, Integral gain and Derivative values for hot-end and heated bed;
|
||||
|
||||
Before start using this plugin I strongly recommend reading some documentation about tunning [teachingtechyt.github.io](https://teachingtechyt.github.io/calibration.html)
|
||||
|
||||
## Supported frameworks
|
||||
|
||||
- Marlin 2.x
|
||||
|
||||
## Screens
|
||||
|
||||

|
||||

|
||||

|
||||
|
||||
## Setup
|
||||
|
||||
@@ -9,9 +26,6 @@ or manually using this URL:
|
||||
|
||||
https://github.com/SergiuToporjinschi/OctoPrint-CalibrationTools/archive/master.zip
|
||||
|
||||
**TODO:** Describe how to install your plugin, if more needs to be done than just installing it via pip or through
|
||||
the plugin manager.
|
||||
|
||||
## Configuration
|
||||
|
||||
**TODO:** Describe your plugin's configuration options (if any).
|
||||
You can set the default values for each tuning process.
|
||||
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 34 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 20 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 26 KiB |
@@ -6,6 +6,14 @@ $(function () {
|
||||
self.controlViewModel = parameters[2];
|
||||
self.terminalViewModel = parameters[3];
|
||||
self.access = parameters[4];
|
||||
self.generalVM = parameters[5];
|
||||
|
||||
self.columnLabelCls = ko.computed(function () {
|
||||
return self.generalVM.isSmall() ? "span4" : "span3";
|
||||
});
|
||||
self.columnFieldCls = ko.computed(function () {
|
||||
return self.generalVM.isSmall() ? "span8" : "span9";
|
||||
});
|
||||
|
||||
self.is_admin = ko.observable(false);
|
||||
self.steps = ko.observable();
|
||||
@@ -69,7 +77,6 @@ $(function () {
|
||||
text: "<span style='font-weight:bold; color: red;'>Heating nuzzle has started!!!</span><br> When extrusion stops you have to fulfil <b>Length after extrusion</b> and save the new value ",
|
||||
type: "warning"
|
||||
});
|
||||
console.log(response);
|
||||
}).fail(function (response) {
|
||||
new PNotify({
|
||||
title: "Error on starting extrusion ",
|
||||
@@ -109,7 +116,7 @@ $(function () {
|
||||
// This is a list of dependencies to inject into the plugin, the order which you request
|
||||
// here is the order in which the dependencies will be injected into your view model upon
|
||||
// instantiation via the parameters argument
|
||||
dependencies: ["loginStateViewModel", "settingsViewModel", "controlViewModel", "terminalViewModel", "accessViewModel"],
|
||||
dependencies: ["loginStateViewModel", "settingsViewModel", "controlViewModel", "terminalViewModel", "accessViewModel", "calibrationToolsGeneralViewModel"],
|
||||
// Finally, this is the list of selectors for all elements we want this view model to be bound to.
|
||||
elements: ["#calibration_eSteps"]
|
||||
});
|
||||
|
||||
@@ -9,6 +9,7 @@ $(function () {
|
||||
}
|
||||
}
|
||||
}
|
||||
this.isSmall = ko.observable($("#tab_plugin_CalibrationTools").width() < 800);
|
||||
ko.extenders.numeric = function (target, options) {
|
||||
var returnObs = ko.pureComputed({
|
||||
read: target,
|
||||
@@ -22,8 +23,11 @@ $(function () {
|
||||
returnObs(target());
|
||||
return returnObs;
|
||||
};
|
||||
|
||||
this.onStartupComplete = function () {
|
||||
this.isSmall($("#tabs_content").width() < 800);
|
||||
}
|
||||
}
|
||||
// OCTOPRINT_VIEWMODELS.push([GeneralViewModel, ["loginStateViewModel"], []]);
|
||||
OCTOPRINT_VIEWMODELS.push({
|
||||
// This is the constructor to call for instantiating the plugin
|
||||
construct: CalibrationToolsGeneralViewModel,
|
||||
|
||||
@@ -4,7 +4,13 @@ $(function () {
|
||||
self.loginStateViewModel = parameters[0];
|
||||
self.settingsViewModel = parameters[1];
|
||||
self.controlViewModel = parameters[2];
|
||||
|
||||
self.generalVM = parameters[5];
|
||||
self.columnLabelCls = ko.computed(function () {
|
||||
return self.generalVM.isSmall() ? "span3" : "span3";
|
||||
});
|
||||
self.columnFieldCls = ko.computed(function () {
|
||||
return self.generalVM.isSmall() ? "span9" : "span9";
|
||||
});
|
||||
self.pidCurrentValues = {
|
||||
"hotEnd": {
|
||||
"P": ko.observable(0),
|
||||
@@ -79,7 +85,6 @@ $(function () {
|
||||
text: "In progress",
|
||||
type: "info"
|
||||
});
|
||||
console.log(response);
|
||||
}).fail(function (response) {
|
||||
new PNotify({
|
||||
title: "Error on starting PID autotune ",
|
||||
@@ -102,7 +107,6 @@ $(function () {
|
||||
text: "In progress",
|
||||
type: "info"
|
||||
});
|
||||
console.log(response);
|
||||
}).fail(function (response) {
|
||||
new PNotify({
|
||||
title: "Error on starting PID autotune ",
|
||||
@@ -119,7 +123,7 @@ $(function () {
|
||||
// This is a list of dependencies to inject into the plugin, the order which you request
|
||||
// here is the order in which the dependencies will be injected into your view model upon
|
||||
// instantiation via the parameters argument
|
||||
dependencies: ["loginStateViewModel", "settingsViewModel", "controlViewModel", "terminalViewModel", "accessViewModel"],
|
||||
dependencies: ["loginStateViewModel", "settingsViewModel", "controlViewModel", "terminalViewModel", "accessViewModel", "calibrationToolsGeneralViewModel"],
|
||||
// Finally, this is the list of selectors for all elements we want this view model to be bound to.
|
||||
elements: ["#calibration_pid"]
|
||||
});
|
||||
|
||||
@@ -4,28 +4,33 @@ $(function () {
|
||||
self.loginStateViewModel = parameters[0];
|
||||
self.settingsViewModel = parameters[1];
|
||||
self.controlViewModel = parameters[2];
|
||||
generalVM = parameters[5];
|
||||
|
||||
self.generalVM = parameters[5];
|
||||
self.columnLabelCls = ko.computed(function () {
|
||||
return self.generalVM.isSmall() ? "span2" : "span3";
|
||||
});
|
||||
self.columnFieldCls = ko.computed(function () {
|
||||
return self.generalVM.isSmall() ? "span10" : "span9";
|
||||
});
|
||||
self.eStepsXYZ = {
|
||||
currentSteps: {
|
||||
X: ko.observable(0).extend(generalVM.decimal3(0.000)),
|
||||
Y: ko.observable(0).extend(generalVM.decimal3(0.000)),
|
||||
Z: ko.observable(0).extend(generalVM.decimal3(0.000))
|
||||
X: ko.observable(0).extend(self.generalVM.decimal3(0.000)),
|
||||
Y: ko.observable(0).extend(self.generalVM.decimal3(0.000)),
|
||||
Z: ko.observable(0).extend(self.generalVM.decimal3(0.000))
|
||||
},
|
||||
gCodeCubeSize: {
|
||||
X: ko.observable().extend(generalVM.decimal3(22.000)),
|
||||
Y: ko.observable().extend(generalVM.decimal3(22.000)),
|
||||
Z: ko.observable().extend(generalVM.decimal3(22.000))
|
||||
X: ko.observable().extend(self.generalVM.decimal3(22.000)),
|
||||
Y: ko.observable().extend(self.generalVM.decimal3(22.000)),
|
||||
Z: ko.observable().extend(self.generalVM.decimal3(22.000))
|
||||
},
|
||||
printedCubeSize: {
|
||||
X: ko.observable().extend(generalVM.decimal3(25.000)),
|
||||
Y: ko.observable().extend(generalVM.decimal3(25.000)),
|
||||
Z: ko.observable().extend(generalVM.decimal3(25.000))
|
||||
X: ko.observable().extend(self.generalVM.decimal3(25.000)),
|
||||
Y: ko.observable().extend(self.generalVM.decimal3(25.000)),
|
||||
Z: ko.observable().extend(self.generalVM.decimal3(25.000))
|
||||
},
|
||||
newSteps: {
|
||||
X: ko.observable().extend(generalVM.decimal3(0.000)),
|
||||
Y: ko.observable().extend(generalVM.decimal3(0.000)),
|
||||
Z: ko.observable().extend(generalVM.decimal3(0.000))
|
||||
X: ko.observable().extend(self.generalVM.decimal3(0.000)),
|
||||
Y: ko.observable().extend(self.generalVM.decimal3(0.000)),
|
||||
Z: ko.observable().extend(self.generalVM.decimal3(0.000))
|
||||
}
|
||||
};
|
||||
|
||||
@@ -69,7 +74,9 @@ $(function () {
|
||||
})
|
||||
};
|
||||
|
||||
|
||||
// self.labelColumnCss = viewModel.profitStatus = ko.pureComputed(function () {
|
||||
// return "span3" $("#tab_plugin_CalibrationTools").width() < 800
|
||||
// });
|
||||
|
||||
self.isAdmin = ko.observable(false);
|
||||
|
||||
|
||||
@@ -1,694 +0,0 @@
|
||||
$(function () {
|
||||
function AccessViewModel(parameters) {
|
||||
var access = this;
|
||||
access.loginState = parameters[0];
|
||||
var GROUP_ADMINS = "admins";
|
||||
var GROUP_GUESTS = "guests";
|
||||
access.users = (function () {
|
||||
var self = {};
|
||||
self.listHelper = new ItemListHelper("users", {
|
||||
name: function (a, b) {
|
||||
if (a["name"].toLocaleLowerCase() < b["name"].toLocaleLowerCase())
|
||||
return -1;
|
||||
if (a["name"].toLocaleLowerCase() > b["name"].toLocaleLowerCase())
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
}, {}, "name", [], [], CONFIG_USERSPERPAGE);
|
||||
self.emptyUser = {
|
||||
name: "",
|
||||
active: false
|
||||
};
|
||||
self.currentUser = ko.observable(self.emptyUser).extend({
|
||||
notify: "always"
|
||||
});
|
||||
self.editor = {
|
||||
name: ko.observable(undefined),
|
||||
groups: ko.observableArray([]),
|
||||
permissions: ko.observableArray([]),
|
||||
password: ko.observable(undefined),
|
||||
repeatedPassword: ko.observable(undefined),
|
||||
passwordMismatch: ko.pureComputed(function () {
|
||||
return self.editor.password() !== self.editor.repeatedPassword();
|
||||
}),
|
||||
apikey: ko.observable(undefined),
|
||||
active: ko.observable(undefined),
|
||||
permissionSelectable: function (permission) {
|
||||
return true;
|
||||
},
|
||||
permissionSelected: function (permission) {
|
||||
var index = self.editor.permissions().indexOf(permission);
|
||||
return index >= 0;
|
||||
},
|
||||
togglePermission: function (permission) {
|
||||
var permissions = self.editor.permissions();
|
||||
var index = permissions.indexOf(permission);
|
||||
if (index < 0) {
|
||||
permissions.push(permission);
|
||||
} else {
|
||||
permissions.splice(index, 1);
|
||||
}
|
||||
self.editor.permissions(permissions);
|
||||
},
|
||||
groupSelected: function (group) {
|
||||
var index = self.editor.groups().indexOf(group);
|
||||
return index >= 0;
|
||||
},
|
||||
toggleGroup: function (group) {
|
||||
var groups = self.editor.groups();
|
||||
var index = groups.indexOf(group);
|
||||
if (index < 0) {
|
||||
groups.push(group);
|
||||
} else {
|
||||
groups.splice(index, 1);
|
||||
}
|
||||
self.editor.groups(groups);
|
||||
},
|
||||
joinedGroupPermissions: function (group) {
|
||||
return access.permissionList(group);
|
||||
},
|
||||
header: ko.observable(undefined),
|
||||
new: ko.observable(true),
|
||||
confirm: undefined,
|
||||
valid: ko.pureComputed(function () {
|
||||
return (self.editor.name() && self.editor.name().trim() && (!self.editor.new() || (self.editor.password() && self.editor.password().trim() && !self.editor.passwordMismatch())));
|
||||
}),
|
||||
dangerRestricted: function () {
|
||||
return false;
|
||||
},
|
||||
dangerRestrictedText: gettext("This user may not have dangerous permissions.")
|
||||
};
|
||||
self.userEditorDialog = undefined;
|
||||
self.changePasswordDialog = undefined;
|
||||
self.currentUser.subscribe(function (newValue) {
|
||||
if (newValue === undefined) {
|
||||
self.editor.name(undefined);
|
||||
self.editor.groups(access.groups.defaults.slice(0));
|
||||
self.editor.permissions([]);
|
||||
self.editor.active(true);
|
||||
self.editor.apikey(undefined);
|
||||
self.editor.header(gettext("Add user"));
|
||||
self.editor.new(true);
|
||||
self.editor.confirm = self.confirmAddUser;
|
||||
} else {
|
||||
self.editor.name(newValue.name);
|
||||
self.editor.groups(newValue.groups.slice(0));
|
||||
self.editor.permissions(newValue.permissions.slice(0));
|
||||
self.editor.active(newValue.active);
|
||||
self.editor.apikey(newValue.apikey);
|
||||
self.editor.header(_.sprintf(gettext('Edit user "%(name)s"'), {
|
||||
name: newValue.name
|
||||
}));
|
||||
self.editor.new(false);
|
||||
self.editor.confirm = self.confirmEditUser;
|
||||
}
|
||||
self.editor.password(undefined);
|
||||
self.editor.repeatedPassword(undefined);
|
||||
});
|
||||
self.requestData = function () {
|
||||
if (!CONFIG_ACCESS_CONTROL)
|
||||
return;
|
||||
if (!access.loginState.hasPermissionKo(access.permissions.ADMIN))
|
||||
return;
|
||||
return OctoPrint.access.users.list().done(self.fromResponse);
|
||||
}
|
||||
;
|
||||
self.fromResponse = function (response) {
|
||||
self.listHelper.updateItems(response.users);
|
||||
}
|
||||
;
|
||||
self.showAddUserDialog = function () {
|
||||
if (!CONFIG_ACCESS_CONTROL)
|
||||
return;
|
||||
self.currentUser(undefined);
|
||||
$('ul.nav-pills a[data-toggle="tab"]:first', self.userEditorDialog).tab("show");
|
||||
self.userEditorDialog.modal({
|
||||
minHeight: function () {
|
||||
return Math.max($.fn.modal.defaults.maxHeight() - 80, 250);
|
||||
}
|
||||
}).css({
|
||||
"margin-left": function () {
|
||||
return -($(this).width() / 2);
|
||||
}
|
||||
});
|
||||
}
|
||||
;
|
||||
self.confirmAddUser = function () {
|
||||
if (!CONFIG_ACCESS_CONTROL)
|
||||
return;
|
||||
var user = {
|
||||
name: self.editor.name(),
|
||||
password: self.editor.password(),
|
||||
groups: self.editor.groups(),
|
||||
permissions: self.editor.permissions(),
|
||||
active: self.editor.active()
|
||||
};
|
||||
self.addUser(user).done(function () {
|
||||
self.currentUser(undefined);
|
||||
self.userEditorDialog.modal("hide");
|
||||
});
|
||||
}
|
||||
;
|
||||
self.showEditUserDialog = function (user) {
|
||||
if (!CONFIG_ACCESS_CONTROL)
|
||||
return;
|
||||
var process = function (user) {
|
||||
self.currentUser(user);
|
||||
$('ul.nav-pills a[data-toggle="tab"]:first', self.userEditorDialog).tab("show");
|
||||
self.userEditorDialog.modal({
|
||||
minHeight: function () {
|
||||
return Math.max($.fn.modal.defaults.maxHeight() - 80, 250);
|
||||
}
|
||||
}).css({
|
||||
"margin-left": function () {
|
||||
return -($(this).width() / 2);
|
||||
}
|
||||
});
|
||||
};
|
||||
OctoPrint.users.get(user.name).done(function (data) {
|
||||
process(data);
|
||||
}).fail(function () {
|
||||
log.warn("Could not fetch current user data, proceeding with client side data copy");
|
||||
process(user);
|
||||
});
|
||||
}
|
||||
;
|
||||
self.confirmEditUser = function () {
|
||||
if (!CONFIG_ACCESS_CONTROL)
|
||||
return;
|
||||
var user = self.currentUser();
|
||||
user.active = self.editor.active();
|
||||
user.groups = self.editor.groups();
|
||||
user.permissions = self.editor.permissions();
|
||||
self.updateUser(user).done(function () {
|
||||
self.currentUser(undefined);
|
||||
self.userEditorDialog.modal("hide");
|
||||
});
|
||||
}
|
||||
;
|
||||
self.showChangePasswordDialog = function (user) {
|
||||
if (!CONFIG_ACCESS_CONTROL)
|
||||
return;
|
||||
self.currentUser(user);
|
||||
self.changePasswordDialog.modal("show");
|
||||
}
|
||||
;
|
||||
self.confirmChangePassword = function () {
|
||||
if (!CONFIG_ACCESS_CONTROL)
|
||||
return;
|
||||
self.updatePassword(self.currentUser().name, self.editor.password()).done(function () {
|
||||
self.currentUser(undefined);
|
||||
self.changePasswordDialog.modal("hide");
|
||||
});
|
||||
}
|
||||
;
|
||||
self.confirmGenerateApikey = function () {
|
||||
if (!CONFIG_ACCESS_CONTROL)
|
||||
return;
|
||||
self.generateApikey(self.currentUser().name).done(function (response) {
|
||||
self._updateApikey(response.apikey);
|
||||
});
|
||||
}
|
||||
;
|
||||
self.copyApikey = function () {
|
||||
copyToClipboard(self.editor.apikey());
|
||||
}
|
||||
;
|
||||
self._updateApikey = function (apikey) {
|
||||
self.editor.apikey(apikey);
|
||||
self.requestData();
|
||||
}
|
||||
;
|
||||
self.confirmDeleteApikey = function () {
|
||||
if (!CONFIG_ACCESS_CONTROL)
|
||||
return;
|
||||
self.deleteApikey(self.currentUser().name).done(function () {
|
||||
self._updateApikey(undefined);
|
||||
});
|
||||
}
|
||||
;
|
||||
self.onStartup = function () {
|
||||
self.userEditorDialog = $("#settings-usersEditorDialog");
|
||||
self.changePasswordDialog = $("#settings-usersDialogChangePassword");
|
||||
}
|
||||
;
|
||||
self.addUser = function (user) {
|
||||
if (!user) {
|
||||
throw OctoPrint.InvalidArgumentError("user must be set");
|
||||
}
|
||||
if (!access.loginState.hasPermissionKo(access.permissions.ADMIN))
|
||||
return $.Deferred().reject("You are not authorized to perform this action").promise();
|
||||
return OctoPrint.access.users.add(user).done(self.fromResponse);
|
||||
}
|
||||
;
|
||||
self.removeUser = function (user) {
|
||||
if (!user) {
|
||||
throw OctoPrint.InvalidArgumentError("user must be set");
|
||||
}
|
||||
if (!access.loginState.hasPermissionKo(access.permissions.ADMIN))
|
||||
return $.Deferred().reject("You are not authorized to perform this action").promise();
|
||||
if (user.name === access.loginState.username()) {
|
||||
new PNotify({
|
||||
title: gettext("Not possible"),
|
||||
text: gettext("You may not delete your own account."),
|
||||
type: "error"
|
||||
});
|
||||
return $.Deferred().reject("You may not delete your own account").promise();
|
||||
}
|
||||
showConfirmationDialog({
|
||||
title: gettext("Are you sure?"),
|
||||
message: _.sprintf(gettext('You are about to delete the user "%(name)s".'), {
|
||||
name: user.name
|
||||
}),
|
||||
proceed: gettext("Delete"),
|
||||
onproceed: function () {
|
||||
OctoPrint.access.users.delete(user.name).done(self.fromResponse);
|
||||
}
|
||||
});
|
||||
}
|
||||
;
|
||||
self.updateUser = function (user) {
|
||||
if (!user) {
|
||||
throw OctoPrint.InvalidArgumentError("user must be set");
|
||||
}
|
||||
return OctoPrint.access.users.update(user.name, user.active, user.admin, user.permissions, user.groups).done(self.fromResponse);
|
||||
}
|
||||
;
|
||||
self.updatePassword = function (username, password) {
|
||||
return OctoPrint.access.users.changePassword(username, password);
|
||||
}
|
||||
;
|
||||
self.generateApikey = function (username) {
|
||||
return OctoPrint.access.users.generateApiKey(username).done(function () {
|
||||
self.requestData();
|
||||
});
|
||||
}
|
||||
;
|
||||
self.deleteApikey = function (username) {
|
||||
return OctoPrint.access.users.resetApiKey(username);
|
||||
}
|
||||
;
|
||||
return self;
|
||||
}
|
||||
)();
|
||||
access.groups = (function () {
|
||||
var self = {};
|
||||
self.listHelper = new ItemListHelper("groups", {
|
||||
name: function (a, b) {
|
||||
if (a["name"].toLocaleLowerCase() < b["name"].toLocaleLowerCase())
|
||||
return -1;
|
||||
if (a["name"].toLocaleLowerCase() > b["name"].toLocaleLowerCase())
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
}, {}, "name", [], [], CONFIG_GROUPSPERPAGE);
|
||||
self.groupsList = self.listHelper.items;
|
||||
self.lookup = {};
|
||||
self.defaults = [];
|
||||
self.emptyGroup = {
|
||||
name: ""
|
||||
};
|
||||
self.currentGroup = ko.observable(self.emptyGroup);
|
||||
self.editor = {
|
||||
key: ko.observable(undefined),
|
||||
name: ko.observable(undefined),
|
||||
description: ko.observable(undefined),
|
||||
permissions: ko.observableArray([]),
|
||||
subgroups: ko.observableArray([]),
|
||||
default: ko.observable(false),
|
||||
permissionSelectable: function (permission) {
|
||||
return self.editor.key() !== GROUP_GUESTS || !permission.dangerous;
|
||||
},
|
||||
permissionSelected: function (permission) {
|
||||
var index = self.editor.permissions().indexOf(permission);
|
||||
return index >= 0;
|
||||
},
|
||||
togglePermission: function (permission) {
|
||||
var permissions = self.editor.permissions();
|
||||
var index = permissions.indexOf(permission);
|
||||
if (index < 0) {
|
||||
permissions.push(permission);
|
||||
} else {
|
||||
permissions.splice(index, 1);
|
||||
}
|
||||
self.editor.permissions(permissions);
|
||||
},
|
||||
subgroupSelectable: function (subgroup) {
|
||||
return (self.editor.key() !== subgroup.key && (self.editor.key() !== GROUP_GUESTS || !subgroup.dangerous));
|
||||
},
|
||||
subgroupSelected: function (subgroup) {
|
||||
var index = self.editor.subgroups().indexOf(subgroup);
|
||||
return index >= 0;
|
||||
},
|
||||
toggleSubgroup: function (subgroup) {
|
||||
var subgroups = self.editor.subgroups();
|
||||
var index = subgroups.indexOf(subgroup);
|
||||
if (index < 0) {
|
||||
subgroups.push(subgroup);
|
||||
} else {
|
||||
subgroups.splice(index, 1);
|
||||
}
|
||||
self.editor.subgroups(subgroups);
|
||||
},
|
||||
joinedGroupPermissions: function (group) {
|
||||
return access.permissionList(group);
|
||||
},
|
||||
header: ko.observable(undefined),
|
||||
new: ko.observable(true),
|
||||
confirm: undefined,
|
||||
valid: ko.pureComputed(function () {
|
||||
return self.editor.name() && self.editor.name().trim();
|
||||
}),
|
||||
dangerRestricted: function () {
|
||||
return self.editor.key() === GROUP_GUESTS;
|
||||
},
|
||||
dangerRestrictedText: gettext("This group may not have dangerous permissions or subgroups.")
|
||||
};
|
||||
self.groupEditorDialog = undefined;
|
||||
self.groupsList.subscribe(function (oldValue) {
|
||||
if (oldValue === undefined || oldValue.length === 0)
|
||||
return;
|
||||
oldValue.forEach(function (p) {
|
||||
delete self[p.key.toUpperCase()];
|
||||
});
|
||||
}, null, "beforeChange");
|
||||
self.groupsList.subscribe(function (newValue) {
|
||||
if (newValue === undefined)
|
||||
return;
|
||||
newValue.forEach(function (g) {
|
||||
var needs = [];
|
||||
g.permissions.forEach(function (p) {
|
||||
for (var key in p.needs) {
|
||||
p.needs[key].forEach(function (value) {
|
||||
needs.push(access.permissions.need(key, value));
|
||||
});
|
||||
}
|
||||
});
|
||||
if (needs.length > 0) {
|
||||
self.registerGroup(g.key.toUpperCase(), needs);
|
||||
}
|
||||
});
|
||||
});
|
||||
self.registerGroup = function (name, group) {
|
||||
Object.defineProperty(self, name, {
|
||||
value: group,
|
||||
enumerable: true,
|
||||
configurable: true
|
||||
});
|
||||
}
|
||||
;
|
||||
self.currentGroup.subscribe(function (newValue) {
|
||||
if (newValue === undefined) {
|
||||
self.editor.key(undefined);
|
||||
self.editor.name(undefined);
|
||||
self.editor.description(undefined);
|
||||
self.editor.permissions([]);
|
||||
self.editor.subgroups([]);
|
||||
self.editor.default(false);
|
||||
self.editor.header(gettext("Add group"));
|
||||
self.editor.new(true);
|
||||
self.editor.confirm = self.confirmAddGroup;
|
||||
} else {
|
||||
self.editor.key(newValue.key);
|
||||
self.editor.name(newValue.name);
|
||||
self.editor.description(newValue.description);
|
||||
self.editor.permissions(newValue.permissions.slice(0));
|
||||
self.editor.subgroups(newValue.subgroups.slice(0));
|
||||
self.editor.default(newValue.default);
|
||||
self.editor.header(_.sprintf(gettext('Edit group "%(name)s"'), {
|
||||
name: newValue.name
|
||||
}));
|
||||
self.editor.new(false);
|
||||
self.editor.confirm = self.confirmEditGroup;
|
||||
}
|
||||
});
|
||||
self.requestData = function () {
|
||||
return OctoPrint.access.groups.list().done(self.fromResponse);
|
||||
}
|
||||
;
|
||||
self.fromResponse = function (response) {
|
||||
var lookup = {};
|
||||
var defaults = [];
|
||||
_.each(response.groups, function (group) {
|
||||
lookup[group.key] = group;
|
||||
if (group.default) {
|
||||
defaults.push(group.key);
|
||||
}
|
||||
});
|
||||
self.lookup = lookup;
|
||||
self.defaults = defaults;
|
||||
self.listHelper.updateItems(response.groups);
|
||||
}
|
||||
;
|
||||
self.showAddGroupDialog = function () {
|
||||
self.currentGroup(undefined);
|
||||
$('ul.nav-pills a[data-toggle="tab"]:first', self.groupEditorDialog).tab("show");
|
||||
self.groupEditorDialog.modal({
|
||||
minHeight: function () {
|
||||
return Math.max($.fn.modal.defaults.maxHeight() - 80, 250);
|
||||
}
|
||||
}).css({
|
||||
"margin-left": function () {
|
||||
return -($(this).width() / 2);
|
||||
}
|
||||
});
|
||||
}
|
||||
;
|
||||
self.confirmAddGroup = function () {
|
||||
var group = {
|
||||
key: self.editor.name().toLowerCase().replace(/[^a-z0-9_ ]/g, "").replace(/ /g, "_"),
|
||||
name: self.editor.name(),
|
||||
description: self.editor.description(),
|
||||
permissions: self.editor.permissions(),
|
||||
subgroups: self.editor.subgroups(),
|
||||
default: self.editor.default()
|
||||
};
|
||||
self.addGroup(group).done(function () {
|
||||
self.currentGroup(undefined);
|
||||
self.groupEditorDialog.modal("hide");
|
||||
});
|
||||
}
|
||||
;
|
||||
self.showEditGroupDialog = function (group) {
|
||||
if (!group.changeable)
|
||||
return;
|
||||
self.currentGroup(group);
|
||||
$('ul.nav-pills a[data-toggle="tab"]:first', self.groupEditorDialog).tab("show");
|
||||
self.groupEditorDialog.modal({
|
||||
minHeight: function () {
|
||||
return Math.max($.fn.modal.defaults.maxHeight() - 80, 250);
|
||||
}
|
||||
}).css({
|
||||
"margin-left": function () {
|
||||
return -($(this).width() / 2);
|
||||
}
|
||||
});
|
||||
}
|
||||
;
|
||||
self.confirmEditGroup = function () {
|
||||
var group = self.currentGroup();
|
||||
var data = {
|
||||
key: group.key,
|
||||
name: group.name,
|
||||
description: self.editor.description(),
|
||||
permissions: self.editor.permissions(),
|
||||
subgroups: self.editor.subgroups(),
|
||||
default: self.editor.default()
|
||||
};
|
||||
self.updateGroup(data).done(function () {
|
||||
self.currentGroup(undefined);
|
||||
self.groupEditorDialog.modal("hide");
|
||||
});
|
||||
}
|
||||
;
|
||||
self.onStartup = function () {
|
||||
self.groupEditorDialog = $("#settings-groupsEditorDialog");
|
||||
}
|
||||
;
|
||||
self.addGroup = function (group) {
|
||||
if (!group) {
|
||||
throw OctoPrint.InvalidArgumentError("group must be set");
|
||||
}
|
||||
return OctoPrint.access.groups.add(group).done(self.fromResponse);
|
||||
}
|
||||
;
|
||||
self.removeGroup = function (group) {
|
||||
if (!group) {
|
||||
throw OctoPrint.InvalidArgumentError("group must be set");
|
||||
}
|
||||
if (!group.removable)
|
||||
return;
|
||||
showConfirmationDialog({
|
||||
title: gettext("Are you sure?"),
|
||||
message: _.sprintf(gettext('You are about to delete the group "%(name)s".'), {
|
||||
name: group.name
|
||||
}),
|
||||
proceed: gettext("Delete"),
|
||||
onproceed: function () {
|
||||
OctoPrint.access.groups.delete(group.key).done(function (response) {
|
||||
self.fromResponse(response);
|
||||
access.users.requestData();
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
;
|
||||
self.updateGroup = function (group) {
|
||||
if (!group) {
|
||||
throw OctoPrint.InvalidArgumentError("group must be set");
|
||||
}
|
||||
return OctoPrint.access.groups.update(group).done(self.fromResponse);
|
||||
}
|
||||
;
|
||||
return self;
|
||||
}
|
||||
)();
|
||||
access.permissions = (function () {
|
||||
var self = {};
|
||||
self.need = function (method, value) {
|
||||
return {
|
||||
method: method,
|
||||
value: value
|
||||
};
|
||||
}
|
||||
;
|
||||
self.roleNeed = function (value) {
|
||||
return self.need("role", value);
|
||||
}
|
||||
;
|
||||
self.permissionList = ko.observableArray([]);
|
||||
self.lookup = {};
|
||||
var registeredPermissions = [];
|
||||
var registerPermission = function (key, permission) {
|
||||
Object.defineProperty(self, key, {
|
||||
value: permission,
|
||||
enumerable: true,
|
||||
configurable: true
|
||||
});
|
||||
registeredPermissions.push(key);
|
||||
};
|
||||
var clearAllRegisteredPermissions = function () {
|
||||
_.each(registeredPermissions, function (key) {
|
||||
delete self[key];
|
||||
});
|
||||
registeredPermissions = [];
|
||||
};
|
||||
self.initialize = function () {
|
||||
clearAllRegisteredPermissions();
|
||||
var permissionList = [];
|
||||
var lookup = {};
|
||||
_.each(PERMISSIONS, function (permission) {
|
||||
var needs = [];
|
||||
_.each(permission.needs, function (value, key) {
|
||||
needs.push(self.need(key, value));
|
||||
});
|
||||
if (needs.length > 0) {
|
||||
registerPermission(permission.key, needs);
|
||||
}
|
||||
if (!permission.combined) {
|
||||
permissionList.push(permission);
|
||||
}
|
||||
lookup[permission.key] = permission;
|
||||
});
|
||||
permissionList.sort(access.permissionComparator);
|
||||
self.permissionList(permissionList);
|
||||
self.lookup = lookup;
|
||||
}
|
||||
;
|
||||
return self;
|
||||
}
|
||||
)();
|
||||
access.groupComparator = function (a, b) {
|
||||
var nameA = a.name ? a.name.toUpperCase() : "";
|
||||
var nameB = b.name ? b.name.toUpperCase() : "";
|
||||
if (nameA < nameB) {
|
||||
return -1;
|
||||
} else if (nameA > nameB) {
|
||||
return 1;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
;
|
||||
access.permissionComparator = function (a, b) {
|
||||
var nameA = a.name ? a.name.toUpperCase() : "";
|
||||
var nameB = b.name ? b.name.toUpperCase() : "";
|
||||
var pluginA = a.plugin || "";
|
||||
var pluginB = b.plugin || "";
|
||||
var compA = pluginA + ":" + nameA;
|
||||
var compB = pluginB + ":" + nameB;
|
||||
if (compA < compB) {
|
||||
return -1;
|
||||
} else if (compA > compB) {
|
||||
return 1;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
;
|
||||
access.groupList = function (data) {
|
||||
if (data.groups === undefined)
|
||||
return "";
|
||||
var mappedGroups = _.filter(_.map(data.groups, function (g) {
|
||||
return access.groups.lookup[g];
|
||||
}), function (g) {
|
||||
return g !== undefined;
|
||||
});
|
||||
mappedGroups.sort(access.groupComparator);
|
||||
return _.map(mappedGroups, function (g) {
|
||||
return g.name;
|
||||
}).join(", ");
|
||||
}
|
||||
;
|
||||
access.subgroupList = function (data) {
|
||||
if (data.subgroups === undefined)
|
||||
return "";
|
||||
var mappedGroups = _.filter(_.map(data.subgroups, function (g) {
|
||||
return access.groups.lookup[g];
|
||||
}), function (g) {
|
||||
return g !== undefined;
|
||||
});
|
||||
mappedGroups.sort(access.groupComparator);
|
||||
return _.map(mappedGroups, function (g) {
|
||||
return g.name;
|
||||
}).join(", ");
|
||||
}
|
||||
;
|
||||
access.permissionList = function (data) {
|
||||
if (!data || data.permissions === undefined)
|
||||
return "";
|
||||
var mappedPermissions = _.filter(_.map(data.permissions, function (p) {
|
||||
return access.permissions.lookup[p];
|
||||
}), function (p) {
|
||||
return p !== undefined;
|
||||
});
|
||||
mappedPermissions.sort(access.permissionComparator);
|
||||
return _.map(mappedPermissions, function (p) {
|
||||
return p.name;
|
||||
}).join(", ");
|
||||
}
|
||||
;
|
||||
access.onStartup = function () {
|
||||
access.groups.onStartup();
|
||||
access.users.onStartup();
|
||||
}
|
||||
;
|
||||
access.onServerConnect = function () {
|
||||
access.permissions.initialize();
|
||||
}
|
||||
;
|
||||
access.onServerReconnect = function () {
|
||||
access.permissions.initialize();
|
||||
}
|
||||
;
|
||||
access.onUserPermissionsChanged = access.onUserLoggedIn = access.onUserLoggedOut = function (user) {
|
||||
if (access.loginState.hasPermission(access.permissions.SETTINGS)) {
|
||||
access.groups.requestData().done(function () {
|
||||
access.users.requestData();
|
||||
});
|
||||
}
|
||||
}
|
||||
;
|
||||
}
|
||||
OCTOPRINT_VIEWMODELS.push([AccessViewModel, ["loginStateViewModel"], []]);
|
||||
});
|
||||
@@ -24,7 +24,7 @@
|
||||
</div>
|
||||
</div>
|
||||
<div class="main row-fluid">
|
||||
<div class="span3">
|
||||
<div id="navigation" class="span3" data-bind="css: {span0: $root.generalVM.isSmall(), span3: !$root.generalVM.isSmall()}">
|
||||
<ul class="nav nav-list">
|
||||
<li class="active">
|
||||
<a data-toggle="tab" href="#calibration_documentation">Documentation</a>
|
||||
@@ -40,7 +40,7 @@
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="span9">
|
||||
<div id="calibrationTool_content" class="span9">
|
||||
{% include "tabs/tab-content.jinja2" %}
|
||||
</div>
|
||||
</div>
|
||||
@@ -49,12 +49,17 @@
|
||||
{% block script%}
|
||||
<script type="text/javascript">
|
||||
OCTOPRINT_VIEWMODELS.push({
|
||||
construct: function () {
|
||||
this.restart = function () { OctoPrint.system.executeCommand('core', 'restart') };
|
||||
|
||||
this.test = function () {
|
||||
construct: function (parameters) {
|
||||
self = this;
|
||||
self.generalVM = parameters[0];
|
||||
self.restart = function () { OctoPrint.system.executeCommand('core', 'restart') };
|
||||
self.test = function () {
|
||||
OctoPrint.simpleApiCommand("CalibrationTools", "pid_save").done(function (response) {
|
||||
console.log(response)
|
||||
new PNotify({
|
||||
title: "Saved",
|
||||
text: "PID values successfully saved",
|
||||
type: "info"
|
||||
});
|
||||
}).fail(function (response) {
|
||||
new PNotify({
|
||||
title: "Test request",
|
||||
@@ -64,14 +69,21 @@
|
||||
});
|
||||
};
|
||||
|
||||
this.onSettingsClick = function () {
|
||||
self.onSettingsClick = function () {
|
||||
$('a#navbar_show_settings').click();
|
||||
$('li#settings_plugin_CalibrationTools_link a').click();
|
||||
$("#settings_plugin_CalibrationTools").click();
|
||||
};
|
||||
self.onStartupComplete = function () {
|
||||
if (self.generalVM.isSmall()) {
|
||||
$("#calibrationTool_content").removeClass("span9");
|
||||
$("#calibrationTool_content").addClass("span12");
|
||||
}
|
||||
}
|
||||
},
|
||||
// dependencies: ["terminalViewModel"],
|
||||
elements: ["#toolBar"]
|
||||
elements: ["#toolBar", "#navigation"],
|
||||
dependencies: ["calibrationToolsGeneralViewModel"],
|
||||
});
|
||||
</script>
|
||||
{% endblock %}
|
||||
@@ -26,12 +26,12 @@
|
||||
{% set max = max|default("") %}
|
||||
{% set unit = unit|trim|default("") %}
|
||||
<div class="row-fluid">
|
||||
<div class="span6">
|
||||
<div data-bind="class: $root.columnLabelCls()">
|
||||
<label for="{{ label }}" class="pull-right" style="margin-top: 5px;" title="{{ title }}">
|
||||
{{ _(label) }}
|
||||
</label>
|
||||
</div>
|
||||
<div class="span6">
|
||||
<div data-bind="class: $root.columnFieldCls()">
|
||||
<div class="input-append">
|
||||
<input type="{{ type }}" id="{{ label }}" title="{{ title }}" class="input-small" step="{{ step }}" min="{{ min }}" max="{{ max }}" data-bind="value: {{ binding }}, enable: {{ enable }}">
|
||||
{% if unit != "" %}
|
||||
@@ -49,12 +49,12 @@
|
||||
{% set max = max|default("") %}
|
||||
{% set unit = unit|trim|default("") %}
|
||||
<div class="row-fluid">
|
||||
<div class="span6">
|
||||
<div data-bind="class: $root.columnLabelCls()">
|
||||
<label for="{{ label }}" class="pull-right" style="margin-top: 5px;" title="{{ title }}">
|
||||
{{ _(label) }}
|
||||
</label>
|
||||
</div>
|
||||
<div class="span6">
|
||||
<div data-bind="class: $root.columnFieldCls()">
|
||||
<div class="input-append input-prepend">
|
||||
<span class="add-on" title="{{ title }}">{{ _(label) }}</span>
|
||||
<input type="{{ type }}" id="{{ label }}" title="{{ title }}" class="input-small" step="{{ step }}" min="{{ min }}" max="{{ max }}" data-bind="value: {{ binding }}, enable: {{ enable }}">
|
||||
|
||||
@@ -1,3 +1,38 @@
|
||||
{% import "macros.jinja2" as snipped %}
|
||||
|
||||
{{ snipped.quote("For using this plugin, I strongly recommending you to read <a href='https://teachingtechyt.github.io/calibration.html#pid' target='_blank'>teachingtechyt.github.io</a>","", "text-warning") }}
|
||||
{{ snipped.quote("Before starting I strongly recommend reading some documentation about tunning <a href='https://teachingtechyt.github.io/calibration.html#intro' target='_blank'>teachingtechyt.github.io</a>","",
|
||||
"text-warning") }}
|
||||
The stepper motors divides a full rotation in a number of equal steps.
|
||||
E-Steps tuning is a process of setting the exact number of steps need it for pushing a fix amount of filament for feeding the hot-end.<br>
|
||||
|
||||
{{ snipped.subSection("E-Steps") }}
|
||||
You will have to:
|
||||
<lu>
|
||||
<li>Mark a specific length of filament at the extruder motor entrance;</li>
|
||||
<li>Set the hot-end on a printing temperature in E-Steps tab;</li>
|
||||
<li>Set the extrusion length and speed;</li>
|
||||
<li>Press "Start extrusion";</li>
|
||||
<li>When extrusion finished, check the remaining length between the extruder and the filament mark location;</li>
|
||||
<li>Refresh the current values from EEPROM;</li>
|
||||
<li>Feed data collected in E-Steps tab and save the results in EEPROM;</li>
|
||||
</lu>
|
||||
|
||||
{{ snipped.subSection("X-Y-Z Steps") }}
|
||||
You will have to:
|
||||
<lu>
|
||||
<li>Print a <a href="https://www.thingiverse.com/thing:1278865" target="_blank">test cube</a> with a known size on all three axes X,Y,X;</li>
|
||||
<li>Refresh the current values from EEPROM;</li>
|
||||
<li>Feed data collected in E-Steps tab and save the results in EEPROM;</li>
|
||||
</lu>
|
||||
|
||||
|
||||
{{ snipped.subSection("PID Autotune") }}
|
||||
You will have to:
|
||||
<lu>
|
||||
<li>Refresh the current values from EEPROM;</li>
|
||||
<li>Set the hot-end index which you want to tune;</li>
|
||||
<li>Set the usual temperature used in your prints for that specific hot-end;</li>
|
||||
<li>Set the usual fan speed used in your prints;</li>
|
||||
<li>Monitor temperature tab, when it starts to cool down save the results in EEPROM;</li>
|
||||
<li>For tuning heated bed the index is already set on -1;</li>
|
||||
</lu>
|
||||
@@ -1,24 +1,36 @@
|
||||
{% import "macros.jinja2" as snipped %}
|
||||
|
||||
{{ snipped.subSection("Process description", true) }}
|
||||
|
||||
You will have to:
|
||||
<lu>
|
||||
<li>Mark a specific length of filament at the extruder motor entrance;</li>
|
||||
<li>Set the hot-end on a printing temperature in E-Steps tab;</li>
|
||||
<li>Set the extrusion length and speed;</li>
|
||||
<li>Press "Start extrusion";</li>
|
||||
<li>When extrusion finished, check the remaining length between the extruder and the filament mark location;</li>
|
||||
<li>Refresh the current values from EEPROM;</li>
|
||||
<li>Feed data collected in E-Steps tab and save the results in EEPROM;</li>
|
||||
</lu>
|
||||
<br>
|
||||
|
||||
{{ snipped.quote("
|
||||
This calibration is best done with the extruder detached from the hot end, so no restriction is present on the movement. If it is convenient, you can partially disassemble the printer so the output of the extruder is
|
||||
open and the filament exits in free air. If this is inconvenient, the process below aims to minimize restrictions by extruding very slowly and with a slightly higher temperature. The results from this should still be
|
||||
reliable.
|
||||
", "
|
||||
<a href='https://teachingtechyt.github.io/calibration.html#esteps' target='_blank'>For more information about how to use this visit teachingtechyt.github.io</a>
|
||||
", "text-warning") }}
|
||||
", "<a href='https://teachingtechyt.github.io/calibration.html#esteps' target='_blank'>teachingtechyt.github.io</a>", "text-warning") }}
|
||||
|
||||
{{ snipped.subSection("Parameters", true) }}
|
||||
|
||||
{{ snipped.subSection("Test parameters") }}
|
||||
|
||||
<!-- M104 S210 command -->
|
||||
<div class="row-fluid">
|
||||
<div class="span6">
|
||||
<div data-bind="class: $root.columnLabelCls()">
|
||||
<label for="temperature" class="pull-right" style="margin-top: 5px;" title="x">
|
||||
Heating
|
||||
</label>
|
||||
</div>
|
||||
<div class="span6">
|
||||
<div data-bind="class: $root.columnFieldCls()">
|
||||
<div class="input-prepend input-append">
|
||||
{{ snipped.linkToMarlin("M104", "Marlin website") }}
|
||||
<span class="add-on" title="Command to preheat the tool before testing">M104 S</span>
|
||||
@@ -29,12 +41,12 @@ reliable.
|
||||
</div>
|
||||
<!-- G1 E100 F50 command -->
|
||||
<div class="row-fluid">
|
||||
<div class="span6">
|
||||
<div data-bind="class: $root.columnLabelCls()">
|
||||
<label for="extrusionLenSpeed" class="pull-right" style="margin-top: 5px;" title="x">
|
||||
Extrusion length & speed
|
||||
</label>
|
||||
</div>
|
||||
<div class="span6">
|
||||
<div data-bind="class: $root.columnFieldCls()">
|
||||
<div class="input-prepend input-append">
|
||||
{{ snipped.linkToMarlin("G000-G001", "Marlin website") }}
|
||||
<span class="add-on" title="Command to extrude filament for testing">G1 E</span>
|
||||
@@ -49,8 +61,8 @@ reliable.
|
||||
{{ snipped.field("Extrusion marking length", "The length marked on filament before extrusion. ", "number", "$root.testParam.markLength", "true", "mm", 0.01, 50) }}
|
||||
|
||||
<div class="row-fluid" style="margin-bottom: 5px;">
|
||||
<div class="span6"></div>
|
||||
<div class="span6">
|
||||
<div data-bind="class: $root.columnLabelCls()"></div>
|
||||
<div data-bind="class: $root.columnFieldCls()">
|
||||
<button class="btn btn-success"
|
||||
data-bind="click: $root.startExtrusion, enable: !$root.startExtrusionActive() && $root.is_admin() && $root.controlViewModel.isOperational() && (!$root.controlViewModel.isPrinting())"
|
||||
title="This will trigger M90, M83, G1 E100 F50, M82, G90 in order for extruding filament">
|
||||
@@ -60,15 +72,15 @@ reliable.
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{{ snipped.subSection("Test results") }}
|
||||
{{ snipped.subSection("Results") }}
|
||||
|
||||
<div class="row-fluid">
|
||||
<div class="span6">
|
||||
<div data-bind="class: $root.columnLabelCls()">
|
||||
<label for="eSteps" class="pull-right" style="margin-top: 5px;" title="Current value for number of steps/mm for E axe in EEPROM">
|
||||
E steps
|
||||
</label>
|
||||
</div>
|
||||
<div class="span6">
|
||||
<div data-bind="class: $root.columnFieldCls()">
|
||||
<div class="input-append">
|
||||
<input type="number" id="eSteps" title="Current value for number of steps/mm for E axe in EEPROM" class="input-small" step="0.01" data-bind="value: $root.steps.E(), enable:false">
|
||||
<span class="add-on" title="Current value for number of steps/mm for E axe in EEPROM">steps/mm</span>
|
||||
@@ -85,12 +97,12 @@ reliable.
|
||||
|
||||
<!-- M92 E900 -->
|
||||
<div class="row-fluid">
|
||||
<div class="span6">
|
||||
<div data-bind="class: $root.columnLabelCls()">
|
||||
<label for="newESteps" class="pull-right" style="margin-top: 5px;" title="The new calculated number of steps/mm for E axe">
|
||||
New E axe steps/mm
|
||||
</label>
|
||||
</div>
|
||||
<div class="span6">
|
||||
<div data-bind="class: $root.columnFieldCls()">
|
||||
<div class="input-prepend input-append">
|
||||
{{ snipped.linkToMarlin("M092", "Marlin website") }}
|
||||
<span class="add-on" title="Command to change number of steps/mm for E axe" data-bind="text: $root.results.newStepsDisplay"></span>
|
||||
@@ -100,8 +112,8 @@ reliable.
|
||||
</div>
|
||||
|
||||
<div class="row-fluid" style="margin-bottom: 5px;">
|
||||
<div class="span6"></div>
|
||||
<div class="span6">
|
||||
<div data-bind="class: $root.columnLabelCls()"></div>
|
||||
<div data-bind="class: $root.columnFieldCls()">
|
||||
<button class="btn btn-primary" data-bind="click: $root.saveESteps, enable: $root.is_admin() && $root.controlViewModel.isOperational() && (!$root.controlViewModel.isPrinting())"
|
||||
title="Saves the new calculated value of steps/mm on printer EEPROM">
|
||||
<i class="fas fa-save" data-color="#000000"></i>  
|
||||
|
||||
@@ -1,18 +1,29 @@
|
||||
{% import "macros.jinja2" as snipped %}
|
||||
|
||||
{{ snipped.subSection("Note", true) }}
|
||||
{{ snipped.subSection("Process description", true) }}
|
||||
You will have to:
|
||||
<lu>
|
||||
<li>Refresh the current values from EEPROM;</li>
|
||||
<li>Set the hot-end index which you want to tune;</li>
|
||||
<li>Set the usual temperature used in your prints for that specific hot-end;</li>
|
||||
<li>Set the usual fan speed used in your prints;</li>
|
||||
<li>Monitor temperature tab, when it starts to cool down save the results in EEPROM;</li>
|
||||
<li>For tuning heated bed the index is already set on -1;</li>
|
||||
</lu>
|
||||
<br>
|
||||
{{ snipped.quote("It is recommended to run the tuning with conditions as close to printing as possible. This means filament loaded and the part cooling fan set to your normal speed. It is not essential, but you may
|
||||
prefer to start this process with the hot end at room temperature.",
|
||||
"<a href='https://teachingtechyt.github.io/calibration.html#pid' target='_blank'>For more information about how to use this visit teachingtechyt.github.io</a>", "text-warning") }}
|
||||
|
||||
{{ snipped.subSection("Current PID values") }}
|
||||
{{ snipped.subSection("Current PID values", true) }}
|
||||
|
||||
<div class="row-fluid">
|
||||
<div class="span5">
|
||||
<div data-bind="class: $root.columnLabelCls()">
|
||||
<label for="hotEndPid" class="pull-right" style="margin-top: 5px;" title="Current hot-end PID">
|
||||
Current hot-end PID
|
||||
</label>
|
||||
</div>
|
||||
<div class="span7">
|
||||
<div data-bind="class: $root.columnFieldCls()">
|
||||
<div class="input-prepend input-append" id="hotEndPid">
|
||||
<span class="add-on" title="Proportional gain">P</span>
|
||||
<span class="add-on numberDisplay" title="Proportional gain" data-bind="text: $root.pidCurrentValues.hotEnd.P()"></span>
|
||||
@@ -24,12 +35,12 @@ prefer to start this process with the hot end at room temperature.",
|
||||
</div>
|
||||
</div>
|
||||
<div class="row-fluid">
|
||||
<div class="span5">
|
||||
<div data-bind="class: $root.columnLabelCls()">
|
||||
<label for="bedPid" class="pull-right" style="margin-top: 5px;" title="Current bed PID">
|
||||
Current bed PID
|
||||
</label>
|
||||
</div>
|
||||
<div class="span7">
|
||||
<div data-bind="class: $root.columnFieldCls()">
|
||||
<div class="input-prepend input-append" id="bedPid">
|
||||
<span class="add-on" title="Proportional gain">P</span>
|
||||
<span class="add-on numberDisplay" title="Proportional gain" data-bind="text: $root.pidCurrentValues.bed.P()"></span>
|
||||
@@ -41,9 +52,9 @@ prefer to start this process with the hot end at room temperature.",
|
||||
</div>
|
||||
</div>
|
||||
<div class="row-fluid">
|
||||
<div class="span5">
|
||||
<div data-bind="class: $root.columnLabelCls()">
|
||||
</div>
|
||||
<div class="span7">
|
||||
<div data-bind="class: $root.columnFieldCls()">
|
||||
<div class="input-prepend input-append" id="bedPid">
|
||||
<button class="btn" data-bind="click: $root.getCurrentValues, enable: $root.controlViewModel.isOperational() && (!$root.controlViewModel.isPrinting())" title="Load current PIDs">
|
||||
<i class="fas fa-sync-alt" style="color:false" data-color="false"></i>  
|
||||
@@ -55,12 +66,12 @@ prefer to start this process with the hot end at room temperature.",
|
||||
|
||||
{{ snipped.subSection("Hot-end tuning") }}
|
||||
<div class="row-fluid">
|
||||
<div class="span5">
|
||||
<div data-bind="class: $root.columnLabelCls()">
|
||||
<label for="fanSpeed" class="pull-right" style="margin-top: 5px;" title="Fan speed">
|
||||
Turn fan to max
|
||||
</label>
|
||||
</div>
|
||||
<div class="span7">
|
||||
<div data-bind="class: $root.columnFieldCls()">
|
||||
<div class="input-prepend input-append">
|
||||
{{ snipped.linkToMarlin("M106", "Marlin website") }}
|
||||
<span class="add-on" title="Command for turning the fan to 100%">M106 S</span>
|
||||
@@ -69,12 +80,12 @@ prefer to start this process with the hot end at room temperature.",
|
||||
</div>
|
||||
</div>
|
||||
<div class="row-fluid">
|
||||
<div class="span5">
|
||||
<div data-bind="class: $root.columnLabelCls()">
|
||||
<label for="tunningPIDNoCycles" class="pull-right" style="margin-top: 5px;" title="x">
|
||||
Tuning PID
|
||||
</label>
|
||||
</div>
|
||||
<div class="span7">
|
||||
<div data-bind="class: $root.columnFieldCls()">
|
||||
<div class="input-prepend input-append">
|
||||
{{ snipped.linkToMarlin("M303", "Marlin website") }}
|
||||
<span class="add-on" title="Command for triggering tool PID tunning">M303 C</span>
|
||||
@@ -90,8 +101,8 @@ prefer to start this process with the hot end at room temperature.",
|
||||
</div>
|
||||
|
||||
<div class="row-fluid" style="margin-bottom: 5px;">
|
||||
<div class="span5"></div>
|
||||
<div class="span7">
|
||||
<div data-bind="class: $root.columnLabelCls()"></div>
|
||||
<div data-bind="class: $root.columnFieldCls()">
|
||||
<button class="btn btn-success" data-bind="click: $root.startPidHotEnd, enable: $root.controlViewModel.isOperational() && (!$root.controlViewModel.isPrinting())"
|
||||
title="This will trigger PID auto tuning (M106 Sx; M303 Ex Sx U1; M500)">
|
||||
<i class="fas fa-play" style="color:false" data-color="false"></i>  
|
||||
@@ -102,12 +113,12 @@ prefer to start this process with the hot end at room temperature.",
|
||||
|
||||
{{ snipped.subSection("Heated bed tuning") }}
|
||||
<div class="row-fluid">
|
||||
<div class="span5">
|
||||
<div data-bind="class: $root.columnLabelCls()">
|
||||
<label for="fanSpeed" class="pull-right" style="margin-top: 5px;" title="Fan speed">
|
||||
Turn fan to max
|
||||
</label>
|
||||
</div>
|
||||
<div class="span7">
|
||||
<div data-bind="class: $root.columnFieldCls()">
|
||||
<div class="input-prepend input-append">
|
||||
{{ snipped.linkToMarlin("M106", "Marlin website") }}
|
||||
<span class="add-on" title="Command for turning the fan to 100%">M106 S</span>
|
||||
@@ -116,12 +127,12 @@ prefer to start this process with the hot end at room temperature.",
|
||||
</div>
|
||||
</div>
|
||||
<div class="row-fluid">
|
||||
<div class="span5">
|
||||
<div data-bind="class: $root.columnLabelCls()">
|
||||
<label for="tunningPIDNoCycles" class="pull-right" style="margin-top: 5px;" title="x">
|
||||
Tuning PID
|
||||
</label>
|
||||
</div>
|
||||
<div class="span7">
|
||||
<div data-bind="class: $root.columnFieldCls()">
|
||||
<div class="input-prepend input-append">
|
||||
{{ snipped.linkToMarlin("M303", "Marlin website") }}
|
||||
<span class="add-on" title="Command for triggering bed PID tunning">M303 C</span>
|
||||
@@ -137,8 +148,8 @@ prefer to start this process with the hot end at room temperature.",
|
||||
</div>
|
||||
|
||||
<div class="row-fluid" style="margin-bottom: 5px;">
|
||||
<div class="span5"></div>
|
||||
<div class="span7">
|
||||
<div data-bind="class: $root.columnLabelCls()"></div>
|
||||
<div data-bind="class: $root.columnFieldCls()">
|
||||
<button class="btn btn-success" data-bind="click: $root.startPidBed, enable: $root.controlViewModel.isOperational() && (!$root.controlViewModel.isPrinting())"
|
||||
title="This will trigger PID auto tuning (M303 E-1 Sx U1; M500)">
|
||||
<i class="fas fa-play" style="color:false" data-color="false"></i>  
|
||||
|
||||
@@ -1,13 +1,23 @@
|
||||
{% import "macros.jinja2" as snipped %}
|
||||
|
||||
{{ snipped.subSection("Process description", true) }}
|
||||
You will have to:
|
||||
<lu>
|
||||
<li>Print a <a href="https://www.thingiverse.com/thing:1278865" target="_blank">test cube</a> with a known size on all three axes X,Y,X;</li>
|
||||
<li>Refresh the current values from EEPROM;</li>
|
||||
<li>Feed data collected in E-Steps tab and save the results in EEPROM;</li>
|
||||
</lu>
|
||||
<br>
|
||||
{{ snipped.quote("This step is not necessary for many people, but is still worth doing if you are going over the machine in detail. Consider this procedure necessary if your printed parts are clearly over or under
|
||||
sized.","<a href='https://teachingtechyt.github.io/calibration.html#xyzsteps' target='_blank'>teachingtechyt.github.io</a>", "text-warning") }}
|
||||
{{ snipped.subSection("X-Y-Z Steps", true) }}
|
||||
<div class="row-fluid">
|
||||
<div class="span3">
|
||||
<label for="tunningPIDNoCycles" class="pull-right" style="margin-top: 5px;" title="x">
|
||||
<div data-bind="class: $root.columnLabelCls()">
|
||||
<label for="tunningPIDNoCycles" class="pull-right" style="margin-top: 5px; white-space: nowrap;" title="x">
|
||||
Current values
|
||||
</label>
|
||||
</div>
|
||||
<div class="span9">
|
||||
<div data-bind="class: $root.columnFieldCls()">
|
||||
<div class="input-prepend input-append">
|
||||
{{ snipped.linkToMarlin("M092", "Marlin website") }}
|
||||
<span class="add-on" title="">M92 X</span>
|
||||
@@ -24,12 +34,12 @@
|
||||
</div>
|
||||
</div>
|
||||
<div class="row-fluid">
|
||||
<div class="span3">
|
||||
<label for="tunningPIDNoCycles" class="pull-right" style="margin-top: 5px;" title="x">
|
||||
GCode cube size
|
||||
<div data-bind="class: $root.columnLabelCls()">
|
||||
<label for="tunningPIDNoCycles" class="pull-right" style="margin-top: 5px; white-space: nowrap;" title="">
|
||||
GCode sizes
|
||||
</label>
|
||||
</div>
|
||||
<div class="span9">
|
||||
<div data-bind="class: $root.columnFieldCls()">
|
||||
<div class="input-prepend input-append">
|
||||
<span class="add-on" title="">X</span>
|
||||
<input type="number" id="" class="input-small numberDisplay" step="0.001" min="0" max="100" title="" data-bind="value: $root.eStepsXYZ.gCodeCubeSize.X">
|
||||
@@ -42,12 +52,12 @@
|
||||
</div>
|
||||
</div>
|
||||
<div class="row-fluid">
|
||||
<div class="span3">
|
||||
<label for="tunningPIDNoCycles" class="pull-right" style="margin-top: 5px;" title="x">
|
||||
Printed cube size
|
||||
<div data-bind="class: $root.columnLabelCls()">
|
||||
<label for="tunningPIDNoCycles" class="pull-right" style="margin-top: 5px; white-space: nowrap;" title="">
|
||||
Printed sizes
|
||||
</label>
|
||||
</div>
|
||||
<div class="span9">
|
||||
<div data-bind="class: $root.columnFieldCls()">
|
||||
<div class="input-prepend input-append">
|
||||
<span class="add-on" title="">X</span>
|
||||
<input type="number" id="" class="input-small numberDisplay" step="0.001" min="0" max="100" title="" data-bind="value: $root.eStepsXYZ.printedCubeSize.X">
|
||||
@@ -60,12 +70,12 @@
|
||||
</div>
|
||||
</div>
|
||||
<div class="row-fluid">
|
||||
<div class="span3">
|
||||
<label for="tunningPIDNoCycles" class="pull-right" style="margin-top: 5px;" title="x">
|
||||
<div data-bind="class: $root.columnLabelCls()">
|
||||
<label for="tunningPIDNoCycles" class="pull-right" style="margin-top: 5px; white-space: nowrap;" title="">
|
||||
New values
|
||||
</label>
|
||||
</div>
|
||||
<div class="span9">
|
||||
<div data-bind="class: $root.columnFieldCls()">
|
||||
<div class="input-prepend input-append">
|
||||
{{ snipped.linkToMarlin("M092", "Marlin website") }}
|
||||
<span class="add-on" title="">M92 X</span>
|
||||
@@ -79,8 +89,8 @@
|
||||
</div>
|
||||
</div>
|
||||
<div class="row-fluid" style="margin-bottom: 5px;">
|
||||
<div class="span3"></div>
|
||||
<div class="span9">
|
||||
<div data-bind="class: $root.columnLabelCls()"></div>
|
||||
<div data-bind="class: $root.columnFieldCls()">
|
||||
<button class="btn btn-success" data-bind="click: $root.saveEStepsXYZ, enable: $root.saveEStepsXYZActive() && $root.controlViewModel.isOperational() && (!$root.controlViewModel.isPrinting())"
|
||||
title="This will save new values to EEPROM (M92 Xx Yx Zx; M500)">
|
||||
<i class="fas fa-save" style="color:false" data-color="false"></i>  
|
||||
|
||||
Reference in New Issue
Block a user