commit
36a746d7d5
|
@ -98,7 +98,7 @@
|
||||||
#define PID_MAX 255 // limits current to nozzle; 255=full current
|
#define PID_MAX 255 // limits current to nozzle; 255=full current
|
||||||
#ifdef PIDTEMP
|
#ifdef PIDTEMP
|
||||||
//#define PID_DEBUG // Sends debug data to the serial port.
|
//#define PID_DEBUG // Sends debug data to the serial port.
|
||||||
//#define PID_OPENLOOP 1 // Puts PID in open loop. M104 sets the output power in %
|
//#define PID_OPENLOOP 1 // Puts PID in open loop. M104/M140 sets the output power from 0 to PID_MAX
|
||||||
#define PID_INTEGRAL_DRIVE_MAX 255 //limit for the integral term
|
#define PID_INTEGRAL_DRIVE_MAX 255 //limit for the integral term
|
||||||
#define K1 0.95 //smoothing factor withing the PID
|
#define K1 0.95 //smoothing factor withing the PID
|
||||||
#define PID_dT ((16.0 * 8.0)/(F_CPU / 64.0 / 256.0)) //sampling period of the
|
#define PID_dT ((16.0 * 8.0)/(F_CPU / 64.0 / 256.0)) //sampling period of the
|
||||||
|
@ -120,6 +120,44 @@
|
||||||
// #define DEFAULT_Kd 440
|
// #define DEFAULT_Kd 440
|
||||||
#endif // PIDTEMP
|
#endif // PIDTEMP
|
||||||
|
|
||||||
|
// Bed Temperature Control
|
||||||
|
// Select PID or bang-bang with PIDTEMPBED. If bang-bang, BED_LIMIT_SWITCHING will enable hysteresis
|
||||||
|
//
|
||||||
|
// uncomment this to enable PID on the bed. It uses the same ferquency PWM as the extruder.
|
||||||
|
// If your PID_dT above is the default, and correct for your hardware/configuration, that means 7.689Hz,
|
||||||
|
// which is fine for driving a square wave into a resistive load and does not significantly impact you FET heating.
|
||||||
|
// This also works fine on a Fotek SSR-10DA Solid State Relay into a 250W heater.
|
||||||
|
// If your configuration is significantly different than this and you don't understand the issues involved, you proabaly
|
||||||
|
// shouldn't use bed PID until someone else verifies your hardware works.
|
||||||
|
// If this is enabled, find your own PID constants below.
|
||||||
|
//#define PIDTEMPBED
|
||||||
|
//
|
||||||
|
//#define BED_LIMIT_SWITCHING
|
||||||
|
|
||||||
|
// This sets the max power delived to the bed, and replaces the HEATER_BED_DUTY_CYCLE_DIVIDER option.
|
||||||
|
// all forms of bed control obey this (PID, bang-bang, bang-bang with hysteresis)
|
||||||
|
// setting this to anything other than 255 enables a form of PWM to the bed just like HEATER_BED_DUTY_CYCLE_DIVIDER did,
|
||||||
|
// so you shouldn't use it unless you are OK with PWM on your bed. (see the comment on enabling PIDTEMPBED)
|
||||||
|
#define MAX_BED_POWER 255 // limits duty cycle to bed; 255=full current
|
||||||
|
|
||||||
|
#ifdef PIDTEMPBED
|
||||||
|
//120v 250W silicone heater into 4mm borosilicate (MendelMax 1.5+)
|
||||||
|
//from FOPDT model - kp=.39 Tp=405 Tdead=66, Tc set to 79.2, argressive factor of .15 (vs .1, 1, 10)
|
||||||
|
#define DEFAULT_bedKp 10.00
|
||||||
|
#define DEFAULT_bedKi .023
|
||||||
|
#define DEFAULT_bedKd 305.4
|
||||||
|
|
||||||
|
//120v 250W silicone heater into 4mm borosilicate (MendelMax 1.5+)
|
||||||
|
//from pidautotune
|
||||||
|
// #define DEFAULT_bedKp 97.1
|
||||||
|
// #define DEFAULT_bedKi 1.41
|
||||||
|
// #define DEFAULT_bedKd 1675.16
|
||||||
|
|
||||||
|
// FIND YOUR OWN: "M303 E-1 C8 S90" to run autotune on the bed at 90 degreesC for 8 cycles.
|
||||||
|
#endif // PIDTEMPBED
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
//this prevents dangerous Extruder moves, i.e. if the temperature is under the limit
|
//this prevents dangerous Extruder moves, i.e. if the temperature is under the limit
|
||||||
//can be software-disabled for whatever purposes by
|
//can be software-disabled for whatever purposes by
|
||||||
#define PREVENT_DANGEROUS_EXTRUDE
|
#define PREVENT_DANGEROUS_EXTRUDE
|
||||||
|
|
|
@ -5,13 +5,10 @@
|
||||||
//=============================Thermal Settings ============================
|
//=============================Thermal Settings ============================
|
||||||
//===========================================================================
|
//===========================================================================
|
||||||
|
|
||||||
// Select one of these only to define how the bed temp is read.
|
|
||||||
//
|
|
||||||
//#define BED_LIMIT_SWITCHING
|
|
||||||
#ifdef BED_LIMIT_SWITCHING
|
#ifdef BED_LIMIT_SWITCHING
|
||||||
#define BED_HYSTERESIS 2 //only disable heating if T>target+BED_HYSTERESIS and enable heating if T>target-BED_HYSTERESIS
|
#define BED_HYSTERESIS 2 //only disable heating if T>target+BED_HYSTERESIS and enable heating if T>target-BED_HYSTERESIS
|
||||||
#endif
|
#endif
|
||||||
#define BED_CHECK_INTERVAL 5000 //ms
|
#define BED_CHECK_INTERVAL 5000 //ms between checks in bang-bang control
|
||||||
|
|
||||||
//// Heating sanity check:
|
//// Heating sanity check:
|
||||||
// This waits for the watchperiod in milliseconds whenever an M104 or M109 increases the target temperature
|
// This waits for the watchperiod in milliseconds whenever an M104 or M109 increases the target temperature
|
||||||
|
|
|
@ -115,6 +115,7 @@
|
||||||
// M301 - Set PID parameters P I and D
|
// M301 - Set PID parameters P I and D
|
||||||
// M302 - Allow cold extrudes
|
// M302 - Allow cold extrudes
|
||||||
// M303 - PID relay autotune S<temperature> sets the target temperature. (default target temperature = 150C)
|
// M303 - PID relay autotune S<temperature> sets the target temperature. (default target temperature = 150C)
|
||||||
|
// M304 - Set bed PID parameters P I and D
|
||||||
// M400 - Finish all moves
|
// M400 - Finish all moves
|
||||||
// M500 - stores paramters in EEPROM
|
// M500 - stores paramters in EEPROM
|
||||||
// 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).
|
||||||
|
@ -986,10 +987,13 @@ void process_commands()
|
||||||
SERIAL_ERROR_START;
|
SERIAL_ERROR_START;
|
||||||
SERIAL_ERRORLNPGM(MSG_ERR_NO_THERMISTORS);
|
SERIAL_ERRORLNPGM(MSG_ERR_NO_THERMISTORS);
|
||||||
#endif
|
#endif
|
||||||
#ifdef PIDTEMP
|
|
||||||
SERIAL_PROTOCOLPGM(" @:");
|
SERIAL_PROTOCOLPGM(" @:");
|
||||||
SERIAL_PROTOCOL(getHeaterPower(tmp_extruder));
|
SERIAL_PROTOCOL(getHeaterPower(tmp_extruder));
|
||||||
#endif
|
|
||||||
|
SERIAL_PROTOCOLPGM(" B@:");
|
||||||
|
SERIAL_PROTOCOL(getHeaterPower(-1));
|
||||||
|
|
||||||
SERIAL_PROTOCOLLN("");
|
SERIAL_PROTOCOLLN("");
|
||||||
return;
|
return;
|
||||||
break;
|
break;
|
||||||
|
@ -1386,6 +1390,24 @@ void process_commands()
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
#endif //PIDTEMP
|
#endif //PIDTEMP
|
||||||
|
#ifdef PIDTEMPBED
|
||||||
|
case 304: // M304
|
||||||
|
{
|
||||||
|
if(code_seen('P')) bedKp = code_value();
|
||||||
|
if(code_seen('I')) bedKi = code_value()*PID_dT;
|
||||||
|
if(code_seen('D')) bedKd = code_value()/PID_dT;
|
||||||
|
updatePID();
|
||||||
|
SERIAL_PROTOCOL(MSG_OK);
|
||||||
|
SERIAL_PROTOCOL(" p:");
|
||||||
|
SERIAL_PROTOCOL(Kp);
|
||||||
|
SERIAL_PROTOCOL(" i:");
|
||||||
|
SERIAL_PROTOCOL(Ki/PID_dT);
|
||||||
|
SERIAL_PROTOCOL(" d:");
|
||||||
|
SERIAL_PROTOCOL(Kd*PID_dT);
|
||||||
|
SERIAL_PROTOCOLLN("");
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
#endif //PIDTEMP
|
||||||
case 240: // M240 Triggers a camera by emulating a Canon RC-1 : http://www.doc-diy.net/photo/rc-1_hacked/
|
case 240: // M240 Triggers a camera by emulating a Canon RC-1 : http://www.doc-diy.net/photo/rc-1_hacked/
|
||||||
{
|
{
|
||||||
#ifdef PHOTOGRAPH_PIN
|
#ifdef PHOTOGRAPH_PIN
|
||||||
|
@ -1418,8 +1440,14 @@ void process_commands()
|
||||||
case 303: // M303 PID autotune
|
case 303: // M303 PID autotune
|
||||||
{
|
{
|
||||||
float temp = 150.0;
|
float temp = 150.0;
|
||||||
|
int e=0;
|
||||||
|
int c=5;
|
||||||
|
if (code_seen('E')) e=code_value();
|
||||||
|
if (e<0)
|
||||||
|
temp=70;
|
||||||
if (code_seen('S')) temp=code_value();
|
if (code_seen('S')) temp=code_value();
|
||||||
PID_autotune(temp);
|
if (code_seen('C')) c=code_value();
|
||||||
|
PID_autotune(temp, e, c);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 400: // M400 finish all moves
|
case 400: // M400 finish all moves
|
||||||
|
|
|
@ -58,15 +58,21 @@ int current_raw_bed = 0;
|
||||||
#endif
|
#endif
|
||||||
#endif //PIDTEMP
|
#endif //PIDTEMP
|
||||||
|
|
||||||
|
#ifdef PIDTEMPBED
|
||||||
|
// used external
|
||||||
|
float pid_setpoint_bed = { 0.0 };
|
||||||
|
|
||||||
|
float bedKp=DEFAULT_bedKp;
|
||||||
|
float bedKi=(DEFAULT_bedKi*PID_dT);
|
||||||
|
float bedKd=(DEFAULT_bedKd/PID_dT);
|
||||||
|
#endif //PIDTEMPBED
|
||||||
|
|
||||||
|
|
||||||
//===========================================================================
|
//===========================================================================
|
||||||
//=============================private variables============================
|
//=============================private variables============================
|
||||||
//===========================================================================
|
//===========================================================================
|
||||||
static volatile bool temp_meas_ready = false;
|
static volatile bool temp_meas_ready = false;
|
||||||
|
|
||||||
static unsigned long previous_millis_bed_heater;
|
|
||||||
//static unsigned long previous_millis_heater;
|
|
||||||
|
|
||||||
#ifdef PIDTEMP
|
#ifdef PIDTEMP
|
||||||
//static cannot be external:
|
//static cannot be external:
|
||||||
static float temp_iState[EXTRUDERS] = { 0 };
|
static float temp_iState[EXTRUDERS] = { 0 };
|
||||||
|
@ -82,7 +88,22 @@ static unsigned long previous_millis_bed_heater;
|
||||||
// static float pid_output[EXTRUDERS];
|
// static float pid_output[EXTRUDERS];
|
||||||
static bool pid_reset[EXTRUDERS];
|
static bool pid_reset[EXTRUDERS];
|
||||||
#endif //PIDTEMP
|
#endif //PIDTEMP
|
||||||
|
#ifdef PIDTEMPBED
|
||||||
|
//static cannot be external:
|
||||||
|
static float temp_iState_bed = { 0 };
|
||||||
|
static float temp_dState_bed = { 0 };
|
||||||
|
static float pTerm_bed;
|
||||||
|
static float iTerm_bed;
|
||||||
|
static float dTerm_bed;
|
||||||
|
//int output;
|
||||||
|
static float pid_error_bed;
|
||||||
|
static float temp_iState_min_bed;
|
||||||
|
static float temp_iState_max_bed;
|
||||||
|
#else //PIDTEMPBED
|
||||||
|
static unsigned long previous_millis_bed_heater;
|
||||||
|
#endif //PIDTEMPBED
|
||||||
static unsigned char soft_pwm[EXTRUDERS];
|
static unsigned char soft_pwm[EXTRUDERS];
|
||||||
|
static unsigned char soft_pwm_bed;
|
||||||
|
|
||||||
#ifdef WATCHPERIOD
|
#ifdef WATCHPERIOD
|
||||||
int watch_raw[EXTRUDERS] = { -1000 }; // the first value used for all
|
int watch_raw[EXTRUDERS] = { -1000 }; // the first value used for all
|
||||||
|
@ -122,7 +143,7 @@ static unsigned long previous_millis_bed_heater;
|
||||||
//============================= functions ============================
|
//============================= functions ============================
|
||||||
//===========================================================================
|
//===========================================================================
|
||||||
|
|
||||||
void PID_autotune(float temp)
|
void PID_autotune(float temp, int extruder, int ncycles)
|
||||||
{
|
{
|
||||||
float input;
|
float input;
|
||||||
int cycles=0;
|
int cycles=0;
|
||||||
|
@ -134,17 +155,37 @@ void PID_autotune(float temp)
|
||||||
long t_high;
|
long t_high;
|
||||||
long t_low;
|
long t_low;
|
||||||
|
|
||||||
long bias=PID_MAX/2;
|
long bias, d;
|
||||||
long d = PID_MAX/2;
|
|
||||||
float Ku, Tu;
|
float Ku, Tu;
|
||||||
float Kp, Ki, Kd;
|
float Kp, Ki, Kd;
|
||||||
float max, min;
|
float max, min;
|
||||||
|
|
||||||
|
if ((extruder > EXTRUDERS)
|
||||||
|
#if (TEMP_BED_PIN <= -1)
|
||||||
|
||(extruder < 0)
|
||||||
|
#endif
|
||||||
|
){
|
||||||
|
SERIAL_ECHOLN("PID Autotune failed. Bad extruder number.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
SERIAL_ECHOLN("PID Autotune start");
|
SERIAL_ECHOLN("PID Autotune start");
|
||||||
|
|
||||||
disable_heater(); // switch off all heaters.
|
disable_heater(); // switch off all heaters.
|
||||||
|
|
||||||
soft_pwm[0] = PID_MAX/2;
|
if (extruder<0)
|
||||||
|
{
|
||||||
|
soft_pwm_bed = (MAX_BED_POWER)/2;
|
||||||
|
bias = d = (MAX_BED_POWER)/2;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
soft_pwm[extruder] = (PID_MAX)/2;
|
||||||
|
bias = d = (PID_MAX)/2;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
for(;;) {
|
for(;;) {
|
||||||
|
|
||||||
|
@ -152,14 +193,17 @@ void PID_autotune(float temp)
|
||||||
CRITICAL_SECTION_START;
|
CRITICAL_SECTION_START;
|
||||||
temp_meas_ready = false;
|
temp_meas_ready = false;
|
||||||
CRITICAL_SECTION_END;
|
CRITICAL_SECTION_END;
|
||||||
input = analog2temp(current_raw[0], 0);
|
input = (extruder<0)?analog2tempBed(current_raw_bed):analog2temp(current_raw[extruder], extruder);
|
||||||
|
|
||||||
max=max(max,input);
|
max=max(max,input);
|
||||||
min=min(min,input);
|
min=min(min,input);
|
||||||
if(heating == true && input > temp) {
|
if(heating == true && input > temp) {
|
||||||
if(millis() - t2 > 5000) {
|
if(millis() - t2 > 5000) {
|
||||||
heating=false;
|
heating=false;
|
||||||
soft_pwm[0] = (bias - d) >> 1;
|
if (extruder<0)
|
||||||
|
soft_pwm_bed = (bias - d) >> 1;
|
||||||
|
else
|
||||||
|
soft_pwm[extruder] = (bias - d) >> 1;
|
||||||
t1=millis();
|
t1=millis();
|
||||||
t_high=t1 - t2;
|
t_high=t1 - t2;
|
||||||
max=temp;
|
max=temp;
|
||||||
|
@ -172,8 +216,8 @@ void PID_autotune(float temp)
|
||||||
t_low=t2 - t1;
|
t_low=t2 - t1;
|
||||||
if(cycles > 0) {
|
if(cycles > 0) {
|
||||||
bias += (d*(t_high - t_low))/(t_low + t_high);
|
bias += (d*(t_high - t_low))/(t_low + t_high);
|
||||||
bias = constrain(bias, 20 ,PID_MAX-20);
|
bias = constrain(bias, 20 ,(extruder<0?(MAX_BED_POWER):(PID_MAX))-20);
|
||||||
if(bias > PID_MAX/2) d = PID_MAX - 1 - bias;
|
if(bias > (extruder<0?(MAX_BED_POWER):(PID_MAX))/2) d = (extruder<0?(MAX_BED_POWER):(PID_MAX)) - 1 - bias;
|
||||||
else d = bias;
|
else d = bias;
|
||||||
|
|
||||||
SERIAL_PROTOCOLPGM(" bias: "); SERIAL_PROTOCOL(bias);
|
SERIAL_PROTOCOLPGM(" bias: "); SERIAL_PROTOCOL(bias);
|
||||||
|
@ -210,7 +254,10 @@ void PID_autotune(float temp)
|
||||||
*/
|
*/
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
soft_pwm[0] = (bias + d) >> 1;
|
if (extruder<0)
|
||||||
|
soft_pwm_bed = (bias + d) >> 1;
|
||||||
|
else
|
||||||
|
soft_pwm[extruder] = (bias + d) >> 1;
|
||||||
cycles++;
|
cycles++;
|
||||||
min=temp;
|
min=temp;
|
||||||
}
|
}
|
||||||
|
@ -221,17 +268,26 @@ void PID_autotune(float temp)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if(millis() - temp_millis > 2000) {
|
if(millis() - temp_millis > 2000) {
|
||||||
temp_millis = millis();
|
int p;
|
||||||
|
if (extruder<0){
|
||||||
|
p=soft_pwm_bed;
|
||||||
|
SERIAL_PROTOCOLPGM("ok B:");
|
||||||
|
}else{
|
||||||
|
p=soft_pwm[extruder];
|
||||||
SERIAL_PROTOCOLPGM("ok T:");
|
SERIAL_PROTOCOLPGM("ok T:");
|
||||||
SERIAL_PROTOCOL(degHotend(0));
|
}
|
||||||
|
|
||||||
|
SERIAL_PROTOCOL(input);
|
||||||
SERIAL_PROTOCOLPGM(" @:");
|
SERIAL_PROTOCOLPGM(" @:");
|
||||||
SERIAL_PROTOCOLLN(getHeaterPower(0));
|
SERIAL_PROTOCOLLN(p);
|
||||||
|
|
||||||
|
temp_millis = millis();
|
||||||
}
|
}
|
||||||
if(((millis() - t1) + (millis() - t2)) > (10L*60L*1000L*2L)) {
|
if(((millis() - t1) + (millis() - t2)) > (10L*60L*1000L*2L)) {
|
||||||
SERIAL_PROTOCOLLNPGM("PID Autotune failed! timeout");
|
SERIAL_PROTOCOLLNPGM("PID Autotune failed! timeout");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if(cycles > 5) {
|
if(cycles > ncycles) {
|
||||||
SERIAL_PROTOCOLLNPGM("PID Autotune finished ! Place the Kp, Ki and Kd constants in the configuration.h");
|
SERIAL_PROTOCOLLNPGM("PID Autotune finished ! Place the Kp, Ki and Kd constants in the configuration.h");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -246,18 +302,19 @@ void updatePID()
|
||||||
temp_iState_max[e] = PID_INTEGRAL_DRIVE_MAX / Ki;
|
temp_iState_max[e] = PID_INTEGRAL_DRIVE_MAX / Ki;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
#ifdef PIDTEMPBED
|
||||||
|
temp_iState_max_bed = PID_INTEGRAL_DRIVE_MAX / bedKi;
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
int getHeaterPower(int heater) {
|
int getHeaterPower(int heater) {
|
||||||
|
if (heater<0)
|
||||||
|
return soft_pwm_bed;
|
||||||
return soft_pwm[heater];
|
return soft_pwm[heater];
|
||||||
}
|
}
|
||||||
|
|
||||||
void manage_heater()
|
void manage_heater()
|
||||||
{
|
{
|
||||||
#ifdef HEATER_BED_DUTY_CYCLE_DIVIDER
|
|
||||||
static int bed_needs_heating=0;
|
|
||||||
static int bed_is_on=0;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef USE_WATCHDOG
|
#ifdef USE_WATCHDOG
|
||||||
wd_reset();
|
wd_reset();
|
||||||
|
@ -298,12 +355,16 @@ void manage_heater()
|
||||||
temp_iState[e] += pid_error[e];
|
temp_iState[e] += pid_error[e];
|
||||||
temp_iState[e] = constrain(temp_iState[e], temp_iState_min[e], temp_iState_max[e]);
|
temp_iState[e] = constrain(temp_iState[e], temp_iState_min[e], temp_iState_max[e]);
|
||||||
iTerm[e] = Ki * temp_iState[e];
|
iTerm[e] = Ki * temp_iState[e];
|
||||||
|
|
||||||
//K1 defined in Configuration.h in the PID settings
|
//K1 defined in Configuration.h in the PID settings
|
||||||
#define K2 (1.0-K1)
|
#define K2 (1.0-K1)
|
||||||
dTerm[e] = (Kd * (pid_input - temp_dState[e]))*K2 + (K1 * dTerm[e]);
|
dTerm[e] = (Kd * (pid_input - temp_dState[e]))*K2 + (K1 * dTerm[e]);
|
||||||
temp_dState[e] = pid_input;
|
temp_dState[e] = pid_input;
|
||||||
|
|
||||||
pid_output = constrain(pTerm[e] + iTerm[e] - dTerm[e], 0, PID_MAX);
|
pid_output = constrain(pTerm[e] + iTerm[e] - dTerm[e], 0, PID_MAX);
|
||||||
}
|
}
|
||||||
|
#else
|
||||||
|
pid_output = constrain(pid_setpoint[e], 0, PID_MAX);
|
||||||
#endif //PID_OPENLOOP
|
#endif //PID_OPENLOOP
|
||||||
#ifdef PID_DEBUG
|
#ifdef PID_DEBUG
|
||||||
SERIAL_ECHOLN(" PIDDEBUG "<<e<<": Input "<<pid_input<<" Output "<<pid_output" pTerm "<<pTerm[e]<<" iTerm "<<iTerm[e]<<" dTerm "<<dTerm[e]);
|
SERIAL_ECHOLN(" PIDDEBUG "<<e<<": Input "<<pid_input<<" Output "<<pid_output" pTerm "<<pTerm[e]<<" iTerm "<<iTerm[e]<<" dTerm "<<dTerm[e]);
|
||||||
|
@ -338,42 +399,58 @@ void manage_heater()
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef HEATER_BED_DUTY_CYCLE_DIVIDER
|
|
||||||
if (bed_needs_heating){
|
|
||||||
if (bed_is_on==0)
|
|
||||||
WRITE(HEATER_BED_PIN,HIGH);
|
|
||||||
if (bed_is_on==1)
|
|
||||||
WRITE(HEATER_BED_PIN,LOW);
|
|
||||||
bed_is_on=(bed_is_on+1) % HEATER_BED_DUTY_CYCLE_DIVIDER;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
#ifndef PIDTEMPBED
|
||||||
if(millis() - previous_millis_bed_heater < BED_CHECK_INTERVAL)
|
if(millis() - previous_millis_bed_heater < BED_CHECK_INTERVAL)
|
||||||
return;
|
return;
|
||||||
previous_millis_bed_heater = millis();
|
previous_millis_bed_heater = millis();
|
||||||
|
#endif
|
||||||
|
|
||||||
#if TEMP_BED_PIN > -1
|
#if TEMP_BED_PIN > -1
|
||||||
|
|
||||||
#ifdef HEATER_BED_DUTY_CYCLE_DIVIDER
|
#ifdef PIDTEMPBED
|
||||||
bed_needs_heating=0;
|
pid_input = analog2tempBed(current_raw_bed);
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifndef BED_LIMIT_SWITCHING
|
#ifndef PID_OPENLOOP
|
||||||
|
pid_error_bed = pid_setpoint_bed - pid_input;
|
||||||
|
pTerm_bed = bedKp * pid_error_bed;
|
||||||
|
temp_iState_bed += pid_error_bed;
|
||||||
|
temp_iState_bed = constrain(temp_iState_bed, temp_iState_min_bed, temp_iState_max_bed);
|
||||||
|
iTerm_bed = bedKi * temp_iState_bed;
|
||||||
|
|
||||||
|
//K1 defined in Configuration.h in the PID settings
|
||||||
|
#define K2 (1.0-K1)
|
||||||
|
dTerm_bed= (bedKd * (pid_input - temp_dState_bed))*K2 + (K1 * dTerm_bed);
|
||||||
|
temp_dState_bed = pid_input;
|
||||||
|
|
||||||
|
pid_output = constrain(pTerm_bed + iTerm_bed - dTerm_bed, 0, MAX_BED_POWER);
|
||||||
|
|
||||||
|
#else
|
||||||
|
pid_output = constrain(pid_setpoint_bed, 0, MAX_BED_POWER);
|
||||||
|
#endif //PID_OPENLOOP
|
||||||
|
|
||||||
|
if((current_raw_bed > bed_minttemp) && (current_raw_bed < bed_maxttemp))
|
||||||
|
{
|
||||||
|
soft_pwm_bed = (int)pid_output >> 1;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
soft_pwm_bed = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
#elif not defined BED_LIMIT_SWITCHING
|
||||||
// Check if temperature is within the correct range
|
// Check if temperature is within the correct range
|
||||||
if((current_raw_bed > bed_minttemp) && (current_raw_bed < bed_maxttemp)) {
|
if((current_raw_bed > bed_minttemp) && (current_raw_bed < bed_maxttemp)) {
|
||||||
if(current_raw_bed >= target_raw_bed)
|
if(current_raw_bed >= target_raw_bed)
|
||||||
{
|
{
|
||||||
WRITE(HEATER_BED_PIN,LOW);
|
soft_pwm_bed = 0;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
#ifdef HEATER_BED_DUTY_CYCLE_DIVIDER
|
soft_pwm_bed = MAX_BED_POWER>>1;
|
||||||
bed_needs_heating=1;
|
|
||||||
#endif
|
|
||||||
WRITE(HEATER_BED_PIN,HIGH);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
soft_pwm_bed = 0;
|
||||||
WRITE(HEATER_BED_PIN,LOW);
|
WRITE(HEATER_BED_PIN,LOW);
|
||||||
}
|
}
|
||||||
#else //#ifdef BED_LIMIT_SWITCHING
|
#else //#ifdef BED_LIMIT_SWITCHING
|
||||||
|
@ -381,18 +458,16 @@ void manage_heater()
|
||||||
if((current_raw_bed > bed_minttemp) && (current_raw_bed < bed_maxttemp)) {
|
if((current_raw_bed > bed_minttemp) && (current_raw_bed < bed_maxttemp)) {
|
||||||
if(current_raw_bed > target_bed_high_temp)
|
if(current_raw_bed > target_bed_high_temp)
|
||||||
{
|
{
|
||||||
WRITE(HEATER_BED_PIN,LOW);
|
soft_pwm_bed = 0;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
if(current_raw_bed <= target_bed_low_temp)
|
if(current_raw_bed <= target_bed_low_temp)
|
||||||
{
|
{
|
||||||
#ifdef HEATER_BED_DUTY_CYCLE_DIVIDER
|
soft_pwm_bed = MAX_BED_POWER>>1;
|
||||||
bed_needs_heating=1;
|
|
||||||
#endif
|
|
||||||
WRITE(HEATER_BED_PIN,HIGH);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
soft_pwm_bed = 0;
|
||||||
WRITE(HEATER_BED_PIN,LOW);
|
WRITE(HEATER_BED_PIN,LOW);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
@ -568,6 +643,10 @@ void tp_init()
|
||||||
temp_iState_min[e] = 0.0;
|
temp_iState_min[e] = 0.0;
|
||||||
temp_iState_max[e] = PID_INTEGRAL_DRIVE_MAX / Ki;
|
temp_iState_max[e] = PID_INTEGRAL_DRIVE_MAX / Ki;
|
||||||
#endif //PIDTEMP
|
#endif //PIDTEMP
|
||||||
|
#ifdef PIDTEMPBED
|
||||||
|
temp_iState_min_bed = 0.0;
|
||||||
|
temp_iState_max_bed = PID_INTEGRAL_DRIVE_MAX / bedKi;
|
||||||
|
#endif //PIDTEMPBED
|
||||||
}
|
}
|
||||||
|
|
||||||
#if (HEATER_0_PIN > -1)
|
#if (HEATER_0_PIN > -1)
|
||||||
|
@ -728,6 +807,7 @@ void disable_heater()
|
||||||
|
|
||||||
#if TEMP_BED_PIN > -1
|
#if TEMP_BED_PIN > -1
|
||||||
target_raw_bed=0;
|
target_raw_bed=0;
|
||||||
|
soft_pwm_bed=0;
|
||||||
#if HEATER_BED_PIN > -1
|
#if HEATER_BED_PIN > -1
|
||||||
WRITE(HEATER_BED_PIN,LOW);
|
WRITE(HEATER_BED_PIN,LOW);
|
||||||
#endif
|
#endif
|
||||||
|
@ -832,6 +912,7 @@ ISR(TIMER0_COMPB_vect)
|
||||||
static unsigned char soft_pwm_0;
|
static unsigned char soft_pwm_0;
|
||||||
static unsigned char soft_pwm_1;
|
static unsigned char soft_pwm_1;
|
||||||
static unsigned char soft_pwm_2;
|
static unsigned char soft_pwm_2;
|
||||||
|
static unsigned char soft_pwm_b;
|
||||||
|
|
||||||
if(pwm_count == 0){
|
if(pwm_count == 0){
|
||||||
soft_pwm_0 = soft_pwm[0];
|
soft_pwm_0 = soft_pwm[0];
|
||||||
|
@ -844,6 +925,10 @@ ISR(TIMER0_COMPB_vect)
|
||||||
soft_pwm_2 = soft_pwm[2];
|
soft_pwm_2 = soft_pwm[2];
|
||||||
if(soft_pwm_2 > 0) WRITE(HEATER_2_PIN,1);
|
if(soft_pwm_2 > 0) WRITE(HEATER_2_PIN,1);
|
||||||
#endif
|
#endif
|
||||||
|
#if HEATER_BED_PIN > -1
|
||||||
|
soft_pwm_b = soft_pwm_bed;
|
||||||
|
if(soft_pwm_b > 0) WRITE(HEATER_BED_PIN,1);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
if(soft_pwm_0 <= pwm_count) WRITE(HEATER_0_PIN,0);
|
if(soft_pwm_0 <= pwm_count) WRITE(HEATER_0_PIN,0);
|
||||||
#if EXTRUDERS > 1
|
#if EXTRUDERS > 1
|
||||||
|
@ -852,6 +937,9 @@ ISR(TIMER0_COMPB_vect)
|
||||||
#if EXTRUDERS > 2
|
#if EXTRUDERS > 2
|
||||||
if(soft_pwm_2 <= pwm_count) WRITE(HEATER_2_PIN,0);
|
if(soft_pwm_2 <= pwm_count) WRITE(HEATER_2_PIN,0);
|
||||||
#endif
|
#endif
|
||||||
|
#if HEATER_BED_PIN > -1
|
||||||
|
if(soft_pwm_b <= pwm_count) WRITE(HEATER_BED_PIN,0);
|
||||||
|
#endif
|
||||||
|
|
||||||
pwm_count++;
|
pwm_count++;
|
||||||
pwm_count &= 0x7f;
|
pwm_count &= 0x7f;
|
||||||
|
|
|
@ -46,11 +46,15 @@ extern int current_raw_bed;
|
||||||
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;
|
|
||||||
|
|
||||||
#ifdef PIDTEMP
|
#ifdef PIDTEMP
|
||||||
|
extern float Kp,Ki,Kd,Kc;
|
||||||
extern float pid_setpoint[EXTRUDERS];
|
extern float pid_setpoint[EXTRUDERS];
|
||||||
#endif
|
#endif
|
||||||
|
#ifdef PIDTEMPBED
|
||||||
|
extern float bedKp,bedKi,bedKd;
|
||||||
|
extern float pid_setpoint_bed;
|
||||||
|
#endif
|
||||||
|
|
||||||
// #ifdef WATCHPERIOD
|
// #ifdef WATCHPERIOD
|
||||||
extern int watch_raw[EXTRUDERS] ;
|
extern int watch_raw[EXTRUDERS] ;
|
||||||
|
@ -88,7 +92,9 @@ FORCE_INLINE void setTargetHotend(const float &celsius, uint8_t extruder) {
|
||||||
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 PIDTEMPBED
|
||||||
|
pid_setpoint_bed = celsius;
|
||||||
|
#elif defined 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);
|
||||||
|
@ -163,7 +169,7 @@ FORCE_INLINE void autotempShutdown(){
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
void PID_autotune(float temp);
|
void PID_autotune(float temp, int extruder, int ncycles);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
222
README.md
222
README.md
|
@ -1,222 +1,22 @@
|
||||||
WARNING:
|
WARNING:
|
||||||
--------
|
--------
|
||||||
THIS IS RELEASE CANDIDATE 2 FOR MARLIN 1.0.0
|
This is an experimental modification to allow PID on your bed heater.
|
||||||
|
|
||||||
The configuration is now split in two files
|
This will run at the same frequency as the main PID loop. Make sure you heater FET or SSR can do this. I use a fotek SSR-10DA and it's fine
|
||||||
Configuration.h for the normal settings
|
|
||||||
Configuration_adv.h for the advanced settings
|
|
||||||
|
|
||||||
Gen7T is not supported.
|
add something like this to you configuration (pulling this branch will get you this
|
||||||
|
|
||||||
Quick Information
|
~~~~~~~~~~~~~~~~~~~~
|
||||||
===================
|
#define PIDTEMPBED
|
||||||
This RepRap firmware is a mashup between <a href="https://github.com/kliment/Sprinter">Sprinter</a>, <a href="https://github.com/simen/grbl/tree">grbl</a> and many original parts.
|
|
||||||
|
|
||||||
Derived from Sprinter and Grbl by Erik van der Zalm.
|
//from FOPDT model - kp=.39 Tp=405 Tdead=66, Tc set to 79.2, argressive factor of .15 (vs .1, 1, 10)
|
||||||
Sprinters lead developers are Kliment and caru.
|
#define DEFAULT_bedKp 10.00
|
||||||
Grbls lead developer is Simen Svale Skogsrud. Sonney Jeon (Chamnit) improved some parts of grbl
|
#define DEFAULT_bedKi .023
|
||||||
A fork by bkubicek for the Ultimaker was merged, and further development was aided by him.
|
#define DEFAULT_bedKd 305.4
|
||||||
Some features have been added by:
|
~~~~~~~~~~~~~~~~~~~~
|
||||||
Lampmaker, Bradley Feldman, and others...
|
|
||||||
|
|
||||||
|
|
||||||
Features:
|
Autotune works for the bed. Give it an "M303 E-1 C8 S90" to run autotune on the bed at 90 degrees for 8 cycles.
|
||||||
|
|
||||||
* Interrupt based movement with real linear acceleration
|
|
||||||
* High steprate
|
|
||||||
* Look ahead (Keep the speed high when possible. High cornering speed)
|
|
||||||
* Interrupt based temperature protection
|
|
||||||
* preliminary support for Matthew Roberts advance algorithm
|
|
||||||
For more info see: http://reprap.org/pipermail/reprap-dev/2011-May/003323.html
|
|
||||||
* Full endstop support
|
|
||||||
* SD Card support
|
|
||||||
* SD Card folders (works in pronterface)
|
|
||||||
* SD Card autostart support
|
|
||||||
* LCD support (ideally 20x4)
|
|
||||||
* LCD menu system for autonomous SD card printing, controlled by an click-encoder.
|
|
||||||
* EEPROM storage of e.g. max-velocity, max-acceleration, and similar variables
|
|
||||||
* many small but handy things originating from bkubicek's fork.
|
|
||||||
* Arc support
|
|
||||||
* Temperature oversampling
|
|
||||||
* Dynamic Temperature setpointing aka "AutoTemp"
|
|
||||||
* Support for QTMarlin, a very beta GUI for PID-tuning and velocity-acceleration testing. https://github.com/bkubicek/QTMarlin
|
|
||||||
* Endstop trigger reporting to the host software.
|
|
||||||
* Updated sdcardlib
|
|
||||||
* Heater power reporting. Useful for PID monitoring.
|
|
||||||
* PID tuning
|
|
||||||
* CoreXY kinematics (www.corexy.com/theory.html)
|
|
||||||
|
|
||||||
The default baudrate is 250000. This baudrate has less jitter and hence errors than the usual 115200 baud, but is less supported by drivers and host-environments.
|
|
||||||
|
|
||||||
|
|
||||||
Differences and additions to the already good Sprinter firmware:
|
|
||||||
================================================================
|
|
||||||
|
|
||||||
*Look-ahead:*
|
|
||||||
|
|
||||||
Marlin has look-ahead. While sprinter has to break and re-accelerate at each corner,
|
|
||||||
lookahead will only decelerate and accelerate to a velocity,
|
|
||||||
so that the change in vectorial velocity magnitude is less than the xy_jerk_velocity.
|
|
||||||
This is only possible, if some future moves are already processed, hence the name.
|
|
||||||
It leads to less over-deposition at corners, especially at flat angles.
|
|
||||||
|
|
||||||
*Arc support:*
|
|
||||||
|
|
||||||
Slic3r can find curves that, although broken into segments, were ment to describe an arc.
|
|
||||||
Marlin is able to print those arcs. The advantage is the firmware can choose the resolution,
|
|
||||||
and can perform the arc with nearly constant velocity, resulting in a nice finish.
|
|
||||||
Also, less serial communication is needed.
|
|
||||||
|
|
||||||
*Temperature Oversampling:*
|
|
||||||
|
|
||||||
To reduce noise and make the PID-differential term more useful, 16 ADC conversion results are averaged.
|
|
||||||
|
|
||||||
*AutoTemp:*
|
|
||||||
|
|
||||||
If your gcode contains a wide spread of extruder velocities, or you realtime change the building speed, the temperature should be changed accordingly.
|
|
||||||
Usually, higher speed requires higher temperature.
|
|
||||||
This can now be performed by the AutoTemp function
|
|
||||||
By calling M109 S<mintemp> T<maxtemp> F<factor> you enter the autotemp mode.
|
|
||||||
|
|
||||||
You can leave it by calling M109 without any F.
|
|
||||||
If active, the maximal extruder stepper rate of all buffered moves will be calculated, and named "maxerate" [steps/sec].
|
|
||||||
The wanted temperature then will be set to t=tempmin+factor*maxerate, while being limited between tempmin and tempmax.
|
|
||||||
If the target temperature is set manually or by gcode to a value less then tempmin, it will be kept without change.
|
|
||||||
Ideally, your gcode can be completely free of temperature controls, apart from a M109 S T F in the start.gcode, and a M109 S0 in the end.gcode.
|
|
||||||
|
|
||||||
*EEPROM:*
|
|
||||||
|
|
||||||
If you know your PID values, the acceleration and max-velocities of your unique machine, you can set them, and finally store them in the EEPROM.
|
|
||||||
After each reboot, it will magically load them from EEPROM, independent what your Configuration.h says.
|
|
||||||
|
|
||||||
*LCD Menu:*
|
|
||||||
|
|
||||||
If your hardware supports it, you can build yourself a LCD-CardReader+Click+encoder combination. It will enable you to realtime tune temperatures,
|
|
||||||
accelerations, velocities, flow rates, select and print files from the SD card, preheat, disable the steppers, and do other fancy stuff.
|
|
||||||
One working hardware is documented here: http://www.thingiverse.com/thing:12663
|
|
||||||
Also, with just a 20x4 or 16x2 display, useful data is shown.
|
|
||||||
|
|
||||||
*SD card folders:*
|
|
||||||
|
|
||||||
If you have an SD card reader attached to your controller, also folders work now. Listing the files in pronterface will show "/path/subpath/file.g".
|
|
||||||
You can write to file in a subfolder by specifying a similar text using small letters in the path.
|
|
||||||
Also, backup copies of various operating systems are hidden, as well as files not ending with ".g".
|
|
||||||
|
|
||||||
*SD card folders:*
|
|
||||||
|
|
||||||
If you place a file auto[0-9].g into the root of the sd card, it will be automatically executed if you boot the printer. The same file will be executed by selecting "Autostart" from the menu.
|
|
||||||
First *0 will be performed, than *1 and so on. That way, you can heat up or even print automatically without user interaction.
|
|
||||||
|
|
||||||
*Endstop trigger reporting:*
|
|
||||||
|
|
||||||
If an endstop is hit while moving towards the endstop, the location at which the firmware thinks that the endstop was triggered is outputed on the serial port.
|
|
||||||
This is useful, because the user gets a warning message.
|
|
||||||
However, also tools like QTMarlin can use this for finding acceptable combinations of velocity+acceleration.
|
|
||||||
|
|
||||||
*Coding paradigm:*
|
|
||||||
|
|
||||||
Not relevant from a user side, but Marlin was split into thematic junks, and has tried to partially enforced private variables.
|
|
||||||
This is intended to make it clearer, what interacts which what, and leads to a higher level of modularization.
|
|
||||||
We think that this is a useful prestep for porting this firmware to e.g. an ARM platform in the future.
|
|
||||||
A lot of RAM (with enabled LCD ~2200 bytes) was saved by storing char []="some message" in Program memory.
|
|
||||||
In the serial communication, a #define based level of abstraction was enforced, so that it is clear that
|
|
||||||
some transfer is information (usually beginning with "echo:"), an error "error:", or just normal protocol,
|
|
||||||
necessary for backwards compatibility.
|
|
||||||
|
|
||||||
*Interrupt based temperature measurements:*
|
|
||||||
|
|
||||||
An interrupt is used to manage ADC conversions, and enforce checking for critical temperatures.
|
|
||||||
This leads to less blocking in the heater management routine.
|
|
||||||
|
|
||||||
|
|
||||||
Non-standard M-Codes, different to an old version of sprinter:
|
|
||||||
==============================================================
|
|
||||||
Movement:
|
|
||||||
|
|
||||||
* G2 - CW ARC
|
|
||||||
* G3 - CCW ARC
|
|
||||||
|
|
||||||
General:
|
|
||||||
|
|
||||||
* M17 - Enable/Power all stepper motors. Compatibility to ReplicatorG.
|
|
||||||
* M18 - Disable all stepper motors; same as M84.Compatibility to ReplicatorG.
|
|
||||||
* M30 - Print time since last M109 or SD card start to serial
|
|
||||||
* M42 - Change pin status via gcode
|
|
||||||
* M80 - Turn on Power Supply
|
|
||||||
* M81 - Turn off Power Supply
|
|
||||||
* M114 - Output current position to serial port
|
|
||||||
* M119 - Output Endstop status to serial port
|
|
||||||
|
|
||||||
Movement variables:
|
|
||||||
|
|
||||||
* M202 - Set max acceleration in units/s^2 for travel moves (M202 X1000 Y1000) Unused in Marlin!!
|
|
||||||
* M203 - Set maximum feedrate that your machine can sustain (M203 X200 Y200 Z300 E10000) in mm/sec
|
|
||||||
* M204 - Set default acceleration: S normal moves T filament only moves (M204 S3000 T7000) im mm/sec^2 also sets minimum segment time in ms (B20000) to prevent buffer underruns and M20 minimum feedrate
|
|
||||||
* M206 - set home offsets. This sets the X,Y,Z coordinates of the endstops (and is added to the {X,Y,Z}_HOME_POS configuration options (and is also added to the coordinates, if any, provided to G82, as with earlier firmware)
|
|
||||||
* M220 - set build speed mulitplying S:factor in percent ; aka "realtime tuneing in the gcode". So you can slow down if you have islands in one height-range, and speed up otherwise.
|
|
||||||
* M221 - set the extrude multiplying S:factor in percent
|
|
||||||
* M400 - Finish all buffered moves.
|
|
||||||
|
|
||||||
Temperature variables:
|
|
||||||
* M301 - Set PID parameters P I and D
|
|
||||||
* M302 - Allow cold extrudes
|
|
||||||
* M303 - PID relay autotune S<temperature> sets the target temperature. (default target temperature = 150C)
|
|
||||||
|
|
||||||
Advance:
|
|
||||||
|
|
||||||
* M200 - Set filament diameter for advance
|
|
||||||
* M205 - advanced settings: minimum travel speed S=while printing T=travel only, B=minimum segment time X= maximum xy jerk, Z=maximum Z jerk
|
|
||||||
|
|
||||||
EEPROM:
|
|
||||||
|
|
||||||
* M500 - stores paramters in EEPROM. This parameters are stored: axis_steps_per_unit, max_feedrate, max_acceleration ,acceleration,retract_acceleration,
|
|
||||||
minimumfeedrate,mintravelfeedrate,minsegmenttime, jerk velocities, PID
|
|
||||||
* 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.
|
|
||||||
* M503 - print the current settings (from memory not from eeprom)
|
|
||||||
|
|
||||||
MISC:
|
|
||||||
|
|
||||||
* M240 - Trigger a camera to take a photograph
|
|
||||||
* M999 - Restart after being stopped by error
|
|
||||||
|
|
||||||
Configuring and compilation:
|
|
||||||
============================
|
|
||||||
|
|
||||||
Install the arduino software IDE/toolset v22
|
|
||||||
http://www.arduino.cc/en/Main/Software
|
|
||||||
|
|
||||||
For gen6 and sanguinololu the Sanguino directory in the Marlin dir needs to be copied to the arduino environment.
|
|
||||||
copy Marlin\sanguino <arduino home>\hardware\Sanguino
|
|
||||||
|
|
||||||
Install Ultimaker's RepG 25 build
|
|
||||||
http://software.ultimaker.com
|
|
||||||
For SD handling and as better substitute (apart from stl manipulation) download
|
|
||||||
the very nice Kliment's printrun/pronterface https://github.com/kliment/Printrun
|
|
||||||
|
|
||||||
Copy the Ultimaker Marlin firmware
|
|
||||||
https://github.com/ErikZalm/Marlin/tree/Marlin_v1
|
|
||||||
(Use the download button)
|
|
||||||
|
|
||||||
Start the arduino IDE.
|
|
||||||
Select Tools -> Board -> Arduino Mega 2560 or your microcontroller
|
|
||||||
Select the correct serial port in Tools ->Serial Port
|
|
||||||
Open Marlin.pde
|
|
||||||
|
|
||||||
Click the Verify/Compile button
|
|
||||||
|
|
||||||
Click the Upload button
|
|
||||||
If all goes well the firmware is uploading
|
|
||||||
|
|
||||||
Start Ultimaker's Custom RepG 25
|
|
||||||
Make sure Show Experimental Profiles is enabled in Preferences
|
|
||||||
Select Sprinter as the Driver
|
|
||||||
|
|
||||||
Press the Connect button.
|
|
||||||
|
|
||||||
KNOWN ISSUES: RepG will display: Unknown: marlin x.y.z
|
|
||||||
|
|
||||||
That's ok. Enjoy Silky Smooth Printing.
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue