Work on switch handling, coolant load switches
authorJoseph Coffland <joseph@cauldrondevelopment.com>
Thu, 26 May 2016 06:13:54 +0000 (23:13 -0700)
committerJoseph Coffland <joseph@cauldrondevelopment.com>
Thu, 26 May 2016 06:13:54 +0000 (23:13 -0700)
src/config.h
src/coolant.c [new file with mode: 0644]
src/coolant.h [new file with mode: 0644]
src/cycle_homing.c
src/cycle_probing.c
src/switch.c
src/switch.h
src/vars.def

index 5e5264f182202ee519f562a959db1f9376e355a6..70dc03b5f5697410f1bdc69540ee7c40d0b1f648 100644 (file)
@@ -40,7 +40,7 @@
 #define AXES                     6 // number of axes
 #define MOTORS                   4 // number of motors on the board
 #define COORDS                   6 // number of supported coordinate systems
-#define SWITCHES                 8 // number of supported limit switches
+#define SWITCHES                10 // number of supported limit switches
 #define PWMS                     2 // number of supported PWM channels
 
 
@@ -88,29 +88,8 @@ typedef enum {
 #define M4_POWER_MODE            MOTOR_POWER_MODE
 
 
-// Switch settings.  See switch.h
-#define SWITCH_TYPE              SW_TYPE_NORMALLY_OPEN
-#define X_SWITCH_MODE_MIN        SW_MODE_HOMING
-#define X_SWITCH_MODE_MAX        SW_MODE_DISABLED
-#define Y_SWITCH_MODE_MIN        SW_MODE_HOMING
-#define Y_SWITCH_MODE_MAX        SW_MODE_DISABLED
-#define Z_SWITCH_MODE_MIN        SW_MODE_DISABLED
-#define Z_SWITCH_MODE_MAX        SW_MODE_HOMING
-#define A_SWITCH_MODE_MIN        SW_MODE_HOMING
-#define A_SWITCH_MODE_MAX        SW_MODE_DISABLED
-#define B_SWITCH_MODE_MIN        SW_MODE_HOMING
-#define B_SWITCH_MODE_MAX        SW_MODE_DISABLED
-#define C_SWITCH_MODE_MIN        SW_MODE_HOMING
-#define C_SWITCH_MODE_MAX        SW_MODE_DISABLED
-
-// Switch ISRs
-#define X_SWITCH_ISR_vect        PORTA_INT0_vect
-#define Y_SWITCH_ISR_vect        PORTD_INT0_vect
-#define Z_SWITCH_ISR_vect        PORTE_INT0_vect
-#define A_SWITCH_ISR_vect        PORTF_INT0_vect
+// Switch settings.  See switch.c
 #define SWITCH_INTLVL            PORT_INT0LVL_MED_gc
-
-// Timer for debouncing switches
 #define SW_LOCKOUT_TICKS         250 // ms
 #define SW_DEGLITCH_TICKS        30  // ms
 
diff --git a/src/coolant.c b/src/coolant.c
new file mode 100644 (file)
index 0000000..a15d385
--- /dev/null
@@ -0,0 +1,51 @@
+/******************************************************************************\
+
+                This file is part of the Buildbotics firmware.
+
+                  Copyright (c) 2015 - 2016 Buildbotics LLC
+                            All rights reserved.
+
+     This file ("the software") is free software: you can redistribute it
+     and/or modify it under the terms of the GNU General Public License,
+      version 2 as published by the Free Software Foundation. You should
+      have received a copy of the GNU General Public License, version 2
+     along with the software. If not, see <http://www.gnu.org/licenses/>.
+
+     The software is distributed in the hope that it will be useful, but
+          WITHOUT ANY WARRANTY; without even the implied warranty of
+      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+               Lesser General Public License for more details.
+
+       You should have received a copy of the GNU Lesser General Public
+                License along with the software.  If not, see
+                       <http://www.gnu.org/licenses/>.
+
+                For information regarding this software email:
+                  "Joseph Coffland" <joseph@buildbotics.com>
+
+\******************************************************************************/
+
+#include "coolant.h"
+#include "config.h"
+
+#include <avr/io.h>
+
+
+void coolant_init() {
+  MIST_PORT.OUTSET = MIST_PIN_bm; // High
+  MIST_PORT.DIRSET = MIST_PIN_bm; // Output
+  FLOOD_PORT.OUTSET = FLOOD_PIN_bm; // High
+  FLOOD_PORT.DIRSET = FLOOD_PIN_bm; // Output
+}
+
+
+void coolant_set_mist(bool x) {
+  if (x) MIST_PORT.OUTCLR = MIST_PIN_bm;
+  else MIST_PORT.OUTSET = MIST_PIN_bm;
+}
+
+
+void coolant_set_flood(bool x) {
+  if (x) FLOOD_PORT.OUTCLR = FLOOD_PIN_bm;
+  else FLOOD_PORT.OUTSET = FLOOD_PIN_bm;
+}
diff --git a/src/coolant.h b/src/coolant.h
new file mode 100644 (file)
index 0000000..6ac70ff
--- /dev/null
@@ -0,0 +1,35 @@
+/******************************************************************************\
+
+                This file is part of the Buildbotics firmware.
+
+                  Copyright (c) 2015 - 2016 Buildbotics LLC
+                            All rights reserved.
+
+     This file ("the software") is free software: you can redistribute it
+     and/or modify it under the terms of the GNU General Public License,
+      version 2 as published by the Free Software Foundation. You should
+      have received a copy of the GNU General Public License, version 2
+     along with the software. If not, see <http://www.gnu.org/licenses/>.
+
+     The software is distributed in the hope that it will be useful, but
+          WITHOUT ANY WARRANTY; without even the implied warranty of
+      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+               Lesser General Public License for more details.
+
+       You should have received a copy of the GNU Lesser General Public
+                License along with the software.  If not, see
+                       <http://www.gnu.org/licenses/>.
+
+                For information regarding this software email:
+                  "Joseph Coffland" <joseph@buildbotics.com>
+
+\******************************************************************************/
+
+#pragma once
+
+#include <stdbool.h>
+
+
+void coolant_init();
+void coolant_set_mist(bool x);
+void coolant_set_flood(bool x);
index 8f35af1b2052db4a3bec29eccc86526235a550fc..db5d48379c3bb068151b4b4f7fd5ff1abfb1a3e5 100644 (file)
@@ -282,10 +282,10 @@ static stat_t _homing_axis_clear(int8_t axis) {
   // Handle an initial switch closure by backing off the closed switch
   // NOTE: Relies on independent switches per axis (not shared)
 
-  if (switch_get_closed(hm.homing_switch))
+  if (switch_get_active(hm.homing_switch))
     _homing_axis_move(axis, hm.latch_backoff, hm.search_velocity);
 
-  else if (switch_get_closed(hm.limit_switch))
+  else if (switch_get_active(hm.limit_switch))
     _homing_axis_move(axis, -hm.latch_backoff, hm.search_velocity);
 
   return _set_homing_func(_homing_axis_search);
@@ -306,7 +306,7 @@ static stat_t _homing_axis_search(int8_t axis) {
 static stat_t _homing_axis_latch(int8_t axis) {
   // verify assumption that we arrived here because of homing switch closure
   // rather than user-initiated feedhold or other disruption
-  if (!switch_get_closed(hm.homing_switch))
+  if (!switch_get_active(hm.homing_switch))
     return _set_homing_func(_homing_abort);
 
   _homing_axis_move(axis, hm.latch_backoff, hm.latch_velocity);
index 8f8165dc9bce1db903598e47930b526700bf3950..3ea5cb2b1548ca2895ec8cdc5a7e260d4d233f66 100644 (file)
@@ -196,7 +196,7 @@ static uint8_t _probing_init() {
 
 static stat_t _probing_start() {
   // initial probe state, don't probe if we're already contacted!
-  bool closed = switch_get_closed(pb.probe_switch);
+  bool closed = switch_get_active(pb.probe_switch);
 
   if (!closed) ritorno(cm_straight_feed(pb.target, pb.flags));
 
@@ -205,7 +205,7 @@ static stat_t _probing_start() {
 
 
 static stat_t _probing_finish() {
-  bool closed = switch_get_closed(pb.probe_switch);
+  bool closed = switch_get_active(pb.probe_switch);
   cm.probe_state = closed ? PROBE_SUCCEEDED : PROBE_FAILED;
 
   for (uint8_t axis = 0; axis < AXES; axis++) {
index 2ca5fcd22e18755bb86d713296fb546b7bb7df42..3ceb00bf764244bad39309eefff088bf975f113d 100644 (file)
 #include <stdbool.h>
 
 
-typedef enum { // state machine for managing debouncing and lockout
+typedef enum {
   SW_IDLE,
   SW_DEGLITCHING,
   SW_LOCKOUT
 } swDebounce_t;
 
+
 typedef struct {
-  bool last;
-  bool state;
   swType_t type;
   swMode_t mode;
-  swDebounce_t debounce; // debounce state
-  int8_t count;          // deglitching and lockout counter
   PORT_t *port;
+  uint8_t pin;
   bool min;
+
+  bool state;
+  swDebounce_t debounce;
+  int8_t count;
 } switch_t;
 
-/* Switch control structures
- * Note 1: The term "thrown" is used because switches could be normally-open
- * or normally-closed. "Thrown" means activated.
- */
+
 typedef struct {
   bool limit_thrown;
   switch_t switches[SWITCHES];
@@ -93,62 +92,72 @@ typedef struct {
 
 swSingleton_t sw = {
   .switches = {
-    {
-      .type = SWITCH_TYPE,
-      .mode = X_SWITCH_MODE_MIN,
-      .debounce = SW_IDLE,
-      .port = &PORT_SWITCH_X,
-      .min = true,
-    }, {
-      .type = SWITCH_TYPE,
-      .mode = X_SWITCH_MODE_MAX,
-      .debounce = SW_IDLE,
-      .port = &PORT_SWITCH_X,
-      .min = false,
-    }, {
-      .type = SWITCH_TYPE,
-      .mode = Y_SWITCH_MODE_MIN,
-      .debounce = SW_IDLE,
-      .port = &PORT_SWITCH_Y,
+    { //    X min
+      .type = SW_TYPE_NORMALLY_OPEN,
+      .mode = SW_MODE_HOMING,
+      .port = &PORTA,
+      .pin  = 6,
+      .min  = true,
+    }, { // X max
+      .type = SW_TYPE_NORMALLY_OPEN,
+      .mode = SW_MODE_DISABLED,
+      .port = &PORTA,
+      .pin  = 7,
+      .min  = false,
+    }, { // Y min
+      .type = SW_TYPE_NORMALLY_OPEN,
+      .mode = SW_MODE_HOMING,
+      .port = &PORTD,
+      .pin  = 6,
+      .min  = true,
+    }, { // Y max
+      .type = SW_TYPE_NORMALLY_OPEN,
+      .mode = SW_MODE_DISABLED,
+      .port = &PORTD,
+      .pin  = 7,
+      .min  = false,
+    }, { // Z min
+      .type = SW_TYPE_NORMALLY_OPEN,
+      .mode = SW_MODE_DISABLED,
+      .port = &PORTE,
+      .pin  = 6,
+      .min  = true,
+    }, { // Z max
+      .type = SW_TYPE_NORMALLY_OPEN,
+      .mode = SW_MODE_HOMING,
+      .port = &PORTE,
+      .pin  = 7,
+      .min  = false,
+    }, { // A min
+      .type = SW_TYPE_NORMALLY_OPEN,
+      .mode = SW_MODE_HOMING,
+      .port = &PORTF,
+      .pin  = 6,
       .min = true,
-   }, {
-      .type = SWITCH_TYPE,
-      .mode = Y_SWITCH_MODE_MAX,
-      .debounce = SW_IDLE,
-      .port = &PORT_SWITCH_Y,
-      .min = false,
-    }, {
-      .type = SWITCH_TYPE,
-      .mode = Z_SWITCH_MODE_MIN,
-      .debounce = SW_IDLE,
-      .port = &PORT_SWITCH_Z,
-      .min = true,
-    }, {
-      .type = SWITCH_TYPE,
-      .mode = Z_SWITCH_MODE_MAX,
-      .debounce = SW_IDLE,
-      .port = &PORT_SWITCH_Z,
-      .min = false,
-    }, {
-      .type = SWITCH_TYPE,
-      .mode = A_SWITCH_MODE_MIN,
-      .debounce = SW_IDLE,
-      .port = &PORT_SWITCH_A,
-      .min = true,
-    }, {
-      .type = SWITCH_TYPE,
-      .mode = A_SWITCH_MODE_MAX,
-      .debounce = SW_IDLE,
-      .port = &PORT_SWITCH_A,
-      .min = false,
+    }, { // A max
+      .type = SW_TYPE_NORMALLY_OPEN,
+      .mode = SW_MODE_DISABLED,
+      .port = &PORTF,
+      .pin  = 7,
+      .min  = false,
+    }, { // EStop
+      .type = SW_TYPE_NORMALLY_CLOSED,
+      .mode = SW_ESTOP_BIT,
+      .port = &PORTD,
+      .pin  = 5,
+    }, { // Probe
+      .type = SW_TYPE_NORMALLY_OPEN,
+      .mode = SW_PROBE_BIT,
+      .port = &PORTF,
+      .pin  = 1,
     },
   }
 };
 
 
-static bool _read_switch(uint8_t i) {
-  return sw.switches[i].port->IN &
-    (sw.switches[i].min ? SW_MIN_BIT_bm : SW_MAX_BIT_bm);
+static bool _read_state(const switch_t *s) {
+  // A normally open switch drives the pin low when thrown
+  return (s->type == SW_TYPE_NORMALLY_OPEN) ^ (s->port->IN & (1 << s->pin));
 }
 
 
@@ -156,49 +165,51 @@ static void _switch_isr() {
   for (int i = 0; i < SWITCHES; i++) {
     switch_t *s = &sw.switches[i];
 
-    bool set = _read_switch(i);
-    if (set == s->last) continue;
-
-    if (s->mode == SW_MODE_DISABLED) return; // never supposed to happen
-    if (s->debounce == SW_LOCKOUT) return;   // switch is in lockout
+    bool state = _read_state(s);
+    if (state == s->state || s->mode == SW_MODE_DISABLED ||
+        s->debounce == SW_LOCKOUT) continue;
 
     // either transitions state from IDLE or overwrites it
     s->debounce = SW_DEGLITCHING;
     // reset deglitch count regardless of entry state
     s->count = -SW_DEGLITCH_TICKS;
-
-    // A NO switch drives the pin LO when thrown
-    s->state = (s->type == SW_TYPE_NORMALLY_OPEN) ^ set;
+    s->state = state;
   }
 }
 
 
 // Switch interrupt handler vectors
-ISR(X_SWITCH_ISR_vect) {_switch_isr();}
-ISR(Y_SWITCH_ISR_vect) {_switch_isr();}
-ISR(Z_SWITCH_ISR_vect) {_switch_isr();}
-ISR(A_SWITCH_ISR_vect) {_switch_isr();}
+ISR(PORTA_INT0_vect) {_switch_isr();}
+ISR(PORTD_INT0_vect) {_switch_isr();}
+ISR(PORTE_INT0_vect) {_switch_isr();}
+ISR(PORTF_INT0_vect) {_switch_isr();}
 
 
-void switch_init() {
-  return; // TODO
+void _switch_enable(switch_t *s, bool enable) {
+  if (enable) {
+    s->port->INT0MASK |= 1 << s->pin;    // Enable INT0
 
-  for (int i = 0; i < SWITCHES; i++) {
-    switch_t *s = &sw.switches[i];
-    PORT_t *port = s->port;
-    uint8_t bm = s->min ? SW_MIN_BIT_bm : SW_MAX_BIT_bm;
+    // Pull up and trigger on both edges
+    (&s->port->PIN0CTRL)[s->pin] = PORT_OPC_PULLUP_gc | PORT_ISC_BOTHEDGES_gc;
 
-    if (s->mode == SW_MODE_DISABLED) continue;
+    // Initialize state
+    s->state = _read_state(s);
 
-    port->DIRCLR = bm;              // See 13.14.14
-    port->INT0MASK |= bm;           // Enable INT0
-    port->INTCTRL |= SWITCH_INTLVL; // Set interrupt level
+  } else {
+    s->port->INT0MASK &= ~(1 << s->pin); // Disable INT0
+    (&s->port->PIN0CTRL)[s->pin] = 0;
+  }
+}
 
-    if (s->min) port->PIN6CTRL = PORT_OPC_PULLUP_gc | PORT_ISC_BOTHEDGES_gc;
-    else port->PIN7CTRL = PORT_OPC_PULLUP_gc | PORT_ISC_BOTHEDGES_gc;
 
-    // Initialize state
-    s->state = (s->type == SW_TYPE_NORMALLY_OPEN) ^ _read_switch(i);
+void switch_init() {
+  for (int i = 0; i < SWITCHES; i++) {
+    switch_t *s = &sw.switches[i];
+
+    s->port->DIRCLR = 1 << s->pin;     // Input
+    s->port->INTCTRL |= SWITCH_INTLVL; // Set interrupt level
+
+    _switch_enable(s, s->mode != SW_MODE_DISABLED);
   }
 }
 
@@ -215,9 +226,8 @@ void switch_rtc_callback() {
     if (++s->count == SW_LOCKOUT_TICKS) {
       s->debounce = SW_IDLE;
 
-      // check if the state has changed while we were in lockout...
-      bool old_state = s->state;
-      if (old_state != _read_switch(i)) {
+      // check if the state has changed while we were in lockout
+      if (s->state != _read_state(s)) {
         s->debounce = SW_DEGLITCHING;
         s->count = -SW_DEGLITCH_TICKS;
       }
@@ -225,22 +235,20 @@ void switch_rtc_callback() {
       continue;
     }
 
-    if (!s->count) { // trigger point
+    if (!s->count) { // switch triggered
       s->debounce = SW_LOCKOUT;
 
-      // regardless of switch type
       if (cm.cycle_state == CYCLE_HOMING || cm.cycle_state == CYCLE_PROBE)
         cm_request_feedhold();
 
-      // should be a limit switch, so fire it.
-      else if (s->mode & SW_LIMIT_BIT)
+      else if (s->mode & SW_LIMIT_BIT || s->mode & SW_ESTOP_BIT)
         sw.limit_thrown = true; // triggers an emergency shutdown
     }
   }
 }
 
 
-bool switch_get_closed(int index) {
+bool switch_get_active(int index) {
   return sw.switches[index].state;
 }
 
@@ -261,7 +269,12 @@ swMode_t switch_get_mode(int index) {
 
 
 void switch_set_mode(int index, swMode_t mode) {
-  sw.switches[index].mode = mode;
+  switch_t *s = &sw.switches[index];
+
+  if (s->mode != mode) {
+    s->mode = mode;
+    _switch_enable(s, s->mode != SW_MODE_DISABLED);
+  }
 }
 
 
@@ -270,6 +283,7 @@ bool switch_get_limit_thrown() {
 }
 
 
+// Var callbacks
 uint8_t get_switch_type(int index) {
   return sw.switches[index].type;
 }
index 42ffd3fe66cd726ed8704be10743a924698af474..4aa6c10e8c2b370fcedcd3ec1fca0ee4c253f2e4 100644 (file)
 
 /// switch modes
 typedef enum {
-  SW_MODE_DISABLED,
-  SW_HOMING_BIT,
-  SW_LIMIT_BIT
+  SW_MODE_DISABLED = 0,
+  SW_HOMING_BIT    = 1 << 0,
+  SW_LIMIT_BIT     = 1 << 1,
+  SW_ESTOP_BIT     = 1 << 2,
+  SW_PROBE_BIT     = 1 << 4,
 } swMode_t;
 
 #define SW_MODE_HOMING        SW_HOMING_BIT   // enable switch for homing only
@@ -59,13 +61,14 @@ typedef enum {
   SW_MIN_X, SW_MAX_X,
   SW_MIN_Y, SW_MAX_Y,
   SW_MIN_Z, SW_MAX_Z,
-  SW_MIN_A, SW_MAX_A
+  SW_MIN_A, SW_MAX_A,
+  SW_ESTOP, SW_PROBE
 } swNums_t;
 
 
 void switch_init();
 void switch_rtc_callback();
-bool switch_get_closed(int index);
+bool switch_get_active(int index);
 swType_t switch_get_type(int index);
 void switch_set_type(int index, swType_t type);
 swMode_t switch_get_mode(int index);
index 61750aa1094429611872660c5d489fc01a1dbe7d..70f10d85835566b5e8f44ead66076baeb8052515 100644 (file)
@@ -26,8 +26,8 @@
 \******************************************************************************/
 
 #define AXES_LABEL "xyzabcuvw"
-#define MOTORS_LABEL "1234"
-#define SWITCHES_LABEL "12345678"
+#define MOTORS_LABEL "0123"
+#define SWITCHES_LABEL "0123456789"
 
 // VAR(name,        code, type,  index, settable, default, help)