From 47af000045cf5b7ea3b46605461c80822faa4ab2 Mon Sep 17 00:00:00 2001 From: OneFinityCNC Date: Thu, 15 Oct 2020 23:17:21 -0400 Subject: [PATCH] Verison 1.0.5 --- CHANGELOG.md | 32 ++ Makefile | 2 + README.md | 63 +++- package.json | 2 +- scripts/config-wifi-external | 259 ++++++++++++++ scripts/upgrade-bbctrl | 6 +- src/js/admin-general-view.js | 82 ++++- src/js/app.js | 16 +- src/js/axis-vars.js | 85 +++-- src/js/control-view.js | 25 +- src/pug/index.pug | 9 + src/pug/templates/admin-general-view.pug | 11 +- src/pug/templates/control-view.pug | 71 +++- src/pwr/config.h | 1 + src/pwr/main.c | 9 + src/py/bbctrl/Web.py | 5 + src/resources/config-template.json | 4 +- .../onefinity_machinist_defaults.json | 324 ++++++++++++++++++ .../onefinity_woodworker_defaults.json | 324 ++++++++++++++++++ src/stylus/style.styl | 8 + 20 files changed, 1282 insertions(+), 56 deletions(-) create mode 100644 scripts/config-wifi-external create mode 100644 src/resources/onefinity_machinist_defaults.json create mode 100644 src/resources/onefinity_woodworker_defaults.json diff --git a/CHANGELOG.md b/CHANGELOG.md index 3355047..c397930 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,35 @@ +OneFinity CNC Controller Firmware Changelog +=========================================== + +Note: This firmware was forked from version 0.4.14 of the Buildbotics firmware +Buildbotics Changelog is provided below + +## v1.0.5 + - Changed the jog commands so that save/restore modal states are not used to avoid situation where spindle/loads could + turn back on if the stop button was used instead of the M5/M9 gcode commands. + - Added tool path status to control page + - Moved over/under/no-fit warnings to tool status from machine status + - Added "home machine" pop up on start if the machine is not homed + - Added confirmation for X0Y0 and Z0 buttons + +## v1.0.4 + - Fixed text sticking out of some dialog boxes + - Added changes to PWR microcontroller to support new precharge circuitry on V3 of the PCB + - Added a Shutdown button under the menu + - Added confirmation dialog to shutdown + - Fixed Reset Defaults for OneFinity settings + - Probe buttons now turn green when probe input is active + - Added defaults for both machinist and woodworker machines + - Re-activated "Upgrade" button under Admin to grab updates directly from the web + +## v1.0.3 + - Changed upgrade scripts to point at OneFinity github repository + - Upgrade function not yet fully implemented + +## v1.0.2 + - Initial release of customized OneFinity firmware + - Includes GUI customizations, stall homing + Buildbotics CNC Controller Firmware Changelog ============================================= diff --git a/Makefile b/Makefile index 0aed58e..4f08c6a 100644 --- a/Makefile +++ b/Makefile @@ -104,6 +104,8 @@ $(TARGET_DIR)/index.html: $(wildcard src/pug/templates/*) $(TARGET_DIR)/index.html: $(wildcard src/js/*) $(TARGET_DIR)/index.html: $(wildcard src/stylus/*) $(TARGET_DIR)/index.html: src/resources/config-template.json +$(TARGET_DIR)/index.html: src/resources/onefinity_woodworker_defaults.json +$(TARGET_DIR)/index.html: src/resources/onefinity_machinist_defaults.json $(TARGET_DIR)/%.html: src/pug/%.pug node_modules @mkdir -p $(shell dirname $@) diff --git a/README.md b/README.md index fb03feb..345ab24 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,62 @@ -# OneFinity CNC Controller Firmware +# Buildbotics CNC Controller Firmware +This repository contains the source code for the Buildbotics CNC Controller. +See [buildbotics.com](https://buildbotics.com/) for more information. -This repository contains the source code for the OneFinity CNC controller. +![Buildboitcs CNC Controller](docs/buildbotics_controller.png) -The OneFinity CNC controller and its firmare is based on the Buildbotics CNC controller (buildbotics.com) \ No newline at end of file +## Overview +![Buildbotics architecture overview](docs/buildbotics_architecture_overview.png) + +The main parts of the Buildbotics CNC Controller software and the technologies +they are built with are as follows: + + * Web App - Frontend user interface + * [Javascript](https://www.w3schools.com/js/) + * [HTML5](https://www.w3schools.com/html/) + * [Stylus](http://stylus-lang.com/) + * [Pug.js](https://pugjs.org/) + * [Vue.js](https://vuejs.org/) + + * Controller OS - RaspberryPi Operating System + * [Raspbian](https://www.raspbian.org/) + + * BBCtrl - Python App + * [Python 3](https://www.python.org/) + * [Tornado Web](https://www.tornadoweb.org/) + + * GPlan - Path Planner Python Module + * [C++](http://www.cplusplus.com/) + * [CAMotics](https://camotics.org/) + + * Main AVR Firmware + Bootloader - Real-time step generation, etc. + * [ATxmega192a3u](https://www.microchip.com/wwwproducts/ATxmega192A3U) + * [C](https://en.wikipedia.org/wiki/C_(programming_language)) + + * Pwr AVR Firmware - Power safety + * [ATtiny1634](https://www.microchip.com/wwwproducts/ATtiny1634) + * [C](https://en.wikipedia.org/wiki/C_(programming_language)) + +## Quickstart Guide + +Be sure to read the [development guide](docs/development.md) for more detailed +instructions. + +On a Debian Linux (9.6.0 stable) system: + + # Install the required packages + sudo apt-get update + sudo apt-get install -y build-essential git wget binfmt-support qemu \ + parted gcc-avr avr-libc avrdude pylint3 python3 python3-tornado curl \ + unzip python3-setuptools + curl -sL https://deb.nodesource.com/setup_11.x | sudo -E bash - + sudo apt-get install -y nodejs + + # Get the source + git clone https://github.com/buildbotics/bbctrl-firmware + + # Build the Firmware + cd bbctrl-firmware + make pkg + +The resulting package will be a ``.tar.bz2`` file in ``dist``. See the +[development guide](docs/development.md) for more information. diff --git a/package.json b/package.json index 0cd9d42..60ddffd 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "bbctrl", - "version": "1.0.3", + "version": "1.0.5", "homepage": "https://onefinitycnc.com/", "repository": "https://github.com/OneFinityCNC/onefinity", "license": "GPL-3.0+", diff --git a/scripts/config-wifi-external b/scripts/config-wifi-external new file mode 100644 index 0000000..018c676 --- /dev/null +++ b/scripts/config-wifi-external @@ -0,0 +1,259 @@ +#!/bin/bash -e + +AP=false +DISABLE=false +SSID= +PASS= +CHANNEL=7 +REBOOT=false + +WLAN0_CFG=/etc/network/interfaces.d/wlan0 +HOSTAPD_CFG=/etc/hostapd/hostapd.conf +DNSMASQ_CFG=/etc/dnsmasq.conf +DHCPCD_CFG=/etc/dhcpcd.conf +WPA_CFG=/etc/wpa_supplicant/wpa_supplicant.conf + + +function query_config() { + if [ -e $WLAN0_CFG ]; then + SSID=$(grep wpa-ssid $WLAN0_CFG | + sed 's/^[[:space:]]*wpa-ssid "\([^"]*\)"/\1/') + echo "{\"ssid\": \"$SSID\", \"mode\": \"client\"}" + + else + if [ -e $HOSTAPD_CFG -a -e /etc/default/hostapd ]; then + SSID=$(grep ^ssid= $HOSTAPD_CFG | sed 's/^ssid=\(.*\)$/\1/') + CHANNEL=$(grep ^channel= $HOSTAPD_CFG | + sed 's/^channel=\(.*\)$/\1/') + + echo -n "{\"ssid\": \"$SSID\", " + echo "\"channel\": $CHANNEL, \"mode\": \"ap\"}" + + else + echo "{\"mode\": \"disabled\"}" + fi + fi + +} + + +function disable_wifi() { + rm -f $WLAN0_CFG $HOSTAPD_CFG /etc/default/hostapd +} + + +function configure_wlan0() { + echo "auto wlan0" + echo "allow-hotplug wlan0" + echo "iface wlan0 inet dhcp" + echo " wpa-scan-ssid 1" + echo " wpa-ap-scan 1" + echo " wpa-key-mgmt WPA-PSK" + echo " wpa-proto RSN WPA" + echo " wpa-pairwise CCMP TKIP" + echo " wpa-group CCMP TKIP" + echo " wpa-ssid \"$SSID\"" + + if [ ${#PASS} -ne 0 ]; then + echo " wpa-psk \"$PASS\"" + fi +} + + +function configure_wpa() { + echo "country=US" + echo "ctrl_interface=DIR=/var/run/wpa_supplicant GROUP=netdev" + echo "update_config=1" + + if [ ${#PASS} -eq 0 ]; then + echo "network={" + echo " ssid=\"$SSID\"" + echo " key_mgmt=NONE" + echo "}" + fi +} + + +function configure_dhcpcd() { + echo "hostname" + echo "clientid" + echo "persistent" + echo "option rapid_commit" + echo "option domain_name_servers, domain_name, domain_search, host_name" + echo "option classless_static_routes" + echo "option ntp_servers" + echo "option interface_mtu" + echo "require dhcp_server_identifier" + echo "slaac private" + + if $AP; then + echo + echo "interface wlan0" + echo " static ip_address=192.168.43.1/24" + fi +} + + +function configure_wifi() { + disable_wifi + echo "source-directory /etc/network/interfaces.d" > /etc/network/interfaces + configure_wlan0 > $WLAN0_CFG + configure_wpa > $WPA_CFG + configure_dhcpcd > $DHCPCD_CFG +} + + +function configure_dnsmasq() { + echo "interface=wlan0" + echo "domain-needed" + echo "bogus-priv" + echo "dhcp-range=192.168.43.2,192.168.43.20,255.255.255.0,12h" +} + + +function configure_hostapd() { + echo "interface=wlan0" + echo "driver=nl80211" + echo "ssid=$SSID" + echo "hw_mode=g" + echo "channel=$CHANNEL" + echo "wmm_enabled=0" + echo "macaddr_acl=0" + echo "auth_algs=1" + echo "ignore_broadcast_ssid=0" + echo "wpa=2" + echo "wpa_passphrase=$PASS" + echo "wpa_key_mgmt=WPA-PSK" + echo "wpa_pairwise=TKIP" + echo "rsn_pairwise=CCMP" +} + + +function is_installed() { + dpkg-query -W --showformat='${Status}' $1 | + grep "install ok installed" >/dev/null + if [ $? -eq 0 ]; then echo true; else echo false; fi +} + + +function configure_ap() { + disable_wifi + + # Install packages + ( + $(is_installed dnsmasq) && + $(is_installed hostapd) && + $(is_installed iptables-persistent) + + ) || ( + export DEBIAN_FRONTEND=noninteractive + apt-get update + apt-get install -yq dnsmasq hostapd iptables-persistent + ) + + configure_dhcpcd > $DHCPCD_CFG + configure_dnsmasq > $DNSMASQ_CFG + configure_hostapd > $HOSTAPD_CFG + + echo "DAEMON_CONF=\"/etc/hostapd/hostapd.conf\"" > /etc/default/hostapd + + # Enable IP forwarding + sed -i 's/#net.ipv4.ip_forward=1/net.ipv4.ip_forward=1/' /etc/sysctl.conf + echo 1 > /proc/sys/net/ipv4/ip_forward + + # Enable IP masquerading + iptables -t nat -F + iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE + iptables-save > /etc/iptables/rules.v4 +} + + +function usage() { + echo "Usage: config-wifi [OPTIONS]" + echo + echo "Configure wifi as either a client or access point." + echo + echo "OPTIONS:" + echo + echo " -a Configure access point." + echo " -d Disable wifi." + echo " -r Reboot when done." + echo " -s Set SSID." + echo " -p Set password." + echo " -c Set wifi channel." + echo " -j Report wifi config as JSON data." + echo +} + + +# Parse args +while [ $# -ne 0 ]; do + case "$1" in + -a) AP=true ;; + -d) DISABLE=true ;; + -r) REBOOT=true; ;; + -s) SSID="$2"; shift ;; + -p) PASS="$2"; shift ;; + -c) CHANNEL="$2"; shift ;; + -j) query_config; exit 0 ;; + + -h) + usage + exit 0 + ;; + + *) + usage + echo "Unknown argument '$1'" + exit 1 + esac + + shift +done + + +if $DISABLE; then + disable_wifi + +else + # Check args + function clean_str() { + echo "$1" | tr -d '\n\r"' + } + + SSID=$(clean_str "$SSID") + PASS=$(clean_str "$PASS") + + LANG=C LC_ALL=C # For correct string byte length + + if [ ${#SSID} -eq 0 -o 32 -lt ${#SSID} ]; then + echo "Invalid or missing SSID '$SSID'" + exit 1 + fi + + if [ ${#PASS} -ne 0 ]; then + if [ ${#PASS} -lt 8 -o 128 -lt ${#PASS} ]; then + echo "Invalid passsword" + exit 1 + fi + fi + + echo "$CHANNEL" | grep '^[0-9]\{1,2\}' > /dev/null + if [ $? -ne 0 ]; then + echo "Invalid channel '$CHANNEL'" + exit 1 + fi + + # Execute + if $AP; then + echo "Configuring Wifi access point" + configure_ap + + else + echo "Configuring Wifi" + configure_wifi + fi +fi + + +if $REBOOT; then nohup reboot & fi diff --git a/scripts/upgrade-bbctrl b/scripts/upgrade-bbctrl index a26d26e..0e2247e 100644 --- a/scripts/upgrade-bbctrl +++ b/scripts/upgrade-bbctrl @@ -3,12 +3,12 @@ ( flock -n 9 - VERSION=$(curl -s https://raw.githubusercontent.com/OneFinityCNC/onefinity/master/latest.txt) + VERSION=$(curl -s https://raw.githubusercontent.com/OneFinityCNC/onefinity-release/master/latest.txt) PKG_NAME=onefinity-$VERSION PKG=/var/lib/bbctrl/firmware/update.tar.bz2 - PKG_URL=https://https://raw.githubusercontent.com/OneFinityCNC/onefinity/master/release/$PKG_NAME.tar.bz2 + PKG_URL=https://raw.githubusercontent.com/OneFinityCNC/onefinity-release/master/$PKG_NAME.tar.bz2 - logger Installing bbctrl firmware $VERSION + logger Installing onefinity firmware $VERSION cd /var/lib/bbctrl mkdir -p firmware diff --git a/src/js/admin-general-view.js b/src/js/admin-general-view.js index 6c5d5fc..049ea25 100644 --- a/src/js/admin-general-view.js +++ b/src/js/admin-general-view.js @@ -42,7 +42,8 @@ module.exports = { confirmReset: false, configReset: false, latest: '', - autoCheckUpgrade: true + autoCheckUpgrade: true, + default_config: '' } }, @@ -72,13 +73,14 @@ module.exports = { restore: function (e) { + debugger; var files = e.target.files || e.dataTransfer.files; if (!files.length) return; var fr = new FileReader(); fr.onload = function (e) { var config; - + debugger; try { config = JSON.parse(e.target.result); } catch (ex) { @@ -98,6 +100,82 @@ module.exports = { fr.readAsText(files[0]); }, + onefinity_woodworker_reset : function () { + var fr = new FileReader(); + + $.ajax({ + type: 'GET', + url: 'onefinity_woodworker_defaults.json', + data: {hid: this.state.hid}, + dataType: 'text', + cache: false + + }).done(function (data) { + debugger; + //console.debug('>', data); + //this.default_config = data; + var config; + try { + config = JSON.parse(data); + } catch(ex) { + api.alert("Invalid default config file"); + return; + } + + api.put('config/save', config).done(function (data) { + this.confirmReset = false; + + this.$dispatch('update'); + this.configRestored = true; + + }.bind(this)).fail(function (error) { + api.alert('Restore failed', error); + }) + + + }.bind(this)) + + + }, + + onefinity_machinist_reset : function () { + var fr = new FileReader(); + + $.ajax({ + type: 'GET', + url: 'onefinity_machinist_defaults.json', + data: {hid: this.state.hid}, + dataType: 'text', + cache: false + + }).done(function (data) { + debugger; + //console.debug('>', data); + //this.default_config = data; + var config; + try { + config = JSON.parse(data); + } catch(ex) { + api.alert("Invalid default config file"); + return; + } + + api.put('config/save', config).done(function (data) { + this.confirmReset = false; + + this.$dispatch('update'); + this.configRestored = true; + + }.bind(this)).fail(function (error) { + api.alert('Restore failed', error); + }) + + + }.bind(this)) + + + }, + reset: function () { this.confirmReset = false; diff --git a/src/js/app.js b/src/js/app.js index 9dc099a..0e3d076 100644 --- a/src/js/app.js +++ b/src/js/app.js @@ -117,7 +117,8 @@ module.exports = new Vue({ latestVersion: '', password: '', ipAddress: '0.0.0.0', - wifiSSID: '' + wifiSSID: '', + confirmShutdown: false } }, @@ -162,7 +163,7 @@ module.exports = new Vue({ $.ajax({ type: 'GET', - url: 'https://https://raw.githubusercontent.com/OneFinityCNC/onefinity/master/latest.txt', + url: 'https://raw.githubusercontent.com/OneFinityCNC/onefinity-release/master/latest.txt', data: {hid: this.state.hid}, cache: false @@ -308,6 +309,7 @@ module.exports = new Vue({ this.check_ip_address(); this.check_ssid(); + }.bind(this)) }, @@ -321,7 +323,7 @@ module.exports = new Vue({ }).done(function (data) { console.debug('>', data); - this.ipAddress = data; + this.ipAddress = 'IP:' + data; this.$broadcast('ipAddress', data); }.bind(this)) }, @@ -335,7 +337,7 @@ module.exports = new Vue({ }).done(function (data) { console.debug('>', data); - this.wifiSSID = data; + this.wifiSSID = 'SSID:' + data; this.$broadcast('wifiSSID', data); }.bind(this)) }, @@ -349,6 +351,12 @@ module.exports = new Vue({ console.debug('get_ssid>', this.wifiSSID); return this.wifiSSID; }, + + shutdown : function() { + this.confirmShutdown = false; + api.put('shutdown'); + + }, connect: function () { this.sock = new Sock('//' + window.location.host + '/sockjs'); diff --git a/src/js/axis-vars.js b/src/js/axis-vars.js index bf2096b..99eff79 100644 --- a/src/js/axis-vars.js +++ b/src/js/axis-vars.js @@ -80,47 +80,41 @@ module.exports = { var fault = this.state[motor_id + 'df'] & 0x1f; var shutdown = this.state.power_shutdown; var title; + var ticon = 'question-circle'; + var tstate = 'NO FILE'; + var toolmsg; + var tklass = (homed ? 'homed' : 'unhomed') + ' axis-' + axis; if (fault || shutdown) { state = shutdown ? 'SHUTDOWN' : 'FAULT'; klass += ' error'; icon = 'exclamation-circle'; - } else if (0 < dim && dim < pathDim) { - state = 'NO FIT'; - klass += ' error'; - icon = 'ban'; - - } else if (homed) { - state = 'HOMED' + } else if(homed) { + state = 'HOMED'; icon = 'check-circle'; + } + + if (0 < dim && dim < pathDim) { + tstate = 'NO FIT'; + tklass += ' error'; + ticon = 'ban'; + + } else { if (over || under) { - state = over ? 'OVER' : 'UNDER'; - klass += ' warn'; - icon = 'exclamation-circle'; + tstate = over ? 'OVER' : 'UNDER'; + tklass += ' warn'; + ticon = 'exclamation-circle'; + } else { + tstate = 'OK'; + ticon = 'check-circle'; } } switch (state) { case 'UNHOMED': title = 'Click the home button to home axis.'; break; case 'HOMED': title = 'Axis successfuly homed.'; break; - - case 'OVER': - title = 'Tool path would move ' + - this._length_str(pathMax + off - max) + ' beyond axis bounds.'; - break; - - case 'UNDER': - title = 'Tool path would move ' + - this._length_str(min - pathMin - off) + ' below axis bounds.'; - break; - - case 'NO FIT': - title = 'Tool path dimensions exceed axis dimensions by ' + - this._length_str(pathDim - dim) + '.'; - break; - case 'FAULT': title = 'Motor driver fault. A potentially damaging electrical ' + 'condition was detected and the motor driver was shutdown. ' + @@ -128,12 +122,37 @@ module.exports = { 'See the "Motor Faults" table on the "Indicators" tab for more ' + 'information.'; break; - case 'SHUTDOWN': title = 'Motor power fault. All motors in shutdown. ' + 'See the "Power Faults" table on the "Indicators" tab for more ' + 'information. Reboot controller to reset.'; } + + switch(tstate) { + + case 'OVER': + toolmsg = 'Caution: The current tool path file would move ' + + this._length_str(pathMax + off - max) + ' above axis limit with the current offset.'; + break; + + case 'UNDER': + toolmsg = 'Caution: The current tool path file would move ' + + this._length_str(min - pathMin - off) + ' below limit with the current offset.'; + break; + + case 'NO FIT': + toolmsg = 'Warning: The current tool path dimensions (' + + this._length_str(pathDim) + ') exceed axis dimensions (' + + this._length_str(dim) + ') by ' + + this._length_str(pathDim - dim) + '.'; + break; + + default: + toolmsg = 'Tool path ' + axis + ' dimensions OK.'; + break; + + } + return { pos: abs - off, @@ -152,7 +171,11 @@ module.exports = { klass: klass, state: state, icon: icon, - title: title + title: title, + ticon: ticon, + tstate: tstate, + toolmsg: toolmsg, + tklass: tklass } }, @@ -194,6 +217,12 @@ module.exports = { if (error) klass += ' error'; else if (warn) klass += ' warn'; + if(!homed && this.ask_home) + { + this.ask_home_msg = true; + this.ask_home = false; + } + return { homed: homed, klass: klass diff --git a/src/js/control-view.js b/src/js/control-view.js index 0536ebf..01295b1 100644 --- a/src/js/control-view.js +++ b/src/js/control-view.js @@ -60,8 +60,7 @@ module.exports = { speed_override: 1, feed_override: 1, manual_home: {x: false, y: false, z: false, a: false, b: false, c: false}, - position_msg: - {x: false, y: false, z: false, a: false, b: false, c: false}, + position_msg: {x: false, y: false, z: false, a: false, b: false, c: false}, axis_position: 0, jog_step: cookie.get_bool('jog-step'), jog_adjust: parseInt(cookie.get('jog-adjust', 2)), @@ -69,7 +68,12 @@ module.exports = { tab: 'auto', jog_incr: 1.0, tool_msg: false, - tool_diameter: 6.35 + tool_diameter: 6.35, + toolpath_msg: {x: false, y: false, z: false, a: false, b: false, c: false}, + ask_home: true, + ask_home_msg: false, + ask_zero_xy_msg: false, + ask_zero_z_msg: false } }, @@ -303,7 +307,10 @@ module.exports = { if(zero_z) zcmd = "Z0"; if(zero_a) acmd = "A0"; - this.send('M70\nG90\nG0' + xcmd + ycmd + zcmd + acmd + '\nM72'); + this.ask_zero_xy_msg = false; + this.ask_zero_z_msg = false; + + this.send('G90\nG0' + xcmd + ycmd + zcmd + acmd + '\n'); }, probe_xyz() { @@ -470,7 +477,7 @@ module.exports = { console.log("Jog command: " + this.jog_incr); //debugger; - this.send('M70\nG91\nG0' + xcmd + ycmd + zcmd + acmd + '\nM72'); + this.send('G91\nG0' + xcmd + ycmd + zcmd + acmd + '\n'); }, send: function (msg) {this.$dispatch('send', msg)}, @@ -581,6 +588,10 @@ module.exports = { home: function (axis) { + + this.ask_home = false; + this.ask_home_msg = false; + if (typeof axis == 'undefined') api.put('home'); else { @@ -606,6 +617,10 @@ module.exports = { this.axis_position = 0; this.position_msg[axis] = true; }, + + show_toolpath_msg : function(axis) { + this.toolpath_msg[axis] = true; + }, set_position: function (axis, position) { diff --git a/src/pug/index.pug b/src/pug/index.pug index 8fdb348..e42f4ba 100644 --- a/src/pug/index.pug +++ b/src/pug/index.pug @@ -86,6 +86,15 @@ html(lang="en") li.pure-menu-heading a.pure-menu-link(href="#help") Help + + button.pure-button.pure-button-primary(@click="confirmShutdown = true") Shutdown + message(:show.sync="confirmShutdown") + h3(slot="header") Confirm shutdown? + p(slot="body") Please wait for black screen before switching off power. + div(slot="footer") + button.pure-button(@click="confirmShutdown = false") Cancel + button.pure-button.button-success(@click="shutdown") Shutdown + #main .header diff --git a/src/pug/templates/admin-general-view.pug b/src/pug/templates/admin-general-view.pug index 00a9818..235240a 100644 --- a/src/pug/templates/admin-general-view.pug +++ b/src/pug/templates/admin-general-view.pug @@ -29,7 +29,7 @@ script#admin-general-view-template(type="text/x-template") #admin-general h2 Firmware button.pure-button.pure-button-primary(@click="check") Check - //button.pure-button.pure-button-primary(@click="upgrade") Upgrade + button.pure-button.pure-button-primary(@click="upgrade") Upgrade label.pure-button.pure-button-primary(@click="upload_firmware") Upload form.upload-firmware.file-upload input(type="file", accept=".bz2", @change="upload") @@ -53,9 +53,14 @@ script#admin-general-view-template(type="text/x-template") message(:show.sync="confirmReset") h3(slot="header") Reset to default configuration? p(slot="body") Non-network configuration changes will be lost. + p(slot="body") Select defaults to restore + p(slot="body") + button.pure-button.button-success(@click="onefinity_woodworker_reset") Woodworker + button.pure-button.button-success(@click="onefinity_machinist_reset") Machinist div(slot="footer") button.pure-button(@click="confirmReset = false") Cancel - button.pure-button.button-success(@click="reset") OK + + message(:show.sync="configReset") h3(slot="header") Success @@ -66,3 +71,5 @@ script#admin-general-view-template(type="text/x-template") button.pure-button.pure-button-primary View Log a(href="/api/bugreport") button.pure-button.pure-button-primary Bug Report + + diff --git a/src/pug/templates/control-view.pug b/src/pug/templates/control-view.pug index 26696ae..db851e2 100644 --- a/src/pug/templates/control-view.pug +++ b/src/pug/templates/control-view.pug @@ -52,13 +52,13 @@ script#control-view-template(type="text/x-template") td(style="height:100px",align="center") button(style="height:100px;width:100px",@click="jog_fn(-1,0,0,0)") X- td(style="height:100px",align="center") - button(style="height:100px;width:100px",@click="goto_zero(1,1,0,0)") + button(style="height:100px;width:100px",@click="ask_zero_xy_msg = true") .fa.fa-bullseye td(style="height:100px",align="center") button(style="height:100px;width:100px",@click="jog_fn(1,0,0,0)") X+ td td(style="height:100px",align="center") - button(style="height:100px;width:100px",@click="goto_zero(0,0,1,0)") Z0 + button(style="height:100px;width:100px",@click='ask_zero_z_msg = true') Z0 tr td(style="height:100px",align="center") button(style="height:100px;width:100px",@click="jog_fn(-1,-1,0,0)") ⬃ @@ -77,6 +77,9 @@ script#control-view-template(type="text/x-template") th.absolute Absolute th.offset Offset th.state State + th.tstate Toolpath + //th.tstate Min + //th.tstate Max th.actions button.pure-button(:disabled="!can_set_axis", title="Zero all axis offsets.", @click="zero()",style="height:60px;width:60px") ∅ @@ -95,6 +98,60 @@ script#control-view-template(type="text/x-template") td.state .fa(:class=`'fa-' + ${axis}.icon`) | {{#{axis}.state}} + td.tstate(:class=`${axis}.tklass`, :title=`${axis}.toolmsg`, @click=`show_toolpath_msg('${axis}')`) + .fa(:class=`'fa-' + ${axis}.ticon`) + | {{#{axis}.tstate}} + //td.tstate: unit-value(:value=`${axis}.pathMin`, precision=4) + //td.tstate: unit-value(:value=`${axis}.pathMax`, precision=4) + + message(:show.sync=`toolpath_msg['${axis}']`) + h3(slot="header") Tool path info {{'#{axis}' | upper}} axis + + div(slot="body") + p {{#{axis}.toolmsg}} + + div(slot="footer") + button.pure-button(@click=`toolpath_msg['${axis}'] = false`) + | OK + + message(:show.sync=`ask_home_msg`) + h3(slot="header") Home Machine + + div(slot="body") + p Home the machine? + + div(slot="footer") + button.pure-button(@click="home()") + | OK + + button.pure-button(@click='ask_home_msg = false; ask_home = false') + | Cancel + + message(:show.sync=`ask_zero_xy_msg`) + h3(slot="header") XY Origin + + div(slot="body") + p Move to XY origin? + + div(slot="footer") + button.pure-button(@click="goto_zero(1,1,0,0)") + | Confirm + + button.pure-button(@click='ask_zero_xy_msg = false') + | Cancel + + message(:show.sync=`ask_zero_z_msg`) + h3(slot="header") Z Origin + + div(slot="body") + p Move to Z origin? + + div(slot="footer") + button.pure-button(@click="goto_zero(0,0,1,0)") + | Confirm + + button.pure-button(@click='ask_zero_z_msg = false') + | Cancel th.actions button.pure-button(:disabled="!can_set_axis", @@ -240,7 +297,7 @@ script#control-view-template(type="text/x-template") .bar(:style="'width:' + (progress || 0) * 100 + '%'") tr td(style="white-space: nowrap;text-align:center") - button(style="height:100px;width:200px",@click="tool_msg = true",) Probe XYZ + button(:class="state['pw'] ? '' : 'load-on'",style="height:100px;width:200px",@click="tool_msg = true",) Probe XYZ message(:show.sync=`tool_msg`) h3(slot="header") Enter probe tool information @@ -249,7 +306,7 @@ script#control-view-template(type="text/x-template") .pure-form .pure-control-group label="{{metric ? 'Diameter (mm)' : 'Diameter (inches)'}}" - input(v-model="tool_diameter", + input(v-model="tool_diameter",size="8", @keyup.enter=`set_tool_diameter(tool_diameter)`) p @@ -261,7 +318,8 @@ script#control-view-template(type="text/x-template") @click=`set_tool_diameter(tool_diameter)`) Set - button(style="height:100px;width:200px",@click="probe_z()") Probe Z + button(:class="state['pw'] ? '' : 'load-on'",style="height:100px;width:200px",@click="probe_z()") Probe Z + .tabs @@ -333,7 +391,8 @@ script#control-view-template(type="text/x-template") |  selected select(title="Select previously uploaded GCode programs.", - v-model="state.selected", @change="load", :disabled="!is_ready") + v-model="state.selected", @change="load", :disabled="!is_ready", + style="max-width:100%") option(v-for="file in state.files", :value="file") {{file}} .progress(v-if="toolpath_progress && toolpath_progress < 1", diff --git a/src/pwr/config.h b/src/pwr/config.h index 206d91e..b482624 100644 --- a/src/pwr/config.h +++ b/src/pwr/config.h @@ -103,6 +103,7 @@ enum { #define VOLTAGE_REF_R2 1000 #define CURRENT_REF_R2 137 #define CURRENT_REF_MUL (100.0 * 2700 / CURRENT_REF_R2) // 2700 from datasheet +#define CAP_PRECHARGE_PERIOD 50 // ms #define REG_SCALE 100 #define AVG_SCALE 3 diff --git a/src/pwr/main.c b/src/pwr/main.c index 92007c4..cddef59 100644 --- a/src/pwr/main.c +++ b/src/pwr/main.c @@ -368,6 +368,13 @@ static void validate_input_voltage() { static void charge_caps() { IO_PORT_SET(SHUNT_PIN); // Disable shunt (hi) + + delay(5); + IO_PORT_SET(PC2_PIN); //Enable pre-charge circuit + delay(CAP_PRECHARGE_PERIOD); //Wait for Vs caps to charge + IO_PORT_CLR(PC2_PIN); //Disable pre-charge circuit + delay(1); + IO_PORT_SET(MOTOR_PIN); // Motor voltage on delay(CAP_CHARGE_TIME); } @@ -407,6 +414,8 @@ void init() { IO_PUE_SET(PWR_RESET); // Pull up reset line IO_PORT_CLR(SHUNT_PIN); // Enable shunt IO_DDR_SET(SHUNT_PIN); // Output + IO_PORT_CLR(PC2_PIN); // Disable cap precharge circuit + IO_DDR_SET(PC2_PIN); //Output // Disable digital IO on ADC lines DIDR0 = (1 << ADC4D) | (1 << ADC3D) | (1 << ADC2D) | (1 << ADC1D) | diff --git a/src/py/bbctrl/Web.py b/src/py/bbctrl/Web.py index 5b1a46c..a19a677 100644 --- a/src/py/bbctrl/Web.py +++ b/src/py/bbctrl/Web.py @@ -80,6 +80,10 @@ class RebootHandler(bbctrl.APIHandler): def put_ok(self): self.get_ctrl().lcd.goodbye('Rebooting...') subprocess.Popen('reboot') + +class ShutdownHandler(bbctrl.APIHandler): + def put_ok(self): + subprocess.Popen(['shutdown','-h','now']) class LogHandler(bbctrl.RequestHandler): @@ -516,6 +520,7 @@ class Web(tornado.web.Application): (r'/api/message/(\d+)/ack', MessageAckHandler), (r'/api/bugreport', BugReportHandler), (r'/api/reboot', RebootHandler), + (r'/api/shutdown', ShutdownHandler), (r'/api/hostname', HostnameHandler), (r'/api/wifi', WifiHandler), (r'/api/remote/username', UsernameHandler), diff --git a/src/resources/config-template.json b/src/resources/config-template.json index 4820da5..3d77138 100644 --- a/src/resources/config-template.json +++ b/src/resources/config-template.json @@ -485,14 +485,14 @@ }, "probe-fast-seek": { "type": "float", - "unit": "mm/s", + "unit": "mm/m", "min": 0, "max": 1000, "default": 200 }, "probe-slow-seek": { "type": "float", - "unit": "mm/s", + "unit": "mm/m", "min": 0, "max": 1000, "default": 25 diff --git a/src/resources/onefinity_machinist_defaults.json b/src/resources/onefinity_machinist_defaults.json new file mode 100644 index 0000000..1425070 --- /dev/null +++ b/src/resources/onefinity_machinist_defaults.json @@ -0,0 +1,324 @@ +{ + "tool": { + "tool-reversed": false, + "tool-enable-mode": "disabled", + "tool-direction-mode": "disabled", + "tool-type": "PWM Spindle", + "min-spin": 0, + "max-spin": 255 + }, + "switches": { + "switch-lockout": 250, + "estop": "disabled", + "switch-debounce": 5, + "probe": "normally-open" + }, + "probe": { + "probe-ydim": 53.975, + "probe-slow-seek": 25, + "probe-fast-seek": 100, + "probe-zdim": 15.4, + "probe-xdim": 53.975 + }, + "version": "1.0.4", + "outputs": { + "load-1": "disabled", + "fault": "disabled", + "load-2": "disabled" + }, + "settings": { + "junction-accel": 199999.999, + "max-deviation": 0.05, + "units": "METRIC" + }, + "motors": [ + { + "latch-velocity": 0.1, + "max-accel": 750, + "max-velocity": 12.75, + "search-velocity": 0.844, + "travel-per-rev": 10, + "idle-current": 0.5, + "drive-current": 2.8, + "latch-backoff": 5.001, + "enabled": true, + "homing-mode": "stall-min", + "reverse": false, + "stall-microstep": 16, + "min-soft-limit": 0, + "max-switch": "disabled", + "step-angle": 1.8, + "stall-current": 0.9, + "stall-sample-time": 200, + "microsteps": 16, + "stall-volts": 2, + "axis": "X", + "min-switch": "disabled", + "max-jerk": 1000, + "max-soft-limit": 410, + "zero-backoff": 1.5 + }, + { + "latch-velocity": 0.1, + "max-accel": 750, + "max-velocity": 12.75, + "search-velocity": 0.844, + "travel-per-rev": 10, + "idle-current": 0.5, + "drive-current": 2.8, + "latch-backoff": 5.001, + "enabled": true, + "homing-mode": "stall-min", + "reverse": false, + "stall-microstep": 16, + "min-soft-limit": 0, + "max-switch": "disabled", + "step-angle": 1.8, + "stall-current": 1, + "stall-sample-time": 200, + "microsteps": 16, + "stall-volts": 2, + "axis": "Y", + "min-switch": "disabled", + "max-jerk": 1000, + "max-soft-limit": 410, + "zero-backoff": 1.5 + }, + { + "latch-velocity": 0.1, + "max-accel": 10, + "max-velocity": 17, + "search-velocity": 0.5, + "travel-per-rev": 10, + "idle-current": 0.5, + "drive-current": 2.8, + "latch-backoff": 5, + "enabled": true, + "homing-mode": "manual", + "reverse": false, + "stall-microstep": 8, + "min-soft-limit": 0, + "max-switch": "disabled", + "step-angle": 1.8, + "stall-current": 1.5, + "stall-sample-time": 50, + "microsteps": 16, + "stall-volts": 6, + "axis": "Y", + "min-switch": "disabled", + "max-jerk": 50, + "max-soft-limit": 752, + "zero-backoff": 1 + }, + { + "latch-velocity": 0.1, + "max-accel": 750, + "max-velocity": 3, + "search-velocity": 0.675, + "travel-per-rev": 4, + "idle-current": 0.5, + "drive-current": 2.8, + "latch-backoff": 5.001, + "enabled": true, + "homing-mode": "stall-max", + "reverse": true, + "stall-microstep": 8, + "min-soft-limit": -133, + "max-switch": "disabled", + "step-angle": 1.8, + "stall-current": 1, + "stall-sample-time": 200, + "microsteps": 16, + "stall-volts": 2, + "axis": "Z", + "min-switch": "disabled", + "max-jerk": 1000, + "max-soft-limit": 0, + "zero-backoff": 1 + } + ], + "modbus-spindle": { + "baud": "9600", + "multi-write": false, + "regs": [ + { + "reg-type": "disabled", + "reg-value": 0, + "reg-addr": 0 + }, + { + "reg-type": "disabled", + "reg-value": 0, + "reg-addr": 0 + }, + { + "reg-type": "disabled", + "reg-value": 0, + "reg-addr": 0 + }, + { + "reg-type": "disabled", + "reg-value": 0, + "reg-addr": 0 + }, + { + "reg-type": "disabled", + "reg-value": 0, + "reg-addr": 0 + }, + { + "reg-type": "disabled", + "reg-value": 0, + "reg-addr": 0 + }, + { + "reg-type": "disabled", + "reg-value": 0, + "reg-addr": 0 + }, + { + "reg-type": "disabled", + "reg-value": 0, + "reg-addr": 0 + }, + { + "reg-type": "disabled", + "reg-value": 0, + "reg-addr": 0 + }, + { + "reg-type": "disabled", + "reg-value": 0, + "reg-addr": 0 + }, + { + "reg-type": "disabled", + "reg-value": 0, + "reg-addr": 0 + }, + { + "reg-type": "disabled", + "reg-value": 0, + "reg-addr": 0 + }, + { + "reg-type": "disabled", + "reg-value": 0, + "reg-addr": 0 + }, + { + "reg-type": "disabled", + "reg-value": 0, + "reg-addr": 0 + }, + { + "reg-type": "disabled", + "reg-value": 0, + "reg-addr": 0 + }, + { + "reg-type": "disabled", + "reg-value": 0, + "reg-addr": 0 + }, + { + "reg-type": "disabled", + "reg-value": 0, + "reg-addr": 0 + }, + { + "reg-type": "disabled", + "reg-value": 0, + "reg-addr": 0 + }, + { + "reg-type": "disabled", + "reg-value": 0, + "reg-addr": 0 + }, + { + "reg-type": "disabled", + "reg-value": 0, + "reg-addr": 0 + }, + { + "reg-type": "disabled", + "reg-value": 0, + "reg-addr": 0 + }, + { + "reg-type": "disabled", + "reg-value": 0, + "reg-addr": 0 + }, + { + "reg-type": "disabled", + "reg-value": 0, + "reg-addr": 0 + }, + { + "reg-type": "disabled", + "reg-value": 0, + "reg-addr": 0 + }, + { + "reg-type": "disabled", + "reg-value": 0, + "reg-addr": 0 + }, + { + "reg-type": "disabled", + "reg-value": 0, + "reg-addr": 0 + }, + { + "reg-type": "disabled", + "reg-value": 0, + "reg-addr": 0 + }, + { + "reg-type": "disabled", + "reg-value": 0, + "reg-addr": 0 + }, + { + "reg-type": "disabled", + "reg-value": 0, + "reg-addr": 0 + }, + { + "reg-type": "disabled", + "reg-value": 0, + "reg-addr": 0 + }, + { + "reg-type": "disabled", + "reg-value": 0, + "reg-addr": 0 + }, + { + "reg-type": "disabled", + "reg-value": 0, + "reg-addr": 0 + } + ], + "bus-id": "1", + "parity": "None" + }, + "pwm-spindle": { + "pwm-min-duty": 1, + "pwm-inverted": false, + "pwm-max-duty": 99.99, + "pwm-freq": 1000, + "dynamic-power": true, + "rapid-auto-off": true + }, + "admin": { + "auto-check-upgrade": true + }, + "gcode": { + "program-start": "(Runs at program start)\nG90 (Absolute distance mode)\nG17 (Select XY plane)\n", + "tool-change": "(Runs on M6, tool change)\nM70\nG21\nS0\nM0 M6 (MSG, Change tool and attach probe)\nF100\n(probe to minimum z soft limit, which is -10)\nG38.2 Z-10\nG92 Z15.4\ng0 Z30\nM0 (MSG, Remove probe, start spindle)\nM72\n\n", + "program-end": "(Runs on M2, program end)\nM2" + } +} diff --git a/src/resources/onefinity_woodworker_defaults.json b/src/resources/onefinity_woodworker_defaults.json new file mode 100644 index 0000000..ec9ed80 --- /dev/null +++ b/src/resources/onefinity_woodworker_defaults.json @@ -0,0 +1,324 @@ +{ + "tool": { + "tool-reversed": false, + "tool-enable-mode": "disabled", + "tool-direction-mode": "disabled", + "tool-type": "PWM Spindle", + "min-spin": 0, + "max-spin": 255 + }, + "switches": { + "switch-lockout": 250, + "estop": "disabled", + "switch-debounce": 5, + "probe": "normally-open" + }, + "probe": { + "probe-ydim": 53.975, + "probe-slow-seek": 25, + "probe-fast-seek": 100, + "probe-zdim": 15.4, + "probe-xdim": 53.975 + }, + "version": "1.0.4", + "outputs": { + "load-1": "disabled", + "fault": "disabled", + "load-2": "disabled" + }, + "settings": { + "junction-accel": 199999.999, + "max-deviation": 0.05, + "units": "METRIC" + }, + "motors": [ + { + "latch-velocity": 0.1, + "max-accel": 750, + "max-velocity": 12.75, + "search-velocity": 0.844, + "travel-per-rev": 10, + "idle-current": 0.5, + "drive-current": 2.8, + "latch-backoff": 5.001, + "enabled": true, + "homing-mode": "stall-min", + "reverse": false, + "stall-microstep": 16, + "min-soft-limit": 0, + "max-switch": "disabled", + "step-angle": 1.8, + "stall-current": 1, + "stall-sample-time": 200, + "microsteps": 16, + "stall-volts": 2, + "axis": "X", + "min-switch": "disabled", + "max-jerk": 1000, + "max-soft-limit": 816, + "zero-backoff": 1.5 + }, + { + "latch-velocity": 0.1, + "max-accel": 750, + "max-velocity": 12.75, + "search-velocity": 0.844, + "travel-per-rev": 10, + "idle-current": 0.5, + "drive-current": 2.8, + "latch-backoff": 5.001, + "enabled": true, + "homing-mode": "stall-min", + "reverse": false, + "stall-microstep": 16, + "min-soft-limit": 0, + "max-switch": "disabled", + "step-angle": 1.8, + "stall-current": 1, + "stall-sample-time": 200, + "microsteps": 16, + "stall-volts": 2, + "axis": "Y", + "min-switch": "disabled", + "max-jerk": 1000, + "max-soft-limit": 816, + "zero-backoff": 1.5 + }, + { + "latch-velocity": 0.1, + "max-accel": 10, + "max-velocity": 17, + "search-velocity": 0.5, + "travel-per-rev": 10, + "idle-current": 0.5, + "drive-current": 2.8, + "latch-backoff": 5, + "enabled": true, + "homing-mode": "manual", + "reverse": false, + "stall-microstep": 8, + "min-soft-limit": 0, + "max-switch": "disabled", + "step-angle": 1.8, + "stall-current": 1.5, + "stall-sample-time": 50, + "microsteps": 16, + "stall-volts": 6, + "axis": "Y", + "min-switch": "disabled", + "max-jerk": 50, + "max-soft-limit": 752, + "zero-backoff": 1 + }, + { + "latch-velocity": 0.1, + "max-accel": 750, + "max-velocity": 3, + "search-velocity": 0.675, + "travel-per-rev": 4, + "idle-current": 0.5, + "drive-current": 2.8, + "latch-backoff": 5.001, + "enabled": true, + "homing-mode": "stall-max", + "reverse": true, + "stall-microstep": 8, + "min-soft-limit": -133, + "max-switch": "disabled", + "step-angle": 1.8, + "stall-current": 1, + "stall-sample-time": 200, + "microsteps": 16, + "stall-volts": 2, + "axis": "Z", + "min-switch": "disabled", + "max-jerk": 1000, + "max-soft-limit": 0, + "zero-backoff": 1 + } + ], + "modbus-spindle": { + "baud": "9600", + "multi-write": false, + "regs": [ + { + "reg-type": "disabled", + "reg-value": 0, + "reg-addr": 0 + }, + { + "reg-type": "disabled", + "reg-value": 0, + "reg-addr": 0 + }, + { + "reg-type": "disabled", + "reg-value": 0, + "reg-addr": 0 + }, + { + "reg-type": "disabled", + "reg-value": 0, + "reg-addr": 0 + }, + { + "reg-type": "disabled", + "reg-value": 0, + "reg-addr": 0 + }, + { + "reg-type": "disabled", + "reg-value": 0, + "reg-addr": 0 + }, + { + "reg-type": "disabled", + "reg-value": 0, + "reg-addr": 0 + }, + { + "reg-type": "disabled", + "reg-value": 0, + "reg-addr": 0 + }, + { + "reg-type": "disabled", + "reg-value": 0, + "reg-addr": 0 + }, + { + "reg-type": "disabled", + "reg-value": 0, + "reg-addr": 0 + }, + { + "reg-type": "disabled", + "reg-value": 0, + "reg-addr": 0 + }, + { + "reg-type": "disabled", + "reg-value": 0, + "reg-addr": 0 + }, + { + "reg-type": "disabled", + "reg-value": 0, + "reg-addr": 0 + }, + { + "reg-type": "disabled", + "reg-value": 0, + "reg-addr": 0 + }, + { + "reg-type": "disabled", + "reg-value": 0, + "reg-addr": 0 + }, + { + "reg-type": "disabled", + "reg-value": 0, + "reg-addr": 0 + }, + { + "reg-type": "disabled", + "reg-value": 0, + "reg-addr": 0 + }, + { + "reg-type": "disabled", + "reg-value": 0, + "reg-addr": 0 + }, + { + "reg-type": "disabled", + "reg-value": 0, + "reg-addr": 0 + }, + { + "reg-type": "disabled", + "reg-value": 0, + "reg-addr": 0 + }, + { + "reg-type": "disabled", + "reg-value": 0, + "reg-addr": 0 + }, + { + "reg-type": "disabled", + "reg-value": 0, + "reg-addr": 0 + }, + { + "reg-type": "disabled", + "reg-value": 0, + "reg-addr": 0 + }, + { + "reg-type": "disabled", + "reg-value": 0, + "reg-addr": 0 + }, + { + "reg-type": "disabled", + "reg-value": 0, + "reg-addr": 0 + }, + { + "reg-type": "disabled", + "reg-value": 0, + "reg-addr": 0 + }, + { + "reg-type": "disabled", + "reg-value": 0, + "reg-addr": 0 + }, + { + "reg-type": "disabled", + "reg-value": 0, + "reg-addr": 0 + }, + { + "reg-type": "disabled", + "reg-value": 0, + "reg-addr": 0 + }, + { + "reg-type": "disabled", + "reg-value": 0, + "reg-addr": 0 + }, + { + "reg-type": "disabled", + "reg-value": 0, + "reg-addr": 0 + }, + { + "reg-type": "disabled", + "reg-value": 0, + "reg-addr": 0 + } + ], + "bus-id": "1", + "parity": "None" + }, + "pwm-spindle": { + "pwm-min-duty": 1, + "pwm-inverted": false, + "pwm-max-duty": 99.99, + "pwm-freq": 1000, + "dynamic-power": true, + "rapid-auto-off": true + }, + "admin": { + "auto-check-upgrade": true + }, + "gcode": { + "program-start": "(Runs at program start)\nG90 (Absolute distance mode)\nG17 (Select XY plane)\n", + "tool-change": "(Runs on M6, tool change)\nM70\nG21\nS0\nM0 M6 (MSG, Change tool and attach probe)\nF100\n(probe to minimum z soft limit, which is -10)\nG38.2 Z-10\nG92 Z15.4\ng0 Z30\nM0 (MSG, Remove probe, start spindle)\nM72\n\n", + "program-end": "(Runs on M2, program end)\nM2" + } +} diff --git a/src/stylus/style.styl b/src/stylus/style.styl index c08c485..6219eca 100644 --- a/src/stylus/style.styl +++ b/src/stylus/style.styl @@ -336,6 +336,14 @@ span.unit .absolute, .offset min-width 6em + + td.tstate + text-align left + + .fa + font-size 140% + margin-left 2px + margin-right 6px tr:nth-child(1) th.actions text-align right