ConfigurationStore.cpp 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294
  1. //! @file
  2. #include "Marlin.h"
  3. #include "planner.h"
  4. #include "temperature.h"
  5. #include "ultralcd.h"
  6. #include "ConfigurationStore.h"
  7. #include "Configuration_var.h"
  8. #ifdef MESH_BED_LEVELING
  9. #include "mesh_bed_leveling.h"
  10. #endif
  11. #ifdef TMC2130
  12. #include "tmc2130.h"
  13. #endif
  14. M500_conf cs;
  15. #define EEPROM_VERSION "V2"
  16. #ifndef DISABLE_M503
  17. void Config_PrintSettings(uint8_t level)
  18. { // Always have this function, even with EEPROM_SETTINGS disabled, the current values will be shown
  19. #ifdef TMC2130
  20. printf_P(PSTR(
  21. "%SSteps per unit:\n%S M92 X%.2f Y%.2f Z%.2f E%.2f\n"
  22. "%SUStep resolution: \n%S M350 X%d Y%d Z%d E%d\n"
  23. "%SMaximum feedrates - normal (mm/s):\n%S M203 X%.2f Y%.2f Z%.2f E%.2f\n"
  24. "%SMaximum feedrates - stealth (mm/s):\n%S M203 X%.2f Y%.2f Z%.2f E%.2f\n"
  25. "%SMaximum acceleration - normal (mm/s2):\n%S M201 X%lu Y%lu Z%lu E%lu\n"
  26. "%SMaximum acceleration - stealth (mm/s2):\n%S M201 X%lu Y%lu Z%lu E%lu\n"
  27. "%SAcceleration: P=print, R=retract, T=travel\n%S M204 P%.2f R%.2f T%.2f\n"
  28. "%SAdvanced variables: S=Min feedrate (mm/s), T=Min travel feedrate (mm/s), B=minimum segment time (ms), X=maximum XY jerk (mm/s), Z=maximum Z jerk (mm/s), E=maximum E jerk (mm/s)\n%S M205 S%.2f T%.2f B%.2f X%.2f Y%.2f Z%.2f E%.2f\n"
  29. "%SHome offset (mm):\n%S M206 X%.2f Y%.2f Z%.2f\n"
  30. ),
  31. echomagic, echomagic, cs.axis_steps_per_unit[X_AXIS], cs.axis_steps_per_unit[Y_AXIS], cs.axis_steps_per_unit[Z_AXIS], cs.axis_steps_per_unit[E_AXIS],
  32. echomagic, echomagic, cs.axis_ustep_resolution[X_AXIS], cs.axis_ustep_resolution[Y_AXIS], cs.axis_ustep_resolution[Z_AXIS], cs.axis_ustep_resolution[E_AXIS],
  33. echomagic, echomagic, cs.max_feedrate_normal[X_AXIS], cs.max_feedrate_normal[Y_AXIS], cs.max_feedrate_normal[Z_AXIS], cs.max_feedrate_normal[E_AXIS],
  34. echomagic, echomagic, cs.max_feedrate_silent[X_AXIS], cs.max_feedrate_silent[Y_AXIS], cs.max_feedrate_silent[Z_AXIS], cs.max_feedrate_silent[E_AXIS],
  35. echomagic, echomagic, cs.max_acceleration_units_per_sq_second_normal[X_AXIS], cs.max_acceleration_units_per_sq_second_normal[Y_AXIS], cs.max_acceleration_units_per_sq_second_normal[Z_AXIS], cs.max_acceleration_units_per_sq_second_normal[E_AXIS],
  36. echomagic, echomagic, cs.max_acceleration_units_per_sq_second_silent[X_AXIS], cs.max_acceleration_units_per_sq_second_silent[Y_AXIS], cs.max_acceleration_units_per_sq_second_silent[Z_AXIS], cs.max_acceleration_units_per_sq_second_silent[E_AXIS],
  37. echomagic, echomagic, cs.acceleration, cs.retract_acceleration, cs.travel_acceleration,
  38. echomagic, echomagic, cs.minimumfeedrate, cs.mintravelfeedrate, cs.minsegmenttime, cs.max_jerk[X_AXIS], cs.max_jerk[Y_AXIS], cs.max_jerk[Z_AXIS], cs.max_jerk[E_AXIS],
  39. echomagic, echomagic, cs.add_homing[X_AXIS], cs.add_homing[Y_AXIS], cs.add_homing[Z_AXIS]
  40. #else //TMC2130
  41. printf_P(PSTR(
  42. "%SSteps per unit:\n%S M92 X%.2f Y%.2f Z%.2f E%.2f\n"
  43. "%SMaximum feedrates (mm/s):\n%S M203 X%.2f Y%.2f Z%.2f E%.2f\n"
  44. "%SMaximum acceleration (mm/s2):\n%S M201 X%lu Y%lu Z%lu E%lu\n"
  45. "%SAcceleration: P=print, R=retract, T=travel\n%S M204 P%.2f R%.2f T%.2f\n"
  46. "%SAdvanced variables: S=Min feedrate (mm/s), T=Min travel feedrate (mm/s), B=minimum segment time (ms), X=maximum XY jerk (mm/s), Z=maximum Z jerk (mm/s), E=maximum E jerk (mm/s)\n%S M205 S%.2f T%.2f B%.2f X%.2f Y%.2f Z%.2f E%.2f\n"
  47. "%SHome offset (mm):\n%S M206 X%.2f Y%.2f Z%.2f\n"
  48. ),
  49. echomagic, echomagic, cs.axis_steps_per_unit[X_AXIS], cs.axis_steps_per_unit[Y_AXIS], cs.axis_steps_per_unit[Z_AXIS], cs.axis_steps_per_unit[E_AXIS],
  50. echomagic, echomagic, max_feedrate[X_AXIS], max_feedrate[Y_AXIS], max_feedrate[Z_AXIS], max_feedrate[E_AXIS],
  51. echomagic, echomagic, max_acceleration_units_per_sq_second[X_AXIS], max_acceleration_units_per_sq_second[Y_AXIS], max_acceleration_units_per_sq_second[Z_AXIS], max_acceleration_units_per_sq_second[E_AXIS],
  52. echomagic, echomagic, cs.acceleration, cs.retract_acceleration, cs.travel_acceleration,
  53. echomagic, echomagic, cs.minimumfeedrate, cs.mintravelfeedrate, cs.minsegmenttime, cs.max_jerk[X_AXIS], cs.max_jerk[Y_AXIS], cs.max_jerk[Z_AXIS], cs.max_jerk[E_AXIS],
  54. echomagic, echomagic, cs.add_homing[X_AXIS], cs.add_homing[Y_AXIS], cs.add_homing[Z_AXIS]
  55. #endif //TMC2130
  56. );
  57. #ifdef PIDTEMP
  58. printf_P(PSTR("%SPID settings:\n%S M301 P%.2f I%.2f D%.2f\n"),
  59. echomagic, echomagic, cs.Kp, unscalePID_i(cs.Ki), unscalePID_d(cs.Kd));
  60. #endif
  61. #ifdef PIDTEMPBED
  62. printf_P(PSTR("%SPID heatbed settings:\n%S M304 P%.2f I%.2f D%.2f\n"),
  63. echomagic, echomagic, cs.bedKp, unscalePID_i(cs.bedKi), unscalePID_d(cs.bedKd));
  64. #endif
  65. #ifdef FWRETRACT
  66. printf_P(PSTR(
  67. "%SRetract: S=Length (mm) F:Speed (mm/m) Z: ZLift (mm)\n%S M207 S%.2f F%.2f Z%.2f\n"
  68. "%SRecover: S=Extra length (mm) F:Speed (mm/m)\n%S M208 S%.2f F%.2f\n"
  69. "%SAuto-Retract: S=0 to disable, 1 to interpret extrude-only moves as retracts or recoveries\n%S M209 S%d\n"
  70. ),
  71. echomagic, echomagic, cs.retract_length, cs.retract_feedrate*60, cs.retract_zlift,
  72. echomagic, echomagic, cs.retract_recover_length, cs.retract_recover_feedrate*60,
  73. echomagic, echomagic, (cs.autoretract_enabled ? 1 : 0)
  74. );
  75. #if EXTRUDERS > 1
  76. printf_P(PSTR("%SMulti-extruder settings:\n%S Swap retract length (mm): %.2f\n%S Swap rec. addl. length (mm): %.2f\n"),
  77. echomagic, echomagic, retract_length_swap, echomagic, retract_recover_length_swap);
  78. #endif
  79. if (cs.volumetric_enabled) {
  80. printf_P(PSTR("%SFilament settings:\n%S M200 D%.2f\n"),
  81. echomagic, echomagic, cs.filament_size[0]);
  82. #if EXTRUDERS > 1
  83. printf_P(PSTR("%S M200 T1 D%.2f\n"),
  84. echomagic, echomagic, cs.filament_size[1]);
  85. #if EXTRUDERS > 2
  86. printf_P(PSTR("%S M200 T1 D%.2f\n"),
  87. echomagic, echomagic, cs.filament_size[2]);
  88. #endif
  89. #endif
  90. } else {
  91. printf_P(PSTR("%SFilament settings: Disabled\n"), echomagic);
  92. }
  93. #endif
  94. if (level >= 10) {
  95. #ifdef LIN_ADVANCE
  96. printf_P(PSTR("%SLinear advance settings:%S M900 K%.2f\n"),
  97. echomagic, echomagic, extruder_advance_K);
  98. #endif //LIN_ADVANCE
  99. }
  100. // Arc Interpolation Settings
  101. printf_P(PSTR(
  102. "%SArc Settings: P:Max length(mm) S:Min length (mm) N:Corrections R:Min segments F:Segments/sec.\n%S M214 P%.2f S%.2f N%d R%d F%d\n"),
  103. echomagic, echomagic, cs.mm_per_arc_segment, cs.min_mm_per_arc_segment, cs.n_arc_correction, cs.min_arc_segments, cs.arc_segments_per_sec);
  104. #ifdef TEMP_MODEL
  105. temp_model_report_settings();
  106. #endif
  107. }
  108. #endif
  109. #ifdef EEPROM_SETTINGS
  110. static_assert (EXTRUDERS == 1, "ConfigurationStore M500_conf not implemented for more extruders, fix filament_size array size.");
  111. static_assert (NUM_AXIS == 4, "ConfigurationStore M500_conf not implemented for more axis."
  112. "Fix axis_steps_per_unit max_feedrate_normal max_acceleration_units_per_sq_second_normal max_jerk max_feedrate_silent"
  113. " max_acceleration_units_per_sq_second_silent array size.");
  114. #ifdef ENABLE_AUTO_BED_LEVELING
  115. static_assert (false, "zprobe_zoffset was not initialized in printers in field to -(Z_PROBE_OFFSET_FROM_EXTRUDER), so it contains"
  116. "0.0, if this is not acceptable, increment EEPROM_VERSION to force use default_conf");
  117. #endif
  118. static_assert (sizeof(M500_conf) == 209, "sizeof(M500_conf) has changed, ensure that EEPROM_VERSION has been incremented, "
  119. "or if you added members in the end of struct, ensure that historically uninitialized values will be initialized."
  120. "If this is caused by change to more then 8bit processor, decide whether make this struct packed to save EEPROM,"
  121. "leave as it is to keep fast code, or reorder struct members to pack more tightly.");
  122. static const M500_conf default_conf PROGMEM =
  123. {
  124. EEPROM_VERSION,
  125. DEFAULT_AXIS_STEPS_PER_UNIT,
  126. DEFAULT_MAX_FEEDRATE,
  127. DEFAULT_MAX_ACCELERATION,
  128. DEFAULT_ACCELERATION,
  129. DEFAULT_RETRACT_ACCELERATION,
  130. DEFAULT_MINIMUMFEEDRATE,
  131. DEFAULT_MINTRAVELFEEDRATE,
  132. DEFAULT_MINSEGMENTTIME,
  133. {DEFAULT_XJERK, DEFAULT_YJERK, DEFAULT_ZJERK, DEFAULT_EJERK},
  134. {0,0,0},
  135. -(Z_PROBE_OFFSET_FROM_EXTRUDER),
  136. DEFAULT_Kp,
  137. DEFAULT_Ki*PID_dT,
  138. DEFAULT_Kd/PID_dT,
  139. DEFAULT_bedKp,
  140. DEFAULT_bedKi*PID_dT,
  141. DEFAULT_bedKd/PID_dT,
  142. 0,
  143. false,
  144. RETRACT_LENGTH,
  145. RETRACT_FEEDRATE,
  146. RETRACT_ZLIFT,
  147. RETRACT_RECOVER_LENGTH,
  148. RETRACT_RECOVER_FEEDRATE,
  149. false,
  150. {DEFAULT_NOMINAL_FILAMENT_DIA,
  151. #if EXTRUDERS > 1
  152. DEFAULT_NOMINAL_FILAMENT_DIA,
  153. #if EXTRUDERS > 2
  154. DEFAULT_NOMINAL_FILAMENT_DIA,
  155. #endif
  156. #endif
  157. },
  158. DEFAULT_MAX_FEEDRATE_SILENT,
  159. DEFAULT_MAX_ACCELERATION_SILENT,
  160. #ifdef TMC2130
  161. { TMC2130_USTEPS_XY, TMC2130_USTEPS_XY, TMC2130_USTEPS_Z, TMC2130_USTEPS_E },
  162. #else // TMC2130
  163. {16,16,16,16},
  164. #endif
  165. DEFAULT_TRAVEL_ACCELERATION,
  166. DEFAULT_MM_PER_ARC_SEGMENT,
  167. DEFAULT_MIN_MM_PER_ARC_SEGMENT,
  168. DEFAULT_N_ARC_CORRECTION,
  169. DEFAULT_MIN_ARC_SEGMENTS,
  170. DEFAULT_ARC_SEGMENTS_PER_SEC
  171. };
  172. void Config_StoreSettings()
  173. {
  174. strcpy_P(cs.version, default_conf.version);
  175. eeprom_update_block(reinterpret_cast<uint8_t*>(&cs), reinterpret_cast<uint8_t*>(EEPROM_M500_base), sizeof(cs));
  176. #ifdef TEMP_MODEL
  177. temp_model_save_settings();
  178. #endif
  179. SERIAL_ECHO_START;
  180. SERIAL_ECHOLNPGM("Settings Stored");
  181. }
  182. //! @brief Read M500 configuration
  183. //! @retval true Succeeded. Stored settings retrieved or default settings retrieved in case EEPROM cs was empty.
  184. //! @retval false Failed. Default settings has been retrieved, because of version mismatch
  185. bool Config_RetrieveSettings()
  186. {
  187. eeprom_read_block(reinterpret_cast<uint8_t*>(cs.version), reinterpret_cast<uint8_t*>(EEPROM_M500_base->version), sizeof(cs.version));
  188. // SERIAL_ECHOLN("Version: [" << ver << "] Stored version: [" << cs.version << "]");
  189. if (strncmp_P(cs.version, default_conf.version, sizeof(EEPROM_VERSION)) == 0) // version number match
  190. {
  191. // Initialize arc interpolation settings in eeprom if they are not already
  192. eeprom_init_default_float(&EEPROM_M500_base->mm_per_arc_segment, pgm_read_float(&default_conf.mm_per_arc_segment));
  193. eeprom_init_default_float(&EEPROM_M500_base->min_mm_per_arc_segment, pgm_read_float(&default_conf.min_mm_per_arc_segment));
  194. eeprom_init_default_byte(&EEPROM_M500_base->n_arc_correction, pgm_read_byte(&default_conf.n_arc_correction));
  195. eeprom_init_default_word(&EEPROM_M500_base->min_arc_segments, pgm_read_word(&default_conf.min_arc_segments));
  196. eeprom_init_default_word(&EEPROM_M500_base->arc_segments_per_sec, pgm_read_word(&default_conf.arc_segments_per_sec));
  197. // Initialize the travel_acceleration in eeprom if not already
  198. eeprom_init_default_float(&EEPROM_M500_base->travel_acceleration, pgm_read_float(&default_conf.travel_acceleration));
  199. // Initialize the max_feedrate_silent and max_acceleration_units_per_sq_second_silent in eeprom if not already
  200. eeprom_init_default_block(&EEPROM_M500_base->max_feedrate_silent, sizeof(EEPROM_M500_base->max_feedrate_silent), default_conf.max_feedrate_silent);
  201. eeprom_init_default_block(&EEPROM_M500_base->max_acceleration_units_per_sq_second_silent, sizeof(EEPROM_M500_base->max_acceleration_units_per_sq_second_silent), default_conf.max_acceleration_units_per_sq_second_silent);
  202. // load the CS to RAM
  203. eeprom_read_block(reinterpret_cast<uint8_t*>(&cs), reinterpret_cast<uint8_t*>(EEPROM_M500_base), sizeof(cs));
  204. calculate_extruder_multipliers();
  205. #ifdef TMC2130
  206. for (uint8_t j = X_AXIS; j <= Y_AXIS; j++)
  207. {
  208. if (cs.max_feedrate_normal[j] > NORMAL_MAX_FEEDRATE_XY)
  209. cs.max_feedrate_normal[j] = NORMAL_MAX_FEEDRATE_XY;
  210. if (cs.max_feedrate_silent[j] > SILENT_MAX_FEEDRATE_XY)
  211. cs.max_feedrate_silent[j] = SILENT_MAX_FEEDRATE_XY;
  212. if (cs.max_acceleration_units_per_sq_second_normal[j] > NORMAL_MAX_ACCEL_XY)
  213. cs.max_acceleration_units_per_sq_second_normal[j] = NORMAL_MAX_ACCEL_XY;
  214. if (cs.max_acceleration_units_per_sq_second_silent[j] > SILENT_MAX_ACCEL_XY)
  215. cs.max_acceleration_units_per_sq_second_silent[j] = SILENT_MAX_ACCEL_XY;
  216. }
  217. if(cs.axis_ustep_resolution[X_AXIS] == 0xff){ cs.axis_ustep_resolution[X_AXIS] = TMC2130_USTEPS_XY; }
  218. if(cs.axis_ustep_resolution[Y_AXIS] == 0xff){ cs.axis_ustep_resolution[Y_AXIS] = TMC2130_USTEPS_XY; }
  219. if(cs.axis_ustep_resolution[Z_AXIS] == 0xff){ cs.axis_ustep_resolution[Z_AXIS] = TMC2130_USTEPS_Z; }
  220. if(cs.axis_ustep_resolution[E_AXIS] == 0xff){ cs.axis_ustep_resolution[E_AXIS] = TMC2130_USTEPS_E; }
  221. tmc2130_set_res(X_AXIS, cs.axis_ustep_resolution[X_AXIS]);
  222. tmc2130_set_res(Y_AXIS, cs.axis_ustep_resolution[Y_AXIS]);
  223. tmc2130_set_res(Z_AXIS, cs.axis_ustep_resolution[Z_AXIS]);
  224. tmc2130_set_res(E_AXIS, cs.axis_ustep_resolution[E_AXIS]);
  225. #endif //TMC2130
  226. reset_acceleration_rates();
  227. // Call updatePID (similar to when we have processed M301)
  228. updatePID();
  229. #ifdef TEMP_MODEL
  230. temp_model_load_settings();
  231. #endif
  232. SERIAL_ECHO_START;
  233. SERIAL_ECHOLNPGM("Stored settings retrieved");
  234. }
  235. else
  236. {
  237. Config_ResetDefault();
  238. //Return false to inform user that eeprom version was changed and firmware is using default hardcoded settings now.
  239. //In case that storing to eeprom was not used yet, do not inform user that hardcoded settings are used.
  240. if (eeprom_is_initialized_block(EEPROM_M500_base->version, sizeof(EEPROM_M500_base->version))) {
  241. return false;
  242. }
  243. }
  244. return true;
  245. }
  246. #endif
  247. void Config_ResetDefault()
  248. {
  249. memcpy_P(&cs,&default_conf, sizeof(cs));
  250. // steps per sq second need to be updated to agree with the units per sq second
  251. reset_acceleration_rates();
  252. #ifdef PIDTEMP
  253. updatePID();
  254. #endif//PIDTEMP
  255. #ifdef TEMP_MODEL
  256. temp_model_reset_settings();
  257. #endif
  258. calculate_extruder_multipliers();
  259. SERIAL_ECHO_START;
  260. SERIAL_ECHOLNPGM("Hardcoded Default Settings Loaded");
  261. }