Skip to content

Commit

Permalink
Merge pull request prusa3d#4493 from gudnimg/print-job-timer-marlin
Browse files Browse the repository at this point in the history
PFW-1206: Implement Marlin's print job timer and add M75-M78
  • Loading branch information
3d-gussner authored Nov 22, 2023
2 parents c5a885d + 134e892 commit bbae8dd
Show file tree
Hide file tree
Showing 11 changed files with 292 additions and 69 deletions.
1 change: 1 addition & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -225,6 +225,7 @@ set(FW_SOURCES
spi.c
SpoolJoin.cpp
stepper.cpp
stopwatch.cpp
strtod.c
swi2c.c
Tcodes.cpp
Expand Down
7 changes: 1 addition & 6 deletions Firmware/Marlin.h
Original file line number Diff line number Diff line change
Expand Up @@ -262,18 +262,13 @@ extern float retract_length_swap;
extern float retract_recover_length_swap;
#endif

extern uint32_t starttime; // milliseconds
extern uint32_t pause_time; // milliseconds
extern uint32_t start_pause_print; // milliseconds
extern ShortTimer usb_timer;
extern bool processing_tcode;
extern bool homing_flag;
extern uint32_t total_filament_used; // mm/100 or 10um

/// @brief Save print statistics to EEPROM
/// @param _total_filament_used has unit mm/100 or 10um
/// @param _total_print_time has unit minutes, for example 123 minutes
void save_statistics(uint32_t _total_filament_used, uint32_t _total_print_time);
void save_statistics();

extern int fan_edge_counter[2];
extern int fan_speed[2];
Expand Down
92 changes: 66 additions & 26 deletions Firmware/Marlin_main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,7 @@
#include "Tcodes.h"
#include "Dcodes.h"
#include "SpoolJoin.h"
#include "stopwatch.h"

#ifndef LA_NOCOMPAT
#include "la10compat.h"
Expand Down Expand Up @@ -174,7 +175,7 @@ static LongTimer crashDetTimer;

bool mesh_bed_leveling_flag = false;

uint32_t total_filament_used;
uint32_t total_filament_used; // unit mm/100 or 10um
HeatingStatus heating_status;
int fan_edge_counter[2];
int fan_speed[2];
Expand Down Expand Up @@ -289,9 +290,6 @@ static uint32_t max_inactive_time = 0;
static uint32_t stepper_inactive_time = DEFAULT_STEPPER_DEACTIVE_TIME*1000l;
static uint32_t safetytimer_inactive_time = DEFAULT_SAFETYTIMER_TIME_MINS*60*1000ul;

uint32_t starttime;
uint32_t pause_time;
uint32_t start_pause_print;
ShortTimer usb_timer;

bool Stopped=false;
Expand Down Expand Up @@ -509,12 +507,12 @@ void servo_init()
}

bool __attribute__((noinline)) printJobOngoing() {
return (IS_SD_PRINTING || usb_timer.running());
return (IS_SD_PRINTING || usb_timer.running() || print_job_timer.isRunning());
}

bool __attribute__((noinline)) printer_active() {
return printJobOngoing()
|| isPrintPaused
|| print_job_timer.isPaused()
|| saved_printing
|| (lcd_commands_type != LcdCommands::Idle)
|| MMU2::mmu2.MMU_PRINT_SAVED()
Expand All @@ -535,7 +533,7 @@ bool check_fsensor() {
bool __attribute__((noinline)) babystep_allowed() {
return ( !homing_flag
&& !mesh_bed_leveling_flag
&& !isPrintPaused
&& !print_job_timer.isPaused()
&& ((lcd_commands_type == LcdCommands::Layer1Cal && CHECK_ALL_HEATERS)
|| printJobOngoing()
|| lcd_commands_type == LcdCommands::Idle
Expand Down Expand Up @@ -633,7 +631,7 @@ void crashdet_detected(uint8_t mask)

void crashdet_recover()
{
if (!isPrintPaused) crashdet_restore_print_and_continue();
if (!print_job_timer.isPaused()) crashdet_restore_print_and_continue();
if (lcd_crash_detect_enabled()) tmc2130_sg_stop_on_crash = true;
}

Expand Down Expand Up @@ -1731,7 +1729,7 @@ void loop()
KEEPALIVE_STATE(NOT_BUSY);
}

if (isPrintPaused && saved_printing_type == PowerPanic::PRINT_TYPE_USB) { //keep believing that usb is being printed. Prevents accessing dangerous menus while pausing.
if (print_job_timer.isPaused() && saved_printing_type == PowerPanic::PRINT_TYPE_USB) { //keep believing that usb is being printed. Prevents accessing dangerous menus while pausing.
usb_timer.start();
}
else if (usb_timer.expired(10000)) { //just need to check if it expired. Nothing else is needed to be done.
Expand Down Expand Up @@ -1828,7 +1826,7 @@ void loop()
}
//check heater every n milliseconds
manage_heater();
manage_inactivity(isPrintPaused);
manage_inactivity(print_job_timer.isPaused());
checkHitEndstops();
lcd_update(0);
#ifdef TMC2130
Expand Down Expand Up @@ -3425,7 +3423,7 @@ static void gcode_M600(const bool automatic, const float x_position, const float
fanSpeed = 0;

// Retract E
if (!isPrintPaused)
if (!print_job_timer.isPaused())
{
current_position[E_AXIS] += e_shift;
plan_buffer_line_curposXYZE(FILAMENTCHANGE_RFEED);
Expand Down Expand Up @@ -3488,7 +3486,7 @@ static void gcode_M600(const bool automatic, const float x_position, const float

// Feed a little of filament to stabilize pressure
if (!automatic) {
if (isPrintPaused)
if (print_job_timer.isPaused())
{
// Return to retracted state during a pause
// @todo is retraction really needed? E-position is reverted a few lines below
Expand Down Expand Up @@ -3524,7 +3522,7 @@ static void gcode_M600(const bool automatic, const float x_position, const float
feedmultiply = feedmultiplyBckp;
enquecommandf_P(MSG_M220, feedmultiplyBckp);
}
if (isPrintPaused) lcd_setstatuspgm(_T(MSG_PRINT_PAUSED));
if (print_job_timer.isPaused()) lcd_setstatuspgm(_T(MSG_PRINT_PAUSED));
else lcd_setstatuspgm(MSG_WELCOME);
custom_message_type = CustomMsg::Status;
}
Expand Down Expand Up @@ -5256,7 +5254,7 @@ void process_commands()
### M24 - Start SD print <a href="https://reprap.org/wiki/G-code#M24:_Start.2Fresume_SD_print">M24: Start/resume SD print</a>
*/
case 24:
if (isPrintPaused)
if (print_job_timer.isPaused())
lcd_resume_print();
else
{
Expand All @@ -5271,7 +5269,7 @@ void process_commands()
}

card.startFileprint();
starttime=_millis();
print_job_timer.start();
if (MMU2::mmu2.Enabled())
{
if (MMU2::mmu2.FindaDetectsFilament() && !fsensor.getFilamentPresent())
Expand Down Expand Up @@ -5389,7 +5387,7 @@ void process_commands()
la10c_reset();
#endif
}
starttime=_millis(); // procedure calls count as normal print time.
print_job_timer.start(); // procedure calls count as normal print time.
}
}
} break;
Expand All @@ -5413,7 +5411,7 @@ void process_commands()
case 31: //M31 take time since the start of the SD print or an M109 command
{
char time[30];
uint32_t t = (_millis() - starttime) / 1000;
uint32_t t = print_job_timer.duration();
int16_t sec, min;
min = t / 60;
sec = t % 60;
Expand Down Expand Up @@ -5875,6 +5873,48 @@ SERIAL_PROTOCOLPGM("\n\n");
break;
}

/*!
### M75 - Start the print job timer <a href="https://reprap.org/wiki/G-code#M75:_Start_the_print_job_timer">M75: Start the print job timer</a>
*/
case 75:
{
print_job_timer.start();
break;
}

/*!
### M76 - Pause the print job timer <a href="https://reprap.org/wiki/G-code#M76:_Pause_the_print_job_timer">M76: Pause the print job timer</a>
*/
case 76:
{
print_job_timer.pause();
break;
}

/*!
### M77 - Stop the print job timer <a href="https://reprap.org/wiki/G-code#M77:_Stop_the_print_job_timer">M77: Stop the print job timer</a>
*/
case 77:
{
print_job_timer.stop();
save_statistics();
break;
}

/*!
### M78 - Show statistical information about the print jobs <a href="https://reprap.org/wiki/G-code#M78:_Show_statistical_information_about_the_print_jobs">M78: Show statistical information about the print jobs</a>
*/
case 78:
{
// @todo useful for maintenance notifications
SERIAL_ECHOPGM("STATS ");
SERIAL_ECHO(eeprom_read_dword((uint32_t *)EEPROM_TOTALTIME));
SERIAL_ECHOPGM(" min ");
SERIAL_ECHO(eeprom_read_dword((uint32_t *)EEPROM_FILAMENTUSED));
SERIAL_ECHOLNPGM(" cm.");
break;
}

/*!
### M79 - Start host timer <a href="https://reprap.org/wiki/G-code#M79:_Start_host_timer">M79: Start host timer</a>
Start the printer-host enable keep-alive timer. While the timer has not expired, the printer will enable host specific features.
Expand Down Expand Up @@ -6050,8 +6090,7 @@ SERIAL_PROTOCOLPGM("\n\n");
LCD_MESSAGERPGM(_T(MSG_HEATING_COMPLETE));
heating_status = HeatingStatus::EXTRUDER_HEATING_COMPLETE;
prusa_statistics(2);

//starttime=_millis();

previous_millis_cmd.start();
}
break;
Expand Down Expand Up @@ -7743,7 +7782,7 @@ SERIAL_PROTOCOLPGM("\n\n");
SERIAL_ECHOPGM("Z:");
SERIAL_ECHOLN(pause_position[Z_AXIS]);
*/
if (!isPrintPaused) {
if (!print_job_timer.isPaused()) {
st_synchronize();
ClearToSend(); //send OK even before the command finishes executing because we want to make sure it is not skipped because of cmdqueue_pop_front();
cmdqueue_pop_front(); //trick because we want skip this command (M601) after restore
Expand All @@ -7757,7 +7796,7 @@ SERIAL_PROTOCOLPGM("\n\n");
*/
case 602:
{
if (isPrintPaused) lcd_resume_print();
if (print_job_timer.isPaused()) lcd_resume_print();
}
break;

Expand Down Expand Up @@ -9631,7 +9670,7 @@ void ThermalStop(bool allow_recovery)

// Either pause or stop the print
if(allow_recovery && printJobOngoing()) {
if (!isPrintPaused) {
if (!print_job_timer.isPaused()) {
lcd_setalertstatuspgm(_T(MSG_PAUSED_THERMAL_ERROR), LCD_STATUS_CRITICAL);

// we cannot make a distinction for the host here, the pause must be instantaneous
Expand Down Expand Up @@ -9765,13 +9804,15 @@ void setPwmFrequency(uint8_t pin, int val)
}
#endif //FAST_PWM_FAN

void save_statistics(uint32_t _total_filament_used, uint32_t _total_print_time) {
void save_statistics() {
uint32_t _previous_filament = eeprom_init_default_dword((uint32_t *)EEPROM_FILAMENTUSED, 0); //_previous_filament unit: meter
uint32_t _previous_time = eeprom_init_default_dword((uint32_t *)EEPROM_TOTALTIME, 0); //_previous_time unit: min

eeprom_update_dword((uint32_t *)EEPROM_TOTALTIME, _previous_time + _total_print_time); // EEPROM_TOTALTIME unit: min
eeprom_update_dword((uint32_t *)EEPROM_FILAMENTUSED, _previous_filament + (_total_filament_used / 1000));
uint32_t time_minutes = print_job_timer.duration() / 60;
eeprom_update_dword((uint32_t *)EEPROM_TOTALTIME, _previous_time + time_minutes); // EEPROM_TOTALTIME unit: min
eeprom_update_dword((uint32_t *)EEPROM_FILAMENTUSED, _previous_filament + (total_filament_used / 1000));

print_job_timer.reset();
total_filament_used = 0;

if (MMU2::mmu2.Enabled()) {
Expand Down Expand Up @@ -10460,7 +10501,6 @@ float temp_compensation_pinda_thermistor_offset(float temperature_pinda)
void long_pause() //long pause print
{
st_synchronize();
start_pause_print = _millis();

// Stop heaters
heating_status = HeatingStatus::NO_HEATING;
Expand Down
7 changes: 4 additions & 3 deletions Firmware/Prusa_farm.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
#include "ultralcd.h"
#include "Filament_sensor.h"
#include "language.h"
#include "stopwatch.h"

#ifdef PRUSA_FARM
uint8_t farm_mode = 0;
Expand Down Expand Up @@ -92,8 +93,8 @@ static void prusa_stat_printinfo() {
SERIAL_ECHOPGM("][FNM:");
SERIAL_ECHO(card.longFilename[0] ? card.longFilename : card.filename);
SERIAL_ECHOPGM("][TIM:");
if (starttime != 0) {
SERIAL_ECHO((_millis() - starttime) / 1000);
if (print_job_timer.isRunning()) {
SERIAL_ECHO(print_job_timer.duration());
}
else {
SERIAL_ECHO(0);
Expand Down Expand Up @@ -237,7 +238,7 @@ void prusa_statistics(uint8_t _message) {
if (busy_state == PAUSED_FOR_USER) {
prusa_statistics_case0(15);
}
else if (isPrintPaused) {
else if (print_job_timer.isPaused()) {
prusa_statistics_case0(14);
}
else if (IS_SD_PRINTING || (eFilamentAction != FilamentAction::None)) {
Expand Down
5 changes: 3 additions & 2 deletions Firmware/cardreader.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
#include "language.h"
#include "Prusa_farm.h"
#include "power_panic.h"
#include "stopwatch.h"

#ifdef SDSUPPORT

Expand Down Expand Up @@ -556,7 +557,7 @@ uint32_t CardReader::getFileSize()

void CardReader::getStatus(bool arg_P)
{
if (isPrintPaused)
if (print_job_timer.isPaused())
{
if (saved_printing && (saved_printing_type == PowerPanic::PRINT_TYPE_SD))
SERIAL_PROTOCOLLNPGM("SD print paused");
Expand All @@ -577,7 +578,7 @@ void CardReader::getStatus(bool arg_P)
SERIAL_PROTOCOL(sdpos);
SERIAL_PROTOCOL('/');
SERIAL_PROTOCOLLN(filesize);
uint16_t time = ( _millis() - starttime ) / 60000U;
uint16_t time = print_job_timer.duration() / 60;
SERIAL_PROTOCOL((int)(time / 60));
SERIAL_PROTOCOL(':');
SERIAL_PROTOCOLLN((int)(time % 60));
Expand Down
8 changes: 4 additions & 4 deletions Firmware/cmdqueue.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
#include "meatpack.h"
#include "messages.h"
#include "language.h"
#include "stopwatch.h"

// Reserve BUFSIZE lines of length MAX_CMD_SIZE plus CMDBUFFER_RESERVE_FRONT.
char cmdbuffer[BUFSIZE * (MAX_CMD_SIZE + 1) + CMDBUFFER_RESERVE_FRONT];
Expand Down Expand Up @@ -366,7 +367,7 @@ void get_command()
}

// start of serial line processing loop
while (((MYSERIAL.available() > 0 && !saved_printing) || (MYSERIAL.available() > 0 && isPrintPaused)) && !cmdqueue_serial_disabled) { //is print is saved (crash detection or filament detection), dont process data from serial line
while (((MYSERIAL.available() > 0 && !saved_printing) || (MYSERIAL.available() > 0 && print_job_timer.isPaused())) && !cmdqueue_serial_disabled) { //is print is saved (crash detection or filament detection), dont process data from serial line

#ifdef ENABLE_MEATPACK
// MeatPack Changes
Expand Down Expand Up @@ -658,12 +659,11 @@ void get_command()

SERIAL_PROTOCOLLNRPGM(_n("Done printing file"));////MSG_FILE_PRINTED
char time[30];
uint32_t t = (_millis() - starttime - pause_time) / 60000;
pause_time = 0;
uint32_t t = print_job_timer.duration() / 60;
int hours, minutes;
minutes = t % 60;
hours = t / 60;
save_statistics(total_filament_used, t);
save_statistics();
sprintf_P(time, PSTR("%i hours %i minutes"),hours, minutes);
SERIAL_ECHO_START;
SERIAL_ECHOLN(time);
Expand Down
3 changes: 2 additions & 1 deletion Firmware/fancheck.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
#include "messages.h"
#include "temperature.h"
#include "stepper.h"
#include "stopwatch.h"

#define FAN_CHECK_PERIOD 5000 //5s
#define FAN_CHECK_DURATION 100 //100ms
Expand Down Expand Up @@ -93,7 +94,7 @@ void fanSpeedError(unsigned char _fan) {

if (printJobOngoing()) {
// A print is ongoing, pause the print normally
if(!isPrintPaused) {
if(!print_job_timer.isPaused()) {
if (usb_timer.running())
lcd_pause_usb_print();
else
Expand Down
Loading

0 comments on commit bbae8dd

Please sign in to comment.