Added PID autotune. (experimental)
M303 Starts autotune. Wait till the Kp Ki and Kd constants are printed. Put these values in Configuration.h
This commit is contained in:
		| @@ -109,6 +109,7 @@ | |||||||
| // M501 - reads parameters from EEPROM (if you need reset them after you changed them temporarily).   | // M501 - reads parameters from EEPROM (if you need reset them after you changed them temporarily).   | ||||||
| // M502 - reverts to the default "factory settings".  You still need to store them in EEPROM afterwards if you want to. | // M502 - reverts to the default "factory settings".  You still need to store them in EEPROM afterwards if you want to. | ||||||
| // M503 - print the current settings (from memory not from eeprom) | // M503 - print the current settings (from memory not from eeprom) | ||||||
|  | // M303 - PID relay autotune S<temperature> sets the target temperature. (default target temperature = 150C) | ||||||
|  |  | ||||||
| //Stepper Movement Variables | //Stepper Movement Variables | ||||||
|  |  | ||||||
| @@ -1197,6 +1198,13 @@ void process_commands() | |||||||
|       allow_cold_extrudes(true); |       allow_cold_extrudes(true); | ||||||
|     } |     } | ||||||
|     break; |     break; | ||||||
|  |     case 303: // M303 PID autotune | ||||||
|  |     { | ||||||
|  |       float temp = 150.0; | ||||||
|  |       if (code_seen('S')) temp=code_value(); | ||||||
|  |       PID_autotune(temp); | ||||||
|  |     } | ||||||
|  |     break; | ||||||
|     case 400: // finish all moves |     case 400: // finish all moves | ||||||
|     { |     { | ||||||
|       st_synchronize(); |       st_synchronize(); | ||||||
|   | |||||||
| @@ -734,7 +734,7 @@ | |||||||
|     #define encrot2 3 |     #define encrot2 3 | ||||||
|     #define encrot3 1 |     #define encrot3 1 | ||||||
|  |  | ||||||
|      |     #define SDCARDDETECT -1 | ||||||
|     //bits in the shift register that carry the buttons for: |     //bits in the shift register that carry the buttons for: | ||||||
|     // left up center down right red |     // left up center down right red | ||||||
|     #define BL_LE 7 |     #define BL_LE 7 | ||||||
|   | |||||||
| @@ -62,7 +62,7 @@ int current_raw_bed = 0; | |||||||
| //=========================================================================== | //=========================================================================== | ||||||
| //=============================private variables============================ | //=============================private variables============================ | ||||||
| //=========================================================================== | //=========================================================================== | ||||||
| static bool temp_meas_ready = false; | static volatile bool temp_meas_ready = false; | ||||||
|  |  | ||||||
| static unsigned long  previous_millis_bed_heater; | static unsigned long  previous_millis_bed_heater; | ||||||
| //static unsigned long previous_millis_heater; | //static unsigned long previous_millis_heater; | ||||||
| @@ -132,7 +132,94 @@ static unsigned long  previous_millis_bed_heater; | |||||||
| //=========================================================================== | //=========================================================================== | ||||||
| //=============================   functions      ============================ | //=============================   functions      ============================ | ||||||
| //=========================================================================== | //=========================================================================== | ||||||
|  |  | ||||||
|  | void PID_autotune(float temp) | ||||||
|  | { | ||||||
|  |   float input; | ||||||
|  |   int cycles=0; | ||||||
|  |   bool heating = true; | ||||||
|  |   soft_pwm[0] = 255>>1; | ||||||
|  |  | ||||||
|  |   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"); | ||||||
|  |  | ||||||
|  |   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); | ||||||
|  |               Kp = 0.6*Ku; | ||||||
|  |               Ki = 2*Kp/Tu; | ||||||
|  |               Kd = Kp*Tu/8; | ||||||
|  |               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; | ||||||
|  |         } | ||||||
|  |       }  | ||||||
|  |     } | ||||||
|  |     if(input > (temp + 20)) { | ||||||
|  |       SERIAL_PROTOCOLLNPGM("PID Autotune failed !!!, Temperature to high"); | ||||||
|  |       return; | ||||||
|  |     } | ||||||
|  |     if(millis() - temp_millis > 2000) { | ||||||
|  |       temp_millis = millis(); | ||||||
|  |       SERIAL_PROTOCOLPGM("ok T:"); | ||||||
|  |       SERIAL_PROTOCOL(degHotend(0));    | ||||||
|  |       SERIAL_PROTOCOLPGM(" @:"); | ||||||
|  |       SERIAL_PROTOCOLLN(getHeaterPower(0));        | ||||||
|  |     } | ||||||
|  |     LCD_STATUS; | ||||||
|  |   } | ||||||
|  | } | ||||||
|  |  | ||||||
| void updatePID() | void updatePID() | ||||||
| { | { | ||||||
| #ifdef PIDTEMP | #ifdef PIDTEMP | ||||||
|   | |||||||
| @@ -1,162 +1,165 @@ | |||||||
| /* | /* | ||||||
|   temperature.h - temperature controller |   temperature.h - temperature controller | ||||||
|   Part of Marlin |   Part of Marlin | ||||||
|  |  | ||||||
|   Copyright (c) 2011 Erik van der Zalm |   Copyright (c) 2011 Erik van der Zalm | ||||||
|  |  | ||||||
|   Grbl is free software: you can redistribute it and/or modify |   Grbl is free software: you can redistribute it and/or modify | ||||||
|   it under the terms of the GNU General Public License as published by |   it under the terms of the GNU General Public License as published by | ||||||
|   the Free Software Foundation, either version 3 of the License, or |   the Free Software Foundation, either version 3 of the License, or | ||||||
|   (at your option) any later version. |   (at your option) any later version. | ||||||
|  |  | ||||||
|   Grbl is distributed in the hope that it will be useful, |   Grbl is distributed in the hope that it will be useful, | ||||||
|   but WITHOUT ANY WARRANTY; without even the implied warranty of |   but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||||
|   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the |   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ||||||
|   GNU General Public License for more details. |   GNU General Public License for more details. | ||||||
|  |  | ||||||
|   You should have received a copy of the GNU General Public License |   You should have received a copy of the GNU General Public License | ||||||
|   along with Grbl.  If not, see <http://www.gnu.org/licenses/>. |   along with Grbl.  If not, see <http://www.gnu.org/licenses/>. | ||||||
| */ | */ | ||||||
|  |  | ||||||
| #ifndef temperature_h | #ifndef temperature_h | ||||||
| #define temperature_h  | #define temperature_h  | ||||||
|  |  | ||||||
| #include "Marlin.h" | #include "Marlin.h" | ||||||
| #include "planner.h" | #include "planner.h" | ||||||
| #ifdef PID_ADD_EXTRUSION_RATE | #ifdef PID_ADD_EXTRUSION_RATE | ||||||
|   #include "stepper.h" |   #include "stepper.h" | ||||||
| #endif | #endif | ||||||
|  |  | ||||||
| // public functions | // public functions | ||||||
| void tp_init();  //initialise the heating | void tp_init();  //initialise the heating | ||||||
| void manage_heater(); //it is critical that this is called periodically. | void manage_heater(); //it is critical that this is called periodically. | ||||||
|  |  | ||||||
| //low leven conversion routines | //low leven conversion routines | ||||||
| // do not use this routines and variables outsie of temperature.cpp | // do not use this routines and variables outsie of temperature.cpp | ||||||
| int temp2analog(int celsius, uint8_t e); | int temp2analog(int celsius, uint8_t e); | ||||||
| int temp2analogBed(int celsius); | int temp2analogBed(int celsius); | ||||||
| float analog2temp(int raw, uint8_t e); | float analog2temp(int raw, uint8_t e); | ||||||
| float analog2tempBed(int raw); | float analog2tempBed(int raw); | ||||||
| extern int target_raw[EXTRUDERS];   | extern int target_raw[EXTRUDERS];   | ||||||
| extern int heatingtarget_raw[EXTRUDERS];   | extern int heatingtarget_raw[EXTRUDERS];   | ||||||
| extern int current_raw[EXTRUDERS]; | extern int current_raw[EXTRUDERS]; | ||||||
| extern int target_raw_bed; | extern int target_raw_bed; | ||||||
| extern int current_raw_bed; | extern int current_raw_bed; | ||||||
| #ifdef BED_LIMIT_SWITCHING | #ifdef BED_LIMIT_SWITCHING | ||||||
|   extern int target_bed_low_temp ;   |   extern int target_bed_low_temp ;   | ||||||
|   extern int target_bed_high_temp ; |   extern int target_bed_high_temp ; | ||||||
| #endif | #endif | ||||||
| extern float Kp,Ki,Kd,Kc; | extern float Kp,Ki,Kd,Kc; | ||||||
|  |  | ||||||
| #ifdef PIDTEMP | #ifdef PIDTEMP | ||||||
|   extern float pid_setpoint[EXTRUDERS]; |   extern float pid_setpoint[EXTRUDERS]; | ||||||
| #endif | #endif | ||||||
|    |    | ||||||
| // #ifdef WATCHPERIOD | // #ifdef WATCHPERIOD | ||||||
|   extern int watch_raw[EXTRUDERS] ; |   extern int watch_raw[EXTRUDERS] ; | ||||||
| //   extern unsigned long watchmillis; | //   extern unsigned long watchmillis; | ||||||
| // #endif | // #endif | ||||||
|  |  | ||||||
|  |  | ||||||
| //high level conversion routines, for use outside of temperature.cpp | //high level conversion routines, for use outside of temperature.cpp | ||||||
| //inline so that there is no performance decrease. | //inline so that there is no performance decrease. | ||||||
| //deg=degreeCelsius | //deg=degreeCelsius | ||||||
|  |  | ||||||
| FORCE_INLINE float degHotend(uint8_t extruder) {   | FORCE_INLINE float degHotend(uint8_t extruder) {   | ||||||
|   return analog2temp(current_raw[extruder], extruder); |   return analog2temp(current_raw[extruder], extruder); | ||||||
| }; | }; | ||||||
|  |  | ||||||
| FORCE_INLINE float degBed() { | FORCE_INLINE float degBed() { | ||||||
|   return analog2tempBed(current_raw_bed); |   return analog2tempBed(current_raw_bed); | ||||||
| }; | }; | ||||||
|  |  | ||||||
| FORCE_INLINE float degTargetHotend(uint8_t extruder) {   | FORCE_INLINE float degTargetHotend(uint8_t extruder) {   | ||||||
|   return analog2temp(target_raw[extruder], extruder); |   return analog2temp(target_raw[extruder], extruder); | ||||||
| }; | }; | ||||||
|  |  | ||||||
| FORCE_INLINE float degTargetBed() {    | FORCE_INLINE float degTargetBed() {    | ||||||
|   return analog2tempBed(target_raw_bed); |   return analog2tempBed(target_raw_bed); | ||||||
| }; | }; | ||||||
|  |  | ||||||
| FORCE_INLINE void setTargetHotend(const float &celsius, uint8_t extruder) {   | FORCE_INLINE void setTargetHotend(const float &celsius, uint8_t extruder) {   | ||||||
|   target_raw[extruder] = temp2analog(celsius, extruder); |   target_raw[extruder] = temp2analog(celsius, extruder); | ||||||
| #ifdef PIDTEMP | #ifdef PIDTEMP | ||||||
|   pid_setpoint[extruder] = celsius; |   pid_setpoint[extruder] = celsius; | ||||||
| #endif //PIDTEMP | #endif //PIDTEMP | ||||||
| }; | }; | ||||||
|  |  | ||||||
| FORCE_INLINE void setTargetBed(const float &celsius) {   | FORCE_INLINE void setTargetBed(const float &celsius) {   | ||||||
|    |    | ||||||
|   target_raw_bed = temp2analogBed(celsius); |   target_raw_bed = temp2analogBed(celsius); | ||||||
|   #ifdef BED_LIMIT_SWITCHING |   #ifdef BED_LIMIT_SWITCHING | ||||||
|     if(celsius>BED_HYSTERESIS) |     if(celsius>BED_HYSTERESIS) | ||||||
|     { |     { | ||||||
|     target_bed_low_temp= temp2analogBed(celsius-BED_HYSTERESIS); |     target_bed_low_temp= temp2analogBed(celsius-BED_HYSTERESIS); | ||||||
|     target_bed_high_temp= temp2analogBed(celsius+BED_HYSTERESIS); |     target_bed_high_temp= temp2analogBed(celsius+BED_HYSTERESIS); | ||||||
|     } |     } | ||||||
|     else |     else | ||||||
|     {  |     {  | ||||||
|       target_bed_low_temp=0; |       target_bed_low_temp=0; | ||||||
|       target_bed_high_temp=0; |       target_bed_high_temp=0; | ||||||
|     } |     } | ||||||
|   #endif |   #endif | ||||||
| }; | }; | ||||||
|  |  | ||||||
| FORCE_INLINE bool isHeatingHotend(uint8_t extruder){   | FORCE_INLINE bool isHeatingHotend(uint8_t extruder){   | ||||||
|   return target_raw[extruder] > current_raw[extruder]; |   return target_raw[extruder] > current_raw[extruder]; | ||||||
| }; | }; | ||||||
|  |  | ||||||
| FORCE_INLINE bool isHeatingBed() { | FORCE_INLINE bool isHeatingBed() { | ||||||
|   return target_raw_bed > current_raw_bed; |   return target_raw_bed > current_raw_bed; | ||||||
| }; | }; | ||||||
|  |  | ||||||
| FORCE_INLINE bool isCoolingHotend(uint8_t extruder) {   | FORCE_INLINE bool isCoolingHotend(uint8_t extruder) {   | ||||||
|   return target_raw[extruder] < current_raw[extruder]; |   return target_raw[extruder] < current_raw[extruder]; | ||||||
| }; | }; | ||||||
|  |  | ||||||
| FORCE_INLINE bool isCoolingBed() { | FORCE_INLINE bool isCoolingBed() { | ||||||
|   return target_raw_bed < current_raw_bed; |   return target_raw_bed < current_raw_bed; | ||||||
| }; | }; | ||||||
|  |  | ||||||
| #define degHotend0() degHotend(0) | #define degHotend0() degHotend(0) | ||||||
| #define degTargetHotend0() degTargetHotend(0) | #define degTargetHotend0() degTargetHotend(0) | ||||||
| #define setTargetHotend0(_celsius) setTargetHotend((_celsius), 0) | #define setTargetHotend0(_celsius) setTargetHotend((_celsius), 0) | ||||||
| #define isHeatingHotend0() isHeatingHotend(0) | #define isHeatingHotend0() isHeatingHotend(0) | ||||||
| #define isCoolingHotend0() isCoolingHotend(0) | #define isCoolingHotend0() isCoolingHotend(0) | ||||||
| #if EXTRUDERS > 1 | #if EXTRUDERS > 1 | ||||||
| #define degHotend1() degHotend(1) | #define degHotend1() degHotend(1) | ||||||
| #define degTargetHotend1() degTargetHotend(1) | #define degTargetHotend1() degTargetHotend(1) | ||||||
| #define setTargetHotend1(_celsius) setTargetHotend((_celsius), 1) | #define setTargetHotend1(_celsius) setTargetHotend((_celsius), 1) | ||||||
| #define isHeatingHotend1() isHeatingHotend(1) | #define isHeatingHotend1() isHeatingHotend(1) | ||||||
| #define isCoolingHotend1() isCoolingHotend(1) | #define isCoolingHotend1() isCoolingHotend(1) | ||||||
| #endif | #endif | ||||||
| #if EXTRUDERS > 2 | #if EXTRUDERS > 2 | ||||||
| #define degHotend2() degHotend(2) | #define degHotend2() degHotend(2) | ||||||
| #define degTargetHotend2() degTargetHotend(2) | #define degTargetHotend2() degTargetHotend(2) | ||||||
| #define setTargetHotend2(_celsius) setTargetHotend((_celsius), 2) | #define setTargetHotend2(_celsius) setTargetHotend((_celsius), 2) | ||||||
| #define isHeatingHotend2() isHeatingHotend(2) | #define isHeatingHotend2() isHeatingHotend(2) | ||||||
| #define isCoolingHotend2() isCoolingHotend(2) | #define isCoolingHotend2() isCoolingHotend(2) | ||||||
| #endif | #endif | ||||||
| #if EXTRUDERS > 3 | #if EXTRUDERS > 3 | ||||||
| #error Invalid number of extruders | #error Invalid number of extruders | ||||||
| #endif | #endif | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
| int getHeaterPower(int heater); | int getHeaterPower(int heater); | ||||||
| void disable_heater(); | void disable_heater(); | ||||||
| void setWatch(); | void setWatch(); | ||||||
| void updatePID(); | void updatePID(); | ||||||
|  |  | ||||||
| FORCE_INLINE void autotempShutdown(){ | FORCE_INLINE void autotempShutdown(){ | ||||||
|  #ifdef AUTOTEMP |  #ifdef AUTOTEMP | ||||||
|  if(autotemp_enabled) |  if(autotemp_enabled) | ||||||
|  { |  { | ||||||
|   autotemp_enabled=false; |   autotemp_enabled=false; | ||||||
|   if(degTargetHotend(ACTIVE_EXTRUDER)>autotemp_min) |   if(degTargetHotend(ACTIVE_EXTRUDER)>autotemp_min) | ||||||
|     setTargetHotend(0,ACTIVE_EXTRUDER); |     setTargetHotend(0,ACTIVE_EXTRUDER); | ||||||
|  } |  } | ||||||
|  #endif |  #endif | ||||||
| } | } | ||||||
| #endif |  | ||||||
|  | void PID_autotune(float temp); | ||||||
|  |  | ||||||
|  | #endif | ||||||
|  |  | ||||||
|   | |||||||
| @@ -315,19 +315,18 @@ void MainMenu::showStatus() | |||||||
|   static int olddegHotEnd0=-1; |   static int olddegHotEnd0=-1; | ||||||
|   static int oldtargetHotEnd0=-1; |   static int oldtargetHotEnd0=-1; | ||||||
|   //force_lcd_update=true; |   //force_lcd_update=true; | ||||||
|   if(force_lcd_update||feedmultiplychanged)  //initial display of content |   if(force_lcd_update)  //initial display of content | ||||||
|   { |   { | ||||||
|     feedmultiplychanged=false; |  | ||||||
|     encoderpos=feedmultiply; |     encoderpos=feedmultiply; | ||||||
|     clear(); |     clear(); | ||||||
|     lcd.setCursor(0,0);lcdprintPGM("\002123/567\001 "); |     lcd.setCursor(0,0);lcdprintPGM("\002---/---\001 "); | ||||||
|     #if defined BED_USES_THERMISTOR || defined BED_USES_AD595  |     #if defined BED_USES_THERMISTOR || defined BED_USES_AD595  | ||||||
|       lcd.setCursor(10,0);lcdprintPGM("B123/567\001 "); |       lcd.setCursor(10,0);lcdprintPGM("B---/---\001 "); | ||||||
|     #endif |     #endif | ||||||
|   } |   } | ||||||
|      |      | ||||||
|   int tHotEnd0=intround(degHotend0()); |   int tHotEnd0=intround(degHotend0()); | ||||||
|   if((abs(tHotEnd0-olddegHotEnd0)>1)||force_lcd_update) //>1 because otherwise the lcd is refreshed to often. |   if((tHotEnd0!=olddegHotEnd0)||force_lcd_update) | ||||||
|   { |   { | ||||||
|     lcd.setCursor(1,0); |     lcd.setCursor(1,0); | ||||||
|     lcd.print(ftostr3(tHotEnd0)); |     lcd.print(ftostr3(tHotEnd0)); | ||||||
| @@ -379,8 +378,15 @@ void MainMenu::showStatus() | |||||||
|     lcdprintPGM("Z:");lcd.print(ftostr52(current_position[2])); |     lcdprintPGM("Z:");lcd.print(ftostr52(current_position[2])); | ||||||
|     oldzpos=currentz; |     oldzpos=currentz; | ||||||
|   } |   } | ||||||
|  |    | ||||||
|   static int oldfeedmultiply=0; |   static int oldfeedmultiply=0; | ||||||
|   int curfeedmultiply=feedmultiply; |   int curfeedmultiply=feedmultiply; | ||||||
|  |    | ||||||
|  |   if(feedmultiplychanged == true) { | ||||||
|  |     feedmultiplychanged == false; | ||||||
|  |     encoderpos = curfeedmultiply; | ||||||
|  |   } | ||||||
|  |    | ||||||
|   if(encoderpos!=curfeedmultiply||force_lcd_update) |   if(encoderpos!=curfeedmultiply||force_lcd_update) | ||||||
|   { |   { | ||||||
|    curfeedmultiply=encoderpos; |    curfeedmultiply=encoderpos; | ||||||
| @@ -391,12 +397,14 @@ void MainMenu::showStatus() | |||||||
|    feedmultiply=curfeedmultiply; |    feedmultiply=curfeedmultiply; | ||||||
|    encoderpos=curfeedmultiply; |    encoderpos=curfeedmultiply; | ||||||
|   } |   } | ||||||
|  |    | ||||||
|   if((curfeedmultiply!=oldfeedmultiply)||force_lcd_update) |   if((curfeedmultiply!=oldfeedmultiply)||force_lcd_update) | ||||||
|   { |   { | ||||||
|    oldfeedmultiply=curfeedmultiply; |    oldfeedmultiply=curfeedmultiply; | ||||||
|    lcd.setCursor(0,2); |    lcd.setCursor(0,2); | ||||||
|    lcd.print(itostr3(curfeedmultiply));lcdprintPGM("% "); |    lcd.print(itostr3(curfeedmultiply));lcdprintPGM("% "); | ||||||
|   } |   } | ||||||
|  |    | ||||||
|   if(messagetext[0]!='\0') |   if(messagetext[0]!='\0') | ||||||
|   { |   { | ||||||
|     lcd.setCursor(0,LCD_HEIGHT-1); |     lcd.setCursor(0,LCD_HEIGHT-1); | ||||||
| @@ -404,7 +412,6 @@ void MainMenu::showStatus() | |||||||
|     uint8_t n=strlen(messagetext); |     uint8_t n=strlen(messagetext); | ||||||
|     for(int8_t i=0;i<LCD_WIDTH-n;i++) |     for(int8_t i=0;i<LCD_WIDTH-n;i++) | ||||||
|       lcd.print(" "); |       lcd.print(" "); | ||||||
|      |  | ||||||
|     messagetext[0]='\0'; |     messagetext[0]='\0'; | ||||||
|   } |   } | ||||||
|    |    | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user