Merge pull request #86 from PavelSindler/keepalive_messages

host keep alive messages
This commit is contained in:
XPila 2017-11-16 20:53:09 +01:00 committed by GitHub
commit 279ea79bf6
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 140 additions and 13 deletions

View File

@ -519,7 +519,13 @@ const bool Z_MAX_ENDSTOP_INVERTING = true; // set to true to invert the logic of
// please keep turned on if you can.
//#define EEPROM_CHITCHAT
// Host Keepalive
//
// When enabled Marlin will send a busy status message to the host
// every couple of seconds when it can't accept commands.
//
#define HOST_KEEPALIVE_FEATURE // Disable this if your host doesn't like keepalive messages
#define HOST_KEEPALIVE_INTERVAL 2 // Number of seconds between "busy" messages. Set with M113.
//LCD and SD support
#define ULTRA_LCD //general LCD support, also 16x2

View File

@ -290,6 +290,10 @@ extern float retract_length, retract_length_swap, retract_feedrate, retract_zlif
extern float retract_recover_length, retract_recover_length_swap, retract_recover_feedrate;
#endif
#ifdef HOST_KEEPALIVE_FEATURE
extern uint8_t host_keepalive_interval;
#endif
extern unsigned long starttime;
extern unsigned long stoptime;
extern int bowden_length[4];
@ -381,6 +385,24 @@ extern void print_world_coordinates();
extern void print_physical_coordinates();
extern void print_mesh_bed_leveling_table();
#ifdef HOST_KEEPALIVE_FEATURE
// States for managing Marlin and host communication
// Marlin sends messages if blocked or busy
enum MarlinBusyState {
NOT_BUSY, // Not in a handler
IN_HANDLER, // Processing a GCode
IN_PROCESS, // Known to be blocking command input (as in G29)
PAUSED_FOR_USER, // Blocking pending any input
PAUSED_FOR_INPUT // Blocking pending text input (concept)
};
#define KEEPALIVE_STATE(n) do { busy_state = n;} while (0)
extern void host_keepalive();
extern MarlinBusyState busy_state;
#endif //HOST_KEEPALIVE_FEATURE
// G-codes
bool gcode_M45(bool onlyZ);
void gcode_M701();

View File

@ -176,6 +176,7 @@
// Rxxx Wait for extruder current temp to reach target temp. Waits when heating and cooling
// IF AUTOTEMP is enabled, S<mintemp> B<maxtemp> F<factor>. Exit autotemp by any M109 without F
// M112 - Emergency stop
// M113 - Get or set the timeout interval for Host Keepalive "busy" messages
// M114 - Output current position to serial port
// M115 - Capabilities string
// M117 - display message
@ -396,6 +397,16 @@ int fanSpeed=0;
bool cancel_heatup = false ;
#ifdef HOST_KEEPALIVE_FEATURE
MarlinBusyState busy_state = NOT_BUSY;
static long prev_busy_signal_ms = -1;
uint8_t host_keepalive_interval = HOST_KEEPALIVE_INTERVAL;
#else
#define host_keepalive();
#define KEEPALIVE_STATE(n);
#endif
#ifdef FILAMENT_SENSOR
//Variables for Filament Sensor input
float filament_width_nominal=DEFAULT_NOMINAL_FILAMENT_DIA; //Set nominal filament width, can be changed with M404
@ -832,7 +843,7 @@ void setup()
// Reset the machine correction matrix.
// It does not make sense to load the correction matrix until the machine is homed.
world2machine_reset();
KEEPALIVE_STATE(PAUSED_FOR_USER);
if (!READ(BTN_ENC))
{
_delay_ms(1000);
@ -1021,7 +1032,7 @@ void setup()
lcd_show_fullscreen_message_and_wait_P(MSG_FOLLOW_CALIBRATION_FLOW);
}
}
KEEPALIVE_STATE(IN_PROCESS);
#endif //DEBUG_DISABLE_STARTMSGS
lcd_update_enable(true);
lcd_implementation_clear();
@ -1029,6 +1040,7 @@ void setup()
// Store the currently running firmware into an eeprom,
// so the next time the firmware gets updated, it will know from which version it has been updated.
update_current_firmware_version_to_eeprom();
if (eeprom_read_byte((uint8_t*)EEPROM_UVLO) == 1) { //previous print was terminated by UVLO
/*
if (lcd_show_fullscreen_message_yes_no_and_wait_P(MSG_RECOVER_PRINT, false)) recover_print();
@ -1068,7 +1080,7 @@ void setup()
}
}
KEEPALIVE_STATE(NOT_BUSY);
}
void trace();
@ -1145,10 +1157,43 @@ int serial_read_stream() {
}
}
#ifdef HOST_KEEPALIVE_FEATURE
/**
* Output a "busy" message at regular intervals
* while the machine is not accepting commands.
*/
void host_keepalive() {
if (farm_mode) return;
long ms = millis();
if (host_keepalive_interval && busy_state != NOT_BUSY) {
if ((ms - prev_busy_signal_ms) < (long)(1000L * host_keepalive_interval)) return;
switch (busy_state) {
case IN_HANDLER:
case IN_PROCESS:
SERIAL_ECHO_START;
SERIAL_ECHOLNPGM("busy: processing");
break;
case PAUSED_FOR_USER:
SERIAL_ECHO_START;
SERIAL_ECHOLNPGM("busy: paused for user");
break;
case PAUSED_FOR_INPUT:
SERIAL_ECHO_START;
SERIAL_ECHOLNPGM("busy: paused for input");
break;
default:
break;
}
}
prev_busy_signal_ms = ms;
}
#endif
// The loop() function is called in an endless loop by the Arduino framework from the default main() routine.
// Before loop(), the setup() function is called by the main() routine.
void loop()
{
KEEPALIVE_STATE(NOT_BUSY);
bool stack_integrity = true;
if (usb_printing_counter > 0 && millis()-_usb_timer > 1000)
@ -1218,6 +1263,7 @@ void loop()
planner_add_sd_length(sdlen.value);
sei();
}
host_keepalive();
}
}
//check heater every n milliseconds
@ -1237,6 +1283,7 @@ void loop()
enquecommand_P((PSTR("D999")));
}
#endif //TMC2130
}
#define DEFINE_PGM_READ_ANY(type, reader) \
@ -1787,9 +1834,11 @@ bool gcode_M45(bool onlyZ) {
// lcd_wait_for_cool_down();
//}
if(!onlyZ){
KEEPALIVE_STATE(PAUSED_FOR_USER);
bool result = lcd_show_fullscreen_message_yes_no_and_wait_P(MSG_STEEL_SHEET_CHECK, false, false);
if(result) lcd_show_fullscreen_message_and_wait_P(MSG_REMOVE_STEEL_SHEET);
lcd_show_fullscreen_message_and_wait_P(MSG_PAPER);
KEEPALIVE_STATE(IN_HANDLER);
lcd_display_message_fullscreen_P(MSG_FIND_BED_OFFSET_AND_SKEW_LINE1);
lcd_implementation_print_at(0, 2, 1);
lcd_printPGM(MSG_FIND_BED_OFFSET_AND_SKEW_LINE2);
@ -1937,12 +1986,14 @@ void process_commands()
#endif
// PRUSA GCODES
KEEPALIVE_STATE(IN_HANDLER);
#ifdef SNMM
float tmp_motor[3] = DEFAULT_PWM_MOTOR_CURRENT;
float tmp_motor_loud[3] = DEFAULT_PWM_MOTOR_CURRENT_LOUD;
int8_t SilentMode;
#endif
if (code_seen("M117")) { //moved to highest priority place to be able to to print strings which includes "G", "PRUSA" and "^"
starpos = (strchr(strchr_pointer + 5, '*'));
if (starpos != NULL)
@ -2782,6 +2833,7 @@ void process_commands()
enquecommand_front_P((PSTR("G28 W0")));
break;
}
KEEPALIVE_STATE(NOT_BUSY); //no need to print busy messages as we print current temperatures periodicaly
SERIAL_ECHOLNPGM("PINDA probe calibration start");
float zero_z;
@ -3363,6 +3415,7 @@ void process_commands()
current_position[E_AXIS] += DEFAULT_RETRACTION;
plan_buffer_line(current_position[X_AXIS], current_position[Y_AXIS], current_position[Z_AXIS], current_position[E_AXIS], 400, active_extruder);
}
KEEPALIVE_STATE(NOT_BUSY);
// Restore custom message state
custom_message = custom_message_old;
custom_message_type = custom_message_type_old;
@ -3569,20 +3622,24 @@ void process_commands()
previous_millis_cmd = millis();
if (codenum > 0){
codenum += millis(); // keep track of when we started waiting
KEEPALIVE_STATE(PAUSED_FOR_USER);
while(millis() < codenum && !lcd_clicked()){
manage_heater();
manage_inactivity(true);
lcd_update();
}
KEEPALIVE_STATE(IN_HANDLER);
lcd_ignore_click(false);
}else{
if (!lcd_detected())
break;
KEEPALIVE_STATE(PAUSED_FOR_USER);
while(!lcd_clicked()){
manage_heater();
manage_inactivity(true);
lcd_update();
}
KEEPALIVE_STATE(IN_HANDLER);
}
if (IS_SD_PRINTING)
LCD_MESSAGERPGM(MSG_RESUMING);
@ -3798,7 +3855,9 @@ void process_commands()
case 47:
// M47: Prusa3D: Show end stops dialog on the display.
KEEPALIVE_STATE(PAUSED_FOR_USER);
lcd_diag_show_end_stops();
KEEPALIVE_STATE(IN_HANDLER);
break;
#if 0
@ -4193,6 +4252,7 @@ Sigma_Exit:
}}
#endif
SERIAL_PROTOCOLLN("");
KEEPALIVE_STATE(NOT_BUSY);
return;
break;
case 109:
@ -4229,12 +4289,15 @@ Sigma_Exit:
/* See if we are heating up or cooling down */
target_direction = isHeatingHotend(tmp_extruder); // true if heating, false if cooling
KEEPALIVE_STATE(NOT_BUSY);
cancel_heatup = false;
wait_for_heater(codenum); //loops until target temperature is reached
LCD_MESSAGERPGM(MSG_HEATING_COMPLETE);
KEEPALIVE_STATE(IN_HANDLER);
heating_status = 2;
if (farm_mode) { prusa_statistics(2); };
@ -4262,6 +4325,7 @@ Sigma_Exit:
cancel_heatup = false;
target_direction = isHeatingBed(); // true if heating, false if cooling
KEEPALIVE_STATE(NOT_BUSY);
while ( (target_direction)&&(!cancel_heatup) ? (isHeatingBed()) : (isCoolingBed()&&(CooldownNoWait==false)) )
{
if(( millis() - codenum) > 1000 ) //Print Temp Reading every 1 second while heating up.
@ -4284,6 +4348,7 @@ Sigma_Exit:
lcd_update();
}
LCD_MESSAGERPGM(MSG_BED_DONE);
KEEPALIVE_STATE(IN_HANDLER);
heating_status = 4;
previous_millis_cmd = millis();
@ -4421,6 +4486,19 @@ Sigma_Exit:
}
}
break;
#ifdef HOST_KEEPALIVE_FEATURE
case 113: // M113 - Get or set Host Keepalive interval
if (code_seen('S')) {
host_keepalive_interval = (uint8_t)code_value_short();
NOMORE(host_keepalive_interval, 60);
}
else {
SERIAL_ECHO_START;
SERIAL_ECHOPAIR("M113 S", (unsigned long)host_keepalive_interval);
SERIAL_PROTOCOLLN("");
}
break;
#endif
case 115: // M115
if (code_seen('V')) {
// Report the Prusa version number.
@ -5253,6 +5331,7 @@ case 404: //M404 Enter the nominal filament width (3mm, 1.75mm ) N<3.0> or disp
int counterBeep = 0;
lcd_wait_interact();
load_filament_time = millis();
KEEPALIVE_STATE(PAUSED_FOR_USER);
while(!lcd_clicked()){
cnt++;
@ -5290,13 +5369,17 @@ case 404: //M404 Enter the nominal filament width (3mm, 1.75mm ) N<3.0> or disp
}
WRITE(BEEPER, LOW);
KEEPALIVE_STATE(IN_HANDLER);
#ifdef SNMM
display_loading();
KEEPALIVE_STATE(PAUSED_FOR_USER);
do {
target[E_AXIS] += 0.002;
plan_buffer_line(target[X_AXIS], target[Y_AXIS], target[Z_AXIS], target[E_AXIS], 500, active_extruder);
delay_keep_alive(2);
} while (!lcd_clicked());
} while (!lcd_clicked());
KEEPALIVE_STATE(IN_HANDLER);
/*if (millis() - load_filament_time > 2) {
load_filament_time = millis();
target[E_AXIS] += 0.001;
@ -5331,7 +5414,9 @@ case 404: //M404 Enter the nominal filament width (3mm, 1.75mm ) N<3.0> or disp
lcd_loading_filament();
while ((lcd_change_fil_state == 0)||(lcd_change_fil_state != 1)){
lcd_change_fil_state = 0;
KEEPALIVE_STATE(PAUSED_FOR_USER);
lcd_alright();
KEEPALIVE_STATE(IN_HANDLER);
switch(lcd_change_fil_state){
// Filament failed to load so load it again
@ -5913,7 +5998,7 @@ case 404: //M404 Enter the nominal filament width (3mm, 1.75mm ) N<3.0> or disp
SERIAL_ECHO(CMDBUFFER_CURRENT_STRING);
SERIAL_ECHOLNPGM("\"(2)");
}
KEEPALIVE_STATE(NOT_BUSY);
ClearToSend();
}

View File

@ -783,6 +783,9 @@ void manage_heater()
volumetric_multiplier[FILAMENT_SENSOR_EXTRUDER_NUM]=0.01;
}
#endif
#ifdef HOST_KEEPALIVE_FEATURE
host_keepalive();
#endif
}
#define PGM_RD_W(x) (short)pgm_read_word(&x)

View File

@ -1989,13 +1989,14 @@ void lcd_menu_statistics()
lcd.print(itostr3(_days));
KEEPALIVE_STATE(PAUSED_FOR_USER);
while (!lcd_clicked())
{
manage_heater();
manage_inactivity(true);
delay(100);
}
KEEPALIVE_STATE(NOT_BUSY);
lcd_quick_feedback();
lcd_return_to_status();
@ -2072,6 +2073,7 @@ void lcd_service_mode_show_result() {
} else lcd_print_at_PGM(11, i + 1, PSTR("N/A"));
}
delay_keep_alive(500);
KEEPALIVE_STATE(PAUSED_FOR_USER);
while (!lcd_clicked()) {
delay_keep_alive(100);
}
@ -2098,6 +2100,7 @@ void lcd_service_mode_show_result() {
while (!lcd_clicked()) {
delay_keep_alive(100);
}
KEEPALIVE_STATE(NOT_BUSY);
delay_keep_alive(500);
lcd_set_custom_characters_arrows();
lcd_return_to_status();
@ -2574,8 +2577,9 @@ void lcd_show_fullscreen_message_and_wait_P(const char *msg)
const char *msg_next = lcd_display_message_fullscreen_P(msg);
bool multi_screen = msg_next != NULL;
lcd_set_custom_characters_nextpage();
// Until confirmed by a button click.
for (;;) {
KEEPALIVE_STATE(PAUSED_FOR_USER);
// Until confirmed by a button click.
for (;;) {
if (!multi_screen) {
lcd.setCursor(19, 3);
// Display the confirm char.
@ -2588,6 +2592,7 @@ void lcd_show_fullscreen_message_and_wait_P(const char *msg)
while (lcd_clicked()) ;
delay(10);
while (lcd_clicked()) ;
KEEPALIVE_STATE(IN_HANDLER);
lcd_set_custom_characters();
lcd_update_enable(true);
lcd_update(2);
@ -2610,6 +2615,7 @@ void lcd_show_fullscreen_message_and_wait_P(const char *msg)
void lcd_wait_for_click()
{
KEEPALIVE_STATE(PAUSED_FOR_USER);
for (;;) {
manage_heater();
manage_inactivity(true);
@ -2617,6 +2623,7 @@ void lcd_wait_for_click()
while (lcd_clicked()) ;
delay(10);
while (lcd_clicked()) ;
KEEPALIVE_STATE(IN_HANDLER);
return;
}
}
@ -2716,6 +2723,7 @@ int8_t lcd_show_fullscreen_message_yes_no_and_wait_P(const char *msg, bool allow
// Wait for user confirmation or a timeout.
unsigned long previous_millis_cmd = millis();
int8_t enc_dif = encoderDiff;
KEEPALIVE_STATE(PAUSED_FOR_USER);
for (;;) {
if (allow_timeouting && millis() - previous_millis_cmd > LCD_TIMEOUT_TO_STATUS)
return -1;
@ -2741,6 +2749,7 @@ int8_t lcd_show_fullscreen_message_yes_no_and_wait_P(const char *msg, bool allow
while (lcd_clicked());
delay(10);
while (lcd_clicked());
KEEPALIVE_STATE(IN_HANDLER);
return yes;
}
}
@ -4022,7 +4031,7 @@ static char snmm_stop_print_menu() { //menu for choosing which filaments will be
lcd_print_at_PGM(1,3,MSG_CURRENT);
char cursor_pos = 1;
int enc_dif = 0;
KEEPALIVE_STATE(PAUSED_FOR_USER);
while (1) {
manage_heater();
manage_inactivity(true);
@ -4050,6 +4059,7 @@ static char snmm_stop_print_menu() { //menu for choosing which filaments will be
while (lcd_clicked());
delay(10);
while (lcd_clicked());
KEEPALIVE_STATE(IN_HANDLER);
return(cursor_pos - 1);
}
}
@ -4072,7 +4082,7 @@ char choose_extruder_menu() {
for (int i = 0; i < 3; i++) {
lcd_print_at_PGM(1, i + 1, MSG_EXTRUDER);
}
KEEPALIVE_STATE(PAUSED_FOR_USER);
while (1) {
for (int i = 0; i < 3; i++) {
@ -4136,6 +4146,7 @@ char choose_extruder_menu() {
while (lcd_clicked());
delay(10);
while (lcd_clicked());
KEEPALIVE_STATE(IN_HANDLER);
return(cursor_pos + first - 1);
}
@ -4344,13 +4355,13 @@ static void extr_adj(int extruder) //loading filament for SNMM
case 3: lcd_display_message_fullscreen_P(MSG_FILAMENT_LOADING_T3); break;
default: lcd_display_message_fullscreen_P(MSG_FILAMENT_LOADING_T0); break;
}
KEEPALIVE_STATE(PAUSED_FOR_USER);
do{
extr_mov(0.001,1000);
delay_keep_alive(2);
} while (!lcd_clicked());
//delay_keep_alive(500);
KEEPALIVE_STATE(IN_HANDLER);
st_synchronize();
//correct = lcd_show_fullscreen_message_yes_no_and_wait_P(MSG_FIL_LOADED_CHECK, false);
//if (!correct) goto START;