Buildbotics CNC Controller Firmware Changelog
=============================================
+## v0.4.7
+ - Fix homing switch to motor channel mapping with non-standard axis order.
+ - Added ``switch-debounce`` and ``switch-lockout`` config options.
+
## v0.4.6
- Fixed a rare ``Negative s-curve time`` error.
- Don't allow manual axis homing when soft limits are not set.
{
"name": "bbctrl",
- "version": "0.4.6",
+ "version": "0.4.7",
"homepage": "http://buildbotics.com/",
"repository": "https://github.com/buildbotics/bbctrl-firmware",
"license": "GPL-3.0+",
#define VFDREG 32 // number of supported VFD modbus registers
// Switch settings. See switch.c
-#define SWITCH_DEBOUNCE 5 // ms
-#define SWITCH_LOCKOUT 250 // ms
+#define SWITCH_DEBOUNCE 5 // ms, default value
+#define SWITCH_LOCKOUT 250 // ms, default value
+#define SWITCH_MAX_DEBOUNCE 5000 // ms
+#define SWITCH_MAX_LOCKOUT 60000 // ms
// Motor ISRs
#include <stdio.h>
+static struct {
+ int16_t debounce;
+ int16_t lockout;
+} sw = {
+ .debounce = SWITCH_DEBOUNCE,
+ .lockout = SWITCH_LOCKOUT,
+};
+
typedef struct {
uint8_t pin;
switch_type_t type;
// Debounce switch
bool state = IN_PIN(s->pin);
if (state == s->state && s->initialized) s->debounce = 0;
- else if ((state && ++s->debounce == SWITCH_DEBOUNCE) ||
- (!state && --s->debounce == -SWITCH_DEBOUNCE)) {
+ else if ((state && ++s->debounce == sw.debounce) ||
+ (!state && --s->debounce == -sw.debounce)) {
s->state = state;
s->debounce = 0;
s->initialized = true;
- s->lockout = SWITCH_LOCKOUT;
+ s->lockout = sw.lockout;
if (s->cb) s->cb((switch_id_t)i, switch_is_active((switch_id_t)i));
}
}
uint8_t get_max_switch(int index) {return _get_state(MAX_SWITCH(index));}
uint8_t get_estop_switch() {return _get_state(SW_ESTOP);}
uint8_t get_probe_switch() {return _get_state(SW_PROBE);}
+
+
+void set_switch_debounce(uint16_t debounce) {
+ sw.debounce = SWITCH_MAX_DEBOUNCE < debounce ? SWITCH_DEBOUNCE : debounce;
+}
+
+
+uint16_t get_switch_debounce() {return sw.debounce;}
+
+
+void set_switch_lockout(uint16_t lockout) {
+ sw.lockout = SWITCH_MAX_LOCKOUT < lockout ? SWITCH_LOCKOUT : lockout;
+}
+
+
+uint16_t get_switch_lockout() {return sw.lockout;}
VAR(max_switch, xw, u8, MOTORS, 0, 1) // Maximum switch state
VAR(estop_switch, ew, u8, 0, 0, 1) // Estop switch state
VAR(probe_switch, pw, u8, 0, 0, 1) // Probe switch state
+VAR(switch_debounce, sd, u16, 0, 1, 1) // Switch debounce time in ms
+VAR(switch_lockout, sc, u16, 0, 1, 1) // Switch lockout time in ms
// Axis
VAR(axis_position, p, f32, AXES, 0, 1) // Axis position
templated-input(v-for="templ in template.switches", :name="$key",
:model.sync="config.switches[$key]", :template="templ")
- label.extra(slot="extra")
+ label.extra(slot="extra", v-if="templ.pin")
| Pin {{templ.pin}}
io-indicator(:name="$key", :state="state")
def seek(switch, active, error):
- cmd = SEEK
-
- if switch == 'probe': cmd += '1'
- elif switch == 'x-min': cmd += '2'
- elif switch == 'x-max': cmd += '3'
- elif switch == 'y-min': cmd += '4'
- elif switch == 'y-max': cmd += '5'
- elif switch == 'z-min': cmd += '6'
- elif switch == 'z-max': cmd += '7'
- elif switch == 'a-min': cmd += '8'
- elif switch == 'a-max': cmd += '9'
- else: raise Exception('Unsupported switch "%s"' % switch)
+ cmd = SEEK + str(switch)
flags = 0
if active: flags |= SEEK_ACTIVE
m = reLogLine.match(line)
if not m: return
- level = m.group('level')
- msg = m.group('msg')
+ level = m.group('level')
+ msg = m.group('msg')
filename = m.group('file')
- line = m.group('line')
- column = m.group('column')
+ line = m.group('line')
+ column = m.group('column')
where = ':'.join(filter(None.__ne__, [filename, line, column]))
if type == 'pause': return Cmd.pause(block['pause-type'])
if type == 'seek':
- return Cmd.seek(block['switch'], block['active'], block['error'])
+ sw = self.ctrl.state.get_switch_id(block['switch'])
+ return Cmd.seek(sw, block['active'], block['error'])
if type == 'end': return '' # Sends id
def motor_latch_velocity(self, motor):
return 1000 * self.get(str(motor) + 'lv', 0)
+
+
+ def get_axis_switch(self, axis, side):
+ axis = axis.lower()
+
+ if not axis in 'xyzabc':
+ raise Exception('Unsupported switch "%s-%s"' % (axis, side))
+
+ if not self.is_axis_enabled(axis):
+ raise Exception('Switch "%s-%s" axis not enabled' % (axis, side))
+
+ motor = self.find_motor(axis)
+ # This must match the switch ID enum in avr/src/switch.h
+ return 2 * motor + 2 + (0 if side.lower() == 'min' else 1)
+
+
+ def get_switch_id(self, switch):
+ # TODO Support other input switches in CAMotics gcode/machine/PortType.h
+ # TODO Support stall homing
+ switch = switch.lower()
+ if switch == 'probe': return 1
+ if switch[1:] == '-min': return self.get_axis_switch(switch[0], 'min')
+ if switch[1:] == '-max': return self.get_axis_switch(switch[0], 'max')
+ raise Exception('Unsupported switch "%s"' % switch)
"default": "normally-open",
"code": "pt",
"pin": 22
+ },
+ "switch-debounce": {
+ "type": "int",
+ "min": 1,
+ "max": 5000,
+ "unit": "ms",
+ "default": 5,
+ "code": "sd",
+ "help": "Minimum time in ms before a switch change is acknowledged."
+ },
+ "switch-lockout": {
+ "type": "int",
+ "min": 0,
+ "max": 60000,
+ "unit": "ms",
+ "default": 250,
+ "code": "sc",
+ "help": "Time in ms to ignore switch changes after an acknowledge change."
}
},