Esempio n. 1
0
void CardReader::removeFile(char* name) {
  if (!cardOK) return;

  file.close();
  sdprinting = false;

  SdFile myDir;
  curDir = &root;
  char *fname = name;

  char *dirname_start, *dirname_end;
  if (name[0] == '/') {
    dirname_start = strchr(name, '/') + 1;
    while (dirname_start > 0) {
      dirname_end = strchr(dirname_start, '/');
      //SERIAL_ECHO("start:");SERIAL_ECHOLN((int)(dirname_start - name));
      //SERIAL_ECHO("end  :");SERIAL_ECHOLN((int)(dirname_end - name));
      if (dirname_end > 0 && dirname_end > dirname_start) {
        char subdirname[FILENAME_LENGTH];
        strncpy(subdirname, dirname_start, dirname_end - dirname_start);
        subdirname[dirname_end - dirname_start] = 0;
        SERIAL_ECHOLN(subdirname);
        if (!myDir.open(curDir, subdirname, O_READ)) {
          SERIAL_PROTOCOLPGM("open failed, File: ");
          SERIAL_PROTOCOL(subdirname);
          SERIAL_PROTOCOLLNPGM(".");
          return;
        }
        else {
          //SERIAL_ECHOLN("dive ok");
        }

        curDir = &myDir;
        dirname_start = dirname_end + 1;
      }
      else { // the remainder after all /fsa/fdsa/ is the filename
        fname = dirname_start;
        //SERIAL_ECHOLN("remainder");
        //SERIAL_ECHOLN(fname);
        break;
      }
    }
  }
  else { // relative path
    curDir = &workDir;
  }

  if (file.remove(curDir, fname)) {
    SERIAL_PROTOCOLPGM("File deleted:");
    SERIAL_PROTOCOLLN(fname);
    sdpos = 0;
  }
  else {
    SERIAL_PROTOCOLPGM("Deletion failed, File: ");
    SERIAL_PROTOCOL(fname);
    SERIAL_PROTOCOLLNPGM(".");
  }
}
Esempio n. 2
0
 void unified_bed_leveling::report_state() {
   echo_name();
   SERIAL_PROTOCOLPGM(" System v" UBL_VERSION " ");
   if (!planner.leveling_active) SERIAL_PROTOCOLPGM("in");
   SERIAL_PROTOCOLLNPGM("active.");
   safe_delay(50);
 }
Esempio n. 3
0
void Endstops::M119() {
  SERIAL_PROTOCOLLNPGM(MSG_M119_REPORT);
  #if HAS_X_MIN
    SERIAL_PROTOCOLPGM(MSG_X_MIN);
    SERIAL_PROTOCOLLN(((READ(X_MIN_PIN)^X_MIN_ENDSTOP_INVERTING) ? MSG_ENDSTOP_HIT : MSG_ENDSTOP_OPEN));
  #endif
  #if HAS_X_MAX
    SERIAL_PROTOCOLPGM(MSG_X_MAX);
    SERIAL_PROTOCOLLN(((READ(X_MAX_PIN)^X_MAX_ENDSTOP_INVERTING) ? MSG_ENDSTOP_HIT : MSG_ENDSTOP_OPEN));
  #endif
  #if HAS_Y_MIN
    SERIAL_PROTOCOLPGM(MSG_Y_MIN);
    SERIAL_PROTOCOLLN(((READ(Y_MIN_PIN)^Y_MIN_ENDSTOP_INVERTING) ? MSG_ENDSTOP_HIT : MSG_ENDSTOP_OPEN));
  #endif
  #if HAS_Y_MAX
    SERIAL_PROTOCOLPGM(MSG_Y_MAX);
    SERIAL_PROTOCOLLN(((READ(Y_MAX_PIN)^Y_MAX_ENDSTOP_INVERTING) ? MSG_ENDSTOP_HIT : MSG_ENDSTOP_OPEN));
  #endif
  #if HAS_Z_MIN
    SERIAL_PROTOCOLPGM(MSG_Z_MIN);
    SERIAL_PROTOCOLLN(((READ(Z_MIN_PIN)^Z_MIN_ENDSTOP_INVERTING) ? MSG_ENDSTOP_HIT : MSG_ENDSTOP_OPEN));
  #endif
  #if HAS_Z_MAX
    SERIAL_PROTOCOLPGM(MSG_Z_MAX);
    SERIAL_PROTOCOLLN(((READ(Z_MAX_PIN)^Z_MAX_ENDSTOP_INVERTING) ? MSG_ENDSTOP_HIT : MSG_ENDSTOP_OPEN));
  #endif
  #if HAS_Z2_MAX
    SERIAL_PROTOCOLPGM(MSG_Z2_MAX);
    SERIAL_PROTOCOLLN(((READ(Z2_MAX_PIN)^Z2_MAX_ENDSTOP_INVERTING) ? MSG_ENDSTOP_HIT : MSG_ENDSTOP_OPEN));
  #endif
  #if HAS_Z_MIN_PROBE_PIN
    SERIAL_PROTOCOLPGM(MSG_Z_PROBE);
    SERIAL_PROTOCOLLN(((READ(Z_MIN_PROBE_PIN)^Z_MIN_PROBE_ENDSTOP_INVERTING) ? MSG_ENDSTOP_HIT : MSG_ENDSTOP_OPEN));
  #endif
} // Endstops::M119
Esempio n. 4
0
void CardReader::getStatus() {
  if (cardOK) {
    SERIAL_PROTOCOLPGM(MSG_SD_PRINTING_BYTE);
    SERIAL_PROTOCOL(sdpos);
    SERIAL_PROTOCOLCHAR('/');
    SERIAL_PROTOCOLLN(filesize);
  } else
    SERIAL_PROTOCOLLNPGM(MSG_SD_NOT_PRINTING);
}
Esempio n. 5
0
  bool unified_bed_leveling::sanity_check() {
    uint8_t error_flag = 0;

    if (settings.calc_num_meshes() < 1) {
      SERIAL_PROTOCOLLNPGM("?Mesh too big for EEPROM.");
      error_flag++;
    }

    return !!error_flag;
  }
Esempio n. 6
0
/* ??? Check se serve */
void MemReader::getStatus()
{
  if(isprinting){
    SERIAL_PROTOCOLPGM(MSG_SD_PRINTING_BYTE);
    SERIAL_PROTOCOL(pos);
    SERIAL_PROTOCOLPGM("/");
    SERIAL_PROTOCOLLN(ScriptLength[program]);
  }
  else{
    SERIAL_PROTOCOLLNPGM(MSG_SD_NOT_PRINTING);
  }
}
Esempio n. 7
0
void CardReader::getStatus()
{
  if(cardOK){
    SERIAL_PROTOCOLPGM(MSG_SD_PRINTING_BYTE);
    SERIAL_PROTOCOL(sdpos);
    SERIAL_PROTOCOLPGM("/");
    SERIAL_PROTOCOLLN(filesize);
  }
  else{
    SERIAL_PROTOCOLLNPGM(MSG_SD_NOT_PRINTING);
  }
  if (card.errorCode())
  {
    SERIAL_PROTOCOLPGM("Card error:");
    SERIAL_PROTOCOLLN(card.errorCode());
  }
}
void get_command() // Routine to retrieve commands from serial when available
{
  while (Serial.available() > 0 && buflen < BUFSIZE)
  {
    serial_char = Serial.read();
    if (serial_char == '\n' || serial_char == '\r' || serial_count >= (MAX_CMD_SIZE - 1))
    {
      if (!serial_count) return; // empty line

      cmdbuffer[bufindw][serial_count] = 0;
      bufindw = (bufindw + 1) % BUFSIZE;
      buflen += 1;
      serial_count = 0;
      SERIAL_PROTOCOLLNPGM(MSG_COMMAND_STORED);
    }
    else
    {
      cmdbuffer[bufindw][serial_count++] = serial_char;
    }
  }
}
Esempio n. 9
0
void CardReader::openFile(char* name,bool read)
{
    if(!cardOK)
        return;
    file.close();
    sdprinting = false;


    SdFile myDir;
    curDir=&root;
    char *fname=name;

    char *dirname_start,*dirname_end;
    if(name[0]=='/')
    {
        dirname_start=strchr(name,'/')+1;
        while(dirname_start>0)
        {
            dirname_end=strchr(dirname_start,'/');
            //SERIAL_ECHO("start:");SERIAL_ECHOLN((int)(dirname_start-name));
            //SERIAL_ECHO("end  :");SERIAL_ECHOLN((int)(dirname_end-name));
            if(dirname_end>0 && dirname_end>dirname_start)
            {
                char subdirname[13];
                strncpy(subdirname, dirname_start, dirname_end-dirname_start);
                subdirname[dirname_end-dirname_start]=0;
                SERIAL_ECHOLN(subdirname);
                if(!myDir.open(curDir,subdirname,O_READ))
                {
                    SERIAL_PROTOCOLPGM(MSG_SD_OPEN_FILE_FAIL);
                    SERIAL_PROTOCOL(subdirname);
                    SERIAL_PROTOCOLLNPGM(".");
                    return;
                }
                else
                {
                    //SERIAL_ECHOLN("dive ok");
                }

                curDir=&myDir;
                dirname_start=dirname_end+1;
            }
            else // the reminder after all /fsa/fdsa/ is the filename
            {
                fname=dirname_start;
                //SERIAL_ECHOLN("remaider");
                //SERIAL_ECHOLN(fname);
                break;
            }

        }
    }
    else //relative path
    {
        curDir=&workDir;
    }
    if(read)
    {
        if (file.open(curDir, fname, O_READ))
        {
            filesize = file.fileSize();
            SERIAL_PROTOCOLPGM(MSG_SD_FILE_OPENED);
            SERIAL_PROTOCOL(fname);
            SERIAL_PROTOCOLPGM(MSG_SD_SIZE);
            SERIAL_PROTOCOLLN(filesize);
            sdpos = 0;

            SERIAL_PROTOCOLLNPGM(MSG_SD_FILE_SELECTED);
            LCD_MESSAGE(fname);
        }
        else
        {
            SERIAL_PROTOCOLPGM(MSG_SD_OPEN_FILE_FAIL);
            SERIAL_PROTOCOL(fname);
            SERIAL_PROTOCOLLNPGM(".");
        }
    }
    else
    {   //write
        if (!file.open(curDir, fname, O_CREAT | O_APPEND | O_WRITE | O_TRUNC))
        {
            SERIAL_PROTOCOLPGM(MSG_SD_OPEN_FILE_FAIL);
            SERIAL_PROTOCOL(fname);
            SERIAL_PROTOCOLLNPGM(".");
        }
        else
        {
            saving = true;
            SERIAL_PROTOCOLPGM(MSG_SD_WRITE_TO_FILE);
            SERIAL_PROTOCOLLN(name);
            LCD_MESSAGE(fname);
        }
    }

}
Esempio n. 10
0
void CardReader::openFile(char* name, bool read, bool replace_current/*=true*/) {
  if (!cardOK) return;
  if (file.isOpen()) { //replacing current file by new file, or subfile call
    if (!replace_current) {
     if (file_subcall_ctr > SD_PROCEDURE_DEPTH - 1) {
       SERIAL_ERROR_START;
       SERIAL_ERRORPGM("trying to call sub-gcode files with too many levels. MAX level is:");
       SERIAL_ERRORLN(SD_PROCEDURE_DEPTH);
       kill();
       return;
     }

     SERIAL_ECHO_START;
     SERIAL_ECHOPGM("SUBROUTINE CALL target:\"");
     SERIAL_ECHO(name);
     SERIAL_ECHOPGM("\" parent:\"");

     //store current filename and position
     getAbsFilename(filenames[file_subcall_ctr]);

     SERIAL_ECHO(filenames[file_subcall_ctr]);
     SERIAL_ECHOPGM("\" pos");
     SERIAL_ECHOLN(sdpos);
     filespos[file_subcall_ctr] = sdpos;
     file_subcall_ctr++;
    }
    else {
     SERIAL_ECHO_START;
     SERIAL_ECHOPGM("Now doing file: ");
     SERIAL_ECHOLN(name);
    }
    file.close();
  }
  else { //opening fresh file
    file_subcall_ctr = 0; //resetting procedure depth in case user cancels print while in procedure
    SERIAL_ECHO_START;
    SERIAL_ECHOPGM("Now fresh file: ");
    SERIAL_ECHOLN(name);
  }
  sdprinting = false;

  SdFile myDir;
  curDir = &root;
  char *fname = name;

  char *dirname_start, *dirname_end;
  if (name[0] == '/') {
    dirname_start = &name[1];
    while(dirname_start > 0) {
      dirname_end = strchr(dirname_start, '/');
      //SERIAL_ECHO("start:");SERIAL_ECHOLN((int)(dirname_start - name));
      //SERIAL_ECHO("end  :");SERIAL_ECHOLN((int)(dirname_end - name));
      if (dirname_end > 0 && dirname_end > dirname_start) {
        char subdirname[FILENAME_LENGTH];
        strncpy(subdirname, dirname_start, dirname_end - dirname_start);
        subdirname[dirname_end - dirname_start] = 0;
        SERIAL_ECHOLN(subdirname);
        if (!myDir.open(curDir, subdirname, O_READ)) {
          SERIAL_PROTOCOLPGM(MSG_SD_OPEN_FILE_FAIL);
          SERIAL_PROTOCOL(subdirname);
          SERIAL_PROTOCOLCHAR('.');
          return;
        }
        else {
          //SERIAL_ECHOLN("dive ok");
        }

        curDir = &myDir;
        dirname_start = dirname_end + 1;
      }
      else { // the remainder after all /fsa/fdsa/ is the filename
        fname = dirname_start;
        //SERIAL_ECHOLN("remainder");
        //SERIAL_ECHOLN(fname);
        break;
      }
    }
  }
  else { //relative path
    curDir = &workDir;
  }

  if (read) {
    if (file.open(curDir, fname, O_READ)) {
      filesize = file.fileSize();
      SERIAL_PROTOCOLPGM(MSG_SD_FILE_OPENED);
      SERIAL_PROTOCOL(fname);
      SERIAL_PROTOCOLPGM(MSG_SD_SIZE);
      SERIAL_PROTOCOLLN(filesize);
      sdpos = 0;

      SERIAL_PROTOCOLLNPGM(MSG_SD_FILE_SELECTED);
      getfilename(0, fname);
      lcd_setstatus(longFilename[0] ? longFilename : fname);
    }
    else {
      SERIAL_PROTOCOLPGM(MSG_SD_OPEN_FILE_FAIL);
      SERIAL_PROTOCOL(fname);
      SERIAL_PROTOCOLCHAR('.');
    }
  }
  else { //write
    if (!file.open(curDir, fname, O_CREAT | O_APPEND | O_WRITE | O_TRUNC)) {
      SERIAL_PROTOCOLPGM(MSG_SD_OPEN_FILE_FAIL);
      SERIAL_PROTOCOL(fname);
      SERIAL_PROTOCOLCHAR('.');
    }
    else {
      saving = true;
      SERIAL_PROTOCOLPGM(MSG_SD_WRITE_TO_FILE);
      SERIAL_PROTOCOLLN(name);
      lcd_setstatus(fname);
    }
  }
}
Esempio n. 11
0
void PID_autotune(float temp, int extruder, int ncycles)
{
  float input = 0.0;
  int cycles = 0;
  bool heating = true;

  millis_t temp_ms = millis(), t1 = temp_ms, t2 = temp_ms;
  long t_high = 0, t_low = 0;

  long bias, d;
  float Ku, Tu;
  float Kp, Ki, Kd;
  float max = 0, min = 10000;

  #if HAS_AUTO_FAN
    millis_t next_auto_fan_check_ms = temp_ms + 2500;
  #endif

  if (extruder >= EXTRUDERS
    #if !HAS_TEMP_BED
       || extruder < 0
    #endif
  ) {
    SERIAL_ECHOLN(MSG_PID_BAD_EXTRUDER_NUM);
    return;
  }
  
  SERIAL_ECHOLN(MSG_PID_AUTOTUNE_START);

  disable_heater(); // switch off all heaters.

  if (extruder < 0)
    soft_pwm_bed = bias = d = MAX_BED_POWER / 2;
  else
    soft_pwm[extruder] = bias = d = PID_MAX / 2;

  // PID Tuning loop
  for (;;) {

    millis_t ms = millis();

    if (temp_meas_ready) { // temp sample ready
      updateTemperaturesFromRawValues();

      input = (extruder<0)?current_temperature_bed:current_temperature[extruder];

      max = max(max, input);
      min = min(min, input);

      #if HAS_AUTO_FAN
        if (ms > next_auto_fan_check_ms) {
          checkExtruderAutoFans();
          next_auto_fan_check_ms = ms + 2500;
        }
      #endif

      if (heating == true && input > temp) {
        if (ms - t2 > 5000) {
          heating = false;
          if (extruder < 0)
            soft_pwm_bed = (bias - d) >> 1;
          else
            soft_pwm[extruder] = (bias - d) >> 1;
          t1 = ms;
          t_high = t1 - t2;
          max = temp;
        }
      }
      if (heating == false && input < temp) {
        if (ms - t1 > 5000) {
          heating = true;
          t2 = ms;
          t_low = t2 - t1;
          if (cycles > 0) {
            long max_pow = extruder < 0 ? MAX_BED_POWER : PID_MAX;
            bias += (d*(t_high - t_low))/(t_low + t_high);
            bias = constrain(bias, 20, max_pow - 20);
            d = (bias > max_pow / 2) ? max_pow - 1 - bias : bias;

            SERIAL_PROTOCOLPGM(MSG_BIAS); SERIAL_PROTOCOL(bias);
            SERIAL_PROTOCOLPGM(MSG_D);    SERIAL_PROTOCOL(d);
            SERIAL_PROTOCOLPGM(MSG_T_MIN);  SERIAL_PROTOCOL(min);
            SERIAL_PROTOCOLPGM(MSG_T_MAX);  SERIAL_PROTOCOLLN(max);
            if (cycles > 2) {
              Ku = (4.0 * d) / (3.14159265 * (max - min) / 2.0);
              Tu = ((float)(t_low + t_high) / 1000.0);
              SERIAL_PROTOCOLPGM(MSG_KU); SERIAL_PROTOCOL(Ku);
              SERIAL_PROTOCOLPGM(MSG_TU); SERIAL_PROTOCOLLN(Tu);
              Kp = 0.6 * Ku;
              Ki = 2 * Kp / Tu;
              Kd = Kp * Tu / 8;
              SERIAL_PROTOCOLLNPGM(MSG_CLASSIC_PID);
              SERIAL_PROTOCOLPGM(MSG_KP); SERIAL_PROTOCOLLN(Kp);
              SERIAL_PROTOCOLPGM(MSG_KI); SERIAL_PROTOCOLLN(Ki);
              SERIAL_PROTOCOLPGM(MSG_KD); SERIAL_PROTOCOLLN(Kd);
              /*
              Kp = 0.33*Ku;
              Ki = Kp/Tu;
              Kd = Kp*Tu/3;
              SERIAL_PROTOCOLLNPGM(" Some overshoot ");
              SERIAL_PROTOCOLPGM(" Kp: "); SERIAL_PROTOCOLLN(Kp);
              SERIAL_PROTOCOLPGM(" Ki: "); SERIAL_PROTOCOLLN(Ki);
              SERIAL_PROTOCOLPGM(" Kd: "); SERIAL_PROTOCOLLN(Kd);
              Kp = 0.2*Ku;
              Ki = 2*Kp/Tu;
              Kd = Kp*Tu/3;
              SERIAL_PROTOCOLLNPGM(" No overshoot ");
              SERIAL_PROTOCOLPGM(" Kp: "); SERIAL_PROTOCOLLN(Kp);
              SERIAL_PROTOCOLPGM(" Ki: "); SERIAL_PROTOCOLLN(Ki);
              SERIAL_PROTOCOLPGM(" Kd: "); SERIAL_PROTOCOLLN(Kd);
              */
            }
          }
          if (extruder < 0)
            soft_pwm_bed = (bias + d) >> 1;
          else
            soft_pwm[extruder] = (bias + d) >> 1;
          cycles++;
          min = temp;
        }
Esempio n. 12
0
void PID_autotune(float temp)
{
  float input;
  int cycles=0;
  bool heating = true;

  unsigned long temp_millis = millis();
  unsigned long t1=temp_millis;
  unsigned long t2=temp_millis;
  long t_high;
  long t_low;

  long bias=127;
  long d = 127;
  float Ku, Tu;
  float Kp, Ki, Kd;
  float max, min;
  
  SERIAL_ECHOLN("PID Autotune start");
  
  disable_heater(); // switch off all heaters.
  
  soft_pwm[0] = 255>>1;
    
  for(;;) {

    if(temp_meas_ready == true) { // temp sample ready
      CRITICAL_SECTION_START;
      temp_meas_ready = false;
      CRITICAL_SECTION_END;
      input = analog2temp(current_raw[0], 0);
      
      max=max(max,input);
      min=min(min,input);
      if(heating == true && input > temp) {
        if(millis() - t2 > 5000) { 
          heating=false;
          soft_pwm[0] = (bias - d) >> 1;
          t1=millis();
          t_high=t1 - t2;
          max=temp;
        }
      }
      if(heating == false && input < temp) {
        if(millis() - t1 > 5000) {
          heating=true;
          t2=millis();
          t_low=t2 - t1;
          if(cycles > 0) {
            bias += (d*(t_high - t_low))/(t_low + t_high);
            bias = constrain(bias, 20 ,235);
            if(bias > 127) d = 254 - bias;
            else d = bias;

            SERIAL_PROTOCOLPGM(" bias: "); SERIAL_PROTOCOL(bias);
            SERIAL_PROTOCOLPGM(" d: "); SERIAL_PROTOCOL(d);
            SERIAL_PROTOCOLPGM(" min: "); SERIAL_PROTOCOL(min);
            SERIAL_PROTOCOLPGM(" max: "); SERIAL_PROTOCOLLN(max);
            if(cycles > 2) {
              Ku = (4.0*d)/(3.14159*(max-min)/2.0);
              Tu = ((float)(t_low + t_high)/1000.0);
              SERIAL_PROTOCOLPGM(" Ku: "); SERIAL_PROTOCOL(Ku);
              SERIAL_PROTOCOLPGM(" Tu: "); SERIAL_PROTOCOLLN(Tu);
              Kp = 0.6*Ku;
              Ki = 2*Kp/Tu;
              Kd = Kp*Tu/8;
              SERIAL_PROTOCOLLNPGM(" Clasic PID ")
              SERIAL_PROTOCOLPGM(" Kp: "); SERIAL_PROTOCOLLN(Kp);
              SERIAL_PROTOCOLPGM(" Ki: "); SERIAL_PROTOCOLLN(Ki);
              SERIAL_PROTOCOLPGM(" Kd: "); SERIAL_PROTOCOLLN(Kd);
              /*
              Kp = 0.33*Ku;
              Ki = Kp/Tu;
              Kd = Kp*Tu/3;
              SERIAL_PROTOCOLLNPGM(" Some overshoot ")
              SERIAL_PROTOCOLPGM(" Kp: "); SERIAL_PROTOCOLLN(Kp);
              SERIAL_PROTOCOLPGM(" Ki: "); SERIAL_PROTOCOLLN(Ki);
              SERIAL_PROTOCOLPGM(" Kd: "); SERIAL_PROTOCOLLN(Kd);
              Kp = 0.2*Ku;
              Ki = 2*Kp/Tu;
              Kd = Kp*Tu/3;
              SERIAL_PROTOCOLLNPGM(" No overshoot ")
              SERIAL_PROTOCOLPGM(" Kp: "); SERIAL_PROTOCOLLN(Kp);
              SERIAL_PROTOCOLPGM(" Ki: "); SERIAL_PROTOCOLLN(Ki);
              SERIAL_PROTOCOLPGM(" Kd: "); SERIAL_PROTOCOLLN(Kd);
              */
            }
          }
          soft_pwm[0] = (bias + d) >> 1;
          cycles++;
          min=temp;
        }
      } 
  /**
   * This function used to be inline code in G26. But there are so many
   * parameters it made sense to turn them into static globals and get
   * this code out of sight of the main routine.
   */
  bool unified_bed_leveling::parse_G26_parameters() {

    g26_extrusion_multiplier  = EXTRUSION_MULTIPLIER;
    g26_retraction_multiplier = RETRACTION_MULTIPLIER;
    g26_nozzle                = NOZZLE;
    g26_filament_diameter     = FILAMENT;
    g26_layer_height          = LAYER_HEIGHT;
    g26_prime_length          = PRIME_LENGTH;
    g26_bed_temp              = BED_TEMP;
    g26_hotend_temp           = HOTEND_TEMP;
    g26_prime_flag            = 0;

    g26_ooze_amount           = parser.linearval('O', OOZE_AMOUNT);
    g26_keep_heaters_on       = parser.boolval('K');
    g26_continue_with_closest = parser.boolval('C');

    if (parser.seenval('B')) {
      g26_bed_temp = parser.value_celsius();
      if (!WITHIN(g26_bed_temp, 15, 140)) {
        SERIAL_PROTOCOLLNPGM("?Specified bed temperature not plausible.");
        return UBL_ERR;
      }
    }

    if (parser.seenval('L')) {
      g26_layer_height = parser.value_linear_units();
      if (!WITHIN(g26_layer_height, 0.0, 2.0)) {
        SERIAL_PROTOCOLLNPGM("?Specified layer height not plausible.");
        return UBL_ERR;
      }
    }

    if (parser.seen('Q')) {
      if (parser.has_value()) {
        g26_retraction_multiplier = parser.value_float();
        if (!WITHIN(g26_retraction_multiplier, 0.05, 15.0)) {
          SERIAL_PROTOCOLLNPGM("?Specified Retraction Multiplier not plausible.");
          return UBL_ERR;
        }
      }
      else {
        SERIAL_PROTOCOLLNPGM("?Retraction Multiplier must be specified.");
        return UBL_ERR;
      }
    }

    if (parser.seenval('S')) {
      g26_nozzle = parser.value_float();
      if (!WITHIN(g26_nozzle, 0.1, 1.0)) {
        SERIAL_PROTOCOLLNPGM("?Specified nozzle size not plausible.");
        return UBL_ERR;
      }
    }

    if (parser.seen('P')) {
      if (!parser.has_value()) {
        #if ENABLED(NEWPANEL)
          g26_prime_flag = -1;
        #else
          SERIAL_PROTOCOLLNPGM("?Prime length must be specified when not using an LCD.");
          return UBL_ERR;
        #endif
      }
      else {
        g26_prime_flag++;
        g26_prime_length = parser.value_linear_units();
        if (!WITHIN(g26_prime_length, 0.0, 25.0)) {
          SERIAL_PROTOCOLLNPGM("?Specified prime length not plausible.");
          return UBL_ERR;
        }
      }
    }

    if (parser.seenval('F')) {
      g26_filament_diameter = parser.value_linear_units();
      if (!WITHIN(g26_filament_diameter, 1.0, 4.0)) {
        SERIAL_PROTOCOLLNPGM("?Specified filament size not plausible.");
        return UBL_ERR;
      }
    }
    g26_extrusion_multiplier *= sq(1.75) / sq(g26_filament_diameter); // If we aren't using 1.75mm filament, we need to
                                                                      // scale up or down the length needed to get the
                                                                      // same volume of filament

    g26_extrusion_multiplier *= g26_filament_diameter * sq(g26_nozzle) / sq(0.3); // Scale up by nozzle size

    if (parser.seenval('H')) {
      g26_hotend_temp = parser.value_celsius();
      if (!WITHIN(g26_hotend_temp, 165, 280)) {
        SERIAL_PROTOCOLLNPGM("?Specified nozzle temperature not plausible.");
        return UBL_ERR;
      }
    }

    if (parser.seen('U')) {
      randomSeed(millis());
      // This setting will persist for the next G26
      random_deviation = parser.has_value() ? parser.value_float() : 50.0;
    }

    #if ENABLED(NEWPANEL)
      g26_repeats = parser.intval('R', GRID_MAX_POINTS + 1);
    #else
      if (!parser.seen('R')) {
        SERIAL_PROTOCOLLNPGM("?(R)epeat must be specified when not using an LCD.");
        return UBL_ERR;
      }
      else
        g26_repeats = parser.has_value() ? parser.value_int() : GRID_MAX_POINTS + 1;
    #endif
    if (g26_repeats < 1) {
      SERIAL_PROTOCOLLNPGM("?(R)epeat value not plausible; must be at least 1.");
      return UBL_ERR;
    }

    g26_x_pos = parser.linearval('X', current_position[X_AXIS]);
    g26_y_pos = parser.linearval('Y', current_position[Y_AXIS]);
    if (!position_is_reachable_xy(g26_x_pos, g26_y_pos)) {
      SERIAL_PROTOCOLLNPGM("?Specified X,Y coordinate out of bounds.");
      return UBL_ERR;
    }

    /**
     * Wait until all parameters are verified before altering the state!
     */
    set_bed_leveling_enabled(!parser.seen('D'));

    return UBL_OK;
  }
  /**
   * This function used to be inline code in G26. But there are so many
   * parameters it made sense to turn them into static globals and get
   * this code out of sight of the main routine.
   */
  bool parse_G26_parameters() {

    extrusion_multiplier  = EXTRUSION_MULTIPLIER;
    retraction_multiplier = RETRACTION_MULTIPLIER;
    nozzle                = NOZZLE;
    filament_diameter     = FILAMENT;
    layer_height          = LAYER_HEIGHT;
    prime_length          = PRIME_LENGTH;
    bed_temp              = BED_TEMP;
    hotend_temp           = HOTEND_TEMP;
    ooze_amount           = OOZE_AMOUNT;
    prime_flag            = 0;
    keep_heaters_on       = false;

    if (code_seen('B')) {
      bed_temp = code_value_temp_abs();
      if (!WITHIN(bed_temp, 15, 140)) {
        SERIAL_PROTOCOLLNPGM("?Specified bed temperature not plausible.");
        return UBL_ERR;
      }
    }

    if (code_seen('C')) continue_with_closest++;

    if (code_seen('L')) {
      layer_height = code_value_linear_units();
      if (!WITHIN(layer_height, 0.0, 2.0)) {
        SERIAL_PROTOCOLLNPGM("?Specified layer height not plausible.");
        return UBL_ERR;
      }
    }

    if (code_seen('Q')) {
      if (code_has_value()) {
        retraction_multiplier = code_value_float();
        if (!WITHIN(retraction_multiplier, 0.05, 15.0)) {
          SERIAL_PROTOCOLLNPGM("?Specified Retraction Multiplier not plausible.");
          return UBL_ERR;
        }
      }
      else {
        SERIAL_PROTOCOLLNPGM("?Retraction Multiplier must be specified.");
        return UBL_ERR;
      }
    }

    if (code_seen('N') || code_seen('n')) {
      nozzle = code_value_float();
      if (!WITHIN(nozzle, 0.1, 1.0)) {
        SERIAL_PROTOCOLLNPGM("?Specified nozzle size not plausible.");
        return UBL_ERR;
      }
    }

    if (code_seen('K')) keep_heaters_on++;

    if (code_seen('O') && code_has_value())
      ooze_amount = code_value_linear_units();

    if (code_seen('P')) {
      if (!code_has_value())
        prime_flag = -1;
      else {
        prime_flag++;
        prime_length = code_value_linear_units();
        if (!WITHIN(prime_length, 0.0, 25.0)) {
          SERIAL_PROTOCOLLNPGM("?Specified prime length not plausible.");
          return UBL_ERR;
        }
      }
    }

    if (code_seen('F')) {
      filament_diameter = code_value_linear_units();
      if (!WITHIN(filament_diameter, 1.0, 4.0)) {
        SERIAL_PROTOCOLLNPGM("?Specified filament size not plausible.");
        return UBL_ERR;
      }
    }
    extrusion_multiplier *= sq(1.75) / sq(filament_diameter);         // If we aren't using 1.75mm filament, we need to
                                                                      // scale up or down the length needed to get the
                                                                      // same volume of filament

    extrusion_multiplier *= filament_diameter * sq(nozzle) / sq(0.3); // Scale up by nozzle size

    if (code_seen('H')) {
      hotend_temp = code_value_temp_abs();
      if (!WITHIN(hotend_temp, 165, 280)) {
        SERIAL_PROTOCOLLNPGM("?Specified nozzle temperature not plausible.");
        return UBL_ERR;
      }
    }

    if (code_seen('R')) {
      randomSeed(millis());
      random_deviation = code_has_value() ? code_value_float() : 50.0;
    }

    x_pos = current_position[X_AXIS];
    y_pos = current_position[Y_AXIS];

    if (code_seen('X')) {
      x_pos = code_value_axis_units(X_AXIS);
      if (!WITHIN(x_pos, X_MIN_POS, X_MAX_POS)) {
        SERIAL_PROTOCOLLNPGM("?Specified X coordinate not plausible.");
        return UBL_ERR;
      }
    }
    else

    if (code_seen('Y')) {
      y_pos = code_value_axis_units(Y_AXIS);
      if (!WITHIN(y_pos, Y_MIN_POS, Y_MAX_POS)) {
        SERIAL_PROTOCOLLNPGM("?Specified Y coordinate not plausible.");
        return UBL_ERR;
      }
    }

    /**
     * We save the question of what to do with the Unified Bed Leveling System's Activation until the very
     * end.  The reason is, if one of the parameters specified up above is incorrect, we don't want to
     * alter the system's status.  We wait until we know everything is correct before altering the state
     * of the system.
     */
    ubl.state.active = !code_seen('D');

    return UBL_OK;
  }