From: Joseph Coffland Date: Thu, 26 May 2016 06:13:54 +0000 (-0700) Subject: Work on switch handling, coolant load switches X-Git-Url: https://git.buildbotics.com/?a=commitdiff_plain;h=5afb34c953c99519d8d7b19cebc55ce266cdf83d;p=bbctrl-firmware Work on switch handling, coolant load switches --- diff --git a/src/config.h b/src/config.h index 5e5264f..70dc03b 100644 --- a/src/config.h +++ b/src/config.h @@ -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 index 0000000..a15d385 --- /dev/null +++ b/src/coolant.c @@ -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 . + + 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 + . + + For information regarding this software email: + "Joseph Coffland" + +\******************************************************************************/ + +#include "coolant.h" +#include "config.h" + +#include + + +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 index 0000000..6ac70ff --- /dev/null +++ b/src/coolant.h @@ -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 . + + 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 + . + + For information regarding this software email: + "Joseph Coffland" + +\******************************************************************************/ + +#pragma once + +#include + + +void coolant_init(); +void coolant_set_mist(bool x); +void coolant_set_flood(bool x); diff --git a/src/cycle_homing.c b/src/cycle_homing.c index 8f35af1..db5d483 100644 --- a/src/cycle_homing.c +++ b/src/cycle_homing.c @@ -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); diff --git a/src/cycle_probing.c b/src/cycle_probing.c index 8f8165d..3ea5cb2 100644 --- a/src/cycle_probing.c +++ b/src/cycle_probing.c @@ -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++) { diff --git a/src/switch.c b/src/switch.c index 2ca5fcd..3ceb00b 100644 --- a/src/switch.c +++ b/src/switch.c @@ -64,27 +64,26 @@ #include -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; } diff --git a/src/switch.h b/src/switch.h index 42ffd3f..4aa6c10 100644 --- a/src/switch.h +++ b/src/switch.h @@ -40,9 +40,11 @@ /// 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); diff --git a/src/vars.def b/src/vars.def index 61750aa..70f10d8 100644 --- a/src/vars.def +++ b/src/vars.def @@ -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)