From: Joseph Coffland Date: Mon, 26 Feb 2018 22:59:25 +0000 (-0800) Subject: - Suppress warning missing config.json warning after config reset. X-Git-Url: https://git.buildbotics.com/?a=commitdiff_plain;h=c6e7ee663aa5545eaccc9c12d4dad400ce0f252c;p=bbctrl-firmware - Suppress warning missing config.json warning after config reset. - Fixed EStop reboot loop. - Removed AVR unexpected reboot error. --- diff --git a/CHANGELOG.md b/CHANGELOG.md index 120a64b..13e69b6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,11 @@ Buildbotics CNC Controller Firmware Change Log ============================================== +## v0.3.15 + - Suppress warning missing config.json warning after config reset. + - Fixed EStop reboot loop. + - Removed AVR unexpected reboot error. + ## v0.3.14 - Fixed: Config fails silently after web disconnect #112 - Always reload the page after a disconnect. diff --git a/package.json b/package.json index b5c255d..208b4d8 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "bbctrl", - "version": "0.3.14", + "version": "0.3.15", "homepage": "http://buildbotics.com/", "repository": "https://github.com/buildbotics/bbctrl-firmware", "license": "GPL-3.0+", diff --git a/src/avr/src/estop.c b/src/avr/src/estop.c index 08ca346..c933560 100644 --- a/src/avr/src/estop.c +++ b/src/avr/src/estop.c @@ -45,7 +45,7 @@ typedef struct { } estop_t; -static estop_t estop = {0}; +static estop_t estop = {false}; static uint16_t estop_reason_eeprom EEMEM; @@ -105,6 +105,10 @@ void estop_trigger(stat_t reason) { void estop_clear() { + // It is important that we don't clear the estop if it's not set because + // it can cause a reboot loop. + if (!estop.triggered) return; + // Check if estop switch is set if (switch_is_active(SW_ESTOP)) { if (_get_reason() != STAT_ESTOP_SWITCH) _set_reason(STAT_ESTOP_SWITCH); diff --git a/src/avr/src/hardware.c b/src/avr/src/hardware.c index 6f67d56..ee81ff7 100644 --- a/src/avr/src/hardware.c +++ b/src/avr/src/hardware.c @@ -127,7 +127,7 @@ void hardware_init() { void hw_request_hard_reset() {hw.hard_reset = true;} -void hw_hard_reset() { +static void _hard_reset() { usart_flush(); cli(); CCP = CCP_IOREG_gc; @@ -137,12 +137,13 @@ void hw_hard_reset() { /// Controller's rest handler void hw_reset_handler() { - if (hw.hard_reset) { - while (!usart_tx_empty() || !eeprom_is_ready()) - continue; + if (!hw.hard_reset) return; - hw_hard_reset(); - } + // Flush serial port and wait for EEPROM writes to finish + while (!usart_tx_empty() || !eeprom_is_ready()) + continue; + + _hard_reset(); } diff --git a/src/avr/src/hardware.h b/src/avr/src/hardware.h index 3bdef89..fdda57e 100644 --- a/src/avr/src/hardware.h +++ b/src/avr/src/hardware.h @@ -34,7 +34,6 @@ void hardware_init(); void hw_request_hard_reset(); -void hw_hard_reset(); void hw_reset_handler(); uint8_t hw_disable_watchdog(); diff --git a/src/avr/src/io.c b/src/avr/src/io.c index e581efb..db2325b 100644 --- a/src/avr/src/io.c +++ b/src/avr/src/io.c @@ -84,19 +84,19 @@ stat_t command_input(char *cmd) { cmd++; // Skip command // Analog or digital - if (cmd[0] == 'd') input_cmd.digital = true; - else if (cmd[0] == 'a') input_cmd.digital = false; + if (*cmd == 'd') input_cmd.digital = true; + else if (*cmd == 'a') input_cmd.digital = false; else return STAT_INVALID_ARGUMENTS; cmd++; // Port index - if (!isdigit(cmd[1])) return STAT_INVALID_ARGUMENTS; - input_cmd.port = cmd[1] - '0'; + if (!isdigit(*cmd)) return STAT_INVALID_ARGUMENTS; + input_cmd.port = *cmd - '0'; cmd++; // Mode - if (!isdigit(cmd[2])) return STAT_INVALID_ARGUMENTS; - input_cmd.mode = cmd[2] - '0'; + if (!isdigit(*cmd)) return STAT_INVALID_ARGUMENTS; + input_cmd.mode = *cmd - '0'; if (INPUT_LOW < input_cmd.mode) return STAT_INVALID_ARGUMENTS; cmd++; diff --git a/src/avr/src/switch.c b/src/avr/src/switch.c index aac99e2..40e3a88 100644 --- a/src/avr/src/switch.c +++ b/src/avr/src/switch.c @@ -38,6 +38,7 @@ typedef struct { switch_callback_t cb; bool state; int8_t debounce; + bool initialized; } switch_t; @@ -83,9 +84,11 @@ void switch_rtc_callback() { // Debounce switch bool state = IN_PIN(s->pin); if (state == s->state) s->debounce = 0; - else if (++s->debounce == SWITCH_DEBOUNCE) { + else if ((state && ++s->debounce == SWITCH_DEBOUNCE) || + (!state && --s->debounce == -SWITCH_DEBOUNCE)) { s->state = state; s->debounce = 0; + s->initialized = true; if (s->cb) s->cb(i, switch_is_active(i)); } } @@ -95,6 +98,8 @@ void switch_rtc_callback() { bool switch_is_active(switch_id_t sw) { if (sw < 0 || num_switches <= sw) return false; + if (!switches[sw].initialized) return false; + // NOTE, switch inputs are active lo switch (switches[sw].type) { case SW_DISABLED: break; // A disabled switch cannot be active diff --git a/src/py/bbctrl/Cmd.py b/src/py/bbctrl/Cmd.py index e7b167e..438e1f2 100644 --- a/src/py/bbctrl/Cmd.py +++ b/src/py/bbctrl/Cmd.py @@ -103,19 +103,19 @@ def speed(speed): return '#s=:' + encode_float(speed) def input(port, mode, timeout): - type = 'd' - index = 0 - m = 0 - - if port == 'digital-in-0': digital, index = 'd', 0 - if port == 'digital-in-1': digital, index = 'd', 1 - if port == 'digital-in-2': digital, index = 'd', 2 - if port == 'digital-in-3': digital, index = 'd', 3 - if port == 'analog-in-0': digital, index = 'a', 0 - if port == 'analog-in-1': digital, index = 'a', 1 - if port == 'analog-in-2': digital, index = 'a', 2 - if port == 'analog-in-3': digital, index = 'a', 3 - + type, index, m = 'd', 0, 0 + + # Analog/digital & port index + if port == 'digital-in-0': type, index = 'd', 0 + if port == 'digital-in-1': type, index = 'd', 1 + if port == 'digital-in-2': type, index = 'd', 2 + if port == 'digital-in-3': type, index = 'd', 3 + if port == 'analog-in-0': type, index = 'a', 0 + if port == 'analog-in-1': type, index = 'a', 1 + if port == 'analog-in-2': type, index = 'a', 2 + if port == 'analog-in-3': type, index = 'a', 3 + + # Mode if mode == 'immediate': m = 0 if mode == 'rise': m = 1 if mode == 'fall': m = 2 diff --git a/src/py/bbctrl/Comm.py b/src/py/bbctrl/Comm.py index 4d98f3a..1c61111 100644 --- a/src/py/bbctrl/Comm.py +++ b/src/py/bbctrl/Comm.py @@ -47,7 +47,6 @@ class Comm(): self.queue = deque() self.in_buf = '' self.command = None - self.reboot_expected = True try: self.sp = serial.Serial(ctrl.args.serial, ctrl.args.baud, @@ -192,13 +191,11 @@ class Comm(): if 'variables' in msg: self._update_vars(msg) - self.reboot_expected = False elif 'msg' in msg: self._log_msg(msg) elif 'firmware' in msg: - if self.reboot_expected: log.info('AVR firmware rebooted') - else: log.error('Unexpected AVR firmware reboot') + log.info('AVR firmware rebooted') self.connect() else: self.ctrl.state.update(msg) @@ -220,7 +217,6 @@ class Comm(): def clear(self): if self.ctrl.state.get('xx', '') == 'ESTOPPED': self.i2c_command(Cmd.CLEAR) - self.reboot_expected = True def pause(self, optional = False): @@ -228,9 +224,7 @@ class Comm(): self.i2c_command(Cmd.PAUSE, byte = data) - def reboot(self): - self.queue_command(Cmd.REBOOT) - self.reboot_expected = True + def reboot(self): self.queue_command(Cmd.REBOOT) def connect(self): diff --git a/src/py/bbctrl/Config.py b/src/py/bbctrl/Config.py index d6c972e..f42fef1 100644 --- a/src/py/bbctrl/Config.py +++ b/src/py/bbctrl/Config.py @@ -30,6 +30,7 @@ import json import logging import pkg_resources import subprocess +import copy import bbctrl @@ -82,7 +83,9 @@ class Config(object): def load(self): try: - config = self.load_path('config.json') + if os.path.exists('config.json'): + config = self.load_path('config.json') + else: config = copy.deepcopy(default_config) try: self.upgrade(config) diff --git a/src/py/bbctrl/Planner.py b/src/py/bbctrl/Planner.py index 4e96ab4..368db4c 100644 --- a/src/py/bbctrl/Planner.py +++ b/src/py/bbctrl/Planner.py @@ -182,6 +182,8 @@ class Planner(): def __encode(self, block): + log.info('Cmd:' + json.dumps(block)) + type = block['type'] if type == 'line': @@ -237,27 +239,6 @@ class Planner(): self.setq.clear() - def stop(self): - self.planner.stop() - self.lastID = 0 - self.setq.clear() - - - def restart(self): - state = self.ctrl.state - id = state.get('id') - - position = {} - for axis in 'xyzabc': - if state.has(axis + 'p'): - position[axis] = state.get(axis + 'p') - - log.info('Planner restart: %d %s' % (id, json.dumps(position))) - self.planner.restart(id, position) - if self.planner.is_synchronizing(): self.planner.synchronize(1) - # TODO if these calls fail we get stuck in a loop - - def mdi(self, cmd): log.info('MDI:' + cmd) self.planner.load_string(cmd, self._get_config(True)) @@ -268,6 +249,36 @@ class Planner(): self.planner.load(path, self._get_config(False)) + def stop(self): + try: + self.planner.stop() + self.lastID = 0 + self.setq.clear() + + except Exception as e: + log.exception(e) + self.reset() + + + def restart(self): + try: + state = self.ctrl.state + id = state.get('id') + + position = {} + for axis in 'xyzabc': + if state.has(axis + 'p'): + position[axis] = state.get(axis + 'p') + + log.info('Planner restart: %d %s' % (id, json.dumps(position))) + self.planner.restart(id, position) + if self.planner.is_synchronizing(): self.planner.synchronize(1) + + except Exception as e: + log.exception(e) + self.reset() + + def has_move(self): return self.planner.has_more() @@ -279,5 +290,5 @@ class Planner(): if cmd is not None: return cmd except Exception as e: - self.reset() log.exception(e) + self.reset()