Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Event probe #1181

Merged
merged 3 commits into from
Apr 25, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
93 changes: 93 additions & 0 deletions FluidNC/data/taig_probe.flnc
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
name: "Taig Mill"
board: "Gecko Blaster v1 M2"

use_line_numbers: true

stepping:
engine: RMT
idle_ms: 255
dir_delay_us: 4
pulse_us: 4
disable_delay_us: 0

start:
must_home: false

spi:
miso_pin: gpio.19
mosi_pin: gpio.23
sck_pin: gpio.18

sdcard:
cs_pin: gpio.5
card_detect_pin: NO_PIN
frequency_hz: 4000000

# uart1:
# txd_pin: gpio.16
# rxd_pin: gpio.0
# rts_pin: NO_PIN
# cts_pin: NO_PIN
# baud: 5000000
# mode: 8N1
#
# uart_channel1:
# report_interval_ms: 200
# uart_num: 1
# message_level: 0

probe:
pin: gpio.0:low:pu

axes:
x:
# 1600 steps/rev * 20 revs/in * 1/25.4 mm/in = 1259.84252 steps/mm
steps_per_mm: 1259.8425
max_rate_mm_per_min: 1000
acceleration_mm_per_sec2: 100
max_travel_mm: 300

motor0:
standard_stepper:
direction_pin: gpio.25
step_pin: gpio.27

y:
# 1600 steps/rev * 20 revs/in * 1/25.4 mm/in = 1259.84252 steps/mm
steps_per_mm: 1259.8425
max_rate_mm_per_min: 1000
acceleration_mm_per_sec2: 100
max_travel_mm: 127

motor0:
standard_stepper:
direction_pin: gpio.15
step_pin: gpio.32

z:
# 3200 steps/rev * 20 revs/in * 1/25.4 mm/in = 2518.g9 steps/mm
steps_per_mm: 2518.69
max_rate_mm_per_min: 600
acceleration_mm_per_sec2: 25
max_travel_mm: 100

motor0:
standard_stepper:
direction_pin: gpio.14
step_pin: gpio.17

i2c0:
sda_pin: gpio.21
scl_pin: gpio.22

oled:
i2c_num: 0
i2c_address: 60
width: 64
height: 48
radio_delay_ms: 500

macros:
startup_line0: g20
after_reset: g20
after_unlock: g20
8 changes: 4 additions & 4 deletions FluidNC/src/Channel.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -103,18 +103,18 @@ void Channel::autoReportGCodeState() {
}
void Channel::autoReport() {
if (_reportInterval) {
auto probeState = config->_probe->get_state();
if (probeState != _lastProbe) {
auto thisProbeState = config->_probe->get_state();
if (thisProbeState != _lastProbe) {
report_recompute_pin_string();
}
if (_reportWco || sys.state != _lastState || probeState != _lastProbe || _lastPinString != report_pin_string ||
if (_reportWco || sys.state != _lastState || thisProbeState != _lastProbe || _lastPinString != report_pin_string ||
(motionState() && (int32_t(xTaskGetTickCount()) - _nextReportTime) >= 0)) {
if (_reportWco) {
report_wco_counter = 0;
}
_reportWco = false;
_lastState = sys.state;
_lastProbe = probeState;
_lastProbe = thisProbeState;
_lastPinString = report_pin_string;

_nextReportTime = xTaskGetTickCount() + _reportInterval;
Expand Down
2 changes: 1 addition & 1 deletion FluidNC/src/Machine/EventPin.h
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ class EventPin {

virtual void update(bool state) {};

void trigger(bool active);
virtual void trigger(bool active);

~EventPin() {}
};
10 changes: 10 additions & 0 deletions FluidNC/src/Machine/ProbeEventPin.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
#if 0
#include "src/Machine/ProbeEventPin.h"
#include "src/Machine/MachineConfig.h" // config

#include "src/Protocol.h" // protocol_send_event_from_ISR()

namespace Machine {

}
#endif
18 changes: 18 additions & 0 deletions FluidNC/src/Machine/ProbeEventPin.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
#pragma once

#include "EventPin.h"
#include "../Pin.h"
namespace Machine {
class ProbeEventPin : public EventPin {
private:
bool _value = 0;
Pin* _pin = nullptr;

public:
ProbeEventPin(const char* legend, Pin& pin);

void init();
void update(bool state) override;
bool get();
};
}
11 changes: 6 additions & 5 deletions FluidNC/src/MotionControl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -274,7 +274,7 @@ bool mc_dwell(int32_t milliseconds) {
return delay_msec(milliseconds, DwellMode::Dwell);
}

volatile ProbeState probeState;
volatile bool probing;

bool probe_succeeded = false;

Expand Down Expand Up @@ -310,8 +310,9 @@ GCUpdatePos mc_probe_cycle(float* target, plan_line_data_t* pl_data, bool away,
}
// Setup and queue probing motion. Auto cycle-start should not start the cycle.
mc_linear(target, pl_data, gc_state.position);
printf("Target %f\n", target[2]);
// Activate the probing state monitor in the stepper module.
probeState = ProbeState::Active;
probing = true;
// Perform probing cycle. Wait here until probe is triggered or motion completes.
protocol_send_event(&cycleStartEvent);
do {
Expand All @@ -326,16 +327,16 @@ GCUpdatePos mc_probe_cycle(float* target, plan_line_data_t* pl_data, bool away,

// Probing cycle complete!
// Set state variables and error out, if the probe failed and cycle with error is enabled.
if (probeState == ProbeState::Active) {
if (probing) {
if (no_error) {
copyAxes(probe_steps, get_motor_steps());
get_motor_steps(probe_steps);
} else {
send_alarm(ExecAlarm::ProbeFailContact);
}
} else {
probe_succeeded = true; // Indicate to system the probing cycle completed successfully.
}
probeState = ProbeState::Off; // Ensure probe state monitor is disabled.
probing = false; // Ensure probe state monitor is disabled.
protocol_execute_realtime(); // Check and execute run-time commands
// Reset the stepper and planner buffers to remove the remainder of the probe motion.
Stepper::reset(); // Reset step segment buffer.
Expand Down
2 changes: 1 addition & 1 deletion FluidNC/src/MotionControl.h
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@

#include <cstdint>

extern volatile ProbeState probeState; // Probing state value. Used to coordinate the probing cycle with stepper ISR.
extern volatile bool probing; // Probing state value. Used to coordinate the probing cycle with stepper ISR.

extern bool probe_succeeded; // Tracks if last probing cycle was successful.

Expand Down
4 changes: 2 additions & 2 deletions FluidNC/src/Planner.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -307,7 +307,7 @@ bool plan_buffer_line(float* target, plan_line_data_t* pl_data) {
float unit_vec[MAX_N_AXIS], delta_mm;
// Copy position data based on type of motion being planned.
if (block->motion.systemMotion) {
copyAxes(position_steps, get_motor_steps());
get_motor_steps(position_steps);
} else {
if (!block->is_jog && Homing::unhomed_axes()) {
log_info("Unhomed axes: " << config->_axes->maskToNames(Homing::unhomed_axes()));
Expand Down Expand Up @@ -426,7 +426,7 @@ void plan_sync_position() {
// TODO: For motor configurations not in the same coordinate frame as the machine position,
// this function needs to be updated to accomodate the difference.
if (config->_axes) {
copyAxes(pl.position, get_motor_steps());
get_motor_steps(pl.position);
}
}

Expand Down
86 changes: 61 additions & 25 deletions FluidNC/src/Probe.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3,54 +3,90 @@
// Use of this source code is governed by a GPLv3 license that can be found in the LICENSE file.

#include "Probe.h"

#include "Pin.h"
#include "Machine/EventPin.h"
#include "Machine/MachineConfig.h"

// Probe pin initialization routine.
void Probe::init() {
static bool show_init_msg = true; // used to show message only once.
extern void protocol_do_probe(void* arg);
ArgEvent probeEvent { protocol_do_probe };

if (_probePin.defined()) {
_probePin.getNative(Pin::Capabilities::Input | Pin::Capabilities::Native);
_probePin.setAttr(Pin::Attr::Input);
class ProbeEventPin : public EventPin {
private:
bool _value = false;
Pin* _pin = nullptr;

if (show_init_msg) {
_probePin.report("Probe Pin:");
show_init_msg = false;
public:
ProbeEventPin(const char* legend, Pin& pin) :
EventPin(&probeEvent, legend), _pin(&pin) {}

void init() {
if (_pin->undefined()) {
return;
}
_value = _pin->read();
_pin->report(_legend);
_pin->setAttr(Pin::Attr::Input);
_pin->registerEvent(static_cast<EventPin*>(this));
update(_pin->read());
}
void update(bool state) { _value = state; }

// Differs from the base class version by sending the event on either edge
void trigger(bool active) override {
update(active);
protocol_send_event(_event, this);
report_recompute_pin_string();
}

if (_toolsetter_Pin.defined()) {
_toolsetter_Pin.getNative(Pin::Capabilities::Input | Pin::Capabilities::Native);
_toolsetter_Pin.setAttr(Pin::Attr::Input);
bool get() { return _value; }
};

if (show_init_msg) {
_toolsetter_Pin.report("Toolsetter Pin:");
}
// Probe pin initialization routine.
void Probe::init() {
if (_probePin.defined()) {
_probeEventPin = new ProbeEventPin("Probe", _probePin);
_probeEventPin->init();
}

if (_toolsetterPin.defined()) {
_toolsetterEventPin = new ProbeEventPin("Toolsetter", _toolsetterPin);
_toolsetterEventPin->init();
}
show_init_msg = false;
}

void Probe::set_direction(bool is_away) {
_isProbeAway = is_away;
void Probe::set_direction(bool away) {
_away = away;
}

// Returns the probe pin state. Triggered = true. Called by gcode parser.
bool Probe::get_state() {
return (_probePin.read() || _toolsetter_Pin.read());
return ((_probeEventPin && _probeEventPin->get()) || (_toolsetterEventPin && _toolsetterEventPin->get()));
}

// Returns true if the probe pin is tripped, accounting for the direction (away or not).
// This function must be extremely efficient as to not bog down the stepper ISR.
// Should be called only in situations where the probe pin is known to be defined.
bool IRAM_ATTR Probe::tripped() {
return (_probePin.read() || _toolsetter_Pin.read()) ^ _isProbeAway;
bool Probe::tripped() {
return get_state() ^ _away;
}

void Probe::validate() {}

void Probe::group(Configuration::HandlerBase& handler) {
handler.item("pin", _probePin);
handler.item("toolsetter_pin", _toolsetter_Pin);
handler.item("toolsetter_pin", _toolsetterPin);
handler.item("check_mode_start", _check_mode_start);
handler.item("hard_stop", _hard_stop);
}
void protocol_do_probe(void* arg) {
Probe* p =config->_probe;
if (p->tripped() && probing) {
probing = false;
get_motor_steps(probe_steps);
if (p->_hard_stop) {
Stepper::reset();
plan_reset();
sys.state = State::Idle;
} else {
protocol_do_motion_cancel();
}
}
}
24 changes: 11 additions & 13 deletions FluidNC/src/Probe.h
Original file line number Diff line number Diff line change
Expand Up @@ -8,22 +8,16 @@
#include "Configuration/Configurable.h"

#include <cstdint>

// Values that define the probing state machine.
enum class ProbeState : uint8_t {
Off = 0, // Probing disabled or not in use. (Must be zero.)
Active = 1, // Actively watching the input pin.
};
class ProbeEventPin;

class Probe : public Configuration::Configurable {
// Inverts the probe pin state depending on user settings and probing cycle mode.
bool _isProbeAway = false;

// Configurable
Pin _probePin;
Pin _toolsetter_Pin;
bool _away = false;
ProbeEventPin* _probeEventPin;
ProbeEventPin* _toolsetterEventPin;

public:
bool _hard_stop = false;
// Configurable
bool _check_mode_start = true;
// _check_mode_start configures the position after a probing cycle
Expand All @@ -32,12 +26,16 @@ class Probe : public Configuration::Configurable {

Probe() = default;

bool exists() const { return _probePin.defined() || _toolsetter_Pin.defined(); }
// Configurable
Pin _probePin;
Pin _toolsetterPin;

bool exists() const { return _probePin.defined() || _toolsetterPin.defined(); }
// Probe pin initialization routine.
void init();

// setup probing direction G38.2 vs. G38.4
void set_direction(bool is_away);
void set_direction(bool away);

// Returns probe pin state. Triggered = true. Called by gcode parser and probe state monitor.
bool get_state();
Expand Down
Loading
Loading