- Supressed firmware rebooted warning.
authorJoseph Coffland <joseph@cauldrondevelopment.com>
Sat, 24 Feb 2018 00:50:12 +0000 (16:50 -0800)
committerJoseph Coffland <joseph@cauldrondevelopment.com>
Sat, 24 Feb 2018 00:50:12 +0000 (16:50 -0800)
 - Error on unexpected AVR reboot.
Fixed estop fault pin.
Use switch inputs for DRV8711 stall and fault

12 files changed:
CHANGELOG.md
package.json
src/avr/src/config.h
src/avr/src/drv8711.c
src/avr/src/estop.c
src/avr/src/switch.c
src/avr/src/switch.h
src/avr/src/vars.c
src/avr/src/vars.def
src/py/bbctrl/Comm.py
src/py/bbctrl/Mach.py
src/py/bbctrl/State.py

index bff502f65206f61aec47404d35c0754ab4c24667..52c0dbfa70c4f06de7ba214d4fa67be92c7bbaa1 100644 (file)
@@ -1,6 +1,11 @@
 Buildbotics CNC Controller Firmware Change Log
 ==============================================
 
+## v0.3.11
+ - Supressed ``firmware rebooted`` warning.
+ - Error on unexpected AVR reboot.
+ - Enabled switch input slew rate limiting.
+
 ## v0.3.10
  - Fixed "Flood" display, changed to "Load 1" and "Load 2".  #108
  - Highlight loads when on.
index 045bb0c68dd761465295e848170386e78e0c0cb1..18e229ed411cef18333f78694f70595b9cac8c98 100644 (file)
@@ -1,6 +1,6 @@
 {
   "name": "bbctrl",
-  "version": "0.3.10",
+  "version": "0.3.11",
   "homepage": "http://buildbotics.com/",
   "repository": "https://github.com/buildbotics/bbctrl-firmware",
   "license": "GPL-3.0+",
index c9d6717341b15b8754e2b736b88104efbe2260c4..06874900a214b7f234c06356ec2e6bdd64a944e4 100644 (file)
@@ -96,7 +96,6 @@ enum {
 
 #define AXES                     6 // number of axes
 #define MOTORS                   4 // number of motors on the board
-#define SWITCHES                10 // number of supported switches
 #define OUTS                     5 // number of supported pin outputs
 
 
index ba8cea20ab34e3cafeff918377b938aed05df0f5..e9f77e67ce5d7711c62bf3cc14531fba7996519b 100644 (file)
@@ -28,6 +28,7 @@
 #include "drv8711.h"
 #include "status.h"
 #include "stepper.h"
+#include "switch.h"
 #include "report.h"
 
 #include <avr/interrupt.h>
@@ -58,6 +59,7 @@ typedef struct {
 typedef struct {
   uint8_t status;
   uint16_t flags;
+  bool stalled;
 
   drv8711_state_t state;
   current_t drive;
@@ -68,15 +70,15 @@ typedef struct {
   stall_callback_t stall_cb;
 
   uint8_t cs_pin;
-  uint8_t stall_pin;
+  switch_id_t stall_sw;
 } drv8711_driver_t;
 
 
 static drv8711_driver_t drivers[DRIVERS] = {
-  {.cs_pin = SPI_CS_X_PIN, .stall_pin = STALL_X_PIN},
-  {.cs_pin = SPI_CS_Y_PIN, .stall_pin = STALL_Y_PIN},
-  {.cs_pin = SPI_CS_Z_PIN, .stall_pin = STALL_Z_PIN},
-  {.cs_pin = SPI_CS_A_PIN, .stall_pin = STALL_A_PIN},
+  {.cs_pin = SPI_CS_X_PIN, .stall_sw = SW_STALL_X},
+  {.cs_pin = SPI_CS_Y_PIN, .stall_sw = SW_STALL_Y},
+  {.cs_pin = SPI_CS_Z_PIN, .stall_sw = SW_STALL_Z},
+  {.cs_pin = SPI_CS_A_PIN, .stall_sw = SW_STALL_A},
 };
 
 
@@ -304,15 +306,29 @@ static void _init_spi_commands() {
 ISR(SPIC_INT_vect) {_spi_send();}
 
 
-ISR(STALL_ISR_vect) {
-  for (int i = 0; i < DRIVERS; i++) {
-    drv8711_driver_t *driver = &drivers[i];
-    if (driver->stall_cb) driver->stall_cb(i);
+static void _stall_change(int driver, bool stalled) {
+  drivers[driver].stalled = stalled;
+
+  // Call stall callback
+  if (stalled && drivers[driver].stall_cb)
+    drivers[driver].stall_cb(driver);
+}
+
+
+static void _stall_switch_cb(switch_id_t sw, bool active) {
+  switch (sw) {
+  case SW_STALL_X: _stall_change(0, active); break;
+  case SW_STALL_Y: _stall_change(1, active); break;
+  case SW_STALL_Z: _stall_change(2, active); break;
+  case SW_STALL_A: _stall_change(3, active); break;
+  default: break;
   }
 }
 
 
-ISR(FAULT_ISR_vect) {motor_fault = !IN_PIN(MOTOR_FAULT_PIN);} // TODO
+static void _motor_fault_switch_cb(switch_id_t sw, bool active) {
+  motor_fault = active; // TODO
+}
 
 
 void drv8711_init() {
@@ -328,23 +344,16 @@ void drv8711_init() {
 
   for (int i = 0; i < DRIVERS; i++) {
     uint8_t cs_pin = drivers[i].cs_pin;
-    uint8_t stall_pin = drivers[i].stall_pin;
-
     OUTSET_PIN(cs_pin);     // High
     DIRSET_PIN(cs_pin);     // Output
-    DIRCLR_PIN(stall_pin);  // Input
 
-    // Stall interrupt
-    PINCTRL_PIN(stall_pin) = PORT_ISC_FALLING_gc;
-    PORT(stall_pin)->INT1MASK |= BM(stall_pin);
-    PORT(stall_pin)->INTCTRL |= PORT_INT1LVL_HI_gc;
+    switch_id_t stall_sw = drivers[i].stall_sw;
+    switch_set_type(stall_sw, SW_NORMALLY_OPEN);
+    switch_set_callback(stall_sw, _stall_switch_cb);
   }
 
-  // Fault interrupt
-  DIRCLR_PIN(MOTOR_FAULT_PIN);
-  PINCTRL_PIN(MOTOR_FAULT_PIN) = PORT_ISC_RISING_gc;
-  PORT(MOTOR_FAULT_PIN)->INT1MASK |= BM(MOTOR_FAULT_PIN);
-  PORT(MOTOR_FAULT_PIN)->INTCTRL |= PORT_INT1LVL_HI_gc;
+  switch_set_type(SW_MOTOR_FAULT, SW_NORMALLY_OPEN);
+  switch_set_callback(SW_MOTOR_FAULT, _motor_fault_switch_cb);
 
   // Configure SPI
   PR.PRPC &= ~PR_SPI_bm; // Disable power reduction
@@ -483,6 +492,7 @@ void print_status_flags(uint16_t flags) {
 
 
 uint16_t get_status_strings(int driver) {return get_driver_flags(driver);}
+bool get_driver_stalled(int driver) {return drivers[driver].stalled;}
 
 
 // Command callback
index 943ce38652169998247ae43d74b0ca1713ac35bd..08ca346486e78d15c55fc0b8da2acb8a8703f066 100644 (file)
@@ -34,6 +34,7 @@
 #include "hardware.h"
 #include "config.h"
 #include "state.h"
+#include "outputs.h"
 #include "exec.h"
 
 #include <avr/eeprom.h>
@@ -75,8 +76,7 @@ void estop_init() {
   if (estop.triggered) state_estop();
 
   // Fault signal
-  SET_PIN(FAULT_PIN, estop.triggered);
-  DIRSET_PIN(FAULT_PIN); // Output
+  outputs_set_active(FAULT_PIN, estop.triggered);
 }
 
 
@@ -87,6 +87,9 @@ void estop_trigger(stat_t reason) {
   if (estop.triggered) return;
   estop.triggered = true;
 
+  // Set fault signal
+  outputs_set_active(FAULT_PIN, true);
+
   // Hard stop the motors and the spindle
   st_shutdown();
   spindle_stop();
@@ -109,7 +112,7 @@ void estop_clear() {
   }
 
   // Clear fault signal
-  OUTCLR_PIN(FAULT_PIN); // Low
+  outputs_set_active(FAULT_PIN, false);
 
   estop.triggered = false;
 
index 52cfbc49281eb63d76402b61f13dc7e70a76ea42..aee93464d3d525b459d42119fdd0015ec651a52e 100644 (file)
@@ -44,25 +44,33 @@ typedef struct {
 
 
 // Order must match indices in var functions below
-static switch_t switches[SWITCHES] = {
-  {.pin = ESTOP_PIN, .type = SW_DISABLED},
-  {.pin = PROBE_PIN, .type = SW_DISABLED},
-  {.pin = MIN_X_PIN, .type = SW_DISABLED},
-  {.pin = MAX_X_PIN, .type = SW_DISABLED},
-  {.pin = MIN_Y_PIN, .type = SW_DISABLED},
-  {.pin = MAX_Y_PIN, .type = SW_DISABLED},
-  {.pin = MIN_Z_PIN, .type = SW_DISABLED},
-  {.pin = MAX_Z_PIN, .type = SW_DISABLED},
-  {.pin = MIN_A_PIN, .type = SW_DISABLED},
-  {.pin = MAX_A_PIN, .type = SW_DISABLED},
+static switch_t switches[] = {
+  {.pin = ESTOP_PIN,       .type = SW_DISABLED},
+  {.pin = PROBE_PIN,       .type = SW_DISABLED},
+  {.pin = MIN_X_PIN,       .type = SW_DISABLED},
+  {.pin = MAX_X_PIN,       .type = SW_DISABLED},
+  {.pin = MIN_Y_PIN,       .type = SW_DISABLED},
+  {.pin = MAX_Y_PIN,       .type = SW_DISABLED},
+  {.pin = MIN_Z_PIN,       .type = SW_DISABLED},
+  {.pin = MAX_Z_PIN,       .type = SW_DISABLED},
+  {.pin = MIN_A_PIN,       .type = SW_DISABLED},
+  {.pin = MAX_A_PIN,       .type = SW_DISABLED},
+  {.pin = STALL_X_PIN,     .type = SW_DISABLED},
+  {.pin = STALL_Y_PIN,     .type = SW_DISABLED},
+  {.pin = STALL_Z_PIN,     .type = SW_DISABLED},
+  {.pin = STALL_A_PIN,     .type = SW_DISABLED},
+  {.pin = MOTOR_FAULT_PIN, .type = SW_DISABLED},
 };
 
 
+const int num_switches = sizeof(switches) / sizeof (switch_t);
+
+
 static bool _read_state(const switch_t *s) {return IN_PIN(s->pin);}
 
 
 static void _switch_isr() {
-  for (int i = 0; i < SWITCHES; i++) {
+  for (int i = 0; i < num_switches; i++) {
     switch_t *s = &switches[i];
     if (s->type == SW_DISABLED || s->triggered) continue;
     s->triggered = _read_state(s) != s->state;
@@ -91,11 +99,12 @@ void _switch_enable(switch_t *s, bool enable) {
 
 
 void switch_init() {
-  for (int i = 0; i < SWITCHES; i++) {
+  for (int i = 0; i < num_switches; i++) {
     switch_t *s = &switches[i];
 
-    // Pull up and trigger on both edges
-    PINCTRL_PIN(s->pin) = PORT_OPC_PULLUP_gc | PORT_ISC_BOTHEDGES_gc;
+    // Pull up, trigger on both edges and enable slew rate limiting
+    PINCTRL_PIN(s->pin) =
+      PORT_OPC_PULLUP_gc | PORT_ISC_BOTHEDGES_gc;// | PORT_SRLEN_bm;
     DIRCLR_PIN(s->pin); // Input
     PORT(s->pin)->INTCTRL |= SWITCH_INTLVL; // Set interrupt level
 
@@ -106,7 +115,7 @@ void switch_init() {
 
 /// Called from RTC on each tick
 void switch_rtc_callback() {
-  for (int i = 0; i < SWITCHES; i++) {
+  for (int i = 0; i < num_switches; i++) {
     switch_t *s = &switches[i];
 
     if (s->type == SW_DISABLED || !s->triggered) continue;
@@ -140,12 +149,13 @@ bool switch_is_enabled(int index) {
 
 
 switch_type_t switch_get_type(int index) {
-  return (index < 0 || SWITCHES <= index) ? SW_DISABLED : switches[index].type;
+  return
+    (index < 0 || num_switches <= index) ? SW_DISABLED : switches[index].type;
 }
 
 
 void switch_set_type(int index, switch_type_t type) {
-  if (index < 0 || SWITCHES <= index) return;
+  if (index < 0 || num_switches <= index) return;
   switch_t *s = &switches[index];
 
   if (s->type != type) {
index 929f327aa34b0be0d1301b631b6ba745d2e5df72..d1dcdd3314a9772dabe53ab4897ce8c6843af678 100644 (file)
@@ -53,6 +53,9 @@ typedef enum {
   SW_MIN_Y, SW_MAX_Y,
   SW_MIN_Z, SW_MAX_Z,
   SW_MIN_A, SW_MAX_A,
+  SW_STALL_X, SW_STALL_Y,
+  SW_STALL_Z, SW_STALL_A,
+  SW_MOTOR_FAULT,
 } switch_id_t;
 
 
index 1c8426aea26311afc77f9adeb77742fb29f98981..8db1a364863e91d80dc7677c531f14f7e76e2e4f 100644 (file)
@@ -247,7 +247,7 @@ static bool _find_var(const char *_name, var_info_t *info) {
   if (!strcmp(IF_ELSE(INDEX)(name + 1, name), #CODE)) {                 \
     IF(INDEX)                                                           \
       (i = strchr(INDEX##_LABEL, name[0]) - INDEX##_LABEL;              \
-       if (INDEX <= i) return false);                                   \
+       if (i < 0) return false);                                        \
                                                                         \
     info->type = TYPE_##TYPE;                                           \
     info->index = i;                                                    \
index d3c1247b16215eeddb53a9bbd9f8b9cb4062397d..3193d9f605cc41c59d5d548abb624d41e6254aab 100644 (file)
@@ -44,6 +44,7 @@ VAR(idle_current,    ic, f32,   MOTORS, 1, 1, "Motor idle current")
 VAR(active_current,  ac, f32,   MOTORS, 0, 1, "Motor current now")
 VAR(driver_flags,    df, u16,   MOTORS, 0, 1, "Motor driver flags")
 VAR(status_strings,  ds, flags, MOTORS, 0, 1, "Motor driver status")
+VAR(driver_stalled,  sl, bool,  MOTORS, 0, 1, "Motor driver status")
 VAR(encoder,         en, s32,   MOTORS, 0, 0, "Motor encoder")
 VAR(error,           ee, s32,   MOTORS, 0, 0, "Motor position error")
 
@@ -106,7 +107,7 @@ VAR(speed_override,  so, f32,   0,      1, 1, "Spindle speed override")
 
 // System
 VAR(velocity,        v,  f32,   0,      0, 1, "Current velocity")
-VAR(acceleration,    a,  f32,   0,      0, 1, "Current acceleration")
+VAR(acceleration,   ax,  f32,   0,      0, 1, "Current acceleration")
 VAR(jerk,            j,  f32,   0,      0, 1, "Current jerk")
 VAR(hw_id,          hid, str,   0,      0, 1, "Hardware ID")
 VAR(echo,            ec, bool,  0,      1, 1, "Enable or disable echo")
index eaf77fdc639c7922d6515b702ff0ba4bef203f52..7183cc2afcb9405aea7df03a29d4d8f0c2830caf 100644 (file)
@@ -47,6 +47,7 @@ class Comm():
         self.queue = deque()
         self.in_buf = ''
         self.command = None
+        self.reboot_expected = False
 
         try:
             self.sp = serial.Serial(ctrl.args.serial, ctrl.args.baud,
@@ -139,6 +140,11 @@ class Comm():
             self.ctrl.state.machine_cmds_and_vars(msg)
             self.queue_command(Cmd.DUMP) # Refresh all vars
 
+            # Set axis positions
+            for axis in 'xyzabc':
+                position = self.ctrl.state.get(axis + 'p', 0)
+                self.queue_command(Cmd.set_axis(axis, position))
+
         except Exception as e:
             log.warning('AVR reload failed: %s', traceback.format_exc())
             self.ctrl.ioloop.call_later(1, self.connect)
@@ -188,7 +194,9 @@ class Comm():
                     self._log_msg(msg)
 
                 elif 'firmware' in msg:
-                    log.warning('firmware rebooted')
+                    if self.reboot_expected: log.info('AVR firmware rebooted')
+                    else: log.error('Unexpected AVR firmware reboot')
+                    self.reboot_expected = False
                     self.connect()
 
                 else: self.ctrl.state.update(msg)
@@ -202,6 +210,11 @@ class Comm():
             log.warning('Serial handler error: %s', traceback.format_exc())
 
 
+    def reboot(self):
+        self.queue_command(Cmd.REBOOT)
+        self.reboot_expected = True
+
+
     def connect(self):
         try:
             # Call connect callback
index 722a477f59dbc59c0e4bfe9f13470477a6d2c91a..69a261a4d3590e2b90956dd611d8899ea57e79e7 100644 (file)
@@ -64,7 +64,7 @@ class Mach():
         ctrl.state.set('cycle', 'idle')
         ctrl.state.add_listener(self._update)
 
-        self.comm.queue_command(Cmd.REBOOT)
+        self.comm.reboot()
 
 
     def _get_cycle(self): return self.ctrl.state.get('cycle')
index 9622284faac2a3bba348be09a722d99f94d738c7..5229767901b9efc29dc3ed701e6cb4ae0d6d7968 100644 (file)
@@ -33,9 +33,6 @@ import bbctrl
 log = logging.getLogger('State')
 
 
-machine_state_vars = '''xp yp zp ap bp cp t fo so'''.split()
-
-
 class State(object):
     def __init__(self, ctrl):
         self.ctrl = ctrl
@@ -152,17 +149,6 @@ class State(object):
             else: self.machine_var_set.add(code)
 
         self.ctrl.config.reload() # Indirectly configures AVR
-        self.restore_machine_state()
-
-
-    def restore_machine_state(self):
-        for name in machine_state_vars:
-            if name in self.vars:
-                value = self.vars[name]
-                if isinstance(value, str): value = '"' + value + '"'
-                if isinstance(value, bool): value = int(value)
-
-                self.ctrl.mach.set(name, value)
 
 
     def find_motor(self, axis):