mirror of
https://github.com/synthetos/g2.git
synced 2026-02-05 18:49:54 +08:00
245 lines
9.8 KiB
C++
245 lines
9.8 KiB
C++
/*
|
|
* alarm.cpp - canonical machine alarm handlers
|
|
* This file is part of the g2core project
|
|
*
|
|
* Copyright (c) 2010 - 2018 Alden S Hart, Jr.
|
|
* Copyright (c) 2014 - 2018 Robert Giseburt
|
|
*
|
|
* 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/>.
|
|
*
|
|
* As a special exception, you may use this file as part of a software library without
|
|
* restriction. Specifically, if other files instantiate templates or use macros or
|
|
* inline functions from this file, or you compile this file and link it with other
|
|
* files to produce an executable, this file does not by itself cause the resulting
|
|
* executable to be covered by the GNU General Public License. This exception does not
|
|
* however invalidate any other reasons why the executable file might be covered by the
|
|
* GNU General Public License.
|
|
*
|
|
* THE SOFTWARE IS DISTRIBUTED IN THE HOPE THAT IT WILL BE USEFUL, BUT WITHOUT ANY
|
|
* WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
|
|
* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
|
|
* SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
|
|
* OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
*/
|
|
|
|
#include "g2core.h" // #1
|
|
#include "config.h" // #2
|
|
#include "gcode.h" // #3
|
|
#include "canonical_machine.h"
|
|
#include "safety_manager.h"
|
|
#include "planner.h"
|
|
#include "report.h"
|
|
#include "spindle.h"
|
|
#include "coolant.h"
|
|
#include "temperature.h"
|
|
#include "util.h"
|
|
|
|
/****************************************************************************************
|
|
* ALARM, SHUTDOWN, and PANIC are nested dolls.
|
|
*
|
|
* cm_alrm() - invoke alarm from command
|
|
* cm_shutd() - invoke shutdown from command
|
|
* cm_pnic() - invoke panic from command
|
|
* cm_clr() - clear alarm or shutdown from command
|
|
*
|
|
* The alarm states can be invoked from the above commands for testing and clearing
|
|
*/
|
|
stat_t cm_alrm(nvObj_t *nv) // invoke alarm from command
|
|
{
|
|
cm_alarm(STAT_ALARM, "sent by host");
|
|
return (STAT_OK);
|
|
}
|
|
|
|
stat_t cm_shutd(nvObj_t *nv) // invoke shutdown from command
|
|
{
|
|
cm_shutdown(STAT_SHUTDOWN, "sent by host");
|
|
return (STAT_OK);
|
|
}
|
|
|
|
stat_t cm_pnic(nvObj_t *nv) // invoke panic from command
|
|
{
|
|
cm_panic(STAT_PANIC, "sent by host");
|
|
return (STAT_OK);
|
|
}
|
|
|
|
stat_t cm_clr(nvObj_t *nv) // clear alarm or shutdown from command line
|
|
{
|
|
cm_clear();
|
|
return (STAT_OK);
|
|
}
|
|
|
|
/****************************************************************************************
|
|
* cm_clear() - clear ALARM and SHUTDOWN states
|
|
* cm_parse_clear() - parse incoming gcode for M30 or M2 clears if in ALARM state
|
|
*
|
|
* Parse clear interprets an M30 or M2 PROGRAM_END as a $clear condition and clear ALARM
|
|
* but not SHUTDOWN or PANIC. Assumes Gcode string has no leading or embedded whitespace
|
|
*/
|
|
|
|
void cm_clear()
|
|
{
|
|
if (cm->machine_state == MACHINE_ALARM) {
|
|
// immediately clear the alarm, then reset the rest of the stuff
|
|
cm->machine_state = MACHINE_PROGRAM_STOP;
|
|
cm_program_stop();
|
|
} else if (cm->machine_state == MACHINE_SHUTDOWN) {
|
|
// immediately clear the shutdown, then reset the rest of the stuff
|
|
cm->machine_state = MACHINE_READY;
|
|
cm_program_end();
|
|
}
|
|
|
|
}
|
|
|
|
void cm_parse_clear(const char *s)
|
|
{
|
|
if (safety_manager->can_clear()) {
|
|
if (toupper(s[0]) == 'M') {
|
|
if (( (s[1]=='3') && (s[2]=='0') && (s[3]==0)) || ((s[1]=='2') && (s[2]==0) )) {
|
|
cm_clear();
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
/****************************************************************************************
|
|
* cm_is_alarmed() - return alarm status code or OK if no alarms
|
|
*/
|
|
|
|
stat_t cm_is_alarmed()
|
|
{
|
|
return safety_manager->is_system_alarmed();
|
|
}
|
|
|
|
/****************************************************************************************
|
|
* cm_halt() - stop motion, spindle, coolant and heaters immediately
|
|
* cm_halt_motion() - stop motion immediately. Does not affect spindle, coolant, or other IO
|
|
*
|
|
* Stop motors and reset all system states accordingly.
|
|
* Does not de-energize motors as in some cases the motors must remain energized
|
|
* in order to prevent an axis from crashing.
|
|
*/
|
|
|
|
void cm_halt(void)
|
|
{
|
|
cm_halt_motion();
|
|
spindle_stop();
|
|
coolant_control_immediate(COOLANT_OFF, COOLANT_BOTH);
|
|
temperature_init();
|
|
}
|
|
|
|
void cm_halt_motion(void)
|
|
{
|
|
mp_halt_runtime(); // stop the runtime. Do this immediately. (Reset is in cm_clear)
|
|
canonical_machine_reset(cm); // halt the currently active machine
|
|
cm->cycle_type = CYCLE_NONE; // Note: leaves machine_state alone
|
|
cm->motion_state = MOTION_STOP;
|
|
cm->hold_state = FEEDHOLD_OFF;
|
|
}
|
|
|
|
/****************************************************************************************
|
|
* cm_alarm() - enter ALARM state
|
|
*
|
|
* An ALARM sets the ALARM machine state, starts a feedhold to stop motion, stops the
|
|
* spindle, turns off coolant, clears out queued planner moves and serial input,
|
|
* and rejects new action commands (gcode blocks, SET commands, and other actions)
|
|
* until the alarm is cleared.
|
|
*
|
|
* ALARM is typically entered by a soft limit or a limit switch being hit. In the
|
|
* limit switch case the INPUT_ACTION will override the feedhold - i.e. if the
|
|
* input action is "FAST_STOP" or "HALT" that setting will take precedence over
|
|
* the feedhold native to the alarm function.
|
|
*
|
|
* Gcode and machine state is preserved. It may be possible to recover the job from
|
|
* an alarm, but in many cases this is not possible. Since ALARM attempts to preserve
|
|
* Gcode and machine state it does not END the job.
|
|
*
|
|
* ALARM may also be invoked from the command line using {alarm:n} or $alarm
|
|
* ALARM can be manually cleared by entering: {clear:n}, {clr:n}, $clear, or $clr
|
|
* ALARMs will also clear on receipt of an M30 or M2 command if one is received
|
|
* while draining the host command queue.
|
|
*/
|
|
|
|
stat_t cm_alarm(const stat_t status, const char *msg)
|
|
{
|
|
if ((cm->machine_state == MACHINE_ALARM) || (cm->machine_state == MACHINE_SHUTDOWN) ||
|
|
(cm->machine_state == MACHINE_PANIC)) {
|
|
return (STAT_OK); // don't alarm if already in an alarm state
|
|
}
|
|
cm_request_feedhold(FEEDHOLD_TYPE_HOLD, FEEDHOLD_EXIT_ALARM); // fast stop and alarm
|
|
rpt_exception(status, msg); // send alarm message
|
|
sr_request_status_report(SR_REQUEST_TIMED);
|
|
return (status);
|
|
}
|
|
|
|
/****************************************************************************************
|
|
* cm_shutdown() - enter shutdown state
|
|
*
|
|
* SHUTDOWN stops all motion, spindle and coolant immediately, sets a SHUTDOWN machine
|
|
* state, clears out queued moves and serial input, and rejects new action commands
|
|
* (gcode blocks, SET commands, and some others).
|
|
*
|
|
* Shutdown is typically invoked as an electrical input signal sent to the board as
|
|
* part of an external emergency stop (Estop). Shutdown is meant to augment but not
|
|
* replace the external Estop functions that shut down power to motors, spindles and
|
|
* other moving parts.
|
|
*
|
|
* Shutdown may also be invoked from the command line using {shutd:n} or $shutd
|
|
* Shutdown must be manually cleared by entering: {clear:n}, {clr:n}, $clear, or $clr
|
|
* Shutdown does not clear on M30 or M2 Gcode commands
|
|
*/
|
|
|
|
stat_t cm_shutdown(const stat_t status, const char *msg)
|
|
{
|
|
if ((cm->machine_state == MACHINE_SHUTDOWN) || (cm->machine_state == MACHINE_PANIC)) {
|
|
return (STAT_OK); // don't shutdown if shutdown or panic'd
|
|
}
|
|
cm_request_feedhold(FEEDHOLD_TYPE_HOLD, FEEDHOLD_EXIT_SHUTDOWN); // fast stop and shutdown
|
|
|
|
spindle_reset(); // stop spindle immediately and set speed to 0 RPM
|
|
coolant_reset(); // stop coolant immediately
|
|
temperature_reset(); // turn off heaters and fans
|
|
|
|
for (uint8_t i = 0; i < HOMING_AXES; i++) { // unhome axes and the machine
|
|
cm->homed[i] = false;
|
|
}
|
|
cm->homing_state = HOMING_NOT_HOMED;
|
|
|
|
// cm1.machine_state = MACHINE_SHUTDOWN; // shut down both machines...
|
|
// cm2.machine_state = MACHINE_SHUTDOWN; //...do this after all other activity
|
|
rpt_exception(status, msg); // send exception report
|
|
sr_request_status_report(SR_REQUEST_TIMED);
|
|
return (status);
|
|
}
|
|
|
|
/****************************************************************************************
|
|
* cm_panic() - enter panic state
|
|
*
|
|
* PANIC occurs if the firmware has detected an unrecoverable internal error
|
|
* such as an assertion failure or a code condition that should never occur.
|
|
* It sets PANIC machine state, and leaves the system inspect able (if possible).
|
|
*
|
|
* PANIC can only be exited by a hardware reset or soft reset (^x)
|
|
*/
|
|
|
|
stat_t cm_panic(const stat_t status, const char *msg)
|
|
{
|
|
debug_trap(msg);
|
|
|
|
if (cm->machine_state == MACHINE_PANIC) { // only do this once
|
|
return (STAT_OK);
|
|
}
|
|
cm_halt_motion(); // halt motors (may have already been done from GPIO)
|
|
spindle_reset(); // stop spindle immediately and set speed to 0 RPM
|
|
coolant_reset(); // stop coolant immediately
|
|
temperature_reset(); // turn off heaters and fans
|
|
|
|
cm1.machine_state = MACHINE_PANIC; // don't reset anything. Panics are not recoverable
|
|
cm2.machine_state = MACHINE_PANIC; // don't reset anything. Panics are not recoverable
|
|
rpt_exception(status, msg); // send panic report
|
|
return (status);
|
|
}
|