Esempio n. 1
0
/** \brief Copy data from EEPROM to variables.
*/
void epr_eeprom_to_data() {
  baudrate = epr_get_long(EPR_BAUDRATE);
  max_inactive_time = epr_get_long(EPR_MAX_INACTIVE_TIME);
  stepper_inactive_time = epr_get_long(EPR_STEPPER_INACTIVE_TIME);
//#define EPR_ACCELERATION_TYPE 1
  axis_steps_per_unit[0] = epr_get_float(EPR_XAXIS_STEPS_PER_MM);
  axis_steps_per_unit[1] = epr_get_float(EPR_YAXIS_STEPS_PER_MM);
  axis_steps_per_unit[2] = epr_get_float(EPR_ZAXIS_STEPS_PER_MM);
  max_feedrate[0] = epr_get_float(EPR_X_MAX_FEEDRATE);
  max_feedrate[1] = epr_get_float(EPR_Y_MAX_FEEDRATE);
  max_feedrate[2] = epr_get_float(EPR_Z_MAX_FEEDRATE);
  homing_feedrate[0] = epr_get_float(EPR_X_HOMING_FEEDRATE);
  homing_feedrate[1] = epr_get_float(EPR_Y_HOMING_FEEDRATE);
  homing_feedrate[2] = epr_get_float(EPR_Z_HOMING_FEEDRATE);
  printer_state.maxJerk = epr_get_float(EPR_MAX_JERK);
  printer_state.maxZJerk = epr_get_float(EPR_MAX_ZJERK);
#ifdef RAMP_ACCELERATION
  max_acceleration_units_per_sq_second[0] = epr_get_float(EPR_X_MAX_ACCEL);
  max_acceleration_units_per_sq_second[1] = epr_get_float(EPR_Y_MAX_ACCEL);
  max_acceleration_units_per_sq_second[2] = epr_get_float(EPR_Z_MAX_ACCEL);
  max_travel_acceleration_units_per_sq_second[0] = epr_get_float(EPR_X_MAX_TRAVEL_ACCEL);
  max_travel_acceleration_units_per_sq_second[1] = epr_get_float(EPR_Y_MAX_TRAVEL_ACCEL);
  max_travel_acceleration_units_per_sq_second[2] = epr_get_float(EPR_Z_MAX_TRAVEL_ACCEL);
#endif
#if USE_OPS==1
  printer_state.opsMode = epr_get_byte(EPR_OPS_MODE);
  printer_state.opsMoveAfter = epr_get_float(EPR_OPS_MOVE_AFTER);
  printer_state.opsMinDistance = epr_get_float(EPR_OPS_MIN_DISTANCE);
  printer_state.opsRetractDistance = epr_get_float(EPR_OPS_RETRACT_DISTANCE);
  printer_state.opsRetractBackslash = epr_get_float(EPR_OPS_RETRACT_BACKSLASH);
#endif
  // now the extruder
  for(byte i=0;i<NUM_EXTRUDER;i++) {
    int o=i*EEPROM_EXTRUDER_LENGTH+EEPROM_EXTRUDER_OFFSET;
    Extruder *e = &extruder[i];
    e->stepsPerMM = epr_get_float(o+EPR_EXTRUDER_STEPS_PER_MM);
    e->maxFeedrate = epr_get_float(o+EPR_EXTRUDER_MAX_FEEDRATE);
    e->maxStartFeedrate = epr_get_float(o+EPR_EXTRUDER_MAX_START_FEEDRATE);
    e->maxAcceleration = epr_get_float(o+EPR_EXTRUDER_MAX_ACCELERATION);
    e->heatManager = epr_get_byte(o+EPR_EXTRUDER_HEAT_MANAGER);
#ifdef TEMP_PID
    e->pidDriveMax = epr_get_byte(o+EPR_EXTRUDER_DRIVE_MAX);
    e->pidDriveMin = epr_get_byte(o+EPR_EXTRUDER_DRIVE_MIN);
    e->pidPGain = epr_get_long(o+EPR_EXTRUDER_PID_PGAIN);
    e->pidIGain = epr_get_long(o+EPR_EXTRUDER_PID_IGAIN);
    e->pidDGain = epr_get_long(o+EPR_EXTRUDER_PID_DGAIN);
    e->pidMax = epr_get_byte(o+EPR_EXTRUDER_PID_MAX);
#endif
    e->yOffset = epr_get_long(o+EPR_EXTRUDER_X_OFFSET);
    e->xOffset = epr_get_long(o+EPR_EXTRUDER_Y_OFFSET);
    e->watchPeriod = epr_get_int(o+EPR_EXTRUDER_WATCH_PERIOD);    
 #ifdef USE_ADVANCE
 #ifdef ENABLE_QUADRATIC_ADVANCE
    e->advanceK = epr_get_float(o+EPR_EXTRUDER_ADVANCE_K);
 #endif
    e->advanceL = epr_get_float(o+EPR_EXTRUDER_ADVANCE_L);
 #endif
  }
  extruder_select(current_extruder->id);
  update_ramps_parameter();
  
}
Esempio n. 2
0
/**
  \brief Execute the command stored in com.
*/
void process_command(GCode *com)
{
    unsigned long codenum; //throw away variable
#ifdef INCLUDE_DEBUG_COMMUNICATION
    if(DEBUG_COMMUNICATION) {
        if(GCODE_HAS_G(com) || (GCODE_HAS_M(com) && com->M!=111)) {
            gcode_command_finished(); // free command cache
            previous_millis_cmd = millis();
            return;
        }
    }
#endif
    if(GCODE_HAS_G(com))
    {
        switch(com->G)
        {
        case 0: // G0 -> G1
        case 1: // G1
            if(get_coordinates(com)) // For X Y Z E F
                queue_move(ALWAYS_CHECK_ENDSTOPS);
            break;
        case 4: // G4 dwell
            codenum = 0;
            if(GCODE_HAS_P(com)) codenum = com->P; // milliseconds to wait
            if(GCODE_HAS_S(com)) codenum = (long)com->S * 1000; // seconds to wait
            codenum += millis();  // keep track of when we started waiting
            while(millis()  < codenum ) {
                gcode_read_serial();
                manage_temperatures(false);
            }
            break;
        case 20: // Units to inches
            unit_inches = 1;
            break;
        case 21: // Units to mm
            unit_inches = 0;
            break;
        case 28: {//G28 Home all Axis one at a time
            wait_until_end_of_move();
            float saved_feedrate = printer_state.feedrate;
            for(byte i=0; i < 4; i++) {
                printer_state.destinationSteps[i] = printer_state.currentPositionSteps[i];
            }

            byte home_all_axis = !(GCODE_HAS_X(com) || GCODE_HAS_Y(com) || GCODE_HAS_Z(com));

            if(home_all_axis || GCODE_HAS_X(com)) {
                if ((X_MIN_PIN > -1 && X_HOME_DIR==-1) || (X_MAX_PIN > -1 && X_HOME_DIR==1)) {
                    printer_state.destinationSteps[0] = 1.5 * printer_state.xMaxSteps * X_HOME_DIR;
                    printer_state.currentPositionSteps[0] = -printer_state.destinationSteps[0];
                    printer_state.feedrate = homing_feedrate[0];
                    queue_move(true);
                    wait_until_end_of_move();
                    printer_state.currentPositionSteps[0] = 0;
                    printer_state.destinationSteps[0] = axis_steps_per_unit[0]*-5 * X_HOME_DIR;
                    queue_move(true);
                    wait_until_end_of_move();
                    printer_state.destinationSteps[0] = axis_steps_per_unit[0]*10 * X_HOME_DIR;
                    queue_move(true);
                    wait_until_end_of_move();
                    printer_state.currentPositionSteps[0] = (X_HOME_DIR == -1) ? 0 : printer_state.xMaxSteps;
                    printer_state.destinationSteps[0] = printer_state.currentPositionSteps[0];
                }
            }

            if(home_all_axis || GCODE_HAS_Y(com)) {
                if ((Y_MIN_PIN > -1 && Y_HOME_DIR==-1) || (Y_MAX_PIN > -1 && Y_HOME_DIR==1)) {
                    printer_state.currentPositionSteps[1] = 0;
                    printer_state.destinationSteps[1] = 1.5 * printer_state.yMaxSteps * Y_HOME_DIR;
                    printer_state.currentPositionSteps[1] = -printer_state.destinationSteps[1];
                    printer_state.feedrate = homing_feedrate[1];
                    queue_move(true);
                    wait_until_end_of_move();
                    printer_state.currentPositionSteps[1] = 0;
                    printer_state.destinationSteps[1] = axis_steps_per_unit[1]*-5 * Y_HOME_DIR;
                    queue_move(true);
                    wait_until_end_of_move();
                    printer_state.destinationSteps[1] = axis_steps_per_unit[1]*10 * Y_HOME_DIR;
                    queue_move(true);
                    wait_until_end_of_move();
                    printer_state.currentPositionSteps[1] = (Y_HOME_DIR == -1) ? 0 : printer_state.yMaxSteps;
                    printer_state.destinationSteps[1] = printer_state.currentPositionSteps[1];
                }
            }

            if(home_all_axis || GCODE_HAS_Z(com)) {
                if ((Z_MIN_PIN > -1 && Z_HOME_DIR==-1) || (Z_MAX_PIN > -1 && Z_HOME_DIR==1)) {
                    printer_state.currentPositionSteps[2] = 0;
                    printer_state.destinationSteps[2] = 1.5 * printer_state.zMaxSteps * Z_HOME_DIR;
                    printer_state.currentPositionSteps[2] = -printer_state.destinationSteps[2];
                    printer_state.feedrate = homing_feedrate[2];
                    queue_move(true);
                    wait_until_end_of_move();
                    printer_state.currentPositionSteps[2] = 0;
                    printer_state.destinationSteps[2] = axis_steps_per_unit[2]*-2 * Z_HOME_DIR;
                    queue_move(true);
                    wait_until_end_of_move();
                    printer_state.destinationSteps[2] = axis_steps_per_unit[2]*10 * Z_HOME_DIR;
                    queue_move(true);
                    wait_until_end_of_move();
                    printer_state.currentPositionSteps[2] = (Z_HOME_DIR == -1) ? 0 : printer_state.zMaxSteps;
                    printer_state.destinationSteps[2] = printer_state.currentPositionSteps[2];
                }
            }
            printer_state.feedrate = saved_feedrate;
        }
        break;
        case 90: // G90
            relative_mode = false;
            break;
        case 91: // G91
            relative_mode = true;
            break;
        case 92: // G92
            if(GCODE_HAS_X(com)) printer_state.currentPositionSteps[0] = com->X*axis_steps_per_unit[0]*(unit_inches?25.4:1.0)-printer_state.offsetX;
            if(GCODE_HAS_Y(com)) printer_state.currentPositionSteps[1] = com->Y*axis_steps_per_unit[1]*(unit_inches?25.4:1.0)-printer_state.offsetY;
            if(GCODE_HAS_Z(com)) printer_state.currentPositionSteps[2] = com->Z*axis_steps_per_unit[2]*(unit_inches?25.4:1.0);
            if(GCODE_HAS_E(com)) {
                printer_state.currentPositionSteps[3] = com->E*axis_steps_per_unit[3]*(unit_inches?25.4:1.0);
            }
            break;

        }
        previous_millis_cmd = millis();
    }

    else if(GCODE_HAS_M(com))  { // Process M Code

        switch( com->M ) {
#ifdef SDSUPPORT

        case 20: // M20 - list SD card
            out.println_P(PSTR("Begin file list"));
            root.ls();
            out.println_P(PSTR("End file list"));
            break;
        case 21: // M21 - init SD card
            sdmode = false;
            initsd();
            break;
        case 22: //M22 - release SD card
            sdmode = false;
            sdactive = false;
            break;
        case 23: //M23 - Select file
            if(sdactive) {
                sdmode = false;
                file.close();
                if (file.open(&root, com->text, O_READ)) {
                    out.print_P(PSTR("File opened:"));
                    out.print(com->text);
                    out.print_P(PSTR(" Size:"));
                    out.println(file.fileSize());
                    sdpos = 0;
                    filesize = file.fileSize();
                    out.println_P(PSTR("File selected"));
                }
                else {
                    out.println_P(PSTR("file.open failed"));
                }
            }
            break;
        case 24: //M24 - Start SD print
            if(sdactive) {
                sdmode = true;
            }
            break;
        case 25: //M25 - Pause SD print
            if(sdmode) {
                sdmode = false;
            }
            break;
        case 26: //M26 - Set SD index
            if(sdactive && GCODE_HAS_S(com)) {
                sdpos = com->S;
                file.seekSet(sdpos);
            }
            break;
        case 27: //M27 - Get SD status
            if(sdactive) {
                out.print_P(PSTR("SD printing byte "));
                out.print(sdpos);
                out.print("/");
                out.println(filesize);
            } else {
                out.println_P(PSTR("Not SD printing"));
            }
            break;
        case 28: //M28 - Start SD write
            if(sdactive) {
                char* npos = 0;
                file.close();
                sdmode = false;
                if (!file.open(&root,com->text, O_CREAT | O_APPEND | O_WRITE | O_TRUNC))  {
                    out.print_P(PSTR("open failed, File: "));
                    out.print(com->text);
                    out.print_P(PSTR("."));
                } else {
                    savetosd = true;
                    out.print_P(PSTR("Writing to file: "));
                    out.println(com->text);
                }
            }
            break;
        case 29: //M29 - Stop SD write
            //processed in write to file routine above
            //savetosd = false;
            break;
        case 30: // M30 filename - Delete file
            if(sdactive) {
                sdmode = false;
                file.close();
                if(SdFile::remove(&root, com->text)) {
                    out.println_P(PSTR("File deleted"));
                } else {
                    out.println_P(PSTR("Deletion failed"));
                }
            }
            break;
#endif
        case 104: // M104
            if(DEBUG_DRYRUN) break;
            wait_until_end_of_move();
            if (GCODE_HAS_S(com)) extruder_set_temperature(com->S);
            break;
        case 140: // M140 set bed temp
            if(DEBUG_DRYRUN) break;
            if (GCODE_HAS_S(com)) heated_bed_set_temperature(com->S);
            break;
        case 105: // M105  get temperature. Always returns the current temperature, doesn't wait until move stopped
            print_temperatures();
            break;
        case 109: // M109 - Wait for extruder heater to reach target.
        {
            if(DEBUG_DRYRUN) break;
            wait_until_end_of_move();
            if (GCODE_HAS_S(com)) extruder_set_temperature(com->S);
            if(current_extruder->currentTemperatureC >= current_extruder->targetTemperature) break;
            codenum = millis();
            long waituntil = 0;
            while(waituntil==0 || (waituntil!=0 && waituntil>millis())) {
                if( (millis() - codenum) > 1000 ) { //Print Temp Reading every 1 second while heating up.
                    print_temperatures();
                    codenum = millis();
                }
                manage_temperatures(false);
                gcode_read_serial();
                if(waituntil==0 && current_extruder->currentTemperatureC >= current_extruder->targetTemperatureC)
                    waituntil = millis()+1000*(long)current_extruder->watchPeriod; // now wait for temp. to stabalize
            }
        }
        break;
        case 190: // M190 - Wait bed for heater to reach target.
            if(DEBUG_DRYRUN) break;
            wait_until_end_of_move();
#if HEATED_BED_SENSOR_TYPE!=0
            if (GCODE_HAS_S(com)) heated_bed_set_temperature(com->S);
            codenum = millis();
            while(current_bed_raw < target_bed_raw) {
                if( (millis()-codenum) > 1000 ) { //Print Temp Reading every 1 second while heating up.
                    print_temperatures();
                    codenum = millis();
                }
                manage_temperatures(false);
            }
#endif
            break;
        case 106: //M106 Fan On
            wait_until_end_of_move();
            if (GCODE_HAS_S(com)) {
                digitalWrite(FAN_PIN, HIGH);
                analogWrite(FAN_PIN, constrain(com->S,0,255) );
            }
            else
                digitalWrite(FAN_PIN, HIGH);
            break;
        case 107: //M107 Fan Off
            wait_until_end_of_move();
            analogWrite(FAN_PIN, 0);

            digitalWrite(FAN_PIN, LOW);
            break;
        case 80: // M81 - ATX Power On
            wait_until_end_of_move();
            if(PS_ON_PIN > -1) pinMode(PS_ON_PIN,OUTPUT); //GND
            break;
        case 81: // M81 - ATX Power Off
            wait_until_end_of_move();
            if(PS_ON_PIN > -1) pinMode(PS_ON_PIN,INPUT); //Floating
            break;
        case 82:
            relative_mode_e = false;
            break;
        case 83:
            relative_mode_e = true;
            break;
        case 84:
            if(GCODE_HAS_S(com)) {
                stepper_inactive_time = com->S * 1000;
            }
            else {
                wait_until_end_of_move();
                kill(true);
            }
            break;
        case 85: // M85
            if(GCODE_HAS_S(com))
                max_inactive_time = (long)com->S * 1000;
            else
                max_inactive_time = 0;
            break;
        case 92: // M92
            if(GCODE_HAS_X(com)) axis_steps_per_unit[0] = com->X;
            if(GCODE_HAS_Y(com)) axis_steps_per_unit[1] = com->Y;
            if(GCODE_HAS_Z(com)) axis_steps_per_unit[2] = com->Z;
            if(GCODE_HAS_E(com)) current_extruder->stepsPerMM = com->E;
            update_ramps_parameter();
            break;
        case 111:
            if(GCODE_HAS_S(com)) debug_level = com->S;
            if(DEBUG_DRYRUN) { // simulate movements without printing
                extruder_set_temperature(0);
#if HEATED_BED_TYPE!=0
                target_bed_raw = 0;
#endif
            }
            break;
        case 115: // M115
            out.println_P(PSTR("FIRMWARE_NAME:Repetier FIRMWARE_URL:https://github.com/repetier/Repetier-Firmware/ PROTOCOL_VERSION:1.0 MACHINE_TYPE:Mendel EXTRUDER_COUNT:1 REPETIER_PROTOCOL:1"));
            break;
        case 114: // M114
            out.print_float_P(PSTR("X:"),printer_state.currentPositionSteps[0]*inv_axis_steps_per_unit[0]*(unit_inches?0.03937:1));
            out.print_float_P(PSTR(" Y:"),printer_state.currentPositionSteps[1]*inv_axis_steps_per_unit[1]*(unit_inches?0.03937:1));
            out.print_float_P(PSTR(" Z:"),printer_state.currentPositionSteps[2]*inv_axis_steps_per_unit[2]*(unit_inches?0.03937:1));
            out.println_float_P(PSTR(" E:"),printer_state.currentPositionSteps[3]*inv_axis_steps_per_unit[3]*(unit_inches?0.03937:1));
            break;
        case 119: // M119
            wait_until_end_of_move();
#if (X_MIN_PIN > -1)
            out.print_P(PSTR("x_min:"));
            out.print_P((digitalRead(X_MIN_PIN)^ENDSTOPS_INVERTING)?PSTR("H "):PSTR("L "));
#endif
#if (X_MAX_PIN > -1)
            out.print_P(PSTR("x_max:"));
            out.print_P((digitalRead(X_MAX_PIN)^ENDSTOPS_INVERTING)?PSTR("H "):PSTR("L "));
#endif
#if (Y_MIN_PIN > -1)
            out.print_P(PSTR("y_min:"));
            out.print_P((digitalRead(Y_MIN_PIN)^ENDSTOPS_INVERTING)?PSTR("H "):PSTR("L "));
#endif
#if (Y_MAX_PIN > -1)
            out.print_P(PSTR("y_max:"));
            out.print_P((digitalRead(Y_MAX_PIN)^ENDSTOPS_INVERTING)?PSTR("H "):PSTR("L "));
#endif
#if (Z_MIN_PIN > -1)
            out.print_P(PSTR("z_min:"));
            out.print_P((digitalRead(Z_MIN_PIN)^ENDSTOPS_INVERTING)?PSTR("H "):PSTR("L "));
#endif
#if (Z_MAX_PIN > -1)
            out.print_P(PSTR("z_max:"));
            out.print_P((digitalRead(Z_MAX_PIN)^ENDSTOPS_INVERTING)?PSTR("H "):PSTR("L "));
#endif
            out.println();
            break;
#ifdef RAMP_ACCELERATION
        case 201: // M201
            if(GCODE_HAS_X(com)) axis_steps_per_sqr_second[0] = com->X * axis_steps_per_unit[0];
            if(GCODE_HAS_Y(com)) axis_steps_per_sqr_second[1] = com->Y * axis_steps_per_unit[1];
            if(GCODE_HAS_Z(com)) axis_steps_per_sqr_second[2] = com->Z * axis_steps_per_unit[2];
            if(GCODE_HAS_E(com)) axis_steps_per_sqr_second[3] = com->E * axis_steps_per_unit[3];
            break;
        case 202: // M202
            if(GCODE_HAS_X(com)) axis_travel_steps_per_sqr_second[0] = com->X * axis_steps_per_unit[0];
            if(GCODE_HAS_Y(com)) axis_travel_steps_per_sqr_second[1] = com->Y * axis_steps_per_unit[1];
            if(GCODE_HAS_Z(com)) axis_travel_steps_per_sqr_second[2] = com->Z * axis_steps_per_unit[2];
            if(GCODE_HAS_E(com)) axis_travel_steps_per_sqr_second[3] = com->E * axis_steps_per_unit[3];
            break;
#endif
        case 203: // M203 Temperature monitor
            if(GCODE_HAS_S(com)) manage_monitor = com->S;
            if(manage_monitor==100) manage_monitor=NUM_EXTRUDER; // Set 100 to heated bed
            break;
        case 205: // M205 Show EEPROM settings
            epr_output_settings();
            break;
        case 206: // M206 T[type] P[pos] [Sint(long] [Xfloat]  Set eeprom value
#if EEPROM_MODE!=0
            epr_update(com);
#else
            out.println_P(PSTR("Error: No EEPROM support compiled."));
#endif
            break;
        case 222: //M222 F_CPU / S
            if(GCODE_HAS_S(com))
                out.println_long_P(PSTR("F_CPU/x="),CPUDivU2(com->S));
            break;
        case 223:
            if(GCODE_HAS_S(com)) {
                extruder_enable();
                printer_state.extruderStepsNeeded+=(int)com->S;
                out.println_int_P(PSTR("Added to:"),printer_state.extruderStepsNeeded);
            }
            break;
#ifdef USE_ADVANCE
        case 232:
            out.print_int_P(PSTR("Max advance="),maxadv);
            if(maxadv>0)
                out.println_float_P(PSTR(", speed="),maxadvspeed);
            else
                out.println();
            maxadv=0;
            maxadvspeed=0;
            break;
#endif
#if USE_OPS==1
        case 231: // M231 S<OPS_MODE> X<Min_Distance> Y<Retract> Z<Backslash> F<ReatrctMove>
            if(GCODE_HAS_S(com) && com->S>=0 && com->S<3)
                printer_state.opsMode = com->S;
            if(GCODE_HAS_X(com) && com->X>=0)
                printer_state.opsMinDistance = com->X;
            if(GCODE_HAS_Y(com) && com->Y>=0)
                printer_state.opsRetractDistance = com->Y;
            if(GCODE_HAS_Z(com) && com->Z>=-printer_state.opsRetractDistance)
                printer_state.opsRetractBackslash = com->Z;
            if(GCODE_HAS_F(com) && com->F>=0 && com->F<=100)
                printer_state.opsMoveAfter = com->F;
            extruder_select(current_extruder->id);
            if(printer_state.opsMode==0) {
                out.println_P(PSTR("OPS disabled"));
            } else {
                if(printer_state.opsMode==1)
                    out.print_P(PSTR("OPS classic mode:"));
                else
                    out.print_P(PSTR("OPS fast mode:"));

                out.print_float_P(PSTR("min distance = "),printer_state.opsMinDistance);
                out.print_float_P(PSTR(", retract = "),printer_state.opsRetractDistance);
                out.print_float_P(PSTR(", backslash = "),printer_state.opsRetractDistance);
                if(printer_state.opsMode==2)
                    out.print_float_P(PSTR(", move after = "),printer_state.opsMoveAfter);
                out.println();
            }
#ifdef DEBUG_OPS
            out.println_int_P(PSTR("Timer diff"),printer_state.timer0Interval);
            out.println_int_P(PSTR("Ret. steps:"),printer_state.opsRetractSteps);
            out.println_int_P(PSTR("PushBack Steps:"),printer_state.opsPushbackSteps);
            out.println_int_P(PSTR("Move after steps:"),printer_state.opsMoveAfterSteps);
#endif
            break;
#endif
        }
    } else if(GCODE_HAS_T(com))  { // Process T code
        wait_until_end_of_move();
        extruder_select(com->T);
    } else {
        if(DEBUG_ERRORS) {
            out.print_P(PSTR("Unknown command:"));
            gcode_print_command(com);
            out.println();
        }
    }
#ifdef ECHO_ON_EXECUTE
    if(DEBUG_ECHO) {
        out.print_P(PSTR("Echo:"));
        gcode_print_command(com);
        out.println();
    }
#endif
    gcode_command_finished(); // free command cache
}