2023-04-27 23:15:06 +03:00
# include <iostream>
# include <sstream>
2023-05-05 15:42:30 +03:00
# include <utility>
# include <array>
2023-04-28 18:42:18 +03:00
# include "grbl_machine.h"
2023-04-28 14:50:58 +03:00
# include "string_utils.h"
2023-04-27 23:15:06 +03:00
grbl : : machine : : machine ( ) {
pipe = new tcp_transport ( " 192.168.5.39 " , 23 ) ;
2023-05-04 14:15:33 +03:00
states [ grbl_machine_state : : disconnected ] = new machine_state_connect ;
states [ grbl_machine_state : : init ] = new machine_state_init ;
states [ grbl_machine_state : : idle ] = new machine_state_idle ;
states [ grbl_machine_state : : check_program ] = new machine_state_check_program ;
states [ grbl_machine_state : : run_program ] = new machine_state_run_program ;
2023-05-09 14:30:39 +03:00
states [ grbl_machine_state : : heightmap_probing ] = new machine_state_heightmap_probing ;
2023-05-04 14:15:33 +03:00
switch_to_state ( grbl_machine_state : : disconnected ) ;
2023-04-27 23:15:06 +03:00
}
grbl : : machine : : ~ machine ( ) {
delete pipe ;
}
void grbl : : machine : : connect ( ) {
pipe - > open ( * this ) ;
}
void grbl : : machine : : on_connected ( grbl : : transport * transport ) {
std : : cout < < " grbl machine connected " < < std : : endl ;
2023-05-04 14:15:33 +03:00
states [ state ] - > on_connected ( this ) ;
2023-04-27 23:15:06 +03:00
// telnet handshake so that we get the banner. banner won't be coming otherwise
// t->send("\xff\xfd\x18\xff\xfd\x20\xff\xfd\x23\xff\xfd\x27");
2023-05-04 14:15:33 +03:00
// pipe->send("\xff\xfd\x18");
2023-04-27 23:15:06 +03:00
}
void grbl : : machine : : on_disconnected ( grbl : : transport * transport ) {
std : : cout < < " grbl machine disconnected " < < std : : endl ;
2023-05-04 14:15:33 +03:00
switch_to_state ( grbl_machine_state : : disconnected ) ;
2023-04-27 23:15:06 +03:00
}
2023-05-23 14:28:08 +03:00
grbl : : realtime_status_report grbl : : parse_status_report ( std : : string line , grbl : : realtime_status_report & result ) {
2023-04-28 14:50:58 +03:00
// grbl::realtime_status_report result;
2023-05-06 00:19:57 +03:00
// pin values are always reset when a report arrives
// if there is no value in the Pn: field then it means
// no pin is active
result . signals . value = 0 ;
auto l = line . substr ( 1 , line . size ( ) - 2 ) ;
2023-04-28 14:50:58 +03:00
auto pieces = split_string ( l , " | " ) ;
for ( auto i = 0 ; i < pieces . size ( ) ; i + + ) {
if ( i = = 0 ) {
// status
auto elements = split_string ( pieces [ i ] , " : " ) ;
result . status = status_from_string ( elements [ 0 ] ) ;
result . sub_status = elements . size ( ) > 1 ? elements [ 1 ] : " " ;
} else {
auto elements = split_string ( pieces [ i ] , " : " ) ;
if ( elements [ 0 ] = = " WPos " ) {
auto axis = split_string ( elements [ 1 ] , " , " ) ;
result . work_pos [ 0 ] = std : : stof ( axis [ 0 ] ) ;
result . work_pos [ 1 ] = std : : stof ( axis [ 1 ] ) ;
result . work_pos [ 2 ] = std : : stof ( axis [ 2 ] ) ;
} else if ( elements [ 0 ] = = " MPos " ) {
auto axis = split_string ( elements [ 1 ] , " , " ) ;
result . machine_pos [ 0 ] = std : : stof ( axis [ 0 ] ) ;
result . machine_pos [ 1 ] = std : : stof ( axis [ 1 ] ) ;
result . machine_pos [ 2 ] = std : : stof ( axis [ 2 ] ) ;
} else if ( elements [ 0 ] = = " Bf " ) {
auto p = split_string ( elements [ 1 ] , " , " ) ;
result . buffers_free = std : : stoi ( p [ 0 ] ) ;
result . rx_chars_free = std : : stoi ( p [ 1 ] ) ;
2023-05-06 00:19:57 +03:00
} else if ( elements [ 0 ] = = " Pn " ) {
2023-05-23 14:28:08 +03:00
for ( auto & c : elements [ 1 ] ) {
2023-05-06 00:19:57 +03:00
switch ( c ) {
case ' P ' :
result . signals . bit . probe = true ;
break ;
case ' X ' :
result . signals . bit . x_limit = true ;
break ;
case ' Y ' :
result . signals . bit . y_limit = true ;
break ;
case ' Z ' :
result . signals . bit . z_limit = true ;
break ;
case ' D ' :
result . signals . bit . door = true ;
break ;
case ' H ' :
result . signals . bit . hold = true ;
break ;
case ' R ' :
result . signals . bit . soft_reset = true ;
break ;
case ' S ' :
result . signals . bit . cycle_start = true ;
break ;
default :
std : : cerr < < " Unknown pin value [ " < < c < < " ] when parsing status report " < < std : : endl ;
break ;
}
}
2023-04-28 14:50:58 +03:00
} else {
// not implemented
}
}
}
return result ;
}
2023-04-28 18:42:18 +03:00
2023-05-23 14:28:08 +03:00
grbl : : machine_status grbl : : status_from_string ( const std : : string & status ) {
2023-04-28 14:50:58 +03:00
if ( status = = " Idle " ) return machine_status : : idle ;
if ( status = = " Run " ) return machine_status : : run ;
if ( status = = " Hold " ) return machine_status : : hold ;
if ( status = = " Jog " ) return machine_status : : jog ;
if ( status = = " Alarm " ) return machine_status : : alarm ;
if ( status = = " Door " ) return machine_status : : door ;
if ( status = = " Check " ) return machine_status : : check ;
if ( status = = " Home " ) return machine_status : : home ;
if ( status = = " Sleep " ) return machine_status : : sleep ;
if ( status = = " Tool " ) return machine_status : : tool ;
return machine_status : : unknown ;
}
2023-05-23 14:28:08 +03:00
void grbl : : machine : : check_program ( const grbl : : program & pgm ) {
2023-04-28 18:42:18 +03:00
running_program = pgm ;
2023-05-23 14:28:08 +03:00
std : : cout < < " checking program ( " < < running_program . filename < < " ) with "
< < running_program . number_of_instructions ( )
2023-05-04 21:30:22 +03:00
< < " instructions " < < std : : endl ;
switch_to_state ( grbl_machine_state : : check_program ) ;
2023-04-28 18:42:18 +03:00
}
2023-05-05 15:42:30 +03:00
void grbl : : machine : : set_work_offset ( std : : string work_offset ) {
std : : cout < < " Setting work offsset " < < work_offset < < std : : endl ;
// if (state != grbl_machine_state::disconnected) {
pipe - > send ( work_offset ) ;
// awaiting_responses++;
// while (awaiting_responses > 0);
current_work_offset = work_offset ;
auto pieces = split_string ( parameters [ work_offset ] , " , " ) ;
current_work_offset_values [ 0 ] = std : : stof ( pieces [ 0 ] ) ;
current_work_offset_values [ 1 ] = std : : stof ( pieces [ 1 ] ) ;
current_work_offset_values [ 2 ] = std : : stof ( pieces [ 2 ] ) ;
// }
}
2023-05-23 14:28:08 +03:00
void grbl : : machine : : run_program ( const grbl : : program & pgm , const std : : string & work_offset ) {
2023-05-04 21:48:55 +03:00
running_program = pgm ;
2023-05-23 14:28:08 +03:00
std : : cout < < " running program ( " < < running_program . filename < < " ) with "
< < running_program . number_of_instructions ( ) < < " instructions "
2023-05-05 11:33:00 +03:00
< < " on work offset " < < work_offset < < std : : endl ;
2023-05-05 15:42:30 +03:00
set_work_offset ( work_offset ) ;
2023-05-05 11:33:00 +03:00
2023-05-04 21:48:55 +03:00
switch_to_state ( grbl_machine_state : : run_program ) ;
}
2023-05-23 14:28:08 +03:00
std : : string grbl : : status_to_string ( const grbl : : machine_status & status ) {
2023-04-28 14:50:58 +03:00
switch ( status ) {
case machine_status : : idle :
return " Idle " ;
case machine_status : : run :
return " Run " ;
case machine_status : : hold :
return " Hold " ;
case machine_status : : jog :
return " Jog " ;
case machine_status : : alarm :
return " Alarm " ;
case machine_status : : door :
return " Door " ;
case machine_status : : check :
return " Check " ;
case machine_status : : home :
return " Home " ;
case machine_status : : sleep :
return " Sleep " ;
case machine_status : : tool :
return " Tool " ;
case machine_status : : unknown :
default :
return " Unknown " ;
}
}
std : : string grbl : : alarm_to_string ( int alarm ) {
switch ( alarm ) {
case 1 :
2023-04-28 16:08:05 +03:00
return " Hard limit has been triggered. \n Machine position is likely lost due to sudden halt. \n Re-homing is highly recommended. " ;
2023-04-28 14:50:58 +03:00
case 2 :
2023-04-28 16:08:05 +03:00
return " Soft limit alarm. G-code motion target exceeds \n machine travel. Machine position retained. \n Alarm may be safely unlocked. " ;
2023-04-28 14:50:58 +03:00
case 3 :
return " Reset while in motion. Machine position is likely lost due to sudden halt. Re-homing is highly recommended. " ;
case 4 :
return " Probe fail. Probe is not in the expected initial state before starting probe cycle when G38.2 and G38.3 is not triggered and G38.4 and G38.5 is triggered. " ;
case 5 :
return " Probe fail. Probe did not contact the workpiece within the programmed travel for G38.2 and G38.4. " ;
case 6 :
return " Homing fail. The active homing cycle was reset. " ;
case 7 :
return " Homing fail. Safety door was opened during homing cycle. " ;
case 8 :
return " Homing fail. Pull off travel failed to clear limit switch. Try increasing pull-off setting or check wiring. " ;
case 9 :
return " Homing fail. Could not find limit switch within search distances. Try increasing max travel, decreasing pull-off distance, or check wiring. " ;
case 10 :
return " Homing fail. Second dual axis limit switch failed to trigger within configured search distance after first. Try increasing trigger fail distance or check wiring. " ;
default :
return " unknown alarm code " ;
}
}
2023-04-28 18:54:49 +03:00
std : : string grbl : : error_to_string ( size_t error ) {
switch ( error ) {
case 1 :
return " G-code words consist of a letter and a value. Letter was not found. " ;
case 2 :
return " Missing the expected G-code word value or numeric value format is not valid. " ;
case 3 :
return " Grbl '$' system command was not recognized or supported. " ;
case 4 :
return " Negative value received for an expected positive value. " ;
case 5 :
return " Homing cycle failure. Homing is not enabled via settings. " ;
case 6 :
return " Minimum step pulse time must be greater than 3usec. " ;
case 7 :
return " An EEPROM read failed. Auto-restoring affected EEPROM to default values. " ;
case 8 :
return " Grbl '$' command cannot be used unless Grbl is IDLE. Ensures smooth operation during a job. " ;
case 9 :
return " G-code commands are locked out during alarm or jog state. " ;
case 10 :
return " Soft limits cannot be enabled without homing also enabled. " ;
case 11 :
return " Max characters per line exceeded. Received command line was not executed. " ;
case 12 :
return " Grbl '$' setting value cause the step rate to exceed the maximum supported. " ;
case 13 :
return " Safety door detected as opened and door state initiated. " ;
case 14 :
return " Build info or startup line exceeded EEPROM line length limit. Line not stored. " ;
case 15 :
return " Jog target exceeds machine travel. Jog command has been ignored. " ;
case 16 :
return " Jog command has no '=' or contains prohibited g-code. " ;
case 17 :
return " Laser mode requires PWM output. " ;
case 20 :
return " Unsupported or invalid g-code command found in block. " ;
case 21 :
return " More than one g-code command from same modal group found in block. " ;
case 22 :
return " Feed rate has not yet been set or is undefined. " ;
case 23 :
return " G-code command in block requires an integer value. " ;
case 24 :
return " More than one g-code command that requires axis words found in block. " ;
case 25 :
return " Repeated g-code word found in block. " ;
case 26 :
return " No axis words found in block for g-code command or current modal state which requires them. " ;
case 27 :
return " Line number value is invalid. " ;
case 28 :
return " G-code command is missing a required value word. " ;
case 29 :
return " G59.x work coordinate systems are not supported. " ;
case 30 :
return " G53 only allowed with G0 and G1 motion modes. " ;
case 31 :
return " Axis words found in block when no command or current modal state uses them. " ;
case 32 :
return " G2 and G3 arcs require at least one in-plane axis word. " ;
case 33 :
return " Motion command target is invalid. " ;
case 34 :
return " Arc radius value is invalid. " ;
case 35 :
return " G2 and G3 arcs require at least one in-plane offset word. " ;
case 36 :
return " Unused value words found in block. " ;
case 37 :
return " G43.1 dynamic tool length offset is not assigned to configured tool length axis. " ;
case 38 :
return " Tool number greater than max supported value. " ;
default :
return " unknown error " ;
}
}
2023-05-04 14:15:33 +03:00
std : : string grbl : : setting_description ( int number ) {
switch ( number ) {
case 0 :
return " Step pulse time (microseconds) \n Sets time length per step. Minimum 3 microseconds. " ;
case 1 :
return " Step idle delay (milliseconds) \n Sets a short hold delay when stopping to let dynamics settle before disabling steppers. Value 255 keeps motors enabled. " ;
case 2 :
return " Step pulse invert (mask) \n Inverts the step signals (active low). " ;
case 3 :
return " Step direction invert (mask) \n Inverts the direction signals (active low). " ;
case 4 :
return " Invert step enable pin (boolean) \n Inverts the stepper driver enable signals (active low). If the stepper drivers shares the same enable signal only X is used. " ;
case 5 :
return " Invert limit pins (mask) \n Inverts the axis limit input signals. " ;
case 6 :
return " Invert probe pin (boolean) \n Inverts the probe input pin signal. " ;
case 10 :
return " Status report options (mask) \n Specifies optional data included in status reports. " ;
case 11 :
return " Junction deviation (mm) \n Sets how fast Grbl travels through consecutive motions. Lower value slows it down. " ;
case 12 :
return " Arc tolerance (mm) \n Sets the G2 and G3 arc tracing accuracy based on radial error. Beware: A very small value may effect performance. " ;
case 13 :
return " Report in inches (boolean) \n Enables inch units when returning any position and rate value that is not a settings value. " ;
case 14 :
return " Invert control pins (mask) \n Inverts the control signals (active low). " ;
case 15 :
return " Invert coolant pins (mask) \n Inverts the coolant and mist signals (active low). " ;
case 16 :
return " Invert spindle signals (mask) \n Inverts the spindle on counterclockwise and PWM signals (active low). " ;
case 17 :
return " Pullup disable control pins (mask) \n Disable the control signals pullup resistors. Potentially enables pulldown resistor if available. " ;
case 18 :
return " Pullup disable limit pins (mask) \n Disable the limit signals pullup resistors. Potentially enables pulldown resistor if available. " ;
case 19 :
return " Pullup disable probe pin (boolean) \n Disable the probe signal pullup resistor. Potentially enables pulldown resistor if available. " ;
case 20 :
return " Soft limits enable (boolean) \n Enables soft limits checks within machine travel and sets alarm when exceeded. Requires homing. " ;
case 21 :
return " Hard limits enable (mask) \n When enabled immediately halts motion and throws an alarm when switch is triggered. In strict mode only homing is possible after switch is triggered. " ;
case 22 :
return " Homing cycle enable (boolean) \n Enables homing cycle. Requires limit switches on all axes. " ;
case 23 :
return " Homing direction invert (mask) \n Homing searches for a switch in the positive direction. Set axis bit to search in negative direction. " ;
case 24 :
return " Homing locate feed rate (mm/min) \n Feed rate to slowly engage limit switch to determine its location accurately. " ;
case 25 :
return " Homing search seek rate (mm/min) \n Seek rate to quickly find the limit switch before the slower locating phase. " ;
case 26 :
return " Homing switch debounce delay (milliseconds) \n Sets a short delay between phases of homing cycle to let a switch debounce. " ;
case 27 :
return " Homing switch pull-off distance (mm) \n Retract distance after triggering switch to disengage it. Homing will fail if switch isn't cleared. " ;
case 28 :
return " G73 Retract distance (mm) \n G73 retract distance (for chip breaking drilling). " ;
case 29 :
return " Pulse delay (microseconds) \n Step pulse delay. " ;
case 30 :
return " Maximum spindle speed (RPM) \n Maximum spindle speed. Sets PWM to maximum duty cycle. " ;
case 31 :
return " Minimum spindle speed (RPM) \n Minimum spindle speed. Sets PWM to minimum duty cycle. " ;
case 32 :
return " Mode of operation (integer) \n Laser mode: consecutive G1/2/3 commands will not halt when spindle speed is changed. Lathe mode: allows use of G7, G8, G96 and G97. " ;
case 33 :
return " Spindle PWM frequency (Hz) \n Spindle PWM frequency. " ;
case 34 :
return " Spindle PWM off value (percent) \n Spindle PWM off value in percent (duty cycle). " ;
case 35 :
return " Spindle PWM min value (percent) \n Spindle PWM min value in percent (duty cycle). " ;
case 36 :
return " Spindle PWM max value (percent) \n Spindle PWM max value in percent (duty cycle). " ;
case 37 :
return " Steppers deenergize (mask) \n Specifies which steppers not to disable when stopped. " ;
case 38 :
return " Spindle PPR (pulses) \n Spindle encoder pulses per revolution. " ;
case 39 :
return " Enable legacy RT commands (boolean) \n Enables \" normal \" processing of ?, ! and ~ characters when part of $-setting or comment. If disabled then they are added to the input string instead. " ;
case 40 :
return " Limit jog commands (boolean) \n Limit jog commands to machine limits for homed axes. " ;
case 43 :
return " Homing passes, (Number of homing passes. Minimum 1) \n maximum 128. " ;
case 44 :
return " Axes homing, first pass (mask) \n Axes to home in first pass. " ;
case 45 :
return " Axes homing, second pass (mask) \n Axes to home in second pass. " ;
case 46 :
return " Axes homing,third pass (mask) \n Axes to home in third pass. " ;
case 47 :
return " Axes homing, fourth pass (mask) \n Axes to home in fourth pass. " ;
case 48 :
return " Axes homing, fifthpass (mask) \n Axes to home in fifth pass. " ;
case 49 :
return " Axes homing, sixth pass (mask) \n Axes to home in sixth pass. " ;
case 50 :
return " Step jog speed (mm/min) \n Step jogging speed in millimeters per minute. " ;
case 51 :
return " Slow jog speed (mm/min) \n Slow jogging speed in millimeters per minute. " ;
case 52 :
return " Fast jog speed (mm/min) \n Fast jogging speed in millimeters per minut. " ;
case 53 :
return " Step jog distance (mm) \n Jog distance for single step jogging. " ;
case 54 :
return " Slow jog distance (mm) \n Jog distance before automatic stop. " ;
case 55 :
return " Fast jog distance (mm) \n Jog distance before automatic stop. " ;
case 60 :
return " Restore overrides () \n Restore overrides to default values at program end. " ;
case 61 :
return " Ignore door when idle () \n Enable this if it is desirable to open the safety door when in IDLE mode (eg. for jogging). " ;
case 62 :
return " Sleep enable () \n Enable sleep mode. " ;
case 63 :
return " Disable laser () \n Disable laser during hold. " ;
case 64 :
return " Force init alarm () \n Starts Grbl in alarm mode after a cold reset. " ;
case 65 :
return " Check limits at init () \n If limit switches are engaged after reset this forces Grbl to start in alarm mode. " ;
case 66 :
return " Homing init lock, (If homing is enabled) \n homing init lock sets Grbl into an alarm state upon power up. Clear by performing a homing cycle. " ;
case 70 :
return " Stream,,Input stream source: 0 - serial, 1 - bluetooth ( 2 - ethernet) \n 3 - WiFi " ;
case 71 :
return " WiFi SSID () \n WiFi SSID. " ;
case 72 :
return " WiFi Password () \n WiFi Password. " ;
case 73 :
return " WiFi Port () \n WiFi Port Number listening for incoming connections. " ;
case 74 :
return " Bluetooth device () \n Bluetooth device name. " ;
case 75 :
return " Bluetooth service () \n Bluetooth service name. " ;
2023-05-04 15:57:34 +03:00
case 80 :
return " Spindle P-gain " ;
case 81 :
return " Spindle I-gain " ;
case 82 :
return " Spindle D-gain " ;
case 84 :
return " Spindle PID max error " ;
case 85 :
return " Spindle PID max I error \n Spindle PID max integrator error " ;
case 90 :
return " Spindle sync P-gain " ;
case 91 :
return " Spindle sync I-gain " ;
case 92 :
return " Spindle sync D-gain " ;
case 95 :
return " Spindle sync PID max I error \n Spindle sync PID max integrator error " ;
2023-05-04 14:15:33 +03:00
case 100 :
return " X-axis travel resolution (step/mm) \n X-axis travel resolution in steps per millimeter. " ;
case 101 :
return " Y-axis travel resolution (step/mm) \n Y-axis travel resolution in steps per millimeter. " ;
case 102 :
return " Z-axis travel resolution (step/mm) \n Z-axis travel resolution in steps per millimeter. " ;
case 103 :
return " A-axis travel resolution (step/mm) \n A-axis travel resolution in steps per millimeter. " ;
case 104 :
return " B-axis travel resolution (step/mm) \n B-axis travel resolution in steps per millimeter. " ;
case 105 :
return " C-axis travel resolution (step/mm) \n C-axis travel resolution in steps per millimeter. " ;
case 110 :
return " X-axis maximum rate (mm/min) \n X-axis maximum rate. Used as G0 rapid rate. " ;
case 111 :
return " Y-axis maximum rate (mm/min) \n Y-axis maximum rate. Used as G0 rapid rate. " ;
case 112 :
return " Z-axis maximum rate (mm/min) \n Z-axis maximum rate. Used as G0 rapid rate. " ;
case 113 :
return " A-axis maximum rate (mm/min) \n A-axis maximum rate. Used as G0 rapid rate. " ;
case 114 :
return " B-axis maximum rate (mm/min) \n B-axis maximum rate. Used as G0 rapid rate. " ;
case 115 :
return " C-axis maximum rate (mm/min) \n C-axis maximum rate. Used as G0 rapid rate. " ;
case 120 :
return " X-axis acceleration (mm/sec^2) \n X-axis acceleration. Used for motion planning to not exceed motor torque and lose steps. " ;
case 121 :
return " Y-axis acceleration (mm/sec^2) \n Y-axis acceleration. Used for motion planning to not exceed motor torque and lose steps. " ;
case 122 :
return " Z-axis acceleration (mm/sec^2) \n Z-axis acceleration. Used for motion planning to not exceed motor torque and lose steps. " ;
case 123 :
return " A-axis acceleration (mm/sec^2) \n A-axis acceleration. Used for motion planning to not exceed motor torque and lose steps. " ;
case 124 :
return " B-axis acceleration (mm/sec^2) \n B-axis acceleration. Used for motion planning to not exceed motor torque and lose steps. " ;
case 125 :
return " C-axis acceleration (mm/sec^2) \n C-axis acceleration. Used for motion planning to not exceed motor torque and lose steps. " ;
case 130 :
return " X-axis maximum travel (mm) \n Maximum X-axis travel distance from homing switch. Determines valid machine space for soft-limits and homing search distances. " ;
case 131 :
return " Y-axis maximum travel (mm) \n Maximum Y-axis travel distance from homing switch. Determines valid machine space for soft-limits and homing search distances. " ;
case 132 :
return " Z-axis maximum travel (mm) \n Maximum Z-axis travel distance from homing switch. Determines valid machine space for soft-limits and homing search distances. " ;
case 133 :
return " A-axis maximum travel (mm) \n Maximum A-axis travel distance from homing switch. Determines valid machine space for soft-limits and homing search distances. " ;
case 134 :
return " B-axis maximum travel (mm) \n Maximum B-axis travel distance from homing switch. Determines valid machine space for soft-limits and homing search distances. " ;
case 135 :
return " C-axis maximum travel (mm) \n Maximum B-axis travel distance from homing switch. Determines valid machine space for soft-limits and homing search distances. " ;
case 160 :
return " X-axis backlash compensation (mm) \n X-axis backlash distance to compensate for. " ;
case 161 :
return " Y-axis backlash compensation (mm) \n Y-axis backlash distance to compensate for. " ;
case 162 :
return " Z-axis backlash compensation (mm) \n Z-axis backlash distance to compensate for. " ;
case 163 :
return " A-axis backlash compensation (mm) \n A-axis backlash distance to compensate for. " ;
case 164 :
return " B-axis backlash compensation (mm) \n B-axis backlash distance to compensate for. " ;
case 165 :
return " C-axis backlash compensation (mm) \n B-axis backlash distance to compensate for. " ;
default :
return " unknown setting " ;
}
}
2023-04-27 23:15:06 +03:00
void grbl : : machine : : on_line_received ( std : : string line , grbl : : transport * transport ) {
2023-04-28 14:50:58 +03:00
if ( line . at ( 0 ) ! = ' < ' )
std : : cout < < " >> " < < line < < std : : endl ;
2023-04-27 23:15:06 +03:00
2023-05-04 14:15:33 +03:00
states [ state ] - > on_line_received ( line ) ;
2023-04-27 23:15:06 +03:00
}
void grbl : : machine : : request_jog ( jog_state jog ) const {
2023-04-28 14:50:58 +03:00
2023-04-27 23:15:06 +03:00
cancel_jog ( ) ;
if ( jog . no_jogging ( ) ) {
return ;
}
std : : stringstream ss ;
ss < < " $J=G91 G21 " ;
if ( jog . left_pressed )
ss < < " X-1000 " ;
else if ( jog . right_pressed )
ss < < " X1000 " ;
if ( jog . up_pressed )
ss < < " Y1000 " ;
else if ( jog . down_pressed )
ss < < " Y-1000 " ;
if ( jog . z_up_pressed )
ss < < " Z1000 " ;
else if ( jog . z_down_pressed )
ss < < " Z-1000 " ;
if ( jog . speed_fast_pressed ) {
ss < < " F10000 " ;
} else if ( jog . speed_slow_pressed ) {
ss < < " F100 " ;
} else {
ss < < " F1000 " ;
}
pipe - > send ( ss . str ( ) ) ;
}
void grbl : : machine : : cancel_jog ( ) const {
pipe - > send_single_char_command ( 0x85 ) ;
2023-04-28 14:50:58 +03:00
}
void grbl : : machine : : request_unlock ( ) {
pipe - > send ( " $X " ) ;
}
void grbl : : machine : : request_home ( ) {
pipe - > send ( " $H " ) ;
}
void grbl : : machine : : request_reset ( ) {
pipe - > send_single_char_command ( 0x18 ) ;
}
2023-04-27 23:15:06 +03:00
2023-04-28 14:50:58 +03:00
void grbl : : machine : : request_cycle_start ( ) {
pipe - > send_single_char_command ( 0x81 ) ;
}
2023-04-27 23:15:06 +03:00
2023-04-28 14:50:58 +03:00
void grbl : : machine : : request_feed_hold ( ) {
pipe - > send_single_char_command ( 0x82 ) ;
2023-04-27 23:15:06 +03:00
}
2023-04-28 18:42:18 +03:00
void grbl : : machine : : reset_machine_state ( ) {
2023-05-04 21:48:55 +03:00
switch_to_state ( grbl_machine_state : : idle ) ;
executed_instructions = 0 ;
2023-04-28 18:42:18 +03:00
}
2023-05-04 14:15:33 +03:00
void grbl : : machine : : switch_to_state ( grbl : : grbl_machine_state new_state ) {
2023-05-04 21:30:22 +03:00
std : : cout < < " Switching from state " < < ( int ) state < < " to " < < ( int ) new_state < < std : : endl ;
std : : cout < < " Exiting from state " < < std : : endl ;
2023-05-04 14:15:33 +03:00
states [ state ] - > on_exit ( this ) ;
state = new_state ;
2023-05-04 21:30:22 +03:00
std : : cout < < " Entering to state " < < std : : endl ;
2023-05-04 14:15:33 +03:00
states [ state ] - > on_enter ( this ) ;
}
2023-05-23 14:28:08 +03:00
const std : : map < std : : string , std : : string , grbl : : settings_cmp > & grbl : : machine : : get_settings ( ) const {
2023-05-04 14:15:33 +03:00
return settings ;
}
2023-05-23 14:28:08 +03:00
const std : : map < std : : string , std : : string , grbl : : parameters_cmp > & grbl : : machine : : get_parameters ( ) const {
2023-05-04 14:15:33 +03:00
return parameters ;
}
2023-05-04 15:57:34 +03:00
void grbl : : machine : : zero_offset ( int which ) {
while ( awaiting_responses > 0 ) ;
pipe - > send ( " G10 L20 P " + std : : to_string ( 1 + which ) + " X0 Y0 Z0 " ) ; // P1 => G54
awaiting_responses + + ;
while ( awaiting_responses > 0 ) ;
pipe - > send ( " $# " ) ;
awaiting_responses + + ;
while ( awaiting_responses > 0 ) ;
2023-05-10 16:14:57 +03:00
push_event ( std : : make_shared < machine_event_parameters_reloaded > ( ) ) ;
2023-05-04 15:57:34 +03:00
}
void grbl : : machine : : zero_offset_axis ( int offset_index , int axis ) {
while ( awaiting_responses > 0 ) ;
pipe - > send ( " G10 L20 P " + std : : to_string ( 1 + offset_index ) + " " + char ( ' X ' + axis ) + " 0 " ) ; // P1 => G54
awaiting_responses + + ;
while ( awaiting_responses > 0 ) ;
pipe - > send ( " $# " ) ;
awaiting_responses + + ;
while ( awaiting_responses > 0 ) ;
2023-05-10 16:14:57 +03:00
push_event ( std : : make_shared < machine_event_parameters_reloaded > ( ) ) ;
2023-05-04 15:57:34 +03:00
}
2023-05-05 15:42:30 +03:00
void grbl : : machine : : go_to_zero ( bool x , bool y , bool z ) {
std : : string command = " G0 " ;
if ( x ) command + = " X0 " ;
if ( y ) command + = " Y0 " ;
if ( z ) command + = " Z0 " ;
while ( awaiting_responses > 0 ) ;
pipe - > send ( command ) ;
awaiting_responses + + ;
while ( awaiting_responses > 0 ) ;
}
const float * grbl : : machine : : get_current_work_offset_values ( ) const {
return current_work_offset_values ;
}
std : : array < float , 3 > grbl : : machine : : get_work_pos ( ) const {
std : : array < float , 3 > result = {
last_report . machine_pos [ 0 ] - current_work_offset_values [ 0 ] ,
last_report . machine_pos [ 1 ] - current_work_offset_values [ 1 ] ,
last_report . machine_pos [ 2 ] - current_work_offset_values [ 2 ] ,
} ;
return result ;
}
2023-05-05 22:25:19 +03:00
void grbl : : machine : : request_jog_fixed ( grbl : : jog_direction dir , float distance , float feed ) {
std : : string command = " $J=G21 G91 " ;
switch ( dir ) {
case jog_direction : : x_up :
command + = " X " ;
break ;
case jog_direction : : x_down :
command + = " X- " ;
break ;
case jog_direction : : y_up :
command + = " Y " ;
break ;
case jog_direction : : y_down :
command + = " Y- " ;
break ;
case jog_direction : : z_up :
command + = " Z " ;
break ;
case jog_direction : : z_down :
command + = " Z- " ;
break ;
}
command + = std : : to_string ( distance ) + " F " + std : : to_string ( feed ) ;
2023-05-06 00:19:57 +03:00
2023-05-05 22:25:19 +03:00
pipe - > send ( command ) ;
awaiting_responses + + ;
}
2023-05-07 11:05:01 +03:00
void grbl : : machine : : start_z_probe ( float min_z , float feed_rate ) {
std : : string command = " G38.2 Z " + std : : to_string ( min_z ) + " F " + std : : to_string ( feed_rate ) ;
pipe - > send ( command ) ;
awaiting_responses + + ;
}
2023-05-23 14:28:08 +03:00
void grbl : : machine : : probe_heightmap ( grbl : : heightmap & grid ) {
2023-05-09 14:30:39 +03:00
std : : cout < < " probing heightmap " < < std : : endl ;
dynamic_cast < machine_state_heightmap_probing * > ( states [ grbl_machine_state : : heightmap_probing ] ) - > grid = & grid ;
switch_to_state ( grbl_machine_state : : heightmap_probing ) ;
}
2023-05-10 16:14:57 +03:00
void grbl : : machine : : push_event ( std : : shared_ptr < machine_event > event ) {
std : : scoped_lock < std : : mutex > lock ( event_mutex ) ;
events . push_back ( event ) ;
}
std : : shared_ptr < grbl : : machine_event > grbl : : machine : : pop_event ( ) {
// TODO: make this more efficient
std : : scoped_lock < std : : mutex > lock ( event_mutex ) ;
if ( events . empty ( ) )
return nullptr ;
else {
auto result = events . front ( ) ;
events . pop_front ( ) ;
return result ;
}
}
2023-04-27 23:15:06 +03:00
bool grbl : : jog_state : : no_jogging ( ) const {
return ! ( up_pressed | | down_pressed | | left_pressed | | right_pressed | | z_up_pressed | | z_down_pressed ) ;
}
2023-05-04 14:15:33 +03:00
// connect state
void grbl : : machine_state_connect : : on_connected ( machine * m ) {
// trigger a soft reset
// m->pipe->send("\xff\xfd\x18");
m - > request_reset ( ) ;
}
void grbl : : machine_state_connect : : on_disconnected ( machine * m ) {
}
void grbl : : machine_state_connect : : on_enter ( grbl : : machine * m ) {
cnc = m ;
}
void grbl : : machine_state_connect : : on_exit ( grbl : : machine * m ) {
}
void grbl : : machine_state_connect : : on_line_received ( std : : string line ) {
// std::cerr << "Should not get content while connecting!" << std::endl;
if ( starts_with ( line , " Grbl " ) ) {
2023-05-10 16:14:57 +03:00
cnc - > push_event ( std : : make_shared < machine_event_banner > ( line ) ) ;
2023-05-04 14:15:33 +03:00
cnc - > switch_to_state ( grbl_machine_state : : init ) ;
}
}
// init state
void grbl : : machine_state_init : : on_enter ( grbl : : machine * m ) {
cnc = m ;
init_state = init_stage : : start ;
move_to_next_init_stage ( ) ;
}
void grbl : : machine_state_init : : on_exit ( grbl : : machine * m ) {
2023-05-10 16:14:57 +03:00
cnc - > push_event ( std : : make_shared < machine_event_init_completed > ( ) ) ;
2023-05-04 14:15:33 +03:00
}
void grbl : : machine_state_init : : on_line_received ( std : : string line ) {
if ( starts_with ( line , " ok " ) ) {
move_to_next_init_stage ( ) ;
} else if ( starts_with ( line , " error " ) ) {
// TODO: how should we act?
std : : cerr < < " Init failed!!!!!!!!!!!!!!!!!! FIXME! " < < std : : endl ;
} else {
if ( starts_with ( line , " $ " ) ) {
auto pieces = split_string ( line , " = " ) ;
cnc - > settings [ pieces [ 0 ] ] = pieces [ 1 ] ;
2023-05-23 14:28:08 +03:00
} else if ( starts_with ( line , " [G " ) | | starts_with ( line , " [H " ) | | starts_with ( line , " [T " ) | |
starts_with ( line , " [P " ) ) {
2023-05-04 14:15:33 +03:00
line = line . substr ( 1 , line . size ( ) - 2 ) ;
// TODO: some parameters have more than two :
auto pieces = split_string ( line , " : " ) ;
cnc - > parameters [ pieces [ 0 ] ] = pieces [ 1 ] ;
}
}
}
void grbl : : machine_state_init : : on_connected ( machine * m ) {
}
void grbl : : machine_state_init : : on_disconnected ( machine * m ) {
}
void grbl : : machine_state_init : : move_to_next_init_stage ( ) {
switch ( init_state ) {
case init_stage : : start :
init_state = init_stage : : set_work_pos ;
2023-05-06 00:19:57 +03:00
cnc - > pipe - > send ( " $10=511 " ) ; // machine pos in report, please. also sensors and buffers info
2023-05-04 14:15:33 +03:00
break ;
case init_stage : : set_work_pos :
init_state = init_stage : : fetch_settings ;
cnc - > pipe - > send ( " $$ " ) ;
break ;
case init_stage : : fetch_settings :
init_state = init_stage : : fetch_parameters ;
cnc - > pipe - > send ( " $# " ) ;
break ;
case init_stage : : fetch_parameters :
std : : cout < < " CNC initialization done " < < std : : endl ;
cnc - > switch_to_state ( grbl_machine_state : : idle ) ;
break ;
}
}
// idle state
void grbl : : machine_state_idle : : on_connected ( machine * m ) {
}
void grbl : : machine_state_idle : : on_disconnected ( machine * m ) {
}
void grbl : : machine_state_idle : : on_enter ( grbl : : machine * m ) {
cnc = m ;
}
void grbl : : machine_state_idle : : on_exit ( grbl : : machine * m ) {
}
void grbl : : machine_state_idle : : on_line_received ( std : : string line ) {
if ( starts_with ( line , " ok " ) ) {
2023-05-04 15:57:34 +03:00
if ( cnc - > awaiting_responses > 0 ) {
cnc - > awaiting_responses - - ;
}
2023-05-04 14:15:33 +03:00
} else if ( starts_with ( line , " error " ) ) {
2023-05-04 15:57:34 +03:00
if ( cnc - > awaiting_responses > 0 ) {
cnc - > awaiting_responses - - ;
}
2023-05-04 14:15:33 +03:00
} else if ( starts_with ( line , " Grbl " ) ) {
2023-05-10 16:14:57 +03:00
cnc - > push_event ( std : : make_shared < machine_event_banner > ( line ) ) ;
2023-05-04 14:15:33 +03:00
cnc - > reset_machine_state ( ) ;
} else if ( starts_with ( line , " < " ) ) {
cnc - > last_report = parse_status_report ( line , cnc - > last_report ) ;
2023-05-10 16:14:57 +03:00
cnc - > push_event ( std : : make_shared < machine_event_report_received > ( cnc - > last_report ) ) ;
2023-05-04 14:15:33 +03:00
} else if ( starts_with ( line , " [MSG: " ) ) {
2023-05-10 16:14:57 +03:00
auto message = line . substr ( 5 , line . size ( ) - 6 ) ;
cnc - > push_event ( std : : make_shared < machine_event_message > ( message ) ) ;
2023-05-04 14:15:33 +03:00
} else if ( starts_with ( line , " ALARM: " ) ) {
2023-05-10 16:14:57 +03:00
auto alarm = std : : stoi ( line . substr ( 6 ) ) ;
cnc - > push_event ( std : : make_shared < machine_event_alarm > ( alarm ) ) ;
2023-05-04 15:57:34 +03:00
} else if ( starts_with ( line , " $ " ) ) {
auto pieces = split_string ( line , " = " ) ;
cnc - > settings [ pieces [ 0 ] ] = pieces [ 1 ] ;
2023-05-23 14:28:08 +03:00
} else if ( starts_with ( line , " [G " ) | | starts_with ( line , " [H " ) | | starts_with ( line , " [T " ) | |
starts_with ( line , " [P " ) ) {
2023-05-04 15:57:34 +03:00
line = line . substr ( 1 , line . size ( ) - 2 ) ;
// TODO: some parameters have more than two :
auto pieces = split_string ( line , " : " ) ;
cnc - > parameters [ pieces [ 0 ] ] = pieces [ 1 ] ;
2023-05-07 11:05:01 +03:00
if ( starts_with ( line , " PRB " ) ) {
auto pieces = split_string ( line , " : " ) ;
auto coords_as_string = split_string ( pieces [ 1 ] , " , " ) ;
float probe_coords [ 3 ] ;
for ( auto i = 0 ; i < 3 ; i + + ) {
probe_coords [ i ] = std : : stof ( coords_as_string [ i ] ) ;
}
bool probe_touched = pieces [ 2 ] = = " 1 " ;
2023-05-10 16:14:57 +03:00
cnc - > push_event ( std : : make_shared < machine_event_probe_result > ( probe_touched , probe_coords ) ) ;
2023-05-07 11:05:01 +03:00
}
2023-05-04 14:15:33 +03:00
}
}
// check program
void grbl : : machine_state_check_program : : on_connected ( machine * m ) {
}
void grbl : : machine_state_check_program : : on_disconnected ( machine * m ) {
}
void grbl : : machine_state_check_program : : on_enter ( grbl : : machine * m ) {
2023-05-04 21:30:22 +03:00
cnc = m ;
2023-05-04 14:15:33 +03:00
2023-05-04 21:30:22 +03:00
stage = check_stage : : start ;
check_failed = false ;
check_error = 0 ;
move_to_next_check_stage ( ) ;
2023-05-04 14:15:33 +03:00
}
void grbl : : machine_state_check_program : : on_exit ( grbl : : machine * m ) {
2023-05-04 21:30:22 +03:00
}
void grbl : : machine_state_check_program : : move_to_next_check_stage ( ) {
switch ( stage ) {
case check_stage : : start :
while ( cnc - > awaiting_responses > 0 ) ;
cnc - > pipe - > send ( " $C " ) ;
cnc - > awaiting_responses + + ;
2023-05-04 14:15:33 +03:00
2023-05-04 21:30:22 +03:00
cnc - > executed_instructions = 0 ;
stage = check_stage : : enable_check_mode ;
break ;
case check_stage : : enable_check_mode :
continue_program ( ) ;
stage = check_stage : : run_program ;
break ;
case check_stage : : run_program :
if ( check_failed | | ! continue_program ( ) ) {
stage = check_stage : : disable_check_mode ;
while ( cnc - > awaiting_responses > 0 ) ;
std : : cout < < " disabling $C mode " < < std : : endl ;
cnc - > pipe - > send ( " $C " ) ;
}
break ;
case check_stage : : disable_check_mode :
if ( check_failed ) {
2023-05-10 16:14:57 +03:00
bool success = false ;
size_t failed_idx = cnc - > executed_instructions - 1 ;
size_t error = check_error ;
cnc - > push_event ( std : : make_shared < machine_event_check_completed > ( success , failed_idx , error ) ) ;
2023-05-04 21:30:22 +03:00
} else {
2023-05-10 16:14:57 +03:00
bool success = true ;
size_t failed_idx = 0 ;
size_t error = 0 ;
cnc - > push_event ( std : : make_shared < machine_event_check_completed > ( success , failed_idx , error ) ) ;
2023-05-04 21:30:22 +03:00
}
cnc - > switch_to_state ( grbl_machine_state : : idle ) ;
break ;
}
2023-05-04 14:15:33 +03:00
}
void grbl : : machine_state_check_program : : on_line_received ( std : : string line ) {
2023-05-04 21:30:22 +03:00
if ( starts_with ( line , " ok " ) ) {
if ( cnc - > awaiting_responses > 0 ) {
cnc - > awaiting_responses - - ;
}
move_to_next_check_stage ( ) ;
} else if ( starts_with ( line , " error " ) ) {
if ( cnc - > awaiting_responses > 0 ) {
cnc - > awaiting_responses - - ;
}
check_failed = true ;
check_error = std : : stoi ( line . substr ( 6 ) ) ;
move_to_next_check_stage ( ) ;
} else if ( starts_with ( line , " Grbl " ) ) {
2023-05-10 16:14:57 +03:00
cnc - > push_event ( std : : make_shared < machine_event_banner > ( line ) ) ;
2023-05-04 21:30:22 +03:00
cnc - > reset_machine_state ( ) ;
} else if ( starts_with ( line , " < " ) ) {
cnc - > last_report = parse_status_report ( line , cnc - > last_report ) ;
2023-05-10 16:14:57 +03:00
cnc - > push_event ( std : : make_shared < machine_event_report_received > ( cnc - > last_report ) ) ;
2023-05-04 21:30:22 +03:00
} else if ( starts_with ( line , " [MSG: " ) ) {
2023-05-10 16:14:57 +03:00
auto message = line . substr ( 5 , line . size ( ) - 6 ) ;
cnc - > push_event ( std : : make_shared < machine_event_message > ( message ) ) ;
2023-05-04 21:30:22 +03:00
} else if ( starts_with ( line , " ALARM: " ) ) {
2023-05-10 16:14:57 +03:00
auto alarm = std : : stoi ( line . substr ( 6 ) ) ;
cnc - > push_event ( std : : make_shared < machine_event_alarm > ( alarm ) ) ;
2023-05-04 21:30:22 +03:00
}
}
bool grbl : : machine_state_check_program : : continue_program ( ) {
if ( cnc - > executed_instructions > = cnc - > running_program . number_of_instructions ( ) )
return false ;
instruction to_send ;
do {
to_send = cnc - > running_program . instruction_at ( cnc - > executed_instructions + + ) ;
2023-05-23 14:28:08 +03:00
} while ( to_send . type ! = instruction_type : : gcode & &
cnc - > executed_instructions < cnc - > running_program . number_of_instructions ( ) ) ;
2023-05-04 21:30:22 +03:00
if ( to_send . type = = instruction_type : : gcode ) {
cnc - > pipe - > send ( to_send . command ) ;
cnc - > awaiting_responses + + ;
return true ;
}
2023-05-04 14:15:33 +03:00
2023-05-04 21:30:22 +03:00
return false ;
2023-05-04 14:15:33 +03:00
}
// run program
void grbl : : machine_state_run_program : : on_connected ( machine * m ) {
}
void grbl : : machine_state_run_program : : on_disconnected ( machine * m ) {
}
void grbl : : machine_state_run_program : : on_enter ( grbl : : machine * m ) {
2023-05-04 21:48:55 +03:00
cnc = m ;
2023-05-04 14:15:33 +03:00
2023-05-04 21:48:55 +03:00
stage = run_stage : : start ;
run_failed = false ;
run_error = 0 ;
move_to_next_run_stage ( ) ;
2023-05-04 14:15:33 +03:00
}
void grbl : : machine_state_run_program : : on_exit ( grbl : : machine * m ) {
}
2023-05-04 21:48:55 +03:00
void grbl : : machine_state_run_program : : move_to_next_run_stage ( ) {
switch ( stage ) {
case run_stage : : start :
cnc - > executed_instructions = 0 ;
continue_program ( ) ;
stage = run_stage : : run_program ;
break ;
case run_stage : : run_program :
if ( run_failed | | ! continue_program ( ) ) {
if ( run_failed ) {
2023-05-10 16:14:57 +03:00
bool success = false ;
size_t failed_index = cnc - > executed_instructions - 1 ;
size_t error = run_error ;
cnc - > push_event ( std : : make_shared < machine_event_run_completed > ( success , failed_index , error ) ) ;
2023-05-04 21:48:55 +03:00
} else {
2023-05-10 16:14:57 +03:00
bool success = true ;
size_t failed_index = 0 ;
size_t error = 0 ;
cnc - > push_event ( std : : make_shared < machine_event_run_completed > ( success , failed_index , error ) ) ;
2023-05-04 21:48:55 +03:00
}
cnc - > switch_to_state ( grbl_machine_state : : idle ) ;
}
break ;
}
}
bool grbl : : machine_state_run_program : : continue_program ( ) {
if ( cnc - > executed_instructions > = cnc - > running_program . number_of_instructions ( ) )
return false ;
instruction to_send ;
do {
to_send = cnc - > running_program . instruction_at ( cnc - > executed_instructions + + ) ;
2023-05-23 14:28:08 +03:00
} while ( to_send . type ! = instruction_type : : gcode & &
cnc - > executed_instructions < cnc - > running_program . number_of_instructions ( ) ) ;
2023-05-04 21:48:55 +03:00
if ( to_send . type = = instruction_type : : gcode ) {
cnc - > pipe - > send ( to_send . command ) ;
cnc - > awaiting_responses + + ;
return true ;
}
return false ;
}
2023-05-04 14:15:33 +03:00
void grbl : : machine_state_run_program : : on_line_received ( std : : string line ) {
2023-05-04 21:48:55 +03:00
if ( starts_with ( line , " ok " ) ) {
if ( cnc - > awaiting_responses > 0 ) {
cnc - > awaiting_responses - - ;
}
move_to_next_run_stage ( ) ;
} else if ( starts_with ( line , " error " ) ) {
if ( cnc - > awaiting_responses > 0 ) {
cnc - > awaiting_responses - - ;
}
run_failed = true ;
run_error = std : : stoi ( line . substr ( 6 ) ) ;
move_to_next_run_stage ( ) ;
2023-05-04 14:15:33 +03:00
2023-05-04 21:48:55 +03:00
} else if ( starts_with ( line , " Grbl " ) ) {
2023-05-10 16:14:57 +03:00
cnc - > push_event ( std : : make_shared < machine_event_banner > ( line ) ) ;
2023-05-04 21:48:55 +03:00
cnc - > reset_machine_state ( ) ;
} else if ( starts_with ( line , " < " ) ) {
cnc - > last_report = parse_status_report ( line , cnc - > last_report ) ;
2023-05-10 16:14:57 +03:00
cnc - > push_event ( std : : make_shared < machine_event_report_received > ( cnc - > last_report ) ) ;
2023-05-04 21:48:55 +03:00
} else if ( starts_with ( line , " [MSG: " ) ) {
2023-05-10 16:14:57 +03:00
auto message = line . substr ( 5 , line . size ( ) - 6 ) ;
cnc - > push_event ( std : : make_shared < machine_event_message > ( message ) ) ;
2023-05-04 21:48:55 +03:00
} else if ( starts_with ( line , " ALARM: " ) ) {
2023-05-10 16:14:57 +03:00
auto alarm = std : : stoi ( line . substr ( 6 ) ) ;
cnc - > push_event ( std : : make_shared < machine_event_alarm > ( alarm ) ) ;
2023-05-04 21:48:55 +03:00
}
2023-05-04 14:15:33 +03:00
}
2023-05-09 14:30:39 +03:00
// heightmap probing
void grbl : : machine_state_heightmap_probing : : on_connected ( grbl : : machine * m ) {
}
void grbl : : machine_state_heightmap_probing : : on_disconnected ( grbl : : machine * m ) {
}
void grbl : : machine_state_heightmap_probing : : on_enter ( grbl : : machine * m ) {
cnc = m ;
stage = heightmap_probing_stage : : start ;
failed = false ;
error = 0 ;
probed_locations = 0 ;
move_to_next_stage ( ) ;
}
void grbl : : machine_state_heightmap_probing : : on_exit ( grbl : : machine * m ) {
}
void grbl : : machine_state_heightmap_probing : : on_line_received ( std : : string line ) {
if ( starts_with ( line , " ok " ) ) {
if ( cnc - > awaiting_responses > 0 ) {
cnc - > awaiting_responses - - ;
}
move_to_next_stage ( ) ;
} else if ( starts_with ( line , " error " ) ) {
if ( cnc - > awaiting_responses > 0 ) {
cnc - > awaiting_responses - - ;
}
failed = true ;
error = std : : stoi ( line . substr ( 6 ) ) ;
move_to_next_stage ( ) ;
} else if ( starts_with ( line , " Grbl " ) ) {
2023-05-10 16:14:57 +03:00
cnc - > push_event ( std : : make_shared < machine_event_banner > ( line ) ) ;
2023-05-09 14:30:39 +03:00
cnc - > reset_machine_state ( ) ;
} else if ( starts_with ( line , " < " ) ) {
cnc - > last_report = parse_status_report ( line , cnc - > last_report ) ;
2023-05-10 16:14:57 +03:00
cnc - > push_event ( std : : make_shared < machine_event_report_received > ( cnc - > last_report ) ) ;
2023-05-09 14:30:39 +03:00
} else if ( starts_with ( line , " [MSG: " ) ) {
2023-05-10 16:14:57 +03:00
auto message = line . substr ( 5 , line . size ( ) - 6 ) ;
cnc - > push_event ( std : : make_shared < machine_event_message > ( message ) ) ;
2023-05-09 14:30:39 +03:00
} else if ( starts_with ( line , " ALARM: " ) ) {
2023-05-10 16:14:57 +03:00
auto alarm = std : : stoi ( line . substr ( 6 ) ) ;
cnc - > push_event ( std : : make_shared < machine_event_alarm > ( alarm ) ) ;
2023-05-09 14:30:39 +03:00
} else if ( starts_with ( line , " [PRB " ) ) {
std : : cout < < " received PRB " < < std : : endl ;
line = line . substr ( 1 , line . size ( ) - 2 ) ;
auto pieces = split_string ( line , " : " ) ;
cnc - > parameters [ pieces [ 0 ] ] = pieces [ 1 ] + " : " + pieces [ 2 ] ;
}
}
bool grbl : : machine_state_heightmap_probing : : continue_program ( ) {
return false ;
}
void grbl : : machine_state_heightmap_probing : : move_to_next_stage ( ) {
switch ( stage ) {
case heightmap_probing_stage : : start :
2023-05-23 14:28:08 +03:00
cnc - > pipe - > send ( " G0 X " + std : : to_string ( grid - > vertices [ 0 ] . x ) + " Y " +
std : : to_string ( grid - > vertices [ 0 ] . y ) + " Z0.5 " ) ;
2023-05-09 14:30:39 +03:00
stage = heightmap_probing_stage : : goto_home ;
break ;
case heightmap_probing_stage : : goto_home :
2023-05-23 14:28:08 +03:00
cnc - > pipe - > send ( " G38.2 Z-65 F5 " ) ;
2023-05-09 14:30:39 +03:00
stage = heightmap_probing_stage : : initial_probe_step_back ;
break ;
case heightmap_probing_stage : : initial_probe_step_back :
// step back a bit (1mm, relative)
2023-05-23 14:28:08 +03:00
cnc - > pipe - > send ( " G91 G0 Z0.3 " ) ;
2023-05-09 14:30:39 +03:00
stage = heightmap_probing_stage : : initial_probe_fine_seek ;
break ;
case heightmap_probing_stage : : initial_probe_fine_seek :
// probe again but finer
2023-05-23 14:28:08 +03:00
cnc - > pipe - > send ( " G38.2 Z-1 F5 " ) ;
2023-05-09 14:30:39 +03:00
stage = heightmap_probing_stage : : initial_probe ;
break ;
case heightmap_probing_stage : : initial_probe :
std : : cout < < " Initial probe: " < < cnc - > parameters [ " PRB " ] ;
std : : cout < < " . Setting this as new zero " < < std : : endl ;
cnc - > pipe - > send ( " G10 L20 P1 Z0 " ) ;
{
auto pieces = split_string ( cnc - > parameters [ " PRB " ] , " : " ) ;
auto axes = split_string ( pieces [ 0 ] , " , " ) ;
z_zero_in_mpos = std : : stof ( axes [ 2 ] ) ;
std : : cout < < " Z zero in mpos: " < < z_zero_in_mpos < < std : : endl ;
grid - > vertices [ probed_locations ] . z = 0 ;
}
stage = heightmap_probing_stage : : goto_next_location ;
break ;
case heightmap_probing_stage : : goto_next_location : {
auto pieces = split_string ( cnc - > parameters [ " PRB " ] , " : " ) ;
auto axes = split_string ( pieces [ 0 ] , " , " ) ;
auto current_z = std : : stof ( axes [ 2 ] ) ;
if ( probed_locations = = 0 ) {
z_zero_in_mpos = current_z ;
std : : cout < < " Z zero in mpos: " < < z_zero_in_mpos < < std : : endl ;
grid - > vertices [ probed_locations ] . z = 0 ;
} else {
auto delta_z = current_z - z_zero_in_mpos ;
std : : cout < < " Z[ " < < probed_locations < < " ] = " < < delta_z < < std : : endl ;
grid - > vertices [ probed_locations ] . z = delta_z ;
2023-05-10 16:14:57 +03:00
cnc - > push_event ( std : : make_shared < machine_event_heightmap_probe_acquired > ( grid , probed_locations ) ) ;
2023-05-09 14:30:39 +03:00
}
}
probed_locations + + ;
if ( probed_locations = = grid - > vertices . size ( ) ) {
cnc - > pipe - > send ( " G0Z15 " ) ; // safe height
stage = heightmap_probing_stage : : done ;
} else {
2023-05-23 14:28:08 +03:00
cnc - > pipe - > send ( " G90 G0 Z1 " ) ;
2023-05-09 14:30:39 +03:00
stage = heightmap_probing_stage : : goto_next_location_move ;
}
break ;
case heightmap_probing_stage : : goto_next_location_move :
cnc - > pipe - > send ( " G0 X " + std : : to_string ( grid - > vertices [ probed_locations ] . x ) + " Y " +
std : : to_string ( grid - > vertices [ probed_locations ] . y ) ) ;
stage = heightmap_probing_stage : : goto_start_probing_at ;
break ;
case heightmap_probing_stage : : goto_start_probing_at :
2023-05-23 14:28:08 +03:00
cnc - > pipe - > send ( " G0 Z0.3 " ) ; // this appears to move Z upwards instead of downwards. why?
2023-05-09 14:30:39 +03:00
// faking the G0 Z0.5
// cnc->pipe->send("G91 G0 Z-1"); // 1.5 - 1 = 0.5.//
stage = heightmap_probing_stage : : probing ;
break ;
case heightmap_probing_stage : : probing :
2023-05-23 14:28:08 +03:00
cnc - > pipe - > send ( " G38.2 Z-1 F5 " ) ;
2023-05-09 14:30:39 +03:00
stage = heightmap_probing_stage : : goto_next_location ;
break ;
case heightmap_probing_stage : : done :
cnc - > switch_to_state ( grbl_machine_state : : idle ) ;
break ;
default :
break ;
}
}
2023-05-10 16:14:57 +03:00
grbl : : machine_event_connect : : machine_event_connect ( ) {
machine_event : : type = machine_event_type : : connected ;
}
grbl : : machine_event_disconnect : : machine_event_disconnect ( ) {
machine_event : : type = machine_event_type : : disconnected ;
}
2023-05-23 14:28:08 +03:00
grbl : : machine_event_report_received : : machine_event_report_received ( const grbl : : realtime_status_report & r )
2023-05-10 16:14:57 +03:00
: report ( r ) {
machine_event : : type = machine_event_type : : report_received ;
}
2023-05-23 14:28:08 +03:00
grbl : : machine_event_banner : : machine_event_banner ( const std : : string & b )
2023-05-10 16:14:57 +03:00
: banner { b } {
machine_event : : type = machine_event_type : : banner ;
}
2023-05-23 14:28:08 +03:00
grbl : : machine_event_message : : machine_event_message ( const std : : string & m )
2023-05-10 16:14:57 +03:00
: message { m } {
machine_event : : type = machine_event_type : : message ;
}
grbl : : machine_event_alarm : : machine_event_alarm ( int code )
: alarm ( code ) {
machine_event : : type = machine_event_type : : alarm ;
}
grbl : : machine_event_init_completed : : machine_event_init_completed ( ) {
machine_event : : type = machine_event_type : : init_completed ;
}
grbl : : machine_event_run_completed : : machine_event_run_completed ( bool success , size_t failed_index , size_t error )
: success ( success ) ,
failed_index ( failed_index ) ,
error ( error ) {
machine_event : : type = machine_event_type : : run_completed ;
}
grbl : : machine_event_check_completed : : machine_event_check_completed ( bool success , size_t failed_idx , size_t error )
: success ( success ) ,
failed_index ( failed_idx ) ,
error ( error ) {
machine_event : : type = machine_event_type : : check_completed ;
}
grbl : : machine_event_settings_reloaded : : machine_event_settings_reloaded ( ) {
machine_event : : type = machine_event_type : : settings_reloaded ;
}
grbl : : machine_event_parameters_reloaded : : machine_event_parameters_reloaded ( ) {
machine_event : : type = machine_event_type : : parameters_reloaded ;
}
grbl : : machine_event_probe_result : : machine_event_probe_result ( bool touched , const float * coords )
: probe_touched ( touched ) ,
probe_coords { coords [ 0 ] , coords [ 1 ] , coords [ 2 ] } {
machine_event : : type = machine_event_type : : probe_result ;
}
2023-05-23 14:28:08 +03:00
grbl : : machine_event_heightmap_probe_acquired : : machine_event_heightmap_probe_acquired ( grbl : : heightmap * g ,
size_t location )
2023-05-10 16:14:57 +03:00
: grid ( g ) ,
probed_location ( location ) {
machine_event : : type = machine_event_type : : heightmap_probe_acquired ;
}