merge changes from upstream

This commit is contained in:
PavelSindler 2019-01-25 17:57:24 +01:00
commit 7e3a1c7d45
20 changed files with 808 additions and 218 deletions

View file

@ -3,16 +3,17 @@ before_install:
- sudo apt-get install -y ninja-build
script:
- bash -x test.sh
- bash -x build.sh
- cp Firmware/variants/1_75mm_MK3-EINSy10a-E3Dv6full.h Firmware/Configuration_prusa.h
- bash -x build.sh || { echo "1_75mm_MK3-EINSy10a-E3Dv6full variant failed" && false; }
- rm Firmware/Configuration_prusa.h
- cp Firmware/variants/1_75mm_MK25-RAMBo13a-E3Dv6full.h Firmware/Configuration_prusa.h
- bash -x build.sh
- bash -x build.sh || { echo "1_75mm_MK25-RAMBo13a-E3Dv6full variant failed" && false; }
- rm Firmware/Configuration_prusa.h
- cp Firmware/variants/1_75mm_MK25-RAMBo10a-E3Dv6full.h Firmware/Configuration_prusa.h
- bash -x build.sh
- bash -x build.sh || { echo "1_75mm_MK25-RAMBo10a-E3Dv6full variant failed" && false; }
- rm Firmware/Configuration_prusa.h
- cp Firmware/variants/1_75mm_MK2-RAMBo13a-E3Dv6full.h Firmware/Configuration_prusa.h
- bash -x build.sh
- bash -x build.sh || { echo "1_75mm_MK2-RAMBo13a-E3Dv6full variant failed" && false; }
- rm Firmware/Configuration_prusa.h
- cp Firmware/variants/1_75mm_MK2-RAMBo10a-E3Dv6full.h Firmware/Configuration_prusa.h
- bash -x build.sh
- bash -x build.sh || { echo "1_75mm_MK2-RAMBo10a-E3Dv6full variant failed" && false; }

View file

@ -14,7 +14,9 @@ set(TEST_SOURCES
Tests/tests.cpp
Tests/Example_test.cpp
Tests/Timer_test.cpp
Tests/AutoDeplete_test.cpp
Firmware/Timer.cpp
Firmware/AutoDeplete.cpp
)
add_executable(tests ${TEST_SOURCES})
target_include_directories(tests PRIVATE Tests)

79
Firmware/AutoDeplete.cpp Normal file
View file

@ -0,0 +1,79 @@
//! @file
//! @author: Marek Bel
//! @date Jan 3, 2019
#include "AutoDeplete.h"
#include "assert.h"
//! @brief bit field marking depleted filaments
//!
//! binary 1 marks filament as depleted
//! Zero initialized value means, that no filament is depleted.
static uint8_t depleted;
static const uint8_t filamentCount = 5;
//! @return binary 1 for all filaments
//! @par fCount number of filaments
static constexpr uint8_t allDepleted(uint8_t fCount)
{
return fCount == 1 ? 1 : ((1 << (fCount - 1)) | allDepleted(fCount - 1));
}
//! @brief Is filament available for printing?
//! @par filament Filament number to be checked
//! @retval true Filament is available for printing.
//! @retval false Filament is not available for printing.
static bool loaded(uint8_t filament)
{
if (depleted & (1 << filament)) return false;
return true;
}
//! @brief Mark filament as not available for printing.
//! @par filament filament to be marked
void ad_markDepleted(uint8_t filament)
{
assert(filament < filamentCount);
if (filament < filamentCount)
{
depleted |= 1 << filament;
}
}
//! @brief Mark filament as available for printing.
//! @par filament filament to be marked
void ad_markLoaded(uint8_t filament)
{
assert(filament < filamentCount);
if (filament < filamentCount)
{
depleted &= ~(1 << filament);
}
}
//! @brief Get alternative filament, which is not depleted
//! @par filament filament
//! @return Filament, if it is depleted, returns next available,
//! if all filaments are depleted, returns filament function parameter.
uint8_t ad_getAlternative(uint8_t filament)
{
assert(filament < filamentCount);
for (uint8_t i = 0; i<filamentCount; ++i)
{
uint8_t nextFilament = (filament + i) % filamentCount;
if (loaded(nextFilament)) return nextFilament;
}
return filament;
}
//! @brief Are all filaments depleted?
//! @retval true All filaments are depleted.
//! @retval false All filaments are not depleted.
bool ad_allDepleted()
{
if (allDepleted(filamentCount) == depleted)
{
return true;
}
return false;
}

17
Firmware/AutoDeplete.h Normal file
View file

@ -0,0 +1,17 @@
//! @file
//! @author: Marek Bel
//! @brief Filament auto deplete engine for multi-material prints with MMUv2 (Now marketed as SpoolJoin)
//!
//! Interface for marking MMUv2 filaments as depleted and getting alternative filament for printing.
#ifndef AUTODEPLETE_H
#define AUTODEPLETE_H
#include <stdint.h>
void ad_markDepleted(uint8_t filament);
void ad_markLoaded(uint8_t filament);
uint8_t ad_getAlternative(uint8_t filament);
bool ad_allDepleted();
#endif /* AUTODEPLETE_H */

View file

@ -126,13 +126,11 @@
// Comment the following line to disable PID and enable bang-bang.
#define PIDTEMP
#define BANG_MAX 255 // limits current to nozzle while in bang-bang mode; 255=full current
#define PID_MAX BANG_MAX // limits current to nozzle while PID is active (see PID_FUNCTIONAL_RANGE below); 255=full current
#define PID_MAX BANG_MAX // limits current to nozzle while PID is active; 255=full current
#ifdef PIDTEMP
//#define PID_DEBUG // Sends debug data to the serial port.
//#define PID_OPENLOOP 1 // Puts PID in open loop. M104/M140 sets the output power from 0 to PID_MAX
//#define SLOW_PWM_HEATERS // PWM with very low frequency (roughly 0.125Hz=8s) and minimum state time of approximately 1s useful for heaters driven by a relay
#define PID_FUNCTIONAL_RANGE 10 // If the temperature difference between the target temperature and the actual temperature
// is more then PID_FUNCTIONAL_RANGE then the PID will be shut off and the heater will be set to min/max.
#define PID_INTEGRAL_DRIVE_MAX PID_MAX //limit for the integral term
#define K1 0.95 //smoothing factor within the PID
#define PID_dT ((OVERSAMPLENR * 10.0)/(F_CPU / 64.0 / 256.0)) //sampling period of the temperature routine

View file

@ -78,6 +78,7 @@
#include <avr/pgmspace.h>
#include "Dcodes.h"
#include "AutoDeplete.h"
#ifdef SWSPI
@ -6947,6 +6948,10 @@ if((eSoundMode==e_SOUND_MODE_LOUD)||(eSoundMode==e_SOUND_MODE_ONCE))
}
else {
tmp_extruder = code_value();
if (mmu_enabled && lcd_autoDepleteEnabled())
{
tmp_extruder = ad_getAlternative(tmp_extruder);
}
}
st_synchronize();
snmm_filaments_used |= (1 << tmp_extruder); //for stop print
@ -7641,6 +7646,7 @@ void Stop()
disable_heater();
if(Stopped == false) {
Stopped = true;
lcd_print_stop();
Stopped_gcode_LastN = gcode_LastN; // Save last g_code for restart
SERIAL_ERROR_START;
SERIAL_ERRORLNRPGM(MSG_ERR_STOPPED);

View file

@ -1,4 +1,4 @@
//mmu.cpp
//! @file
#include "mmu.h"
#include "planner.h"
@ -14,6 +14,7 @@
#include "printers.h"
#include <avr/pgmspace.h>
#include "io_atmega2560.h"
#include "AutoDeplete.h"
#ifdef TMC2130
#include "tmc2130.h"
@ -245,7 +246,7 @@ void mmu_loop(void)
mmu_printf_P(PSTR("T%d\n"), filament);
mmu_state = 3; // wait for response
mmu_fil_loaded = true;
if(ir_sensor_detected) mmu_idl_sens = 1; //if idler sensor detected, use it for T-code
mmu_idl_sens = 1;
}
else if ((mmu_cmd >= MMU_CMD_L0) && (mmu_cmd <= MMU_CMD_L4))
{
@ -263,7 +264,7 @@ void mmu_loop(void)
#endif //MMU_DEBUG
mmu_puts_P(PSTR("C0\n")); //send 'continue loading'
mmu_state = 3;
if(ir_sensor_detected) mmu_idl_sens = 1; //if idler sensor detected use it for C0 code
mmu_idl_sens = 1;
}
else if (mmu_cmd == MMU_CMD_U0)
{
@ -326,8 +327,15 @@ void mmu_loop(void)
if (!mmu_finda && CHECK_FSENSOR && fsensor_enabled) {
fsensor_stop_and_save_print();
enquecommand_front_P(PSTR("FSENSOR_RECOVER")); //then recover
if (lcd_autoDepleteEnabled()) enquecommand_front_P(PSTR("M600 AUTO")); //save print and run M600 command
else enquecommand_front_P(PSTR("M600")); //save print and run M600 command
ad_markDepleted(mmu_extruder);
if (lcd_autoDepleteEnabled() && !ad_allDepleted())
{
enquecommand_front_P(PSTR("M600 AUTO")); //save print and run M600 command
}
else
{
enquecommand_front_P(PSTR("M600")); //save print and run M600 command
}
}
mmu_state = 1;
if (mmu_cmd == 0)
@ -339,19 +347,20 @@ void mmu_loop(void)
}
return;
case 3: //response to mmu commands
if (mmu_idl_sens && ir_sensor_detected) {
if (PIN_GET(IR_SENSOR_PIN) == 0 && mmu_loading_flag)
{
if (mmu_idl_sens)
{
if (PIN_GET(MMU_IDLER_SENSOR_PIN) == 0 && mmu_loading_flag)
{
#ifdef MMU_DEBUG
printf_P(PSTR("MMU <= 'A'\n"));
printf_P(PSTR("MMU <= 'A'\n"));
#endif //MMU_DEBUG
mmu_puts_P(PSTR("A\n")); //send 'abort' request
mmu_idl_sens = 0;
//printf_P(PSTR("MMU IDLER_SENSOR = 0 - ABORT\n"));
}
//else
//printf_P(PSTR("MMU IDLER_SENSOR = 1 - WAIT\n"));
}
mmu_puts_P(PSTR("A\n")); //send 'abort' request
mmu_idl_sens = 0;
//printf_P(PSTR("MMU IDLER_SENSOR = 0 - ABORT\n"));
}
//else
//printf_P(PSTR("MMU IDLER_SENSOR = 1 - WAIT\n"));
}
if (mmu_rx_ok() > 0)
{
#ifdef MMU_DEBUG
@ -420,69 +429,96 @@ int8_t mmu_set_filament_type(uint8_t extruder, uint8_t filament)
return timeout?1:0;
}
//! @brief Enqueue MMUv2 command
//!
//! Call manage_response() after enqueuing to process command.
//! If T command is enqueued, it disables current for extruder motor if TMC2130 driver present.
//! If T or L command is enqueued, it marks filament loaded in AutoDeplete module.
void mmu_command(uint8_t cmd)
{
#ifdef TMC2130
if ((cmd >= MMU_CMD_T0) && (cmd <= MMU_CMD_T4))
{
//disable extruder motor
#ifdef TMC2130
tmc2130_set_pwr(E_AXIS, 0);
//printf_P(PSTR("E-axis disabled\n"));
}
#endif //TMC2130
//printf_P(PSTR("E-axis disabled\n"));
ad_markLoaded(cmd - MMU_CMD_T0);
}
if ((cmd >= MMU_CMD_L0) && (cmd <= MMU_CMD_L4))
{
ad_markLoaded(cmd - MMU_CMD_L0);
}
mmu_cmd = cmd;
mmu_ready = false;
}
void mmu_load_step() {
//! @brief Rotate extruder idler to catch filament
//! @par synchronize
//! * true blocking call
//! * false non-blocking call
void mmu_load_step(bool synchronize)
{
current_position[E_AXIS] = current_position[E_AXIS] + MMU_LOAD_FEEDRATE * 0.1;
plan_buffer_line(current_position[X_AXIS], current_position[Y_AXIS], current_position[Z_AXIS], current_position[E_AXIS], MMU_LOAD_FEEDRATE, active_extruder);
st_synchronize();
if (synchronize) st_synchronize();
}
//! @brief Is nozzle hot enough to move extruder wheels and do we have idler sensor?
//!
//! Do load steps only if temperature is higher then min. temp for safe extrusion and
//! idler sensor present.
//! Otherwise "cold extrusion prevented" would be send to serial line periodically
//! and watchdog reset will be triggered by lack of keep_alive processing.
//!
//! @retval true temperature is high enough to move extruder
//! @retval false temperature is not high enough to move extruder, turned
//! off E-stepper to prevent over-heating and allow filament pull-out if necessary
bool can_extrude()
{
if ((degHotend(active_extruder) < EXTRUDE_MINTEMP) || !mmu_idler_sensor_detected)
{
disable_e0();
delay_keep_alive(100);
return false;
}
return true;
}
bool mmu_get_response(uint8_t move)
{
mmu_loading_flag = false;
if (!ir_sensor_detected) move = MMU_NO_MOVE;
mmu_loading_flag = false;
printf_P(PSTR("mmu_get_response - begin move:%d\n"), move);
KEEPALIVE_STATE(IN_PROCESS);
while (mmu_cmd != 0)
{
// mmu_loop();
delay_keep_alive(100);
}
while (!mmu_ready)
{
// mmu_loop();
if ((mmu_state != 3) && (mmu_last_cmd == 0))
break;
//Do load steps only if temperature is higher then min. temp for safe extrusion.
//Otherwise "cold extrusion prevented" would be send to serial line periodically
if (degHotend(active_extruder) < EXTRUDE_MINTEMP) {
disable_e0(); //turn off E-stepper to prevent overheating and alow filament pull-out if necessary
delay_keep_alive(100);
continue;
}
switch (move) {
case MMU_LOAD_MOVE:
mmu_loading_flag = true;
mmu_load_step();
case MMU_LOAD_MOVE:
mmu_loading_flag = true;
if (can_extrude()) mmu_load_step();
//don't rely on "ok" signal from mmu unit; if filament detected by idler sensor during loading stop loading movements to prevent infinite loading
if (PIN_GET(IR_SENSOR_PIN) == 0) move = MMU_NO_MOVE;
break;
case MMU_UNLOAD_MOVE:
if (PIN_GET(IR_SENSOR_PIN) == 0) //filament is still detected by idler sensor, printer helps with unlading
{
printf_P(PSTR("Unload 1\n"));
current_position[E_AXIS] = current_position[E_AXIS] - MMU_LOAD_FEEDRATE * MMU_LOAD_TIME_MS*0.001;
plan_buffer_line(current_position[X_AXIS], current_position[Y_AXIS], current_position[Z_AXIS], current_position[E_AXIS], MMU_LOAD_FEEDRATE, active_extruder);
st_synchronize();
if (PIN_GET(MMU_IDLER_SENSOR_PIN) == 0) //filament is still detected by idler sensor, printer helps with unlading
{
if (can_extrude())
{
printf_P(PSTR("Unload 1\n"));
current_position[E_AXIS] = current_position[E_AXIS] - MMU_LOAD_FEEDRATE * MMU_LOAD_TIME_MS*0.001;
plan_buffer_line(current_position[X_AXIS], current_position[Y_AXIS], current_position[Z_AXIS], current_position[E_AXIS], MMU_LOAD_FEEDRATE, active_extruder);
st_synchronize();
}
}
else //filament was unloaded from idler, no additional movements needed
{
@ -492,12 +528,15 @@ bool mmu_get_response(uint8_t move)
}
break;
case MMU_TCODE_MOVE: //first do unload and then continue with infinite loading movements
if (PIN_GET(IR_SENSOR_PIN) == 0) //filament detected by idler sensor, we must unload first
{
printf_P(PSTR("Unload 2\n"));
current_position[E_AXIS] = current_position[E_AXIS] - MMU_LOAD_FEEDRATE * MMU_LOAD_TIME_MS*0.001;
plan_buffer_line(current_position[X_AXIS], current_position[Y_AXIS], current_position[Z_AXIS], current_position[E_AXIS], MMU_LOAD_FEEDRATE, active_extruder);
st_synchronize();
if (PIN_GET(MMU_IDLER_SENSOR_PIN) == 0) //filament detected by idler sensor, we must unload first
{
if (can_extrude())
{
printf_P(PSTR("Unload 2\n"));
current_position[E_AXIS] = current_position[E_AXIS] - MMU_LOAD_FEEDRATE * MMU_LOAD_TIME_MS*0.001;
plan_buffer_line(current_position[X_AXIS], current_position[Y_AXIS], current_position[Z_AXIS], current_position[E_AXIS], MMU_LOAD_FEEDRATE, active_extruder);
st_synchronize();
}
}
else //delay to allow mmu unit to pull out filament from bondtech gears and then start with infinite loading
{
@ -505,6 +544,7 @@ bool mmu_get_response(uint8_t move)
disable_e0(); //turn off E-stepper to prevent overheating and alow filament pull-out if necessary
delay_keep_alive(MMU_LOAD_TIME_MS);
move = MMU_LOAD_MOVE;
printf_P(PSTR("mmu_get_response - begin move:%d\n"), move);
}
break;
case MMU_NO_MOVE:
@ -518,27 +558,20 @@ bool mmu_get_response(uint8_t move)
mmu_ready = false;
// printf_P(PSTR("mmu_get_response - end %d\n"), ret?1:0);
return ret;
/* //waits for "ok" from mmu
//function returns true if "ok" was received
//if timeout is set to true function return false if there is no "ok" received before timeout
bool response = true;
LongTimer mmu_get_reponse_timeout;
KEEPALIVE_STATE(IN_PROCESS);
mmu_get_reponse_timeout.start();
while (mmu_rx_ok() <= 0)
{
delay_keep_alive(100);
if (timeout && mmu_get_reponse_timeout.expired(5 * 60 * 1000ul))
{ //5 minutes timeout
response = false;
break;
}
}
printf_P(PSTR("mmu_get_response - end %d\n"), response?1:0);
return response;*/
}
//! @brief Wait for active extruder to reach temperature set
//!
//! This function is blocking and showing lcd_wait_for_heater() screen
//! which is constantly updated with nozzle temperature.
void mmu_wait_for_heater_blocking()
{
while ((degTargetHotend(active_extruder) - degHotend(active_extruder)) > 5)
{
delay_keep_alive(1000);
lcd_wait_for_heater();
}
}
void manage_response(bool move_axes, bool turn_off_nozzle, uint8_t move)
{
@ -633,11 +666,7 @@ void manage_response(bool move_axes, bool turn_off_nozzle, uint8_t move)
lcd_display_message_fullscreen_P(_i("MMU OK. Resuming temperature..."));
delay_keep_alive(3000);
}
while ((degTargetHotend(active_extruder) - degHotend(active_extruder)) > 5)
{
delay_keep_alive(1000);
lcd_wait_for_heater();
}
mmu_wait_for_heater_blocking();
}
if (move_axes) {
lcd_clear();
@ -751,7 +780,7 @@ void mmu_M600_load_filament(bool automatic)
#endif //MMU_M600_SWITCH_EXTRUDER
}
else {
tmp_extruder = (tmp_extruder+1)%5;
tmp_extruder = ad_getAlternative(tmp_extruder);
}
lcd_update_enable(false);
lcd_clear();
@ -940,7 +969,7 @@ static const E_step ramming_sequence[] PROGMEM =
};
//! @brief Unload sequence to optimize shape of the tip of the unloaded filament
static void filament_ramming()
void mmu_filament_ramming()
{
for(uint8_t i = 0; i < (sizeof(ramming_sequence)/sizeof(E_step));++i)
{
@ -972,7 +1001,7 @@ void extr_unload()
if (mmu_extruder == MMU_FILAMENT_UNKNOWN) lcd_print(" ");
else lcd_print(mmu_extruder + 1);
filament_ramming();
mmu_filament_ramming();
mmu_command(MMU_CMD_U0);
// get response
@ -1366,6 +1395,7 @@ void mmu_continue_loading()
setAllTargetHotends(0);
lcd_setstatuspgm(_i("MMU load failed "));////MSG_RECOVERING_PRINT c=20 r=1
mmu_fil_loaded = false; //so we can retry same T-code again
isPrintPaused = true;
}
}
else { //mmu_ir_sensor_detected == false

View file

@ -1,4 +1,7 @@
//mmu.h
//! @file
#ifndef MMU_H
#define MMU_H
#include <inttypes.h>
@ -71,7 +74,7 @@ extern void mmu_command(uint8_t cmd);
extern bool mmu_get_response(uint8_t move = 0);
extern void manage_response(bool move_axes, bool turn_off_nozzle, uint8_t move = 0);
extern void manage_response(bool move_axes, bool turn_off_nozzle, uint8_t move = MMU_NO_MOVE);
extern void mmu_load_to_nozzle();
@ -119,3 +122,8 @@ extern void mmu_eject_fil_2();
extern void mmu_eject_fil_3();
extern void mmu_eject_fil_4();
extern void mmu_continue_loading();
extern void mmu_filament_ramming();
extern void mmu_wait_for_heater_blocking();
extern void mmu_load_step(bool synchronize = true);
#endif //MMU_H

View file

@ -41,6 +41,15 @@
#include "adc.h"
#include "ConfigurationStore.h"
#include "Timer.h"
#include "Configuration_prusa.h"
extern "C" {
extern void timer02_init(void);
extern void timer02_set_pwm0(uint8_t pwm0);
}
//===========================================================================
//=============================public variables============================
@ -103,15 +112,15 @@ static volatile bool temp_meas_ready = false;
#ifdef PIDTEMP
//static cannot be external:
static float temp_iState[EXTRUDERS] = { 0 };
static float temp_dState[EXTRUDERS] = { 0 };
static float iState_sum[EXTRUDERS] = { 0 };
static float dState_last[EXTRUDERS] = { 0 };
static float pTerm[EXTRUDERS];
static float iTerm[EXTRUDERS];
static float dTerm[EXTRUDERS];
//int output;
static float pid_error[EXTRUDERS];
static float temp_iState_min[EXTRUDERS];
static float temp_iState_max[EXTRUDERS];
static float iState_sum_min[EXTRUDERS];
static float iState_sum_max[EXTRUDERS];
// static float pid_input[EXTRUDERS];
// static float pid_output[EXTRUDERS];
static bool pid_reset[EXTRUDERS];
@ -152,6 +161,8 @@ static volatile bool temp_meas_ready = false;
# define ARRAY_BY_EXTRUDERS(v1, v2, v3) { v1 }
#endif
static ShortTimer oTimer4minTempHeater,oTimer4minTempBed;
// Init min and max temp with extreme values to prevent false errors during startup
static int minttemp_raw[EXTRUDERS] = ARRAY_BY_EXTRUDERS( HEATER_0_RAW_LO_TEMP , HEATER_1_RAW_LO_TEMP , HEATER_2_RAW_LO_TEMP );
static int maxttemp_raw[EXTRUDERS] = ARRAY_BY_EXTRUDERS( HEATER_0_RAW_HI_TEMP , HEATER_1_RAW_HI_TEMP , HEATER_2_RAW_HI_TEMP );
@ -252,6 +263,7 @@ static void temp_runaway_stop(bool isPreheat, bool isBed);
if (extruder<0)
{
soft_pwm_bed = (MAX_BED_POWER)/2;
timer02_set_pwm0(soft_pwm_bed << 1);
bias = d = (MAX_BED_POWER)/2;
}
else
@ -288,7 +300,10 @@ static void temp_runaway_stop(bool isPreheat, bool isBed);
if(millis() - t2 > 5000) {
heating=false;
if (extruder<0)
{
soft_pwm_bed = (bias - d) >> 1;
timer02_set_pwm0(soft_pwm_bed << 1);
}
else
soft_pwm[extruder] = (bias - d) >> 1;
t1=millis();
@ -342,7 +357,10 @@ static void temp_runaway_stop(bool isPreheat, bool isBed);
}
}
if (extruder<0)
{
soft_pwm_bed = (bias + d) >> 1;
timer02_set_pwm0(soft_pwm_bed << 1);
}
else
soft_pwm[extruder] = (bias + d) >> 1;
pid_cycle++;
@ -413,7 +431,7 @@ void updatePID()
{
#ifdef PIDTEMP
for(int e = 0; e < EXTRUDERS; e++) {
temp_iState_max[e] = PID_INTEGRAL_DRIVE_MAX / cs.Ki;
iState_sum_max[e] = PID_INTEGRAL_DRIVE_MAX / cs.Ki;
}
#endif
#ifdef PIDTEMPBED
@ -582,6 +600,12 @@ void checkExtruderAutoFans()
#endif // any extruder auto fan pins set
// ready for eventually parameters adjusting
void resetPID(uint8_t) // only for compiler-warning elimination (if function do nothing)
//void resetPID(uint8_t extruder)
{
}
void manage_heater()
{
#ifdef WATCHDOG
@ -593,9 +617,13 @@ void manage_heater()
if(temp_meas_ready != true) //better readability
return;
// more precisely - this condition partially stabilizes time interval for regulation values evaluation (@ ~ 230ms)
updateTemperaturesFromRawValues();
check_max_temp();
check_min_temp();
#ifdef TEMP_RUNAWAY_BED_HYSTERESIS
temp_runaway_check(0, target_temperature_bed, current_temperature_bed, (int)soft_pwm_bed, true);
#endif
@ -611,38 +639,42 @@ void manage_heater()
pid_input = current_temperature[e];
#ifndef PID_OPENLOOP
pid_error[e] = target_temperature[e] - pid_input;
if(pid_error[e] > PID_FUNCTIONAL_RANGE) {
pid_output = BANG_MAX;
pid_reset[e] = true;
}
else if(pid_error[e] < -PID_FUNCTIONAL_RANGE || target_temperature[e] == 0) {
if(target_temperature[e] == 0) {
pid_output = 0;
pid_reset[e] = true;
}
else {
if(pid_reset[e] == true) {
temp_iState[e] = 0.0;
} else {
pid_error[e] = target_temperature[e] - pid_input;
if(pid_reset[e]) {
iState_sum[e] = 0.0;
dTerm[e] = 0.0; // 'dState_last[e]' initial setting is not necessary (see end of if-statement)
pid_reset[e] = false;
}
#ifndef PonM
pTerm[e] = cs.Kp * pid_error[e];
temp_iState[e] += pid_error[e];
temp_iState[e] = constrain(temp_iState[e], temp_iState_min[e], temp_iState_max[e]);
iTerm[e] = cs.Ki * temp_iState[e];
//K1 defined in Configuration.h in the PID settings
iState_sum[e] += pid_error[e];
iState_sum[e] = constrain(iState_sum[e], iState_sum_min[e], iState_sum_max[e]);
iTerm[e] = cs.Ki * iState_sum[e];
// K1 defined in Configuration.h in the PID settings
#define K2 (1.0-K1)
dTerm[e] = (cs.Kd * (pid_input - temp_dState[e]))*K2 + (K1 * dTerm[e]);
pid_output = pTerm[e] + iTerm[e] - dTerm[e];
dTerm[e] = (cs.Kd * (pid_input - dState_last[e]))*K2 + (K1 * dTerm[e]); // e.g. digital filtration of derivative term changes
pid_output = pTerm[e] + iTerm[e] - dTerm[e]; // subtraction due to "Derivative on Measurement" method (i.e. derivative of input instead derivative of error is used)
if (pid_output > PID_MAX) {
if (pid_error[e] > 0 ) temp_iState[e] -= pid_error[e]; // conditional un-integration
if (pid_error[e] > 0 ) iState_sum[e] -= pid_error[e]; // conditional un-integration
pid_output=PID_MAX;
} else if (pid_output < 0){
if (pid_error[e] < 0 ) temp_iState[e] -= pid_error[e]; // conditional un-integration
} else if (pid_output < 0) {
if (pid_error[e] < 0 ) iState_sum[e] -= pid_error[e]; // conditional un-integration
pid_output=0;
}
#else // PonM ("Proportional on Measurement" method)
iState_sum[e] += cs.Ki * pid_error[e];
iState_sum[e] -= cs.Kp * (pid_input - dState_last[e]);
iState_sum[e] = constrain(iState_sum[e], 0, PID_INTEGRAL_DRIVE_MAX);
dTerm[e] = cs.Kd * (pid_input - dState_last[e]);
pid_output = iState_sum[e] - dTerm[e]; // subtraction due to "Derivative on Measurement" method (i.e. derivative of input instead derivative of error is used)
pid_output = constrain(pid_output, 0, PID_MAX);
#endif // PonM
}
temp_dState[e] = pid_input;
dState_last[e] = pid_input;
#else
pid_output = constrain(target_temperature[e], 0, PID_MAX);
#endif //PID_OPENLOOP
@ -659,7 +691,7 @@ void manage_heater()
SERIAL_ECHO(" iTerm ");
SERIAL_ECHO(iTerm[e]);
SERIAL_ECHO(" dTerm ");
SERIAL_ECHOLN(dTerm[e]);
SERIAL_ECHOLN(-dTerm[e]);
#endif //PID_DEBUG
#else /* PID off */
pid_output = 0;
@ -669,16 +701,12 @@ void manage_heater()
#endif
// Check if temperature is within the correct range
#ifdef AMBIENT_THERMISTOR
if(((current_temperature_ambient < MINTEMP_MINAMBIENT) || (current_temperature[e] > minttemp[e])) && (current_temperature[e] < maxttemp[e]))
#else //AMBIENT_THERMISTOR
if((current_temperature[e] > minttemp[e]) && (current_temperature[e] < maxttemp[e]))
#endif //AMBIENT_THERMISTOR
if((current_temperature[e] < maxttemp[e]) && (target_temperature[e] != 0))
{
soft_pwm[e] = (int)pid_output >> 1;
}
else
{
{
soft_pwm[e] = 0;
}
@ -763,55 +791,61 @@ void manage_heater()
pid_output = constrain(target_temperature_bed, 0, MAX_BED_POWER);
#endif //PID_OPENLOOP
#ifdef AMBIENT_THERMISTOR
if(((current_temperature_bed > BED_MINTEMP) || (current_temperature_ambient < MINTEMP_MINAMBIENT)) && (current_temperature_bed < BED_MAXTEMP))
#else //AMBIENT_THERMISTOR
if((current_temperature_bed > BED_MINTEMP) && (current_temperature_bed < BED_MAXTEMP))
#endif //AMBIENT_THERMISTOR
if(current_temperature_bed < BED_MAXTEMP)
{
soft_pwm_bed = (int)pid_output >> 1;
timer02_set_pwm0(soft_pwm_bed << 1);
}
else {
soft_pwm_bed = 0;
timer02_set_pwm0(soft_pwm_bed << 1);
}
#elif !defined(BED_LIMIT_SWITCHING)
// Check if temperature is within the correct range
if((current_temperature_bed > BED_MINTEMP) && (current_temperature_bed < BED_MAXTEMP))
if(current_temperature_bed < BED_MAXTEMP)
{
if(current_temperature_bed >= target_temperature_bed)
{
soft_pwm_bed = 0;
timer02_set_pwm0(soft_pwm_bed << 1);
}
else
{
soft_pwm_bed = MAX_BED_POWER>>1;
timer02_set_pwm0(soft_pwm_bed << 1);
}
}
else
{
soft_pwm_bed = 0;
timer02_set_pwm0(soft_pwm_bed << 1);
WRITE(HEATER_BED_PIN,LOW);
}
#else //#ifdef BED_LIMIT_SWITCHING
// Check if temperature is within the correct band
if((current_temperature_bed > BED_MINTEMP) && (current_temperature_bed < BED_MAXTEMP))
if(current_temperature_bed < BED_MAXTEMP)
{
if(current_temperature_bed > target_temperature_bed + BED_HYSTERESIS)
{
soft_pwm_bed = 0;
timer02_set_pwm0(soft_pwm_bed << 1);
}
else if(current_temperature_bed <= target_temperature_bed - BED_HYSTERESIS)
{
soft_pwm_bed = MAX_BED_POWER>>1;
timer02_set_pwm0(soft_pwm_bed << 1);
}
}
else
{
soft_pwm_bed = 0;
timer02_set_pwm0(soft_pwm_bed << 1);
WRITE(HEATER_BED_PIN,LOW);
}
#endif
if(target_temperature_bed==0)
soft_pwm_bed = 0;
#endif
#ifdef HOST_KEEPALIVE_FEATURE
@ -983,7 +1017,6 @@ static void updateTemperaturesFromRawValues()
CRITICAL_SECTION_END;
}
void tp_init()
{
#if MB(RUMBA) && ((TEMP_SENSOR_0==-1)||(TEMP_SENSOR_1==-1)||(TEMP_SENSOR_2==-1)||(TEMP_SENSOR_BED==-1))
@ -997,8 +1030,8 @@ void tp_init()
// populate with the first value
maxttemp[e] = maxttemp[0];
#ifdef PIDTEMP
temp_iState_min[e] = 0.0;
temp_iState_max[e] = PID_INTEGRAL_DRIVE_MAX / cs.Ki;
iState_sum_min[e] = 0.0;
iState_sum_max[e] = PID_INTEGRAL_DRIVE_MAX / cs.Ki;
#endif //PIDTEMP
#ifdef PIDTEMPBED
temp_iState_min_bed = 0.0;
@ -1050,10 +1083,12 @@ void tp_init()
adc_init();
timer02_init();
// Use timer0 for temperature measurement
// Interleave temperature interrupt with millies interrupt
OCR0B = 128;
TIMSK0 |= (1<<OCIE0B);
OCR2B = 128;
TIMSK2 |= (1<<OCIE2B);
// Wait for temperature measurement to settle
delay(250);
@ -1361,6 +1396,7 @@ void disable_heater()
#if defined(TEMP_BED_PIN) && TEMP_BED_PIN > -1
target_temperature_bed=0;
soft_pwm_bed=0;
timer02_set_pwm0(soft_pwm_bed << 1);
#if defined(HEATER_BED_PIN) && HEATER_BED_PIN > -1
WRITE(HEATER_BED_PIN,LOW);
#endif
@ -1525,8 +1561,8 @@ void adc_ready(void) //callback from adc when sampling finished
} // extern "C"
// Timer 0 is shared with millies
ISR(TIMER0_COMPB_vect)
// Timer2 (originaly timer0) is shared with millies
ISR(TIMER2_COMPB_vect)
{
static bool _lock = false;
if (_lock) return;
@ -1534,11 +1570,6 @@ ISR(TIMER0_COMPB_vect)
asm("sei");
if (!temp_meas_ready) adc_cycle();
else
{
check_max_temp();
check_min_temp();
}
lcd_buttons_update();
static unsigned char pwm_count = (1 << SOFT_PWM_SCALE);
@ -1598,7 +1629,7 @@ ISR(TIMER0_COMPB_vect)
#endif
#if defined(HEATER_BED_PIN) && HEATER_BED_PIN > -1
soft_pwm_b = soft_pwm_bed;
if(soft_pwm_b > 0) WRITE(HEATER_BED_PIN,1); else WRITE(HEATER_BED_PIN,0);
//if(soft_pwm_b > 0) WRITE(HEATER_BED_PIN,1); else WRITE(HEATER_BED_PIN,0);
#endif
}
#ifdef FAN_SOFT_PWM
@ -1735,7 +1766,7 @@ ISR(TIMER0_COMPB_vect)
state_timer_heater_b = MIN_STATE_TIME;
}
state_heater_b = 1;
WRITE(HEATER_BED_PIN, 1);
//WRITE(HEATER_BED_PIN, 1);
}
} else {
// turn OFF heather only if the minimum time is up
@ -1934,26 +1965,49 @@ void check_min_temp_bed()
void check_min_temp()
{
static bool bCheckingOnHeater=false; // state variable, which allows to short no-checking delay (is set, when temperature is (first time) over heaterMintemp)
static bool bCheckingOnBed=false; // state variable, which allows to short no-checking delay (is set, when temperature is (first time) over bedMintemp)
#ifdef AMBIENT_THERMISTOR
static uint8_t heat_cycles = 0;
if (current_temperature_raw_ambient > OVERSAMPLENR*MINTEMP_MINAMBIENT_RAW)
{
if (READ(HEATER_0_PIN) == HIGH)
{
// if ((heat_cycles % 10) == 0)
// printf_P(PSTR("X%d\n"), heat_cycles);
if (heat_cycles > 50) //reaction time 5-10s
check_min_temp_heater0();
else
heat_cycles++;
}
else
heat_cycles = 0;
return;
}
if(current_temperature_raw_ambient>(OVERSAMPLENR*MINTEMP_MINAMBIENT_RAW)) // thermistor is NTC type, so operator is ">" ;-)
{ // ambient temperature is low
#endif //AMBIENT_THERMISTOR
// *** 'common' part of code for MK2.5 & MK3
// * nozzle checking
if(target_temperature[active_extruder]>minttemp[active_extruder])
{ // ~ nozzle heating is on
bCheckingOnHeater=bCheckingOnHeater||(current_temperature[active_extruder]>=minttemp[active_extruder]); // for eventually delay cutting
if(oTimer4minTempHeater.expired(HEATER_MINTEMP_DELAY)||(!oTimer4minTempHeater.running())||bCheckingOnHeater)
{
bCheckingOnHeater=true; // not necessary
check_min_temp_heater0(); // delay is elapsed or temperature is/was over minTemp => periodical checking is active
}
}
else { // ~ nozzle heating is off
oTimer4minTempHeater.start();
bCheckingOnHeater=false;
}
// * bed checking
if(target_temperature_bed>BED_MINTEMP)
{ // ~ bed heating is on
bCheckingOnBed=bCheckingOnBed||(current_temperature_bed>=BED_MINTEMP); // for eventually delay cutting
if(oTimer4minTempBed.expired(BED_MINTEMP_DELAY)||(!oTimer4minTempBed.running())||bCheckingOnBed)
{
bCheckingOnBed=true; // not necessary
check_min_temp_bed(); // delay is elapsed or temperature is/was over minTemp => periodical checking is active
}
}
else { // ~ bed heating is off
oTimer4minTempBed.start();
bCheckingOnBed=false;
}
// *** end of 'common' part
#ifdef AMBIENT_THERMISTOR
}
else { // ambient temperature is standard
check_min_temp_heater0();
check_min_temp_bed();
}
#endif //AMBIENT_THERMISTOR
check_min_temp_heater0();
check_min_temp_bed();
}
#if (defined(FANCHECK) && defined(TACH_0) && (TACH_0 > -1))

View file

@ -27,8 +27,8 @@
#include "stepper.h"
#endif
#define ENABLE_TEMPERATURE_INTERRUPT() TIMSK0 |= (1<<OCIE0B)
#define DISABLE_TEMPERATURE_INTERRUPT() TIMSK0 &= ~(1<<OCIE0B)
#define ENABLE_TEMPERATURE_INTERRUPT() TIMSK2 |= (1<<OCIE2B)
#define DISABLE_TEMPERATURE_INTERRUPT() TIMSK2 &= ~(1<<OCIE2B)
// public functions
void tp_init(); //initialize the heating
@ -87,6 +87,8 @@ extern int current_voltage_raw_bed;
extern volatile int babystepsTodo[3];
#endif
void resetPID(uint8_t extruder);
inline void babystepsTodoZadd(int n)
{
if (n != 0) {
@ -137,11 +139,15 @@ FORCE_INLINE float degTargetBed() {
FORCE_INLINE void setTargetHotend(const float &celsius, uint8_t extruder) {
target_temperature[extruder] = celsius;
resetPID(extruder);
};
static inline void setTargetHotendSafe(const float &celsius, uint8_t extruder)
{
if (extruder<EXTRUDERS) target_temperature[extruder] = celsius;
if (extruder<EXTRUDERS) {
target_temperature[extruder] = celsius;
resetPID(extruder);
}
}
static inline void setAllTargetHotends(const float &celsius)

103
Firmware/timer02.c Normal file
View file

@ -0,0 +1,103 @@
//timer02.c
// use atmega timer2 as main system timer instead of timer0
// timer0 is used for fast pwm (OC0B output)
// original OVF handler is disabled
#include <avr/io.h>
#include <avr/interrupt.h>
#include <Arduino.h>
uint8_t timer02_pwm0 = 0;
void timer02_set_pwm0(uint8_t pwm0)
{
if (timer02_pwm0 == pwm0) return;
if (pwm0)
{
TCCR0A |= (2 << COM0B0);
OCR0B = pwm0 - 1;
}
else
{
TCCR0A &= ~(2 << COM0B0);
OCR0B = 0;
}
}
void timer02_init(void)
{
//save sreg
uint8_t _sreg = SREG;
//disable interrupts for sure
cli();
//mask timer0 interrupts - disable all
TIMSK0 &= ~(1<<TOIE0);
TIMSK0 &= ~(1<<OCIE0A);
TIMSK0 &= ~(1<<OCIE0B);
//setup timer0
TCCR0A = 0x00; //COM_A-B=00, WGM_0-1=00
TCCR0B = (1 << CS00); //WGM_2=0, CS_0-2=011
//switch timer0 to fast pwm mode
TCCR0A |= (3 << WGM00); //WGM_0-1=11
//set OCR0B register to zero
OCR0B = 0;
//disable OCR0B output (will be enabled in timer02_set_pwm0)
TCCR0A &= ~(2 << COM0B0);
//setup timer2
TCCR2A = 0x00; //COM_A-B=00, WGM_0-1=00
TCCR2B = (3 << CS20); //WGM_2=0, CS_0-2=011
//mask timer2 interrupts - enable OVF, disable others
TIMSK2 |= (1<<TOIE2);
TIMSK2 &= ~(1<<OCIE2A);
TIMSK2 &= ~(1<<OCIE2B);
//set timer2 OCR registers (OCRB interrupt generated 0.5ms after OVF interrupt)
OCR2A = 0;
OCR2B = 128;
//restore sreg (enable interrupts)
SREG = _sreg;
}
//following code is OVF handler for timer 2
//it is copy-paste from wiring.c and modified for timer2
//variables timer0_overflow_count and timer0_millis are declared in wiring.c
// the prescaler is set so that timer0 ticks every 64 clock cycles, and the
// the overflow handler is called every 256 ticks.
#define MICROSECONDS_PER_TIMER0_OVERFLOW (clockCyclesToMicroseconds(64 * 256))
// the whole number of milliseconds per timer0 overflow
#define MILLIS_INC (MICROSECONDS_PER_TIMER0_OVERFLOW / 1000)
// the fractional number of milliseconds per timer0 overflow. we shift right
// by three to fit these numbers into a byte. (for the clock speeds we care
// about - 8 and 16 MHz - this doesn't lose precision.)
#define FRACT_INC ((MICROSECONDS_PER_TIMER0_OVERFLOW % 1000) >> 3)
#define FRACT_MAX (1000 >> 3)
extern volatile unsigned long timer0_overflow_count;
extern volatile unsigned long timer0_millis;
unsigned char timer0_fract = 0;
ISR(TIMER2_OVF_vect)
{
// copy these to local variables so they can be stored in registers
// (volatile variables must be read from memory on every access)
unsigned long m = timer0_millis;
unsigned char f = timer0_fract;
m += MILLIS_INC;
f += FRACT_INC;
if (f >= FRACT_MAX)
{
f -= FRACT_MAX;
m += 1;
}
timer0_fract = f;
timer0_millis = m;
timer0_overflow_count++;
}

View file

@ -163,6 +163,7 @@ static void lcd_selftest_screen_step(int _row, int _col, int _state, const char
static bool lcd_selftest_manual_fan_check(int _fan, bool check_opposite);
static bool lcd_selftest_fan_dialog(int _fan);
static bool lcd_selftest_fsensor();
static bool selftest_irsensor();
static void lcd_selftest_error(int _error_no, const char *_error_1, const char *_error_2);
static void lcd_colorprint_change();
#ifdef SNMM
@ -237,6 +238,8 @@ bool wait_for_unclick;
// float raw_Ki, raw_Kd;
#endif
bool bMain; // flag (i.e. 'fake parameter') for 'lcd_sdcard_menu()' function
const char STR_SEPARATOR[] PROGMEM = "------------";
@ -5886,7 +5889,10 @@ static void lcd_main_menu()
if (!is_usb_printing && (lcd_commands_type != LCD_COMMAND_V2_CAL))
{
//if (farm_mode) MENU_ITEM_SUBMENU_P(MSG_FARM_CARD_MENU, lcd_farm_sdcard_menu);
/*else*/ MENU_ITEM_SUBMENU_P(_T(MSG_CARD_MENU), lcd_sdcard_menu);
/*else*/ {
bMain=true; // flag ('fake parameter') for 'lcd_sdcard_menu()' function
MENU_ITEM_SUBMENU_P(_T(MSG_CARD_MENU), lcd_sdcard_menu);
}
}
#if SDCARDDETECT < 1
MENU_ITEM_GCODE_P(_i("Change SD card"), PSTR("M21")); // SD-card changed by user////MSG_CNG_SDCARD c=0 r=0
@ -5895,6 +5901,7 @@ static void lcd_main_menu()
} else
{
bMain=true; // flag (i.e. 'fake parameter') for 'lcd_sdcard_menu()' function
MENU_ITEM_SUBMENU_P(_i("No SD card"), lcd_sdcard_menu);////MSG_NO_CARD c=0 r=0
#if SDCARDDETECT < 1
MENU_ITEM_GCODE_P(_i("Init. SD card"), PSTR("M21")); // Manually initialize the SD-card via user interface////MSG_INIT_SDCARD c=0 r=0
@ -6227,7 +6234,10 @@ void lcd_sdcard_menu()
MENU_BEGIN();
MENU_ITEM_BACK_P(_T(MSG_MAIN));
if(bMain) // i.e. default menu-item
MENU_ITEM_BACK_P(_T(MSG_MAIN));
else // i.e. menu-item after card insertion
MENU_ITEM_FUNCTION_P(_T(MSG_WATCH),lcd_return_to_status);
card.getWorkDirName();
if (card.filename[0] == '/')
{
@ -6323,28 +6333,24 @@ bool lcd_selftest()
_result = true;
#endif
}
if (_result)
{
_progress = lcd_selftest_screen(3, _progress, 3, true, 1000);
_result = lcd_selfcheck_check_heater(false);
}
if (_result)
{
//current_position[Z_AXIS] += 15; //move Z axis higher to avoid false triggering of Z end stop in case that we are very low - just above heatbed
_progress = lcd_selftest_screen(4, _progress, 3, true, 2000);
_progress = lcd_selftest_screen(3, _progress, 3, true, 2000);
#ifdef TMC2130
_result = lcd_selfcheck_axis_sg(X_AXIS);
_result = lcd_selfcheck_axis_sg(X_AXIS);
#else
_result = lcd_selfcheck_axis(X_AXIS, X_MAX_POS);
_result = lcd_selfcheck_axis(X_AXIS, X_MAX_POS);
#endif //TMC2130
}
if (_result)
{
_progress = lcd_selftest_screen(4, _progress, 3, true, 0);
_progress = lcd_selftest_screen(3, _progress, 3, true, 0);
#ifndef TMC2130
_result = lcd_selfcheck_pulleys(X_AXIS);
@ -6354,7 +6360,7 @@ bool lcd_selftest()
if (_result)
{
_progress = lcd_selftest_screen(5, _progress, 3, true, 1500);
_progress = lcd_selftest_screen(4, _progress, 3, true, 1500);
#ifdef TMC2130
_result = lcd_selfcheck_axis_sg(Y_AXIS);
#else
@ -6364,7 +6370,7 @@ bool lcd_selftest()
if (_result)
{
_progress = lcd_selftest_screen(5, _progress, 3, true, 0);
_progress = lcd_selftest_screen(4, _progress, 3, true, 0);
#ifndef TMC2130
_result = lcd_selfcheck_pulleys(Y_AXIS);
#endif // TMC2130
@ -6385,7 +6391,7 @@ bool lcd_selftest()
current_position[Z_AXIS] = current_position[Z_AXIS] + 10;
plan_buffer_line(current_position[X_AXIS], current_position[Y_AXIS], current_position[Z_AXIS], current_position[3], manual_feedrate[0] / 60, active_extruder);
st_synchronize();
_progress = lcd_selftest_screen(6, _progress, 3, true, 1500);
_progress = lcd_selftest_screen(5, _progress, 3, true, 1500);
_result = lcd_selfcheck_axis(2, Z_MAX_POS);
if (eeprom_read_byte((uint8_t*)EEPROM_WIZARD_ACTIVE) != 1) {
enquecommand_P(PSTR("G28 W"));
@ -6412,25 +6418,46 @@ bool lcd_selftest()
if (_result)
{
_progress = lcd_selftest_screen(7, _progress, 3, true, 2000); //check bed
_progress = lcd_selftest_screen(6, _progress, 3, true, 2000); //check bed
_result = lcd_selfcheck_check_heater(true);
}
if (_result)
{
_progress = lcd_selftest_screen(7, _progress, 3, true, 1000); //check nozzle
_result = lcd_selfcheck_check_heater(false);
}
if (_result)
{
_progress = lcd_selftest_screen(8, _progress, 3, true, 2000); //bed ok
#ifdef PAT9125
if (mmu_enabled == false) {
_progress = lcd_selftest_screen(9, _progress, 3, true, 2000); //check filaments sensor
_result = lcd_selftest_fsensor();
}
_progress = lcd_selftest_screen(8, _progress, 3, true, 2000); //nozzle ok
}
#ifdef FILAMENT_SENSOR
if (_result)
{
if (mmu_enabled)
{
_progress = lcd_selftest_screen(9, _progress, 3, true, 2000); //check filaments sensor
_result = selftest_irsensor();
if (_result)
{
_progress = lcd_selftest_screen(10, _progress, 3, true, 2000); //fil sensor OK
}
} else
{
#ifdef PAT9125
_progress = lcd_selftest_screen(9, _progress, 3, true, 2000); //check filaments sensor
_result = lcd_selftest_fsensor();
if (_result)
{
_progress = lcd_selftest_screen(10, _progress, 3, true, 2000); //fil sensor OK
}
#endif //PAT9125
}
}
#endif //FILAMENT_SENSOR
if (_result)
{
if (mmu_enabled == false)
{
_progress = lcd_selftest_screen(10, _progress, 3, true, 2000); //fil sensor OK
}
#endif // PAT9125
_progress = lcd_selftest_screen(11, _progress, 3, true, 5000); //all correct
}
else
@ -6642,7 +6669,7 @@ static bool lcd_selfcheck_axis(int _axis, int _travel)
}
else
{
_progress = lcd_selftest_screen(4 + _axis, _progress, 3, false, 0);
_progress = lcd_selftest_screen(3 + _axis, _progress, 3, false, 0);
_lcd_refresh = 0;
}
@ -6809,7 +6836,7 @@ static bool lcd_selfcheck_check_heater(bool _isbed)
manage_heater();
manage_inactivity(true);
_progress = (_isbed) ? lcd_selftest_screen(7, _progress, 2, false, 400) : lcd_selftest_screen(3, _progress, 2, false, 400);
_progress = (_isbed) ? lcd_selftest_screen(6, _progress, 2, false, 400) : lcd_selftest_screen(7, _progress, 2, false, 400);
/*if (_isbed) {
MYSERIAL.print("Bed temp:");
MYSERIAL.println(degBed());
@ -6835,9 +6862,10 @@ static bool lcd_selfcheck_check_heater(bool _isbed)
MYSERIAL.print("Opposite result:");
MYSERIAL.println(_opposite_result);
*/
if (_opposite_result < ((_isbed) ? 10 : 3))
if (_opposite_result < ((_isbed) ? 30 : 9))
{
if (_checked_result >= ((_isbed) ? 3 : 10))
if (_checked_result >= ((_isbed) ? 9 : 30))
{
_stepresult = true;
}
@ -6985,6 +7013,70 @@ static bool lcd_selftest_fsensor(void)
}
return (!fsensor_not_responding);
}
//! @brief Self-test of infrared barrier filament sensor mounted on MK3S with MMUv2 printer
//!
//! Test whether sensor is not triggering filament presence when extruder idler is moving without filament.
//!
//! Steps:
//! * Backup current active extruder temperature
//! * Pre-heat to PLA extrude temperature.
//! * Unload filament possibly present.
//! * Move extruder idler same way as during filament load
//! and sample MMU_IDLER_SENSOR_PIN.
//! * Check that pin doesn't go low.
//!
//! @retval true passed
//! @retval false failed
static bool selftest_irsensor()
{
class TempBackup
{
public:
TempBackup():
m_temp(degTargetHotend(active_extruder)),
m_extruder(active_extruder){}
~TempBackup(){setTargetHotend(m_temp,m_extruder);}
private:
float m_temp;
uint8_t m_extruder;
};
uint8_t progress;
{
TempBackup tempBackup;
setTargetHotend(ABS_PREHEAT_HOTEND_TEMP,active_extruder);
mmu_wait_for_heater_blocking();
progress = lcd_selftest_screen(9, 0, 1, true, 0);
mmu_filament_ramming();
}
progress = lcd_selftest_screen(9, progress, 1, true, 0);
mmu_command(MMU_CMD_U0);
manage_response(false, false);
for(uint_least8_t i = 0; i < 200; ++i)
{
if (0 == (i % 32)) progress = lcd_selftest_screen(9, progress, 1, true, 0);
mmu_load_step(false);
while (blocks_queued())
{
if (PIN_GET(MMU_IDLER_SENSOR_PIN) == 0) return false;
#ifdef TMC2130
manage_heater();
// Vojtech: Don't disable motors inside the planner!
if (!tmc2130_update_sg())
{
manage_inactivity(true);
}
#else //TMC2130
manage_heater();
// Vojtech: Don't disable motors inside the planner!
manage_inactivity(true);
#endif //TMC2130
}
}
return true;
}
#endif //FILAMENT_SENSOR
static bool lcd_selftest_manual_fan_check(int _fan, bool check_opposite)
@ -7147,7 +7239,7 @@ static int lcd_selftest_screen(int _step, int _progress, int _progress_scale, bo
lcd_update_enable(false);
int _step_block = 0;
const char *_indicator = (_progress > _progress_scale) ? "-" : "|";
const char *_indicator = (_progress >= _progress_scale) ? "-" : "|";
if (_clear) lcd_clear();
@ -7158,12 +7250,12 @@ static int lcd_selftest_screen(int _step, int _progress, int _progress_scale, bo
if (_step == 0) lcd_puts_P(_T(MSG_SELFTEST_FAN));
if (_step == 1) lcd_puts_P(_T(MSG_SELFTEST_FAN));
if (_step == 2) lcd_puts_P(_i("Checking endstops"));////MSG_SELFTEST_CHECK_ENDSTOPS c=20 r=0
if (_step == 3) lcd_puts_P(_i("Checking hotend "));////MSG_SELFTEST_CHECK_HOTEND c=20 r=0
if (_step == 4) lcd_puts_P(_i("Checking X axis "));////MSG_SELFTEST_CHECK_X c=20 r=0
if (_step == 5) lcd_puts_P(_i("Checking Y axis "));////MSG_SELFTEST_CHECK_Y c=20 r=0
if (_step == 6) lcd_puts_P(_i("Checking Z axis "));////MSG_SELFTEST_CHECK_Z c=20 r=0
if (_step == 7) lcd_puts_P(_T(MSG_SELFTEST_CHECK_BED));
if (_step == 8) lcd_puts_P(_T(MSG_SELFTEST_CHECK_BED));
if (_step == 3) lcd_puts_P(_i("Checking X axis "));////MSG_SELFTEST_CHECK_X c=20 r=0
if (_step == 4) lcd_puts_P(_i("Checking Y axis "));////MSG_SELFTEST_CHECK_Y c=20 r=0
if (_step == 5) lcd_puts_P(_i("Checking Z axis "));////MSG_SELFTEST_CHECK_Z c=20 r=0
if (_step == 6) lcd_puts_P(_T(MSG_SELFTEST_CHECK_BED));
if (_step == 7
|| _step == 8) lcd_puts_P(_i("Checking hotend "));////MSG_SELFTEST_CHECK_HOTEND c=20 r=0
if (_step == 9) lcd_puts_P(_T(MSG_SELFTEST_CHECK_FSENSOR));
if (_step == 10) lcd_puts_P(_T(MSG_SELFTEST_CHECK_FSENSOR));
if (_step == 11) lcd_puts_P(_i("All correct "));////MSG_SELFTEST_CHECK_ALLCORRECT c=20 r=0
@ -7191,26 +7283,27 @@ static int lcd_selftest_screen(int _step, int _progress, int _progress_scale, bo
else if (_step < 9)
{
//SERIAL_ECHOLNPGM("Other tests");
_step_block = 3;
lcd_selftest_screen_step(3, 9, ((_step == _step_block) ? 1 : (_step < _step_block) ? 0 : 2), "Hotend", _indicator);
_step_block = 4;
_step_block = 3;
lcd_selftest_screen_step(2, 2, ((_step == _step_block) ? 1 : (_step < _step_block) ? 0 : 2), "X", _indicator);
_step_block = 5;
_step_block = 4;
lcd_selftest_screen_step(2, 8, ((_step == _step_block) ? 1 : (_step < _step_block) ? 0 : 2), "Y", _indicator);
_step_block = 6;
_step_block = 5;
lcd_selftest_screen_step(2, 14, ((_step == _step_block) ? 1 : (_step < _step_block) ? 0 : 2), "Z", _indicator);
_step_block = 7;
_step_block = 6;
lcd_selftest_screen_step(3, 0, ((_step == _step_block) ? 1 : (_step < _step_block) ? 0 : 2), "Bed", _indicator);
_step_block = 7;
lcd_selftest_screen_step(3, 9, ((_step == _step_block) ? 1 : (_step < _step_block) ? 0 : 2), "Hotend", _indicator);
}
if (_delay > 0) delay_keep_alive(_delay);
_progress++;
return (_progress > _progress_scale * 2) ? 0 : _progress;
return (_progress >= _progress_scale * 2) ? 0 : _progress;
}
static void lcd_selftest_screen_step(int _row, int _col, int _state, const char *_name, const char *_indicator)
@ -7517,7 +7610,9 @@ void menu_lcd_lcdupdate_func(void)
if (lcd_oldcardstatus)
{
card.initsd();
LCD_MESSAGERPGM(_i("Card inserted"));////MSG_SD_INSERTED c=0 r=0
LCD_MESSAGERPGM(_T(WELCOME_MSG));
bMain=false; // flag (i.e. 'fake parameter') for 'lcd_sdcard_menu()' function
menu_submenu(lcd_sdcard_menu);
//get_description();
}
else

View file

@ -1,6 +1,7 @@
#ifndef CONFIGURATION_PRUSA_H
#define CONFIGURATION_PRUSA_H
#include <limits.h>
/*------------------------------------
GENERAL SETTINGS
*------------------------------------*/
@ -102,10 +103,18 @@ EXTRUDER SETTINGS
*------------------------------------*/
// Mintemps
#define HEATER_0_MINTEMP 15
#define HEATER_0_MINTEMP 30
#define HEATER_1_MINTEMP 5
#define HEATER_2_MINTEMP 5
#define BED_MINTEMP 15
#define HEATER_MINTEMP_DELAY 15000 // [ms] ! if changed, check maximal allowed value @ ShortTimer
#if HEATER_MINTEMP_DELAY>USHRT_MAX
#error "Check maximal allowed value @ ShortTimer (see HEATER_MINTEMP_DELAY definition)"
#endif
#define BED_MINTEMP 30
#define BED_MINTEMP_DELAY 50000 // [ms] ! if changed, check maximal allowed value @ ShortTimer
#if BED_MINTEMP_DELAY>USHRT_MAX
#error "Check maximal allowed value @ ShortTimer (see BED_MINTEMP_DELAY definition)"
#endif
// Maxtemps
#if defined(E3D_PT100_EXTRUDER_WITH_AMP) || defined(E3D_PT100_EXTRUDER_NO_AMP)

View file

@ -1,6 +1,7 @@
#ifndef CONFIGURATION_PRUSA_H
#define CONFIGURATION_PRUSA_H
#include <limits.h>
/*------------------------------------
GENERAL SETTINGS
*------------------------------------*/
@ -102,10 +103,18 @@ EXTRUDER SETTINGS
*------------------------------------*/
// Mintemps
#define HEATER_0_MINTEMP 15
#define HEATER_0_MINTEMP 30
#define HEATER_1_MINTEMP 5
#define HEATER_2_MINTEMP 5
#define BED_MINTEMP 15
#define HEATER_MINTEMP_DELAY 15000 // [ms] ! if changed, check maximal allowed value @ ShortTimer
#if HEATER_MINTEMP_DELAY>USHRT_MAX
#error "Check maximal allowed value @ ShortTimer (see HEATER_MINTEMP_DELAY definition)"
#endif
#define BED_MINTEMP 30
#define BED_MINTEMP_DELAY 50000 // [ms] ! if changed, check maximal allowed value @ ShortTimer
#if BED_MINTEMP_DELAY>USHRT_MAX
#error "Check maximal allowed value @ ShortTimer (see BED_MINTEMP_DELAY definition)"
#endif
// Maxtemps
#if defined(E3D_PT100_EXTRUDER_WITH_AMP) || defined(E3D_PT100_EXTRUDER_NO_AMP)

View file

@ -1,6 +1,7 @@
#ifndef CONFIGURATION_PRUSA_H
#define CONFIGURATION_PRUSA_H
#include <limits.h>
/*------------------------------------
GENERAL SETTINGS
*------------------------------------*/
@ -155,10 +156,18 @@
*------------------------------------*/
// Mintemps
#define HEATER_0_MINTEMP 15
#define HEATER_0_MINTEMP 30
#define HEATER_1_MINTEMP 5
#define HEATER_2_MINTEMP 5
#define BED_MINTEMP 15
#define HEATER_MINTEMP_DELAY 15000 // [ms] ! if changed, check maximal allowed value @ ShortTimer
#if HEATER_MINTEMP_DELAY>USHRT_MAX
#error "Check maximal allowed value @ ShortTimer (see HEATER_MINTEMP_DELAY definition)"
#endif
#define BED_MINTEMP 30
#define BED_MINTEMP_DELAY 50000 // [ms] ! if changed, check maximal allowed value @ ShortTimer
#if BED_MINTEMP_DELAY>USHRT_MAX
#error "Check maximal allowed value @ ShortTimer (see BED_MINTEMP_DELAY definition)"
#endif
// Maxtemps
#if defined(E3D_PT100_EXTRUDER_WITH_AMP) || defined(E3D_PT100_EXTRUDER_NO_AMP)

View file

@ -1,6 +1,7 @@
#ifndef CONFIGURATION_PRUSA_H
#define CONFIGURATION_PRUSA_H
#include <limits.h>
/*------------------------------------
GENERAL SETTINGS
*------------------------------------*/
@ -156,10 +157,18 @@
*------------------------------------*/
// Mintemps
#define HEATER_0_MINTEMP 15
#define HEATER_0_MINTEMP 30
#define HEATER_1_MINTEMP 5
#define HEATER_2_MINTEMP 5
#define BED_MINTEMP 15
#define HEATER_MINTEMP_DELAY 15000 // [ms] ! if changed, check maximal allowed value @ ShortTimer
#if HEATER_MINTEMP_DELAY>USHRT_MAX
#error "Check maximal allowed value @ ShortTimer (see HEATER_MINTEMP_DELAY definition)"
#endif
#define BED_MINTEMP 30
#define BED_MINTEMP_DELAY 50000 // [ms] ! if changed, check maximal allowed value @ ShortTimer
#if BED_MINTEMP_DELAY>USHRT_MAX
#error "Check maximal allowed value @ ShortTimer (see BED_MINTEMP_DELAY definition)"
#endif
// Maxtemps
#if defined(E3D_PT100_EXTRUDER_WITH_AMP) || defined(E3D_PT100_EXTRUDER_NO_AMP)

View file

@ -1,6 +1,7 @@
#ifndef CONFIGURATION_PRUSA_H
#define CONFIGURATION_PRUSA_H
#include <limits.h>
/*------------------------------------
GENERAL SETTINGS
*------------------------------------*/
@ -276,7 +277,15 @@
#define HEATER_0_MINTEMP 15
#define HEATER_1_MINTEMP 5
#define HEATER_2_MINTEMP 5
#define HEATER_MINTEMP_DELAY 15000 // [ms] ! if changed, check maximal allowed value @ ShortTimer
#if HEATER_MINTEMP_DELAY>USHRT_MAX
#error "Check maximal allowed value @ ShortTimer (see HEATER_MINTEMP_DELAY definition)"
#endif
#define BED_MINTEMP 15
#define BED_MINTEMP_DELAY 50000 // [ms] ! if changed, check maximal allowed value @ ShortTimer
#if BED_MINTEMP_DELAY>USHRT_MAX
#error "Check maximal allowed value @ ShortTimer (see BED_MINTEMP_DELAY definition)"
#endif
// Maxtemps
#if defined(E3D_PT100_EXTRUDER_WITH_AMP) || defined(E3D_PT100_EXTRUDER_NO_AMP)

View file

@ -20,7 +20,7 @@ The script downloads Arduino with our modifications and Rambo board support inst
a. install `"Arduino Software IDE"` for your preferred operating system
`https://www.arduino.cc -> Software->Downloads`
it is recommended to use older version `"1.6.9"`, as it is used on out build server to produce official builds.
it is recommended to use version `"1.8.5"`, as it is used on out build server to produce official builds.
_note: in the case of persistent compilation problems, check the version of the currently used C/C++ compiler (GCC) - should be `4.8.1`; version can be verified by entering the command
`avr-gcc --version`
if you are not sure where the file is placed (depends on how `"Arduino Software IDE"` was installed), you can use the search feature within the file system_

146
Tests/AutoDeplete_test.cpp Normal file
View file

@ -0,0 +1,146 @@
/**
* @file
* @author Marek Bel
*/
#include "catch.hpp"
#include "../Firmware/AutoDeplete.h"
TEST_CASE( "AutoDeplete test.", "[AutoDeplete]" )
{
CHECK(ad_allDepleted() == false);
CHECK(ad_getAlternative(0) == 0);
CHECK(ad_getAlternative(1) == 1);
CHECK(ad_getAlternative(2) == 2);
CHECK(ad_getAlternative(3) == 3);
CHECK(ad_getAlternative(4) == 4);
ad_markDepleted(1);
CHECK(ad_getAlternative(0) == 0);
CHECK(ad_getAlternative(1) == 2);
CHECK(ad_getAlternative(2) == 2);
CHECK(ad_getAlternative(3) == 3);
CHECK(ad_getAlternative(4) == 4);
CHECK(ad_allDepleted() == false);
ad_markDepleted(3);
CHECK(ad_getAlternative(0) == 0);
CHECK(ad_getAlternative(1) == 2);
CHECK(ad_getAlternative(2) == 2);
CHECK(ad_getAlternative(3) == 4);
CHECK(ad_getAlternative(4) == 4);
CHECK(ad_allDepleted() == false);
ad_markDepleted(4);
CHECK(ad_getAlternative(0) == 0);
CHECK(ad_getAlternative(1) == 2);
CHECK(ad_getAlternative(2) == 2);
CHECK(ad_getAlternative(3) == 0);
CHECK(ad_getAlternative(4) == 0);
CHECK(ad_allDepleted() == false);
ad_markDepleted(4);
CHECK(ad_getAlternative(0) == 0);
CHECK(ad_getAlternative(1) == 2);
CHECK(ad_getAlternative(2) == 2);
CHECK(ad_getAlternative(3) == 0);
CHECK(ad_getAlternative(4) == 0);
CHECK(ad_allDepleted() == false);
ad_markDepleted(0);
CHECK(ad_getAlternative(0) == 2);
CHECK(ad_getAlternative(1) == 2);
CHECK(ad_getAlternative(2) == 2);
CHECK(ad_getAlternative(3) == 2);
CHECK(ad_getAlternative(4) == 2);
CHECK(ad_allDepleted() == false);
ad_markDepleted(2);
CHECK(ad_getAlternative(0) == 0);
CHECK(ad_getAlternative(1) == 1);
CHECK(ad_getAlternative(2) == 2);
CHECK(ad_getAlternative(3) == 3);
CHECK(ad_getAlternative(4) == 4);
CHECK(ad_allDepleted() == true);
ad_markDepleted(2);
CHECK(ad_getAlternative(0) == 0);
CHECK(ad_getAlternative(1) == 1);
CHECK(ad_getAlternative(2) == 2);
CHECK(ad_getAlternative(3) == 3);
CHECK(ad_getAlternative(4) == 4);
CHECK(ad_allDepleted() == true);
ad_markLoaded(4);
CHECK(ad_getAlternative(0) == 4);
CHECK(ad_getAlternative(1) == 4);
CHECK(ad_getAlternative(2) == 4);
CHECK(ad_getAlternative(3) == 4);
CHECK(ad_getAlternative(4) == 4);
CHECK(ad_allDepleted() == false);
ad_markLoaded(0);
CHECK(ad_getAlternative(0) == 0);
CHECK(ad_getAlternative(1) == 4);
CHECK(ad_getAlternative(2) == 4);
CHECK(ad_getAlternative(3) == 4);
CHECK(ad_getAlternative(4) == 4);
CHECK(ad_allDepleted() == false);
ad_markLoaded(3);
CHECK(ad_getAlternative(0) == 0);
CHECK(ad_getAlternative(1) == 3);
CHECK(ad_getAlternative(2) == 3);
CHECK(ad_getAlternative(3) == 3);
CHECK(ad_getAlternative(4) == 4);
CHECK(ad_allDepleted() == false);
ad_markLoaded(3);
CHECK(ad_getAlternative(0) == 0);
CHECK(ad_getAlternative(1) == 3);
CHECK(ad_getAlternative(2) == 3);
CHECK(ad_getAlternative(3) == 3);
CHECK(ad_getAlternative(4) == 4);
CHECK(ad_allDepleted() == false);
ad_markLoaded(2);
CHECK(ad_getAlternative(0) == 0);
CHECK(ad_getAlternative(1) == 2);
CHECK(ad_getAlternative(2) == 2);
CHECK(ad_getAlternative(3) == 3);
CHECK(ad_getAlternative(4) == 4);
CHECK(ad_allDepleted() == false);
ad_markLoaded(1);
CHECK(ad_getAlternative(0) == 0);
CHECK(ad_getAlternative(1) == 1);
CHECK(ad_getAlternative(2) == 2);
CHECK(ad_getAlternative(3) == 3);
CHECK(ad_getAlternative(4) == 4);
CHECK(ad_allDepleted() == false);
ad_markLoaded(1);
CHECK(ad_getAlternative(0) == 0);
CHECK(ad_getAlternative(1) == 1);
CHECK(ad_getAlternative(2) == 2);
CHECK(ad_getAlternative(3) == 3);
CHECK(ad_getAlternative(4) == 4);
CHECK(ad_allDepleted() == false);
}

View file

@ -12,7 +12,7 @@ if [ ! -f "PF-build-env-Linux64-$BUILD_ENV.zip" ]; then
fi
if [ ! -d "../../PF-build-env-$BUILD_ENV" ]; then
unzip PF-build-env-Linux64-$BUILD_ENV.zip -d ../../PF-build-env-$BUILD_ENV || exit 4
unzip -q PF-build-env-Linux64-$BUILD_ENV.zip -d ../../PF-build-env-$BUILD_ENV || exit 4
fi
cd ../../PF-build-env-$BUILD_ENV || exit 5