From: Joseph Coffland Date: Tue, 13 Feb 2018 00:05:53 +0000 (-0800) Subject: - Added alternate units for motor parameters X-Git-Url: https://git.buildbotics.com/?a=commitdiff_plain;h=c4c0e1c368506191643869f420907ee856f73bac;p=bbctrl-firmware - Added alternate units for motor parameters - Automatic config file upgrading - Fixed planner/jog sync - Fixed planner limits config - Accel units mm/min² -> m/min² - Search and latch velocity mm/min -> m/min - Fixed password update (broken in last version) - Start Web server eariler in case of Python coding errors --- diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 0000000..745d8f5 --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,12 @@ +Buildbotics CNC Controller Firmware Change Log +============================================== + +## v0.3.4 + - Added alternate units for motor parameters + - Automatic config file upgrading + - Fixed planner/jog sync + - Fixed planner limits config + - Accel units mm/min² -> m/min² + - Search and latch velocity mm/min -> m/min + - Fixed password update (broken in last version) + - Start Web server eariler in case of Python coding errors diff --git a/Makefile b/Makefile index 8b15435..b10db0a 100644 --- a/Makefile +++ b/Makefile @@ -61,8 +61,10 @@ $(GPLAN_TARGET): $(GPLAN_MOD) $(GPLAN_MOD): $(GPLAN_IMG) ./scripts/gplan-init-build.sh - git -C rpi-share/cbang pull - git -C rpi-share/camotics pull + git -C rpi-share/cbang fetch + git -C rpi-share/cbang reset --hard FETCH_HEAD + git -C rpi-share/camotics fetch + git -C rpi-share/camotics reset --hard FETCH_HEAD cp ./scripts/gplan-build.sh rpi-share/ sudo ./scripts/rpi-chroot.sh $(GPLAN_IMG) /mnt/host/gplan-build.sh diff --git a/package.json b/package.json index 214a07f..8cbb856 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "bbctrl", - "version": "0.3.3", + "version": "0.3.4", "homepage": "http://buildbotics.com/", "repository": "https://github.com/buildbotics/bbctrl-firmware", "license": "GPL-3.0+", diff --git a/scripts/gplan-init-build.sh b/scripts/gplan-init-build.sh index a4cbde3..6459f49 100755 --- a/scripts/gplan-init-build.sh +++ b/scripts/gplan-init-build.sh @@ -31,11 +31,18 @@ if [ ! -e $GPLAN_IMG ]; then fi # Get repos +function fetch_local_repo() { + mkdir -p $1 + git -C $1 init + git -C $1 fetch -t "$2" $3 + git -C $1 reset --hard FETCH_HEAD +} + mkdir -p rpi-share || true if [ ! -e rpi-share/cbang ]; then if [ "$CBANG_HOME" != "" ]; then - git clone $CBANG_HOME rpi-share/cbang + fetch_local_repo rpi-share/cbang "$CBANG_HOME" master else git clone https://github.com/CauldronDevelopmentLLC/cbang \ rpi-share/cbang @@ -44,7 +51,7 @@ fi if [ ! -e rpi-share/camotics ]; then if [ "$CAMOTICS_HOME" != "" ]; then - git clone $CAMOTICS_HOME rpi-share/camotics + fetch_local_repo rpi-share/camotics "$CAMOTICS_HOME" master else git clone https://github.com/CauldronDevelopmentLLC/camotics \ rpi-share/camotics diff --git a/src/avr/src/config.h b/src/avr/src/config.h index 0393dda..1dde933 100644 --- a/src/avr/src/config.h +++ b/src/avr/src/config.h @@ -211,7 +211,7 @@ enum { #define CURRENT_SENSE_REF 2.75 // volts #define MAX_CURRENT 10 // amps #define VELOCITY_MULTIPLIER 1000.0 -#define ACCEL_MULTIPLIER 1000.0 +#define ACCEL_MULTIPLIER 1000000.0 #define JERK_MULTIPLIER 1000000.0 #define SYNC_QUEUE_SIZE 4096 #define EXEC_FILL_TARGET 8 diff --git a/src/avr/src/exec.c b/src/avr/src/exec.c index e8f75a3..5315a24 100644 --- a/src/avr/src/exec.c +++ b/src/avr/src/exec.c @@ -58,7 +58,6 @@ void exec_init() { memset(&ex, 0, sizeof(ex)); ex.feed_override = 1; ex.spindle_override = 1; - // TODO implement pause // TODO implement move stepping // TODO implement overrides // TODO implement optional pause diff --git a/src/jade/templates/motor-view.jade b/src/jade/templates/motor-view.jade index 9827706..2a5777d 100644 --- a/src/jade/templates/motor-view.jade +++ b/src/jade/templates/motor-view.jade @@ -8,3 +8,24 @@ script#motor-view-template(type="text/x-template") templated-input(v-for="templ in category", :name="$key", :model.sync="motor[$key]", :template="templ") + + label.extra(v-if="$key == 'max-velocity'", slot="extra", + title="Revolutions Per Minute") + | ({{1000 * motor[$key] / motor['travel-per-rev'] | fixed 0}} RPM) + + label.extra(v-if="$key == 'max-accel'", slot="extra", + title="G-force") + | ({{motor[$key] * 0.0283254504 | fixed 3}} g) + + label.extra(v-if="$key == 'max-jerk'", slot="extra", + title="G-force per minute") + | ({{motor[$key] * 0.0283254504 | fixed 2}} g/min) + + label.extra(v-if="$key == 'step-angle'", slot="extra", + title="Steps per revolution") + | ({{360 / motor[$key] | fixed 0}} steps/rev) + + label.extra(v-if="$key == 'travel-per-rev'", slot="extra", + title="Micrometers per step") + | ({{motor[$key] * motor['step-angle'] / 0.36 | fixed 1}} + |  Âµm/step) diff --git a/src/jade/templates/templated-input.jade b/src/jade/templates/templated-input.jade index 855d91d..85bdbdb 100644 --- a/src/jade/templates/templated-input.jade +++ b/src/jade/templates/templated-input.jade @@ -1,5 +1,6 @@ script#templated-input-template(type="text/x-template") - .pure-control-group(:class="name") + .pure-control-group(class="tmpl-input-{{name}}", + title="Default {{template.default}} {{template.unit}}") label(:for="name") {{name}} select(v-if="template.type == 'enum' || template.values", v-model="model", @@ -29,3 +30,5 @@ script#templated-input-template(type="text/x-template") | {{model}} label.units {{template.unit}} + + slot(name="extra") diff --git a/src/js/app.js b/src/js/app.js index 228db44..58947ad 100644 --- a/src/js/app.js +++ b/src/js/app.js @@ -63,7 +63,7 @@ module.exports = new Vue({ send: function (msg) { if (this.status == 'connected') { console.debug('>', msg); - this.sock.send(msg) + this.sock.send(msg); } }, @@ -122,7 +122,7 @@ module.exports = new Vue({ }.bind(this)).fail(function () { alert('Invalid password'); - }.bind(this)); + }.bind(this)) }, @@ -164,18 +164,18 @@ module.exports = new Vue({ if (key == 'msg') this.$broadcast('message', msg.msg); else Vue.set(this.state, key, msg[key]); } - }.bind(this); + }.bind(this) this.sock.onopen = function (e) { this.status = 'connected'; this.$emit(this.status); this.$broadcast(this.status); - }.bind(this); + }.bind(this) this.sock.onclose = function (e) { this.status = 'disconnected'; this.$broadcast(this.status); - }.bind(this); + }.bind(this) }, diff --git a/src/js/motor-view.js b/src/js/motor-view.js index 71ca620..fb1623f 100644 --- a/src/js/motor-view.js +++ b/src/js/motor-view.js @@ -15,7 +15,7 @@ module.exports = { watch: { - index: function() {this.update();} + index: function() {this.update()} }, diff --git a/src/py/bbctrl/AVR.py b/src/py/bbctrl/AVR.py index b9ccdfd..478d9bf 100644 --- a/src/py/bbctrl/AVR.py +++ b/src/py/bbctrl/AVR.py @@ -22,9 +22,9 @@ log = logging.getLogger('AVR') # Mark axis homed and set absolute position axis_homing_procedure = ''' - G28.2 %(axis)s0 F[#<_%(axis)s_sv>] + G28.2 %(axis)s0 F[#<_%(axis)s_sv> * 1000] G38.6 %(axis)s[#<_%(axis)s_hd> * [#<_%(axis)s_tm> - #<_%(axis)s_tn>] * 1.5] - G38.8 %(axis)s[#<_%(axis)s_hd> * -#<_%(axis)s_lb>] F[#<_%(axis)s_lv>] + G38.8 %(axis)s[#<_%(axis)s_hd> * -#<_%(axis)s_lb>] F[#<_%(axis)s_lv> * 1000] G38.6 %(axis)s[#<_%(axis)s_hd> * #<_%(axis)s_lb> * 1.5] G91 G0 G53 %(axis)s[#<_%(axis)s_hd> * -#<_%(axis)s_zb>] G90 G28.3 %(axis)s[#<_%(axis)s_hp>] diff --git a/src/py/bbctrl/Config.py b/src/py/bbctrl/Config.py index d66ecbe..5ac4f8f 100644 --- a/src/py/bbctrl/Config.py +++ b/src/py/bbctrl/Config.py @@ -26,13 +26,17 @@ default_config = { class Config(object): def __init__(self, ctrl): self.ctrl = ctrl - self.version = pkg_resources.require('bbctrl')[0].version - default_config['version'] = self.version - # Load config template - with open(bbctrl.get_resource('http/config-template.json'), 'r', - encoding = 'utf-8') as f: - self.template = json.load(f) + try: + self.version = pkg_resources.require('bbctrl')[0].version + default_config['version'] = self.version + + # Load config template + with open(bbctrl.get_resource('http/config-template.json'), 'r', + encoding = 'utf-8') as f: + self.template = json.load(f) + + except Exception as e: log.exception(e) def load_path(self, path): @@ -43,7 +47,10 @@ class Config(object): def load(self): try: config = self.load_path('config.json') - config['version'] = self.version + + try: + self.upgrade(config) + except Exception as e: log.exception(e) # Add missing sections for key, value in default_config.items(): @@ -56,11 +63,26 @@ class Config(object): return default_config - def save(self, config): - self.update(config) + def upgrade(self, config): + version = tuple(map(int, config['version'].split('.'))) + + if version < (0, 2, 4): + for motor in config['motors']: + for key in 'max-jerk max-velocity'.split(): + if key in motor: motor[key] /= 1000 + + if version < (0, 3, 4): + for motor in config['motors']: + for key in 'max-accel latch-velocity search-velocity'.split(): + if key in motor: motor[key] /= 1000 config['version'] = self.version + + def save(self, config): + self.upgrade(config) + self.update(config) + with open('config.json', 'w') as f: json.dump(config, f) diff --git a/src/py/bbctrl/Ctrl.py b/src/py/bbctrl/Ctrl.py index 039e4da..7a22817 100644 --- a/src/py/bbctrl/Ctrl.py +++ b/src/py/bbctrl/Ctrl.py @@ -33,15 +33,19 @@ class Ctrl(object): self.msgs = bbctrl.Messages(self) self.state = bbctrl.State(self) - self.planner = bbctrl.Planner(self) - self.i2c = bbctrl.I2C(args.i2c_port) self.config = bbctrl.Config(self) - self.lcd = bbctrl.LCD(self) self.web = bbctrl.Web(self) - self.avr = bbctrl.AVR(self) - self.jog = bbctrl.Jog(self) - self.pwr = bbctrl.Pwr(self) - self.avr.connect() + try: + self.planner = bbctrl.Planner(self) + self.i2c = bbctrl.I2C(args.i2c_port) + self.lcd = bbctrl.LCD(self) + self.avr = bbctrl.AVR(self) + self.jog = bbctrl.Jog(self) + self.pwr = bbctrl.Pwr(self) - self.lcd.add_new_page(IPPage(self.lcd)) + self.avr.connect() + + self.lcd.add_new_page(IPPage(self.lcd)) + + except Exception as e: log.exception(e) diff --git a/src/py/bbctrl/Planner.py b/src/py/bbctrl/Planner.py index ee25cb6..d7bcd43 100644 --- a/src/py/bbctrl/Planner.py +++ b/src/py/bbctrl/Planner.py @@ -51,14 +51,18 @@ class Planner(): value = state.get(axis + 'p', None) if value is not None: start[axis] = value - return { + config = { "start": start, "max-vel": get_vector('vm', 1000), - "max-accel": get_vector('am', 1000), + "max-accel": get_vector('am', 1000000), "max-jerk": get_vector('jm', 1000000), # TODO junction deviation & accel } + log.info('Config:' + json.dumps(config)) + + return config + def update(self, update): if 'id' in update: self.planner.set_active(update['id']) @@ -116,7 +120,7 @@ class Planner(): raise Exception('Cannot issue MDI command while GCode running') log.info('MDI:' + cmd) - self.planner.load_string(cmd) + self.planner.load_string(cmd, self.get_config()) self.mode = 'mdi' @@ -125,11 +129,11 @@ class Planner(): raise Exception('Busy, cannot start new GCode program') log.info('GCode:' + path) - self.planner.load('upload' + path) + self.planner.load('upload' + path, self.get_config()) def reset(self): - self.planner = gplan.Planner(self.get_config()) + self.planner = gplan.Planner() self.planner.set_resolver(self.get_var) self.planner.set_logger(self.log, 1, 'LinePlanner:3') @@ -172,11 +176,6 @@ class Planner(): def next(self): - if not self.is_running(): - config = self.get_config() - log.info('Planner config:' + json.dumps(config)) - self.planner.set_config(config) - while self.planner.has_more(): cmd = self.planner.next() self.lastID = cmd['id'] diff --git a/src/py/bbctrl/Web.py b/src/py/bbctrl/Web.py index 201cf25..8eb44f4 100644 --- a/src/py/bbctrl/Web.py +++ b/src/py/bbctrl/Web.py @@ -82,7 +82,7 @@ class PasswordHandler(bbctrl.APIHandler): check_password(self.json['current']) # Set password - s = '%s:%s' % (username, self.json['password']) + s = '%s:%s' % (get_username(), self.json['password']) s = s.encode('utf-8') p = subprocess.Popen(['chpasswd', '-c', 'MD5'], diff --git a/src/py/inevent/EventStream.py b/src/py/inevent/EventStream.py index ac68222..404815e 100644 --- a/src/py/inevent/EventStream.py +++ b/src/py/inevent/EventStream.py @@ -143,6 +143,9 @@ class EventStream(object): return self + def next(self): return self.__next__() + + def __next__(self): """ Returns the next waiting event. diff --git a/src/resources/config-template.json b/src/resources/config-template.json index a1638bb..fa754ba 100644 --- a/src/resources/config-template.json +++ b/src/resources/config-template.json @@ -57,8 +57,8 @@ "max-accel": { "type": "float", "min": 0, - "unit": "m/min²", - "default": 1000, + "unit": "km/min²", + "default": 10, "code": "am" }, "max-jerk": { @@ -122,15 +122,15 @@ "search-velocity": { "type": "float", "min": 0, - "unit": "mm/min", - "default": 500, + "unit": "m/min", + "default": 0.5, "code": "sv" }, "latch-velocity": { "type": "float", "min": 0, - "unit": "mm/min", - "default": 100, + "unit": "m/min", + "default": 0.1, "code": "lv" }, "latch-backoff": { diff --git a/src/stylus/style.styl b/src/stylus/style.styl index 289060d..388add5 100644 --- a/src/stylus/style.styl +++ b/src/stylus/style.styl @@ -129,6 +129,9 @@ body text-transform capitalize .pure-control-group + label.units + width 6em + label.units text-align left @@ -136,10 +139,6 @@ body width 24em height 12em - .switch - h3, .pure-control-group - display inline-block - @keyframes blink 50% fill #ff9d00