diff --git a/TinyG2/canonical_machine.h b/TinyG2/canonical_machine.h index 235cc5fe..5c307db3 100755 --- a/TinyG2/canonical_machine.h +++ b/TinyG2/canonical_machine.h @@ -239,6 +239,10 @@ typedef struct cmSingleton { // struct to manage cm globals and cycles uint8_t hold_state; // hold: feedhold sub-state machine uint8_t homing_state; // home: homing cycle sub-state machine uint8_t homed[AXES]; // individual axis homing flags + + uint8_t probe_state; // 1==success, 0==failed + float probe_results[AXES]; // probing results + uint8_t g28_flag; // true = complete a G28 move uint8_t g30_flag; // true = complete a G30 move uint8_t g10_persist_flag; //.G10 changed offsets - persist them @@ -259,10 +263,6 @@ typedef struct cmSingleton { // struct to manage cm globals and cycles /**** Externs - See canonical_machine.c for allocation ****/ extern cmSingleton_t cm; // canonical machine controller singleton -//extern GCodeState_t gm; // core gcode model state -//extern GCodeStateX_t gmx; // extended gcode model state -//extern GCodeInput_t gn; // gcode input values - transient -//extern GCodeInput_t gf; // gcode input flags - transient /***************************************************************************** * @@ -564,10 +564,8 @@ stat_t cm_goto_g28_position(float target[], float flags[]); // G28 stat_t cm_set_g30_position(void); // G30.1 stat_t cm_goto_g30_position(float target[], float flags[]); // G30 -stat_t cm_probe_cycle_start(void); // G38.2 +stat_t cm_straight_probe(float target[], float flags[]); // G38.2 stat_t cm_probe_callback(void); // G38.2 main loop callback -int8_t cm_probe_get_axis(void); -void cm_probe_set_position(float); stat_t cm_set_coord_system(uint8_t coord_system); // G54 - G59 stat_t cm_set_coord_offsets(uint8_t coord_system, float offset[], float flag[]); // G10 L2 diff --git a/TinyG2/cycle_probing.cpp b/TinyG2/cycle_probing.cpp index fdbba1d0..9d906bc8 100755 --- a/TinyG2/cycle_probing.cpp +++ b/TinyG2/cycle_probing.cpp @@ -1,9 +1,8 @@ /* - * cycle_probing.cpp - probing cycle extension to canonical_machine.c - * Part of TinyG2 project - * - * Copyright (c) 2013 Rob Grzyck - * Copyright (c) 2010 - 2013 Alden S Hart, Jr. + * cycle_probing.c - probing cycle extension to canonical_machine.c + * Part of TinyG project + * + * Copyright (c) 2010 - 2014 Alden S Hart, Jr. * * 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 @@ -34,104 +33,51 @@ #include "canonical_machine.h" #include "planner.h" #include "stepper.h" +#include "spindle.h" #include "report.h" #include "switch.h" -#ifdef __cplusplus -extern "C"{ -#endif - /**** Probe singleton structure ****/ -struct pbProbingSingleton { // persistent homing runtime variables - // controls for probing cycle - int8_t axis; // axis currently being homed - uint8_t min_mode; // mode for min switch fo this axis - uint8_t max_mode; // mode for max switch fo this axis - int8_t homing_switch; // homing switch for current axis (index into switch flag table) - int8_t limit_switch; // limit switch for current axis, or -1 if none - uint8_t homing_closed; // 0=open, 1=closed - uint8_t limit_closed; // 0=open, 1=closed - uint8_t (*func)(int8_t axis);// binding for callback function state machine - float open_position; - - // per-axis parameters - float direction; // set to 1 for positive (max), -1 for negative (to min); - float search_travel; // signed distance to travel in search - float search_velocity; // search speed as positive number - float latch_velocity; // latch speed as positive number - float latch_backoff; // max distance to back off switch during latch phase - float zero_backoff; // distance to back off switch before setting zero - float max_clear_backoff; // maximum distance of switch clearing backoffs before erring out +struct pbProbingSingleton { // persistent homing runtime variables + stat_t (*func)(); // binding for callback function state machine - // state saved from gcode model - float saved_feed_rate; // F setting - uint8_t saved_units_mode; // G20,G21 global setting - uint8_t saved_coord_system; // G54 - G59 setting - uint8_t saved_distance_mode;// G90,G91 global setting - float saved_jerk; // saved and restored for each axis homed + uint8_t probe_switch_axis; // probe switch axis + uint8_t probe_switch_position; //...and position + uint8_t saved_switch_type; // saved switch type NC/NO + uint8_t saved_switch_mode; +// uint8_t saved_switch_mode[NUM_SWITCHES]; +// uint8_t probe_switch; // what switch should we check? + + // probe destination + float target[AXES]; + float flags[AXES]; + + float saved_jerk[AXES]; // saved and restored for each axis }; static struct pbProbingSingleton pb; - /**** NOTE: global prototypes and other .h info is located in canonical_machine.h ****/ -static stat_t _set_pb_func(uint8_t (*func)(int8_t axis)); -static stat_t _probing_axis_start(int8_t axis); -static stat_t _probing_axis_clear(int8_t axis); -static stat_t _probing_axis_backoff_home(int8_t axis); -static stat_t _probing_axis_backoff_limit(int8_t axis); -static stat_t _probing_axis_search(int8_t axis); -static stat_t _probing_axis_latch(int8_t axis); -static stat_t _probing_axis_zero_backoff(int8_t axis); -static stat_t _probing_axis_set_zero(int8_t axis); -static stat_t _probing_axis_move(int8_t axis, float target, float velocity); -static stat_t _probing_finalize_exit(int8_t axis); -static stat_t _probing_error_exit(int8_t axis); -static int8_t _get_next_axis(int8_t axis); +static stat_t _probing_init(); +static stat_t _probing_start(); +static stat_t _probing_finish(); +static stat_t _probing_finalize_exit(); +//static stat_t _probing_error_exit(); + +static stat_t _set_pb_func(uint8_t (*func)()); /***************************************************************************** - * cm_probing_cycle_start() - G28.1 homing cycle using limit switches + * cm_probing_cycle_start() - G38.2 homing cycle using limit switches * cm_probing_callback() - main loop callback for running the homing cycle * - * Homing works from a G28.1 according to the following writeup: - * https://github.com/synthetos/TinyG/wiki/TinyG-Homing-(version-0.95-and-above) - * - * --- How does this work? --- - * - * Homing is invoked using a G28.1 command with 1 or more axes specified in the - * command: e.g. g28.1 x0 y0 z0 (FYI: the number after each axis is irrelevant) - * - * Homing is always run in the following order - for each enabeled axis: - * Z,X,Y,A Note: B and C cannot be homed - * - * At the start of a homing cycle those switches configured for homing - * (or for homing and limits) are treated as homing switches (they are modal). - * - * After initialization the following sequence is run for each axis to be homed: - * - * 0. If a homing or limit switch is closed on invocation, clear off the switch - * 1. Drive towards the homing switch at search velocity until switch is hit - * 2. Drive away from the homing switch at latch velocity until switch opens - * 3. Back off switch by the zero backoff distance and set zero for that axis - * - * Homing works as a state machine that is driven by registering a callback - * function at hm.func() for the next state to be run. Once the axis is - * initialized each callback basically does two things (1) start the move - * for the current function, and (2) register the next state with hm.func(). - * When a move is started it will either be interrupted if the homing switch - * changes state, This will cause the move to stop with a feedhold. The other - * thing that can happen is the move will run to its full length if no switch - * change is detected (hit or open), - * - * Once all moves for an axis are complete the next axis in the sequence is homed - * - * When a homing cycle is intiated the homing state is set to HOMING_NOT_HOMED - * When homing comples successfully this si set to HOMING_HOMED, otherwise it - * remains HOMING_NOT_HOMED. */ /* --- Some further details --- + * + * All cm_probe_cycle_start does is prevent any new commands from queueing to the + * planner so that the planner can move to a sop and report MACHINE_PROGRAM_STOP. + * OK, it also queues the function that's called once motion has stopped. * * Note: When coding a cycle (like this one) you get to perform one queued * move per entry into the continuation, then you must exit. @@ -141,300 +87,201 @@ static int8_t _get_next_axis(int8_t axis); * the cycle to be done. Otherwise there is a nasty race condition in the * tg_controller() that will accept the next command before the position of * the final move has been recorded in the Gcode model. That's what the call - * to cm_isbusy() is about. + * to cm_get_runtime_busy() is about. + * + * ESTEE: is this still true??? ASH: Yes. */ -uint8_t cm_probe_cycle_start(void) +uint8_t cm_straight_probe(float target[], float flags[]) { - // save relevant non-axis parameters from Gcode model - pb.saved_units_mode = cm.gm.units_mode; - pb.saved_coord_system = cm.gm.coord_system; - pb.saved_distance_mode = cm.gm.distance_mode; - pb.saved_feed_rate = cm.gm.feed_rate; - - pb.open_position = 0; - - // set working values - cm_set_units_mode(MILLIMETERS); - cm_set_distance_mode(INCREMENTAL_MODE); - cm_set_coord_system(ABSOLUTE_COORDS); // homing is done in machine coordinates + // trap zero feed rate condition + if ((cm.gm.inverse_feed_rate_mode == false) && (fp_ZERO(cm.gm.feed_rate))) { + return (STAT_GCODE_FEEDRATE_ERROR); + } - pb.axis = -1; // set to retrieve initial axis - pb.func = _probing_axis_start; // bind initial processing function - cm.cycle_state = CYCLE_PROBE; - st_energize_motors(); // enable motors if not already enabled + // trap error conditions (1) no axis (axes) specified, (2) no feed rate specified + + // set probe move endpoint + copy_vector(pb.target, target); // set probe move endpoint + copy_vector(pb.flags, flags); // set axes involved on the move + clear_vector(cm.probe_results); // clear the old probe position. + // NOTE: relying on probe_result will not detect a probe to 0,0,0. + + cm.probe_state = PROBE_WAITING; // wait until planner queue empties before completing initialization + pb.func = _probing_init; // bind probing initialization function return (STAT_OK); } uint8_t cm_probe_callback(void) { - if (cm.cycle_state != CYCLE_PROBE) { return (STAT_NOOP);} // exit if not in a homing cycle + if ((cm.cycle_state != CYCLE_PROBE) && (cm.probe_state != PROBE_WAITING)) { + return (STAT_NOOP); // exit if not in a probe cycle or waiting for one + } if (cm_get_runtime_busy() == true) { return (STAT_EAGAIN);} // sync to planner move ends - return (pb.func(pb.axis)); // execute the current homing move + return (pb.func()); // execute the current homing move } -int8_t cm_probe_get_axis(void) +/* + * _probing_init() - G38.2 homing cycle using limit switches + * + * These initializations are required before starting the probing cycle. + * They must be done after the planner has exhasted all current CYCLE moves as + * they affect the runtime (specifically the switch modes). Side effects would + * include limit switches initiating probe actions instead of just killing movement + */ + +static uint8_t _probing_init() { - return pb.axis; + // so optimistic... ;) + // NOTE: it is *not* an error condition for the probe not to trigger. + // it is an error for the limit or homing switches to fire, or for some other configuration error. + cm.probe_state = PROBE_FAILED; + cm.cycle_state = CYCLE_PROBE; + + // axis inits + for( uint8_t axis=0; axismode == SW_MODE_DISABLED) { @@ -190,6 +190,19 @@ static void _trigger_cycle_start(switch_t *s) uint8_t get_switch_mode(uint8_t sw_num) { return (0);} // ++++ + +/* + * read_switch() - read switch state from the switch structure + * NOTE: This does NOT read the pin itself. See poll_switch + */ +uint8_t read_switch(uint8_t axis, uint8_t position) +{ +// if (axis >= AXES) return (SW_DISABLED); +// if (axis > SW_MAX) return (SW_DISABLED); + return (sw.s[axis][position].state); +} + + /*********************************************************************************** * CONFIGURATION AND INTERFACE FUNCTIONS * Functions to get and set variables from the cfgArray table diff --git a/TinyG2/switch.h b/TinyG2/switch.h index 9626780c..b4028dce 100755 --- a/TinyG2/switch.h +++ b/TinyG2/switch.h @@ -58,8 +58,8 @@ #define SW_MODE_MAX_VALUE SW_MODE_HOMING_LIMIT enum swType { - SW_NORMALLY_OPEN = 0, - SW_NORMALLY_CLOSED + SW_TYPE_NORMALLY_OPEN = 0, + SW_TYPE_NORMALLY_CLOSED }; @@ -89,6 +89,20 @@ enum swEdge { #define SW_PAIRS AXES // array sizing #define SW_POSITIONS 2 // array sizing +enum swNums { // indexes into switch arrays + SW_MIN_X = 0, + SW_MAX_X, + SW_MIN_Y, + SW_MAX_Y, + SW_MIN_Z, + SW_MAX_Z, + SW_MIN_A, + SW_MAX_A, + NUM_SWITCHES // must be last one. Used for array sizing and for loops +}; +#define SW_OFFSET SW_MAX_X // offset between MIN and MAX switches +#define NUM_SWITCH_PAIRS (NUM_SWITCHES/2) + /* * Switch control structures */ @@ -116,7 +130,7 @@ extern switches_t sw; * Function prototypes */ void switch_init(void); -uint8_t read_switch(switch_t *s, uint8_t pin_value); +uint8_t poll_switch(switch_t *s, uint8_t pin_value); uint8_t get_switch_mode(uint8_t sw_num); stat_t poll_switches(void); diff --git a/TinyG2/tinyg2.h b/TinyG2/tinyg2.h index 23ab6978..c4a53bda 100755 --- a/TinyG2/tinyg2.h +++ b/TinyG2/tinyg2.h @@ -36,7 +36,7 @@ #include "MotatePins.h" #ifndef TINYG_FIRMWARE_BUILD -#define TINYG_FIRMWARE_BUILD 026.14 // tinyg merge - more work on controller.cpp +#define TINYG_FIRMWARE_BUILD 026.15 // tinyg merge - gcode parser #endif #define TINYG_FIRMWARE_VERSION 0.8 // firmware major version #define TINYG_HARDWARE_PLATFORM 3 // hardware platform indicator (2 = Native Arduino Due)