From 00674af3a82e6b6b517a12ae3e77803df4f4892d Mon Sep 17 00:00:00 2001 From: Bernhard Kubicek Date: Sat, 5 Nov 2011 14:13:20 +0100 Subject: [PATCH] merge from the branch bkubicek/Marlin/zalmmerge --- Marlin/Configuration.h | 463 ++-- Marlin/{EEPROM.h => EEPROMwrite.h} | 252 +-- Marlin/Makefile | 582 ++--- Marlin/Marlin.h | 165 +- Marlin/Marlin.pde | 2466 ++++++++++----------- Marlin/fastio.h | 10 +- Marlin/lcd.h | 10 - Marlin/lcd.pde | 1 - Marlin/planner.cpp | 18 +- Marlin/planner.h | 182 +- Marlin/stepper.cpp | 2 +- Marlin/stepper.h | 84 +- Marlin/temperature.cpp | 29 +- Marlin/temperature.h | 113 +- Marlin/thermistortables.h | 180 +- Marlin/ultralcd.h | 2 +- Marlin/ultralcd.pde | 3186 ++++++++++++++-------------- README | 64 +- README.md | 69 + merging still needs.txt | 58 + 20 files changed, 4067 insertions(+), 3869 deletions(-) rename Marlin/{EEPROM.h => EEPROMwrite.h} (94%) delete mode 100644 Marlin/lcd.h delete mode 100644 Marlin/lcd.pde create mode 100644 README.md create mode 100644 merging still needs.txt diff --git a/Marlin/Configuration.h b/Marlin/Configuration.h index b8c41301c..0df1ba6fe 100644 --- a/Marlin/Configuration.h +++ b/Marlin/Configuration.h @@ -1,220 +1,243 @@ -#ifndef CONFIGURATION_H -#define CONFIGURATION_H - -//#define DEBUG_STEPS - -// BASIC SETTINGS: select your board type, thermistor type, axis scaling, and endstop configuration - -//// The following define selects which electronics board you have. Please choose the one that matches your setup -// MEGA/RAMPS up to 1.2 = 3, -// RAMPS 1.3 = 33 -// Gen6 = 5, -// Sanguinololu 1.2 and above = 62 -// Ultimaker = 7, -#define MOTHERBOARD 7 -//#define MOTHERBOARD 5 - - -//// Thermistor settings: -// 1 is 100k thermistor -// 2 is 200k thermistor -// 3 is mendel-parts thermistor -// 4 is 10k thermistor -// 5 is ParCan supplied 104GT-2 100K -// 6 is EPCOS 100k -// 7 is 100k Honeywell thermistor 135-104LAG-J01 -#define THERMISTORHEATER_1 3 -#define THERMISTORHEATER_2 3 -#define THERMISTORBED 3 - -//#define HEATER_1_USES_THERMISTOR -//#define HEATER_2_USES_THERMISTOR -#define HEATER_1_USES_AD595 -//#define HEATER_2_USES_AD595 - -// Select one of these only to define how the bed temp is read. -//#define BED_USES_THERMISTOR -//#define BED_USES_AD595 - -#define HEATER_CHECK_INTERVAL 50 -#define BED_CHECK_INTERVAL 5000 - - -//// Endstop Settings -#define ENDSTOPPULLUPS // Comment this out (using // at the start of the line) to disable the endstop pullup resistors -// The pullups are needed if you directly connect a mechanical endswitch between the signal and ground pins. -const bool ENDSTOPS_INVERTING = true; // set to true to invert the logic of the endstops. -// For optos H21LOB set to true, for Mendel-Parts newer optos TCST2103 set to false - -// This determines the communication speed of the printer -//#define BAUDRATE 250000 -#define BAUDRATE 115200 -//#define BAUDRATE 230400 - -// Comment out (using // at the start of the line) to disable SD support: - -// #define ULTRA_LCD //any lcd -#define LCD_WIDTH 16 -#define LCD_HEIGHT 2 - -//#define ULTIPANEL -#ifdef ULTIPANEL - //#define NEWPANEL //enable this if you have a click-encoder panel - #define SDSUPPORT - #define ULTRA_LCD - #define LCD_WIDTH 20 -#define LCD_HEIGHT 4 -#endif - - -//#define SDSUPPORT // Enable SD Card Support in Hardware Console - - - -const int dropsegments=5; //everything with this number of steps will be ignored as move - -//// ADVANCED SETTINGS - to tweak parameters - -#include "thermistortables.h" - -// For Inverting Stepper Enable Pins (Active Low) use 0, Non Inverting (Active High) use 1 -#define X_ENABLE_ON 0 -#define Y_ENABLE_ON 0 -#define Z_ENABLE_ON 0 -#define E_ENABLE_ON 0 - -// Disables axis when it's not being used. -#define DISABLE_X false -#define DISABLE_Y false -#define DISABLE_Z false -#define DISABLE_E false - -// Inverting axis direction -#define INVERT_X_DIR true // for Mendel set to false, for Orca set to true -#define INVERT_Y_DIR false // for Mendel set to true, for Orca set to false -#define INVERT_Z_DIR true // for Mendel set to false, for Orca set to true -#define INVERT_E_DIR false // for direct drive extruder v9 set to true, for geared extruder set to false - -//// ENDSTOP SETTINGS: -// Sets direction of endstops when homing; 1=MAX, -1=MIN -#define X_HOME_DIR -1 -#define Y_HOME_DIR -1 -#define Z_HOME_DIR -1 - -#define min_software_endstops false //If true, axis won't move to coordinates less than zero. -#define max_software_endstops false //If true, axis won't move to coordinates greater than the defined lengths below. -#define X_MAX_LENGTH 210 -#define Y_MAX_LENGTH 210 -#define Z_MAX_LENGTH 210 - -//// MOVEMENT SETTINGS -#define NUM_AXIS 4 // The axis order in all axis related arrays is X, Y, Z, E -//note: on bernhards ultimaker 200 200 12 are working well. -#define HOMING_FEEDRATE {50*60, 50*60, 12*60, 0} // set the homing speeds -//the followint checks if an extrusion is existent in the move. if _not_, the speed of the move is set to the maximum speed. -//!!!!!!Use only if you know that your printer works at the maximum declared speeds. -// works around the skeinforge cool-bug. There all moves are slowed to have a minimum layer time. However slow travel moves= ooze -#define TRAVELING_AT_MAXSPEED -#define AXIS_RELATIVE_MODES {false, false, false, false} - -#define MAX_STEP_FREQUENCY 40000 // Max step frequency for Ultimaker (5000 pps / half step) - -// default settings - -#define DEFAULT_AXIS_STEPS_PER_UNIT {79.87220447,79.87220447,200*8/3,14} // default steps per unit for ultimaker -#define DEFAULT_MAX_FEEDRATE {160*60, 160*60, 10*60, 500000} -#define DEFAULT_MAX_ACCELERATION {9000,9000,150,10000} // X, Y, Z, E maximum start speed for accelerated moves. E default values are good for skeinforge 40+, for older versions raise them a lot. - -#define DEFAULT_ACCELERATION 3000 // X, Y, Z and E max acceleration in mm/s^2 for printing moves -#define DEFAULT_RETRACT_ACCELERATION 7000 // X, Y, Z and E max acceleration in mm/s^2 for r retracts - -#define DEFAULT_MINIMUMFEEDRATE 10 // minimum feedrate -#define DEFAULT_MINTRAVELFEEDRATE 10 - -// minimum time in microseconds that a movement needs to take if the buffer is emptied. Increase this number if you see blobs while printing high speed & high detail. It will slowdown on the detailed stuff. -#define DEFAULT_MINSEGMENTTIME 20000 -#define DEFAULT_XYJERK 30.0*60 -#define DEFAULT_ZJERK 10.0*60 - - -// The watchdog waits for the watchperiod in milliseconds whenever an M104 or M109 increases the target temperature -//this enables the watchdog interrupt. -#define USE_WATCHDOG -//you cannot reboot on a mega2560 due to a bug in he bootloader. Hence, you have to reset manually, and this is done hereby: -#define RESET_MANUAL - -#define WATCHDOG_TIMEOUT 4 - - - -//// Experimental watchdog and minimal temp -// The watchdog waits for the watchperiod in milliseconds whenever an M104 or M109 increases the target temperature -// If the temperature has not increased at the end of that period, the target temperature is set to zero. It can be reset with another M104/M109 -//#define WATCHPERIOD 5000 //5 seconds - -// Actual temperature must be close to target for this long before M109 returns success -//#define TEMP_RESIDENCY_TIME 20 // (seconds) -//#define TEMP_HYSTERESIS 5 // (C°) range of +/- temperatures considered "close" to the target one - -//// The minimal temperature defines the temperature below which the heater will not be enabled -#define MINTEMP 5 -#define BED_MINTEMP 5 - - -// When temperature exceeds max temp, your heater will be switched off. -// This feature exists to protect your hotend from overheating accidentally, but *NOT* from thermistor short/failure! -// You should use MINTEMP for thermistor short/failure protection. -#define MAXTEMP 275 -#define BED_MAXTEMP 150 - -/// PID settings: -// Uncomment the following line to enable PID support. -//#define SMOOTHING -//#define SMOOTHFACTOR 5.0 -//float current_raw_average=0; - -#define PIDTEMP -#ifdef PIDTEMP -//#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_MAX 255 // limits current to nozzle -#define PID_INTEGRAL_DRIVE_MAX 255 -#define PID_dT 0.10 // 100ms sample time -#define DEFAULT_Kp 20.0 -#define DEFAULT_Ki 1.5*PID_dT -#define DEFAULT_Kd 80/PID_dT -#define DEFAULT_Kc 0 -#endif // PIDTEMP - - -// extruder advance constant (s2/mm3) -// -// advance (steps) = STEPS_PER_CUBIC_MM_E * EXTUDER_ADVANCE_K * cubic mm per second ^ 2 -// -// hooke's law says: force = k * distance -// bernoulli's priniciple says: v ^ 2 / 2 + g . h + pressure / density = constant -// so: v ^ 2 is proportional to number of steps we advance the extruder -//#define ADVANCE - -#ifdef ADVANCE -#define EXTRUDER_ADVANCE_K .3 - -#define D_FILAMENT 1.7 -#define STEPS_MM_E 65 -#define EXTRUTION_AREA (0.25 * D_FILAMENT * D_FILAMENT * 3.14159) -#define STEPS_PER_CUBIC_MM_E (axis_steps_per_unit[E_AXIS]/ EXTRUTION_AREA) - -#endif // ADVANCE - -#if defined SDSUPPORT -// The number of linear motions that can be in the plan at any give time. - #define BLOCK_BUFFER_SIZE 16 // SD,LCD,Buttons take more memory, block buffer needs to be smaller -#else - #define BLOCK_BUFFER_SIZE 16 // maximize block buffer -#endif - -#ifdef SIMPLE_LCD - #define BLOCK_BUFFER_SIZE 16 // A little less buffer for just a simple LCD -#endif - -#endif +#ifndef CONFIGURATION_H +#define CONFIGURATION_H + +//#define DEBUG_STEPS + +// BASIC SETTINGS: select your board type, thermistor type, axis scaling, and endstop configuration + +//// The following define selects which electronics board you have. Please choose the one that matches your setup +// MEGA/RAMPS up to 1.2 = 3, +// RAMPS 1.3 = 33 +// Gen6 = 5, +// Sanguinololu 1.2 and above = 62 +// Ultimaker = 7, +#define MOTHERBOARD 7 +//#define MOTHERBOARD 5 + + +//// Thermistor settings: +// 1 is 100k thermistor +// 2 is 200k thermistor +// 3 is mendel-parts thermistor +// 4 is 10k thermistor +// 5 is ParCan supplied 104GT-2 100K +// 6 is EPCOS 100k +// 7 is 100k Honeywell thermistor 135-104LAG-J01 +#define THERMISTORHEATER_1 3 +#define THERMISTORHEATER_2 3 +#define THERMISTORBED 3 + +//#define HEATER_1_USES_THERMISTOR +//#define HEATER_2_USES_THERMISTOR +#define HEATER_1_USES_AD595 +//#define HEATER_2_USES_AD595 + +// Select one of these only to define how the bed temp is read. +//#define BED_USES_THERMISTOR +//#define BED_USES_AD595 + +#define HEATER_CHECK_INTERVAL 50 +#define BED_CHECK_INTERVAL 5000 + + +//// Endstop Settings +#define ENDSTOPPULLUPS // Comment this out (using // at the start of the line) to disable the endstop pullup resistors +// The pullups are needed if you directly connect a mechanical endswitch between the signal and ground pins. +const bool ENDSTOPS_INVERTING = true; // set to true to invert the logic of the endstops. +// For optos H21LOB set to true, for Mendel-Parts newer optos TCST2103 set to false + +// This determines the communication speed of the printer +//#define BAUDRATE 250000 +#define BAUDRATE 115200 +//#define BAUDRATE 230400 + +// Comment out (using // at the start of the line) to disable SD support: + +// #define ULTRA_LCD //any lcd + + +#define ULTIPANEL +#ifdef ULTIPANEL + //#define NEWPANEL //enable this if you have a click-encoder panel + #define SDSUPPORT + #define ULTRA_LCD + #define LCD_WIDTH 20 +#define LCD_HEIGHT 4 +#else //no panel but just lcd + #ifdef ULTRA_LCD + #define LCD_WIDTH 16 + #define LCD_HEIGHT 2 + #endif +#endif + + +//#define SDSUPPORT // Enable SD Card Support in Hardware Console + + + +const int dropsegments=5; //everything with this number of steps will be ignored as move + +//// ADVANCED SETTINGS - to tweak parameters + +#include "thermistortables.h" + +// For Inverting Stepper Enable Pins (Active Low) use 0, Non Inverting (Active High) use 1 +#define X_ENABLE_ON 0 +#define Y_ENABLE_ON 0 +#define Z_ENABLE_ON 0 +#define E_ENABLE_ON 0 + +// Disables axis when it's not being used. +#define DISABLE_X false +#define DISABLE_Y false +#define DISABLE_Z false +#define DISABLE_E false + +// Inverting axis direction +#define INVERT_X_DIR true // for Mendel set to false, for Orca set to true +#define INVERT_Y_DIR false // for Mendel set to true, for Orca set to false +#define INVERT_Z_DIR true // for Mendel set to false, for Orca set to true +#define INVERT_E_DIR false // for direct drive extruder v9 set to true, for geared extruder set to false + +//// ENDSTOP SETTINGS: +// Sets direction of endstops when homing; 1=MAX, -1=MIN +#define X_HOME_DIR -1 +#define Y_HOME_DIR -1 +#define Z_HOME_DIR -1 + +#define min_software_endstops false //If true, axis won't move to coordinates less than zero. +#define max_software_endstops false //If true, axis won't move to coordinates greater than the defined lengths below. +#define X_MAX_LENGTH 210 +#define Y_MAX_LENGTH 210 +#define Z_MAX_LENGTH 210 + +//// MOVEMENT SETTINGS +#define NUM_AXIS 4 // The axis order in all axis related arrays is X, Y, Z, E +//note: on bernhards ultimaker 200 200 12 are working well. +#define HOMING_FEEDRATE {50*60, 50*60, 12*60, 0} // set the homing speeds +//the followint checks if an extrusion is existent in the move. if _not_, the speed of the move is set to the maximum speed. +//!!!!!!Use only if you know that your printer works at the maximum declared speeds. +// works around the skeinforge cool-bug. There all moves are slowed to have a minimum layer time. However slow travel moves= ooze +#define TRAVELING_AT_MAXSPEED +#define AXIS_RELATIVE_MODES {false, false, false, false} + +#define MAX_STEP_FREQUENCY 40000 // Max step frequency for Ultimaker (5000 pps / half step) + +// default settings + +#define DEFAULT_AXIS_STEPS_PER_UNIT {79.87220447,79.87220447,200*8/3,14} // default steps per unit for ultimaker +#define DEFAULT_MAX_FEEDRATE {160*60, 160*60, 10*60, 500000} +#define DEFAULT_MAX_ACCELERATION {9000,9000,150,10000} // X, Y, Z, E maximum start speed for accelerated moves. E default values are good for skeinforge 40+, for older versions raise them a lot. + +#define DEFAULT_ACCELERATION 3000 // X, Y, Z and E max acceleration in mm/s^2 for printing moves +#define DEFAULT_RETRACT_ACCELERATION 7000 // X, Y, Z and E max acceleration in mm/s^2 for r retracts + +#define DEFAULT_MINIMUMFEEDRATE 10 // minimum feedrate +#define DEFAULT_MINTRAVELFEEDRATE 10 + +// minimum time in microseconds that a movement needs to take if the buffer is emptied. Increase this number if you see blobs while printing high speed & high detail. It will slowdown on the detailed stuff. +#define DEFAULT_MINSEGMENTTIME 20000 +#define DEFAULT_XYJERK 30.0*60 +#define DEFAULT_ZJERK 10.0*60 + + +// The watchdog waits for the watchperiod in milliseconds whenever an M104 or M109 increases the target temperature +//this enables the watchdog interrupt. +#define USE_WATCHDOG +//you cannot reboot on a mega2560 due to a bug in he bootloader. Hence, you have to reset manually, and this is done hereby: +#define RESET_MANUAL + +#define WATCHDOG_TIMEOUT 4 + + + +//// Experimental watchdog and minimal temp +// The watchdog waits for the watchperiod in milliseconds whenever an M104 or M109 increases the target temperature +// If the temperature has not increased at the end of that period, the target temperature is set to zero. It can be reset with another M104/M109 +//#define WATCHPERIOD 5000 //5 seconds + +// Actual temperature must be close to target for this long before M109 returns success +//#define TEMP_RESIDENCY_TIME 20 // (seconds) +//#define TEMP_HYSTERESIS 5 // (C°) range of +/- temperatures considered "close" to the target one + +//// The minimal temperature defines the temperature below which the heater will not be enabled +#define MINTEMP 5 +#define BED_MINTEMP 5 + + +// When temperature exceeds max temp, your heater will be switched off. +// This feature exists to protect your hotend from overheating accidentally, but *NOT* from thermistor short/failure! +// You should use MINTEMP for thermistor short/failure protection. +#define MAXTEMP 275 +#define BED_MAXTEMP 150 + + + + + + + +#define PIDTEMP +#ifdef PIDTEMP + /// PID settings: + // Uncomment the following line to enable PID support. + //#define SMOOTHING + //#define SMOOTHFACTOR 5.0 + //float current_raw_average=0; + #define K1 0.95 //smoothing of the PID + //#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_MAX 255 // limits current to nozzle + #define PID_INTEGRAL_DRIVE_MAX 255 + #define PID_dT 0.1 + //machine with red silicon: 1950:45 second ; with fan fully blowin 3000:47 + + #define PID_CRITIAL_GAIN 3000 + #define PID_SWING_AT_CRITIAL 45 //seconds + #define PIDIADD 5 + /* + //PID according to Ziegler-Nichols method + float Kp = 0.6*PID_CRITIAL_GAIN; + float Ki =PIDIADD+2*Kp/PID_SWING_AT_CRITIAL*PID_dT; + float Kd = Kp*PID_SWING_AT_CRITIAL/8./PID_dT; + */ + //PI according to Ziegler-Nichols method + #define DEFAULT_Kp (PID_CRITIAL_GAIN/2.2) + #define DEFAULT_Ki (1.2*Kp/PID_SWING_AT_CRITIAL*PID_dT) + #define DEFAULT_Kd (0) + + #define PID_ADD_EXTRUSION_RATE + #ifdef PID_ADD_EXTRUSION_RATE + #define DEFAULT_Kc (5) //heatingpower=Kc*(e_speed) + #endif +#endif // PIDTEMP + +// extruder advance constant (s2/mm3) +// +// advance (steps) = STEPS_PER_CUBIC_MM_E * EXTUDER_ADVANCE_K * cubic mm per second ^ 2 +// +// hooke's law says: force = k * distance +// bernoulli's priniciple says: v ^ 2 / 2 + g . h + pressure / density = constant +// so: v ^ 2 is proportional to number of steps we advance the extruder +//#define ADVANCE + +#ifdef ADVANCE +#define EXTRUDER_ADVANCE_K .3 + +#define D_FILAMENT 1.7 +#define STEPS_MM_E 65 +#define EXTRUTION_AREA (0.25 * D_FILAMENT * D_FILAMENT * 3.14159) +#define STEPS_PER_CUBIC_MM_E (axis_steps_per_unit[E_AXIS]/ EXTRUTION_AREA) + +#endif // ADVANCE + +// THE BLOCK_BUFFER_SIZE NEEDS TO BE A POWER OF 2, e.g. 8,16,32 +#if defined SDSUPPORT +// The number of linear motions that can be in the plan at any give time. + #define BLOCK_BUFFER_SIZE 16 // SD,LCD,Buttons take more memory, block buffer needs to be smaller +#else + #define BLOCK_BUFFER_SIZE 16 // maximize block buffer +#endif + + +#endif diff --git a/Marlin/EEPROM.h b/Marlin/EEPROMwrite.h similarity index 94% rename from Marlin/EEPROM.h rename to Marlin/EEPROMwrite.h index 0390d94e4..2247e2f52 100644 --- a/Marlin/EEPROM.h +++ b/Marlin/EEPROMwrite.h @@ -1,123 +1,129 @@ - -#include "planner.h" -#include "temperature.h" - -//====================================================================================== -template int EEPROM_writeAnything(int &ee, const T& value) -{ - const byte* p = (const byte*)(const void*)&value; - int i; - for (i = 0; i < sizeof(value); i++) - EEPROM.write(ee++, *p++); - return i; -} -//====================================================================================== -template int EEPROM_readAnything(int &ee, T& value) -{ - byte* p = (byte*)(void*)&value; - int i; - for (i = 0; i < sizeof(value); i++) - *p++ = EEPROM.read(ee++); - return i; -} -//====================================================================================== - -#define EEPROM_OFFSET 100 - -#define EEPROM_VERSION "V04" // IMPORTANT: Whenever there are changes made to the variables stored in EEPROM - // in the functions below, also increment the version number. This makes sure that - // the default values are used whenever there is a change to the data, to prevent - // wrong data being written to the variables. - // ALSO: always make sure the variables in the Store and retrieve sections are in the same order. -void StoreSettings() { - char ver[4]= "000"; - int i=EEPROM_OFFSET; - EEPROM_writeAnything(i,ver); // invalidate data first - EEPROM_writeAnything(i,axis_steps_per_unit); - EEPROM_writeAnything(i,max_feedrate); - EEPROM_writeAnything(i,max_acceleration_units_per_sq_second); - EEPROM_writeAnything(i,acceleration); - EEPROM_writeAnything(i,retract_acceleration); - EEPROM_writeAnything(i,minimumfeedrate); - EEPROM_writeAnything(i,mintravelfeedrate); - EEPROM_writeAnything(i,minsegmenttime); - EEPROM_writeAnything(i,max_xy_jerk); - EEPROM_writeAnything(i,max_z_jerk); - #ifdef PIDTEMP - EEPROM_writeAnything(i,Kp); - EEPROM_writeAnything(i,Ki); - EEPROM_writeAnything(i,Kd); -#else - EEPROM_writeAnything(i,3000); - EEPROM_writeAnything(i,0); - EEPROM_writeAnything(i,0); -#endif - char ver2[4]=EEPROM_VERSION; - i=EEPROM_OFFSET; - EEPROM_writeAnything(i,ver2); // validate data - ECHOLN("Settings Stored"); - -} - -void RetrieveSettings(bool def=false){ // if def=true, the default values will be used - int i=EEPROM_OFFSET; - char stored_ver[4]; - char ver[4]=EEPROM_VERSION; - EEPROM_readAnything(i,stored_ver); //read stored version -// ECHOLN("Version: [" << ver << "] Stored version: [" << stored_ver << "]"); - if ((!def)&&(strncmp(ver,stored_ver,3)==0)) { // version number match - EEPROM_readAnything(i,axis_steps_per_unit); - EEPROM_readAnything(i,max_feedrate); - EEPROM_readAnything(i,max_acceleration_units_per_sq_second); - EEPROM_readAnything(i,acceleration); - EEPROM_readAnything(i,retract_acceleration); - EEPROM_readAnything(i,minimumfeedrate); - EEPROM_readAnything(i,mintravelfeedrate); - EEPROM_readAnything(i,minsegmenttime); - EEPROM_readAnything(i,max_xy_jerk); - EEPROM_readAnything(i,max_z_jerk); -#ifndef PIDTEMP - float Kp,Ki,Kd; -#endif - EEPROM_readAnything(i,Kp); - EEPROM_readAnything(i,Ki); - EEPROM_readAnything(i,Kd); - - ECHOLN("Stored settings retreived:"); - } - else { - float tmp1[]=DEFAULT_AXIS_STEPS_PER_UNIT; - float tmp2[]=DEFAULT_MAX_FEEDRATE; - long tmp3[]=DEFAULT_MAX_ACCELERATION; - for (int i=0;i<4;i++) { - axis_steps_per_unit[i]=tmp1[i]; - max_feedrate[i]=tmp2[i]; - max_acceleration_units_per_sq_second[i]=tmp3[i]; - } - acceleration=DEFAULT_ACCELERATION; - retract_acceleration=DEFAULT_RETRACT_ACCELERATION; - minimumfeedrate=DEFAULT_MINIMUMFEEDRATE; - minsegmenttime=DEFAULT_MINSEGMENTTIME; - mintravelfeedrate=DEFAULT_MINTRAVELFEEDRATE; - max_xy_jerk=DEFAULT_XYJERK; - max_z_jerk=DEFAULT_ZJERK; - ECHOLN("Using Default settings:"); - } - ECHOLN("Steps per unit:"); - ECHOLN(" M92 X" <<_FLOAT(axis_steps_per_unit[0],3) << " Y" << _FLOAT(axis_steps_per_unit[1],3) << " Z" << _FLOAT(axis_steps_per_unit[2],3) << " E" << _FLOAT(axis_steps_per_unit[3],3)); - ECHOLN("Maximum feedrates (mm/s):"); - ECHOLN(" M203 X" <<_FLOAT(max_feedrate[0]/60,2)<<" Y" << _FLOAT(max_feedrate[1]/60,2) << " Z" << _FLOAT(max_feedrate[2]/60,2) << " E" << _FLOAT(max_feedrate[3]/60,2)); - ECHOLN("Maximum Acceleration (mm/s2):"); - ECHOLN(" M201 X" <<_FLOAT(max_acceleration_units_per_sq_second[0],0) << " Y" << _FLOAT(max_acceleration_units_per_sq_second[1],0) << " Z" << _FLOAT(max_acceleration_units_per_sq_second[2],0) << " E" << _FLOAT(max_acceleration_units_per_sq_second[3],0)); - ECHOLN("Acceleration: S=acceleration, T=retract acceleration"); - ECHOLN(" M204 S" <<_FLOAT(acceleration,2) << " T" << _FLOAT(retract_acceleration,2)); - ECHOLN("Advanced variables: S=Min feedrate (mm/s), T=Min travel feedrate (mm/s), B=minimum segment time (ms), X=maximum xY jerk (mm/s), Z=maximum Z jerk (mm/s)"); - ECHOLN(" M205 S" <<_FLOAT(minimumfeedrate/60,2) << " T" << _FLOAT(mintravelfeedrate/60,2) << " B" << _FLOAT(minsegmenttime,2) << " X" << _FLOAT(max_xy_jerk/60,2) << " Z" << _FLOAT(max_z_jerk/60,2)); -#ifdef PIDTEMP - ECHOLN("PID settings:"); - ECHOLN(" M301 P" << _FLOAT(Kp,3) << " I" << _FLOAT(Ki,3) << " D" << _FLOAT(Kd,3)); -#endif - -} - - +#ifndef __EEPROMH +#define __EEPROMH +#include "planner.h" +#include "temperature.h" +#include +#include "Marlin.h" +#include "streaming.h" + +//====================================================================================== +template int EEPROM_writeAnything(int &ee, const T& value) +{ + const byte* p = (const byte*)(const void*)&value; + int i; + for (i = 0; i < (int)sizeof(value); i++) + EEPROM.write(ee++, *p++); + return i; +} +//====================================================================================== +template int EEPROM_readAnything(int &ee, T& value) +{ + byte* p = (byte*)(void*)&value; + int i; + for (i = 0; i < (int)sizeof(value); i++) + *p++ = EEPROM.read(ee++); + return i; +} +//====================================================================================== + +#define EEPROM_OFFSET 100 + +#define EEPROM_VERSION "V04" // IMPORTANT: Whenever there are changes made to the variables stored in EEPROM + // in the functions below, also increment the version number. This makes sure that + // the default values are used whenever there is a change to the data, to prevent + // wrong data being written to the variables. + // ALSO: always make sure the variables in the Store and retrieve sections are in the same order. +void StoreSettings() { + char ver[4]= "000"; + int i=EEPROM_OFFSET; + EEPROM_writeAnything(i,ver); // invalidate data first + EEPROM_writeAnything(i,axis_steps_per_unit); + EEPROM_writeAnything(i,max_feedrate); + EEPROM_writeAnything(i,max_acceleration_units_per_sq_second); + EEPROM_writeAnything(i,acceleration); + EEPROM_writeAnything(i,retract_acceleration); + EEPROM_writeAnything(i,minimumfeedrate); + EEPROM_writeAnything(i,mintravelfeedrate); + EEPROM_writeAnything(i,minsegmenttime); + EEPROM_writeAnything(i,max_xy_jerk); + EEPROM_writeAnything(i,max_z_jerk); + #ifdef PIDTEMP + EEPROM_writeAnything(i,Kp); + EEPROM_writeAnything(i,Ki); + EEPROM_writeAnything(i,Kd); +#else + EEPROM_writeAnything(i,3000); + EEPROM_writeAnything(i,0); + EEPROM_writeAnything(i,0); +#endif + char ver2[4]=EEPROM_VERSION; + i=EEPROM_OFFSET; + EEPROM_writeAnything(i,ver2); // validate data + ECHOLN("Settings Stored"); + +} + +void RetrieveSettings(bool def=false){ // if def=true, the default values will be used + int i=EEPROM_OFFSET; + char stored_ver[4]; + char ver[4]=EEPROM_VERSION; + EEPROM_readAnything(i,stored_ver); //read stored version +// ECHOLN("Version: [" << ver << "] Stored version: [" << stored_ver << "]"); + if ((!def)&&(strncmp(ver,stored_ver,3)==0)) { // version number match + EEPROM_readAnything(i,axis_steps_per_unit); + EEPROM_readAnything(i,max_feedrate); + EEPROM_readAnything(i,max_acceleration_units_per_sq_second); + EEPROM_readAnything(i,acceleration); + EEPROM_readAnything(i,retract_acceleration); + EEPROM_readAnything(i,minimumfeedrate); + EEPROM_readAnything(i,mintravelfeedrate); + EEPROM_readAnything(i,minsegmenttime); + EEPROM_readAnything(i,max_xy_jerk); + EEPROM_readAnything(i,max_z_jerk); +#ifndef PIDTEMP + float Kp,Ki,Kd; +#endif + EEPROM_readAnything(i,Kp); + EEPROM_readAnything(i,Ki); + EEPROM_readAnything(i,Kd); + + ECHOLN("Stored settings retreived:"); + } + else { + float tmp1[]=DEFAULT_AXIS_STEPS_PER_UNIT; + float tmp2[]=DEFAULT_MAX_FEEDRATE; + long tmp3[]=DEFAULT_MAX_ACCELERATION; + for (int i=0;i<4;i++) { + axis_steps_per_unit[i]=tmp1[i]; + max_feedrate[i]=tmp2[i]; + max_acceleration_units_per_sq_second[i]=tmp3[i]; + } + acceleration=DEFAULT_ACCELERATION; + retract_acceleration=DEFAULT_RETRACT_ACCELERATION; + minimumfeedrate=DEFAULT_MINIMUMFEEDRATE; + minsegmenttime=DEFAULT_MINSEGMENTTIME; + mintravelfeedrate=DEFAULT_MINTRAVELFEEDRATE; + max_xy_jerk=DEFAULT_XYJERK; + max_z_jerk=DEFAULT_ZJERK; + ECHOLN("Using Default settings:"); + } + ECHOLN("Steps per unit:"); + ECHOLN(" M92 X" <<_FLOAT(axis_steps_per_unit[0],3) << " Y" << _FLOAT(axis_steps_per_unit[1],3) << " Z" << _FLOAT(axis_steps_per_unit[2],3) << " E" << _FLOAT(axis_steps_per_unit[3],3)); + ECHOLN("Maximum feedrates (mm/s):"); + ECHOLN(" M203 X" <<_FLOAT(max_feedrate[0]/60,2)<<" Y" << _FLOAT(max_feedrate[1]/60,2) << " Z" << _FLOAT(max_feedrate[2]/60,2) << " E" << _FLOAT(max_feedrate[3]/60,2)); + ECHOLN("Maximum Acceleration (mm/s2):"); + ECHOLN(" M201 X" <<_FLOAT(max_acceleration_units_per_sq_second[0],0) << " Y" << _FLOAT(max_acceleration_units_per_sq_second[1],0) << " Z" << _FLOAT(max_acceleration_units_per_sq_second[2],0) << " E" << _FLOAT(max_acceleration_units_per_sq_second[3],0)); + ECHOLN("Acceleration: S=acceleration, T=retract acceleration"); + ECHOLN(" M204 S" <<_FLOAT(acceleration,2) << " T" << _FLOAT(retract_acceleration,2)); + ECHOLN("Advanced variables: S=Min feedrate (mm/s), T=Min travel feedrate (mm/s), B=minimum segment time (ms), X=maximum xY jerk (mm/s), Z=maximum Z jerk (mm/s)"); + ECHOLN(" M205 S" <<_FLOAT(minimumfeedrate/60,2) << " T" << _FLOAT(mintravelfeedrate/60,2) << " B" << _FLOAT(minsegmenttime,2) << " X" << _FLOAT(max_xy_jerk/60,2) << " Z" << _FLOAT(max_z_jerk/60,2)); +#ifdef PIDTEMP + ECHOLN("PID settings:"); + ECHOLN(" M301 P" << _FLOAT(Kp,3) << " I" << _FLOAT(Ki,3) << " D" << _FLOAT(Kd,3)); +#endif + +} + +#endif + + diff --git a/Marlin/Makefile b/Marlin/Makefile index 6fafba13b..f456e3cbd 100644 --- a/Marlin/Makefile +++ b/Marlin/Makefile @@ -1,274 +1,320 @@ +TARGET = $(notdir $(CURDIR)) +# CHANGE BELOW: +#~ INSTALL_DIR = /Applications/Arduino.app/Contents/Resources/Java +INSTALL_DIR = /home/bkubicek/software/arduino-0022 +#~ PORT = /dev/cu.usbserial* +PORT = /dev/ttyACM0 + +# Get these values from: +# $(INSTALL_DIR)/hardware/boards.txt +# (arduino-0022/hardware/arduino/boards.txt) +# The values below are for the "Arduino Duemilanove or Nano w/ ATmega328" +# now for "Arduino Mega 2560" +UPLOAD_SPEED = 115200 +UPLOAD_PROTOCOL = stk500v2 +BUILD_MCU = atmega2560 +BUILD_F_CPU = 16000000L + +# getting undefined reference to `__cxa_pure_virtual' +#~ [http://www.arduino.cc/cgi-bin/yabb2/YaBB.pl?num=1254180518 Arduino Forum - Makefile] +#~ http://www.arduino.cc/playground/OpenBSD/CLI +#~ [http://arduino.cc/forum/index.php?topic=52041.0 A "simple" makefile for Arduino] +#~ [http://www.arduino.cc/cgi-bin/yabb2/YaBB.pl?num=1275488191 Arduino Forum - Configuring avr-gcc options in arduino IDE] +# found in /usr/lib/gcc/avr/4.3.5/cc1plus; fixed with -Wl,--gc-section + +############################################################################ +# Below here nothing should be changed... + +ARDUINO = $(INSTALL_DIR)/hardware/arduino/cores/arduino # -# Arduino 0022 Makefile -# Uno with DOGS102 Shield +#~ AVR_TOOLS_PATH = $(INSTALL_DIR)/hardware/tools/avr/bin +# in Ubuntu, avr-gcc is installed separate; +# only avrdude comes with the IDE +AVR_TOOLS_PATH = /usr/bin +AVR_DUDE_PATH = $(INSTALL_DIR)/hardware/tools # -# written by olikraus@gmail.com -# -# Features: -# - boards.txt is used to derive parameters -# - All intermediate files are put into a separate directory (TMPDIRNAME) -# - Simple use: Copy Makefile into the same directory of the .pde file -# -# Limitations: -# - requires UNIX environment -# - TMPDIRNAME must be subdirectory of the current directory. -# -# Targets -# all build everything -# upload build and upload to arduino -# clean remove all temporary files (includes final hex file) -# -# History -# 001 28 Apr 2010 first release -# 002 05 Oct 2010 added 'uno' -# - -#=== user configuration === -# All ...PATH variables must have a '/' at the end - -# Board (and prozessor) information: see $(ARDUINO_PATH)hardware/arduino/boards.txt -# Some examples: -# BOARD DESCRIPTION -# uno Arduino Uno -# atmega328 Arduino Duemilanove or Nano w/ ATmega328 -# diecimila Arduino Diecimila, Duemilanove, or Nano w/ ATmega168 -# mega Arduino Mega -# mini Arduino Mini -# lilypad328 LilyPad Arduino w/ ATmega328 -BOARD:=mega - -# additional (comma separated) defines -# -DDOGM128_HW board is connected to DOGM128 display -# -DDOGM132_HW board is connected to DOGM132 display -# -DDOGS102_HW board is connected to DOGS102 display -# -DDOG_REVERSE 180 degree rotation -# -DDOG_SPI_SW_ARDUINO force SW shiftOut -DEFS=-DDOGS102_HW -DDOG_DOUBLE_MEMORY -DDOG_SPI_SW_ARDUINO - -# The location where the avr tools (e.g. avr-gcc) are located. Requires a '/' at the end. -# Can be empty if all tools are accessable through the search path -AVR_TOOLS_PATH:=/usr/bin/ - -# Install path of the arduino software. Requires a '/' at the end. -ARDUINO_PATH:=/home/bkubicek/software/arduino-0022/ - -# Install path for avrdude. Requires a '/' at the end. Can be empty if avrdude is in the search path. -AVRDUDE_PATH:= - -# The unix device where we can reach the arduino board -# Uno: /dev/ttyACM0 -# Duemilanove: /dev/ttyUSB0 -AVRDUDE_PORT:=/dev/ttyACM0 - -# List of all libaries which should be included. -#EXTRA_DIRS=$(ARDUINO_PATH)libraries/LiquidCrystal/ -#EXTRA_DIRS+=$(ARDUINO_PATH)libraries/Dogm/ -#EXTRA_DIRS+=/home/kraus/src/arduino/dogm128/hg/libraries/Dogm/ - -#=== fetch parameter from boards.txt processor parameter === -# the basic idea is to get most of the information from boards.txt - -BOARDS_TXT:=$(ARDUINO_PATH)hardware/arduino/boards.txt - -# get the MCU value from the $(BOARD).build.mcu variable. For the atmega328 board this is atmega328p -MCU:=$(shell sed -n -e "s/$(BOARD).build.mcu=\(.*\)/\1/p" $(BOARDS_TXT)) -# get the F_CPU value from the $(BOARD).build.f_cpu variable. For the atmega328 board this is 16000000 -F_CPU:=$(shell sed -n -e "s/$(BOARD).build.f_cpu=\(.*\)/\1/p" $(BOARDS_TXT)) - -# avrdude -# get the AVRDUDE_UPLOAD_RATE value from the $(BOARD).upload.speed variable. For the atmega328 board this is 57600 -AVRDUDE_UPLOAD_RATE:=$(shell sed -n -e "s/$(BOARD).upload.speed=\(.*\)/\1/p" $(BOARDS_TXT)) -# get the AVRDUDE_PROGRAMMER value from the $(BOARD).upload.protocol variable. For the atmega328 board this is stk500 -# AVRDUDE_PROGRAMMER:=$(shell sed -n -e "s/$(BOARD).upload.protocol=\(.*\)/\1/p" $(BOARDS_TXT)) -# use stk500v1, because stk500 will default to stk500v2 -AVRDUDE_PROGRAMMER:=stk500v1 - -#=== identify user files === -PDESRC:=$(shell ls *.pde) -TARGETNAME=$(basename $(PDESRC)) - -CDIRS:=$(EXTRA_DIRS) $(addsuffix utility/,$(EXTRA_DIRS)) -CDIRS:=*.c utility/*.c $(addsuffix *.c,$(CDIRS)) $(ARDUINO_PATH)hardware/arduino/cores/arduino/*.c -CSRC:=$(shell ls $(CDIRS) 2>/dev/null) - -CCSRC:=$(shell ls *.cc 2>/dev/null) - -CPPDIRS:=$(EXTRA_DIRS) $(addsuffix utility/,$(EXTRA_DIRS)) -CPPDIRS:=*.cpp utility/*.cpp $(addsuffix *.cpp,$(CPPDIRS)) $(ARDUINO_PATH)hardware/arduino/cores/arduino/*.cpp -CPPSRC:=$(shell ls $(CPPDIRS) 2>/dev/null) - -#=== build internal variables === - -# the name of the subdirectory where everything is stored -TMPDIRNAME:=tmp -TMPDIRPATH:=$(TMPDIRNAME)/ - -AVRTOOLSPATH:=$(AVR_TOOLS_PATH) - -OBJCOPY:=$(AVRTOOLSPATH)avr-objcopy -OBJDUMP:=$(AVRTOOLSPATH)avr-objdump -SIZE:=$(AVRTOOLSPATH)avr-size - -CPPSRC:=$(addprefix $(TMPDIRPATH),$(PDESRC:.pde=.cpp)) $(CPPSRC) - -COBJ:=$(CSRC:.c=.o) -CCOBJ:=$(CCSRC:.cc=.o) -CPPOBJ:=$(CPPSRC:.cpp=.o) - -OBJFILES:=$(COBJ) $(CCOBJ) $(CPPOBJ) -DIRS:= $(dir $(OBJFILES)) - -DEPFILES:=$(OBJFILES:.o=.d) -# assembler files from avr-gcc -S -ASSFILES:=$(OBJFILES:.o=.s) -# disassembled object files with avr-objdump -S -DISFILES:=$(OBJFILES:.o=.dis) - - -LIBNAME:=$(TMPDIRPATH)$(TARGETNAME).a -ELFNAME:=$(TMPDIRPATH)$(TARGETNAME).elf -HEXNAME:=$(TMPDIRPATH)$(TARGETNAME).hex - -AVRDUDE_FLAGS = -V -F -AVRDUDE_FLAGS += -C $(ARDUINO_PATH)/hardware/tools/avrdude.conf -AVRDUDE_FLAGS += -p $(MCU) -AVRDUDE_FLAGS += -P $(AVRDUDE_PORT) -AVRDUDE_FLAGS += -c $(AVRDUDE_PROGRAMMER) -AVRDUDE_FLAGS += -b $(AVRDUDE_UPLOAD_RATE) -AVRDUDE_FLAGS += -U flash:w:$(HEXNAME) - -AVRDUDE = avrdude - -#=== predefined variable override === -# use "make -p -f/dev/null" to see the default rules and definitions - -# Build C and C++ flags. Include path information must be placed here -COMMON_FLAGS = -DF_CPU=$(F_CPU) -mmcu=$(MCU) $(DEFS) -# COMMON_FLAGS += -gdwarf-2 -COMMON_FLAGS += -Os -COMMON_FLAGS += -Wall -funsigned-char -funsigned-bitfields -fpack-struct -fshort-enums -COMMON_FLAGS += -I. -COMMON_FLAGS += -I$(ARDUINO_PATH)hardware/arduino/cores/arduino -COMMON_FLAGS += $(addprefix -I,$(EXTRA_DIRS)) -COMMON_FLAGS += -ffunction-sections -fdata-sections -Wl,--gc-sections -COMMON_FLAGS += -Wl,--relax -COMMON_FLAGS += -mcall-prologues - -CFLAGS = $(COMMON_FLAGS) -std=gnu99 -Wstrict-prototypes -CXXFLAGS = $(COMMON_FLAGS) - -# Replace standard build tools by avr tools -CC = $(AVRTOOLSPATH)avr-gcc -CXX = $(AVRTOOLSPATH)avr-g++ -AR = @$(AVRTOOLSPATH)avr-ar - - -# "rm" must be able to delete a directory tree -RM = rm -rf - -#=== rules === - -# add rules for the C/C++ files where the .o file is placed in the TMPDIRPATH -# reuse existing variables as far as possible - -$(TMPDIRPATH)%.o: %.c - @echo compile $< - @$(COMPILE.c) $(OUTPUT_OPTION) $< - -$(TMPDIRPATH)%.o: %.cc - @echo compile $< - @$(COMPILE.cc) $(OUTPUT_OPTION) $< - -$(TMPDIRPATH)%.o: %.cpp - @echo compile $< - @$(COMPILE.cpp) $(OUTPUT_OPTION) $< - -$(TMPDIRPATH)%.s: %.c - @$(COMPILE.c) $(OUTPUT_OPTION) -S $< - -$(TMPDIRPATH)%.s: %.cc - @$(COMPILE.cc) $(OUTPUT_OPTION) -S $< - -$(TMPDIRPATH)%.s: %.cpp - @$(COMPILE.cpp) $(OUTPUT_OPTION) -S $< - -$(TMPDIRPATH)%.dis: $(TMPDIRPATH)%.o - @$(OBJDUMP) -S $< > $@ - -.SUFFIXES: .elf .hex .pde +SRC = $(ARDUINO)/pins_arduino.c $(ARDUINO)/wiring.c \ + $(ARDUINO)/wiring_analog.c $(ARDUINO)/wiring_digital.c \ + $(ARDUINO)/wiring_pulse.c \ + $(ARDUINO)/wiring_shift.c $(ARDUINO)/WInterrupts.c +# added applet/$(TARGET).cpp as in IDE 0022 +CXXSRC = $(ARDUINO)/HardwareSerial.cpp $(ARDUINO)/WMath.cpp \ + $(ARDUINO)/Print.cpp \ + $(ARDUINO)/main.cpp +# applet/$(TARGET).cpp # no need, having a rule now for applet/$(TARGET).cpp.o +# added main.cpp, as in 0022 +FORMAT = ihex + +# Name of this Makefile (used for "make depend"). +MAKEFILE = Makefile + +# Debugging format. +# Native formats for AVR-GCC's -g are stabs [default], or dwarf-2. +# AVR (extended) COFF requires stabs, plus an avr-objcopy run. +DEBUG = stabs + +OPT = 2 + +# Place -D or -U options here +#~ CDEFS = -DBUILD_F_CPU=$(BUILD_F_CPU) +#~ CXXDEFS = -DBUILD_F_CPU=$(BUILD_F_CPU) +# now called DF_CPU +CDEFS = -DF_CPU=$(BUILD_F_CPU) -DARDUINO=22 +CXXDEFS = -DF_CPU=$(BUILD_F_CPU) -DARDUINO=22 + +# Place -I options here +CINCS = -I$(ARDUINO) -I$(INSTALL_DIR)/libraries/LiquidCrystal/ -I$(INSTALL_DIR)/libraries/EEPROM/ +CXXINCS = -I$(ARDUINO) + +# Compiler flag to set the C Standard level. +# c89 - "ANSI" C +# gnu89 - c89 plus GCC extensions +# c99 - ISO C99 standard (not yet fully implemented) +# gnu99 - c99 plus GCC extensions +CSTANDARD = -std=gnu99 +CDEBUG = -g$(DEBUG) +# note that typically, IDE 0022 uses -w to suppress warnings (both in cpp and c)! +CWARN = -Wall +#~ CWARN = -w +# "-Wstrict-prototypes" is valid for Ada/C/ObjC but not for C++: +CCWARN = -Wstrict-prototypes +CTUNING = -funsigned-char -funsigned-bitfields -fpack-struct -fshort-enums +#CEXTRA = -Wa,-adhlns=$(<:.c=.lst) + +# to eliminate pins_ardiuno warnings: +# http://arduino.cc/pipermail/developers_arduino.cc/2010-December/004005.html + +# [http://www.arduino.cc/cgi-bin/yabb2/YaBB.pl?num=1254180518 Arduino Forum - Makefile] +#~ For building the objects files "-ffunction-sections -fdata-sections" was missing +#~ and the final avr-gcc call needs "-Wl,--gc-section". +CXSECTF = -fno-exceptions -ffunction-sections -fdata-sections +CFINALF = -Wl,--gc-section + +CFLAGS = $(CDEBUG) $(CDEFS) $(CINCS) -O$(OPT) $(CWARN) $(CCWARN) $(CSTANDARD) $(CEXTRA) +# added CWARN also to .cpp +CXXFLAGS = $(CDEFS) $(CINCS) -O$(OPT) $(CWARN) $(CXSECTF) +#ASFLAGS = -Wa,-adhlns=$(<:.S=.lst),-gstabs +LDFLAGS = -lm + +# Programming support using avrdude. Settings and variables. +AVRDUDE_PORT = $(PORT) +AVRDUDE_WRITE_FLASH = -U flash:w:applet/$(TARGET).hex +AVRDUDE_FLAGS = -V -F \ + -p $(BUILD_MCU) -P $(AVRDUDE_PORT) -c $(UPLOAD_PROTOCOL) \ + -b $(UPLOAD_SPEED) -C $(INSTALL_DIR)/hardware/tools/avrdude.conf +# -b $(UPLOAD_SPEED) -C $(INSTALL_DIR)/hardware/tools/avr/etc/avrdude.conf + +# Program settings +CC = $(AVR_TOOLS_PATH)/avr-gcc +CXX = $(AVR_TOOLS_PATH)/avr-g++ +OBJCOPY = $(AVR_TOOLS_PATH)/avr-objcopy +OBJDUMP = $(AVR_TOOLS_PATH)/avr-objdump +AR = $(AVR_TOOLS_PATH)/avr-ar +SIZE = $(AVR_TOOLS_PATH)/avr-size +NM = $(AVR_TOOLS_PATH)/avr-nm +#~ AVRDUDE = $(AVR_TOOLS_PATH)/avrdude +AVRDUDE = $(AVR_DUDE_PATH)/avrdude +REMOVE = rm -f +MV = mv -f + +# Define all object files. +# NOTE: obj files will be created in respective src directories (libraries or $(INSTALL_DIR)); +# make clean deletes them fine +# note that srcs are in libraries or other directories; +# $(CXXSRC:.cpp=.o) will cause obj files to be in same loc as src files +#~ OBJ = $(SRC:.c=.o) $(CXXSRC:.cpp=.o) $(ASRC:.S=.o) +# to change the output directory for object files; +# must change the obj list here! +# and then, match to corresponding rule somehow? +# or leave this - and parse in rule (auth automatic variable $(@F))? +# "Suffix Replacement" +OBJ = $(SRC:.c=.o) $(CXXSRC:.cpp=.o) $(ASRC:.S=.o) + +# added - OBJ list, transformed into applet/ +OBJT = $(addprefix applet/,$(notdir $(OBJ))) +ALLSRC = $(SRC) $(CXXSRC) $(ASRC) + +# Define all listing files. +LST = $(ASRC:.S=.lst) $(CXXSRC:.cpp=.lst) $(SRC:.c=.lst) + +# Combine all necessary flags and optional flags. +# Add target processor to flags. +ALL_CFLAGS = -mmcu=$(BUILD_MCU) -I. $(CFLAGS) +ALL_CXXFLAGS = -mmcu=$(BUILD_MCU) -I. $(CXXFLAGS) +ALL_ASFLAGS = -mmcu=$(BUILD_MCU) -I. -x assembler-with-cpp $(ASFLAGS) + +# depended libraries of .pde need to be added from +# $(INSTALL_DIR)/libraries (TODO: and/or ~/sketchbook/libraries) +# grep for 'include', test if exists, add... +# note: prefix "a real tab character" http://www.delorie.com/djgpp/doc/ug/larger/makefiles.html +# $$ to escape $ for shell; +# note: must NOT put comments # inside bash execution; +# those would get removed by make; making shell see "EOF in backquote substitution" +# echo $$ix ; \ +# 'shell' twice - for each subprocess! Backtick doesn't get expanded? +GREPRES:=$(shell for ix in $(shell grep include $(TARGET).pde | sed 's/.*[<"]\(.*\).h[>"].*/\1/'); do \ + if [ -d $(INSTALL_DIR)/libraries/$$ix ] ; then \ + LINCS="$$LINCS -I$(INSTALL_DIR)/libraries/$$ix" ;\ + fi; \ + done; \ + echo $$LINCS) +# append includes: +CINCS += $(GREPRES) +CXXINCS += $(GREPRES) +# append library source .cpp files too (CXXSRC) +GREPRESB:=$(shell for ix in $(shell grep include $(TARGET).pde | sed 's/.*[<"]\(.*\).h[>"].*/\1/'); do \ + if [ -d $(INSTALL_DIR)/libraries/$$ix ] ; then \ + CPPSRCS="$$CPPSRCS $(INSTALL_DIR)/libraries/$$ix/*.cpp" ;\ + fi; \ + done; \ + echo $$CPPSRCS) +CXXSRC += $(GREPRESB) +# added - only CXX obj from libraries: +CXXLIBOBJ = $(GREPRESB:.cpp=.o) + +# Default target. +all: applet_files build sizeafter + +build: elf hex + +applet_files: $(TARGET).pde + # Here is the "preprocessing". + # It creates a .cpp file based with the same name as the .pde file. + # On top of the new .cpp file comes the WProgram.h header. + # At the end there is a generic main() function attached. + # Then the .cpp file will be compiled. Errors during compile will + # refer to this new, automatically generated, file. + # Not the original .pde file you actually edit... + test -d applet || mkdir applet + # @ supresses printout of the cmdline itself; so only the out of echo is printed + @echo ALL OBJT: $(OBJT) + @echo ALL CXXLIBOBJ: $(CXXLIBOBJ) +# echo '#include "WProgram.h"' > applet/$(TARGET).cpp + @echo "#include \"WProgram.h\"\nvoid setup();\nvoid loop();\n" > applet/$(TARGET).cpp + cat $(TARGET).pde >> applet/$(TARGET).cpp + # no more need to cat main.cpp (v0022) - now it is compiled in +# cat $(ARDUINO)/main.cpp >> applet/$(TARGET).cpp + + +elf: applet/$(TARGET).elf +hex: applet/$(TARGET).hex +eep: applet/$(TARGET).eep +lss: applet/$(TARGET).lss +sym: applet/$(TARGET).sym + +# Program the device. +upload: applet/$(TARGET).hex + $(AVRDUDE) $(AVRDUDE_FLAGS) $(AVRDUDE_WRITE_FLASH) + +# Display size of file. +HEXSIZE = $(SIZE) --target=$(FORMAT) applet/$(TARGET).hex +ELFSIZE = $(SIZE) applet/$(TARGET).elf +sizebefore: + @if [ -f applet/$(TARGET).elf ]; then echo; echo $(MSG_SIZE_BEFORE); $(HEXSIZE); echo; fi + +sizeafter: + @if [ -f applet/$(TARGET).elf ]; then echo; echo $(MSG_SIZE_AFTER); $(HEXSIZE); echo; fi + +# Convert ELF to COFF for use in debugging / simulating in AVR Studio or VMLAB. +COFFCONVERT=$(OBJCOPY) --debugging \ + --change-section-address .data-0x800000 \ + --change-section-address .bss-0x800000 \ + --change-section-address .noinit-0x800000 \ + --change-section-address .eeprom-0x810000 + +coff: applet/$(TARGET).elf + $(COFFCONVERT) -O coff-avr applet/$(TARGET).elf $(TARGET).cof + +extcoff: $(TARGET).elf + $(COFFCONVERT) -O coff-ext-avr applet/$(TARGET).elf $(TARGET).cof + +.SUFFIXES: .elf .hex .eep .lss .sym .elf.hex: - @$(OBJCOPY) -O ihex -R .eeprom $< $@ - -$(TMPDIRPATH)%.cpp: %.pde - @cat $(ARDUINO_PATH)hardware/arduino/cores/arduino/main.cpp > $@ - @cat $< >> $@ - @echo >> $@ - @echo 'extern "C" void __cxa_pure_virtual() { while (1); }' >> $@ - - -.PHONY: all -all: tmpdir $(HEXNAME) assemblersource showsize - ls -al $(HEXNAME) $(ELFNAME) - -$(ELFNAME): $(LIBNAME)($(addprefix $(TMPDIRPATH),$(OBJFILES))) - $(LINK.o) $(COMMON_FLAGS) $(LIBNAME) $(LOADLIBES) $(LDLIBS) -o $@ - -$(LIBNAME)(): $(addprefix $(TMPDIRPATH),$(OBJFILES)) - -#=== create temp directory === -# not really required, because it will be also created during the dependency handling -.PHONY: tmpdir -tmpdir: - @test -d $(TMPDIRPATH) || mkdir $(TMPDIRPATH) - -#=== create assembler files for each C/C++ file === -.PHONY: assemblersource -assemblersource: $(addprefix $(TMPDIRPATH),$(ASSFILES)) $(addprefix $(TMPDIRPATH),$(DISFILES)) - - -#=== show the section sizes of the ELF file === -.PHONY: showsize -showsize: $(ELFNAME) - $(SIZE) $< - -#=== clean up target === -# this is simple: the TMPDIRPATH is removed -.PHONY: clean + $(OBJCOPY) -O $(FORMAT) -R .eeprom $< $@ + +.elf.eep: + -$(OBJCOPY) -j .eeprom --set-section-flags=.eeprom="alloc,load" \ + --change-section-lma .eeprom=0 -O $(FORMAT) $< $@ + +# Create extended listing file from ELF output file. +.elf.lss: + $(OBJDUMP) -h -S $< > $@ + +# Create a symbol table from ELF output file. +.elf.sym: + $(NM) -n $< > $@ + +# Link: create ELF output file from library. +# NOTE: applet/$(TARGET).cpp.o MUST BE BEFORE applet/core.a +# in the dependency list, so its rule runs first! +applet/$(TARGET).elf: $(TARGET).pde applet/$(TARGET).cpp.o applet/core.a +# $(CC) $(ALL_CFLAGS) -o $@ applet/$(TARGET).cpp -L. applet/core.a $(LDFLAGS) +# changed as in IDE v0022: link cpp obj files + @echo $$(tput bold)$$(tput setaf 2) $(CC) $$(tput sgr0) $(ALL_CFLAGS) $(CFINALF) -o $@ applet/$(TARGET).cpp.o $(CXXOBJ) -L. applet/core.a $(LDFLAGS) + @$(CC) $(ALL_CFLAGS) $(CFINALF) -o $@ applet/$(TARGET).cpp.o $(CXXOBJ) -L. applet/core.a $(LDFLAGS) + +# added: cpp.o depends on cpp (and .pde which generates it) +# $< "first item in the dependencies list"; $@ "left side of the :"; $^ "right side of the :" +# http://www.cs.colby.edu/maxwell/courses/tutorials/maketutor/ +applet/$(TARGET).cpp.o: applet/$(TARGET).cpp + @echo $$(tput bold) $(CXX) $$(tput sgr0) -c $(ALL_CXXFLAGS) $< -o $@ + @$(CXX) -c $(ALL_CXXFLAGS) $< -o $@ + +#~ applet/core.a: $(OBJ) +#~ @for i in $(OBJ); do echo $(AR) rcs applet/core.a $$i; $(AR) rcs applet/core.a $$i; done + +applet/core.a: $(OBJT) + @for i in $(OBJT); do echo $(AR) rcs applet/core.a $$i; $(AR) rcs applet/core.a $$i; done + +# iterate through OBJ to find the original location; then build depending on source extension +# TODO: add handling of assembler files +applet/%.o: + @for iob in $(OBJ); do \ + if [ "`basename $$iob`" = "`basename $@`" ]; then \ + for ios in $(ALLSRC); do \ + if [ "$${iob%%.*}" = "$${ios%%.*}" ]; then \ + case $${ios##*.} in \ + "cpp") \ + echo "$$(tput bold)$$(tput setaf 1) $(CXX) $$(tput sgr0) -c $(ALL_CXXFLAGS) $$ios -o $@"; \ + $(CXX) -c $(ALL_CXXFLAGS) $$ios -o $@;; \ + "c") \ + echo "$$(tput bold)$$(tput setaf 1) $(CC) $$(tput sgr0) -c $(ALL_CFLAGS) $$ios -o $@"; \ + $(CC) -c $(ALL_CFLAGS) $$ios -o $@;; \ + esac; \ + fi; \ + done; \ + fi; \ + done; + +#~ # Compile: create object files from C++ source files. +#~ .cpp.o: +#~ $(CXX) -c $(ALL_CXXFLAGS) $< -o $@ + +#~ # Compile: create object files from C source files. +#~ .c.o: +#~ $(CC) -c $(ALL_CFLAGS) $< -o $@ + +#~ # Compile: create assembler files from C source files. +#~ .c.s: +#~ $(CC) -S $(ALL_CFLAGS) $< -o $@ + +#~ # Assemble: create object files from assembler source files. +#~ .S.o: +#~ $(CC) -c $(ALL_ASFLAGS) $< -o $@ + +#~ # Automatic dependencies +#~ %.d: %.c +#~ $(CC) -M $(ALL_CFLAGS) $< | sed "s;$(notdir $*).o:;$*.o $*.d:;" > $@ + +#~ %.d: %.cpp +#~ $(CXX) -M $(ALL_CXXFLAGS) $< | sed "s;$(notdir $*).o:;$*.o $*.d:;" > $@ + +# Target: clean project. clean: - $(RM) $(TMPDIRPATH) - -# Program the device. -# step 1: reset the arduino board with the stty command -# step 2: user avrdude to upload the software -.PHONY: upload -upload: $(HEXNAME) - stty -F $(AVRDUDE_PORT) hupcl - $(AVRDUDE) $(AVRDUDE_FLAGS) - - -# === dependency handling === -# From the gnu make manual (section 4.14, Generating Prerequisites Automatically) -# Additionally (because this will be the first executed rule) TMPDIRPATH is created here. -# Instead of "sed" the "echo" command is used -# cd $(TMPDIRPATH); mkdir -p $(DIRS) 2> /dev/null; cd .. -DEPACTION=test -d $(TMPDIRPATH) || mkdir $(TMPDIRPATH);\ -mkdir -p $(addprefix $(TMPDIRPATH),$(DIRS));\ -set -e; echo -n $@ $(dir $@) > $@; $(CC) -MM $(COMMON_FLAGS) $< >> $@ - - -$(TMPDIRPATH)%.d: %.c - @$(DEPACTION) - -$(TMPDIRPATH)%.d: %.cc - @$(DEPACTION) - - -$(TMPDIRPATH)%.d: %.cpp - @$(DEPACTION) - -# Include dependency files. If a .d file is missing, a warning is created and the .d file is created -# This warning is not a problem (gnu make manual, section 3.3 Including Other Makefiles) --include $(addprefix $(TMPDIRPATH),$(DEPFILES)) - + $(REMOVE) applet/$(TARGET).hex applet/$(TARGET).eep applet/$(TARGET).cof applet/$(TARGET).elf \ + applet/$(TARGET).map applet/$(TARGET).sym applet/$(TARGET).lss applet/core.a \ + $(OBJT) applet/$(TARGET).cpp.o \ + $(OBJ) $(LST) $(SRC:.c=.s) $(SRC:.c=.d) $(CXXSRC:.cpp=.s) $(CXXSRC:.cpp=.d) +.PHONY: all build elf hex eep lss sym program coff extcoff clean applet_files sizebefore sizeafter diff --git a/Marlin/Marlin.h b/Marlin/Marlin.h index cc43f00b2..f85dad357 100644 --- a/Marlin/Marlin.h +++ b/Marlin/Marlin.h @@ -1,83 +1,82 @@ -#ifndef __MARLINH -#define __MARLINH - -// Tonokip RepRap firmware rewrite based off of Hydra-mmm firmware. -// Licence: GPL -#include -#include "fastio.h" - - -#define ECHO(x) Serial << "echo: " << x; -#define ECHOLN(x) Serial << "echo: "< -1 -#define enable_x() WRITE(X_ENABLE_PIN, X_ENABLE_ON) -#define disable_x() WRITE(X_ENABLE_PIN,!X_ENABLE_ON) -#else -#define enable_x() ; -#define disable_x() ; -#endif -#if Y_ENABLE_PIN > -1 -#define enable_y() WRITE(Y_ENABLE_PIN, Y_ENABLE_ON) -#define disable_y() WRITE(Y_ENABLE_PIN,!Y_ENABLE_ON) -#else -#define enable_y() ; -#define disable_y() ; -#endif -#if Z_ENABLE_PIN > -1 -#define enable_z() WRITE(Z_ENABLE_PIN, Z_ENABLE_ON) -#define disable_z() WRITE(Z_ENABLE_PIN,!Z_ENABLE_ON) -#else -#define enable_z() ; -#define disable_z() ; -#endif - -#if E_ENABLE_PIN > -1 - - #define enable_e() WRITE(E_ENABLE_PIN, E_ENABLE_ON) - #define disable_e() WRITE(E_ENABLE_PIN,!E_ENABLE_ON) - -#else -#define enable_e() ; -#define disable_e() ; -#endif - -#define X_AXIS 0 -#define Y_AXIS 1 -#define Z_AXIS 2 -#define E_AXIS 3 - -void FlushSerialRequestResend(); -void ClearToSend(); - -void get_coordinates(); -void prepare_move(); -void kill(byte debug); - -//void check_axes_activity(); -//void plan_init(); -//void st_init(); -//void tp_init(); -//void plan_buffer_line(float x, float y, float z, float e, float feed_rate); -//void plan_set_position(float x, float y, float z, float e); -//void st_wake_up(); -//void st_synchronize(); -void enquecommand(const char *cmd); -void wd_reset(); - -#ifndef CRITICAL_SECTION_START -#define CRITICAL_SECTION_START unsigned char _sreg = SREG; cli(); -#define CRITICAL_SECTION_END SREG = _sreg; -#endif //CRITICAL_SECTION_START - -extern float homing_feedrate[]; -extern bool axis_relative_modes[]; - -void manage_inactivity(byte debug); - -#endif +#ifndef __MARLINH +#define __MARLINH + +// Tonokip RepRap firmware rewrite based off of Hydra-mmm firmware. +// Licence: GPL +#include +#include "fastio.h" + + +#define ECHO(x) Serial << "echo: " << x; +#define ECHOLN(x) Serial << "echo: "< -1 +#define enable_x() WRITE(X_ENABLE_PIN, X_ENABLE_ON) +#define disable_x() WRITE(X_ENABLE_PIN,!X_ENABLE_ON) +#else +#define enable_x() ; +#define disable_x() ; +#endif +#if Y_ENABLE_PIN > -1 +#define enable_y() WRITE(Y_ENABLE_PIN, Y_ENABLE_ON) +#define disable_y() WRITE(Y_ENABLE_PIN,!Y_ENABLE_ON) +#else +#define enable_y() ; +#define disable_y() ; +#endif +#if Z_ENABLE_PIN > -1 +#define enable_z() WRITE(Z_ENABLE_PIN, Z_ENABLE_ON) +#define disable_z() WRITE(Z_ENABLE_PIN,!Z_ENABLE_ON) +#else +#define enable_z() ; +#define disable_z() ; +#endif + +#if E_ENABLE_PIN > -1 + + #define enable_e() WRITE(E_ENABLE_PIN, E_ENABLE_ON) + #define disable_e() WRITE(E_ENABLE_PIN,!E_ENABLE_ON) + +#else +#define enable_e() ; +#define disable_e() ; +#endif + +#define X_AXIS 0 +#define Y_AXIS 1 +#define Z_AXIS 2 +#define E_AXIS 3 + +void FlushSerialRequestResend(); +void ClearToSend(); + +void get_coordinates(); +void prepare_move(); +void kill(); + +//void check_axes_activity(); +//void plan_init(); +//void st_init(); +//void tp_init(); +//void plan_buffer_line(float x, float y, float z, float e, float feed_rate); +//void plan_set_position(float x, float y, float z, float e); +//void st_wake_up(); +//void st_synchronize(); +void enquecommand(const char *cmd); + + +#ifndef CRITICAL_SECTION_START +#define CRITICAL_SECTION_START unsigned char _sreg = SREG; cli(); +#define CRITICAL_SECTION_END SREG = _sreg; +#endif //CRITICAL_SECTION_START + +extern float homing_feedrate[]; +extern bool axis_relative_modes[]; + +void wd_reset() ; +#endif diff --git a/Marlin/Marlin.pde b/Marlin/Marlin.pde index cb55131df..3cf8d3bdf 100644 --- a/Marlin/Marlin.pde +++ b/Marlin/Marlin.pde @@ -1,1233 +1,1233 @@ -/* - Reprap firmware based on Sprinter and grbl. - Copyright (C) 2011 Camiel Gubbels / Erik van der Zalm - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . - */ - -/* - This firmware is a mashup between Sprinter and grbl. - (https://github.com/kliment/Sprinter) - (https://github.com/simen/grbl/tree) - - It has preliminary support for Matthew Roberts advance algorithm - http://reprap.org/pipermail/reprap-dev/2011-May/003323.html - */ - -#include -#include "fastio.h" -#include "Configuration.h" -#include "pins.h" -#include "Marlin.h" -#include "ultralcd.h" -#include "streaming.h" -#include "planner.h" -#include "stepper.h" -#include "temperature.h" - -#ifdef SIMPLE_LCD - #include "Simplelcd.h" -#endif - -char version_string[] = "1.0.0 Alpha 1"; - -#ifdef SDSUPPORT -#include "SdFat.h" -#endif //SDSUPPORT - - -// look here for descriptions of gcodes: http://linuxcnc.org/handbook/gcode/g-code.html -// http://objects.reprap.org/wiki/Mendel_User_Manual:_RepRapGCodes - -//Implemented Codes -//------------------- -// G0 -> G1 -// G1 - Coordinated Movement X Y Z E -// G4 - Dwell S or P -// G28 - Home all Axis -// G90 - Use Absolute Coordinates -// G91 - Use Relative Coordinates -// G92 - Set current position to cordinates given - -//RepRap M Codes -// M104 - Set extruder target temp -// M105 - Read current temp -// M106 - Fan on -// M107 - Fan off -// M109 - Wait for extruder current temp to reach target temp. -// M114 - Display current position - -//Custom M Codes -// M20 - List SD card -// M21 - Init SD card -// M22 - Release SD card -// M23 - Select SD file (M23 filename.g) -// M24 - Start/resume SD print -// M25 - Pause SD print -// M26 - Set SD position in bytes (M26 S12345) -// M27 - Report SD print status -// M28 - Start SD write (M28 filename.g) -// M29 - Stop SD write -// M42 - Change pin status via gcode -// M80 - Turn on Power Supply -// M81 - Turn off Power Supply -// M82 - Set E codes absolute (default) -// M83 - Set E codes relative while in Absolute Coordinates (G90) mode -// M84 - Disable steppers until next move, -// or use S to specify an inactivity timeout, after which the steppers will be disabled. S0 to disable the timeout. -// M85 - Set inactivity shutdown timer with parameter S. To disable set zero (default) -// M92 - Set axis_steps_per_unit - same syntax as G92 -// M115 - Capabilities string -// M140 - Set bed target temp -// M190 - Wait for bed current temp to reach target temp. -// M200 - Set filament diameter -// M201 - Set max acceleration in units/s^2 for print moves (M201 X1000 Y1000) -// 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 -// M205 - advanced settings: minimum travel speed S=while printing T=travel only, B=minimum segment time X= maximum xy jerk, Z=maximum Z jerk -// M220 - set speed factor override percentage S:factor in percent -// M301 - Set PID parameters P I and D -// M500 - stores paramters in EEPROM -// M501 - reads parameters from EEPROM (if you need reset them after you changed them temporarily). D -// M502 - reverts to the default "factory settings". You still need to store them in EEPROM afterwards if you want to. - -//Stepper Movement Variables - -char axis_codes[NUM_AXIS] = { - 'X', 'Y', 'Z', 'E'}; -float destination[NUM_AXIS] = { - 0.0, 0.0, 0.0, 0.0}; -float current_position[NUM_AXIS] = { - 0.0, 0.0, 0.0, 0.0}; -bool home_all_axis = true; -float feedrate = 1500.0, next_feedrate, saved_feedrate; -long gcode_N, gcode_LastN; - -float homing_feedrate[] = HOMING_FEEDRATE; -bool axis_relative_modes[] = AXIS_RELATIVE_MODES; - -bool relative_mode = false; //Determines Absolute or Relative Coordinates -bool relative_mode_e = false; //Determines Absolute or Relative E Codes while in Absolute Coordinates mode. E is always relative in Relative Coordinates mode. - -uint8_t fanpwm=0; - -volatile int feedmultiply=100; //100->1 200->2 -int saved_feedmultiply; -volatile bool feedmultiplychanged=false; -// comm variables -#define MAX_CMD_SIZE 96 -#define BUFSIZE 4 -char cmdbuffer[BUFSIZE][MAX_CMD_SIZE]; -bool fromsd[BUFSIZE]; -int bufindr = 0; -int bufindw = 0; -int buflen = 0; -int i = 0; -char serial_char; -int serial_count = 0; -boolean comment_mode = false; -char *strchr_pointer; // just a pointer to find chars in the cmd string like X, Y, Z, E, etc -extern float HeaterPower; - -#include "EEPROM.h" - -const int sensitive_pins[] = SENSITIVE_PINS; // Sensitive pin list for M42 - -float tt = 0, bt = 0; -#ifdef WATCHPERIOD -int watch_raw = -1000; -unsigned long watchmillis = 0; -#endif //WATCHPERIOD - -//Inactivity shutdown variables -unsigned long previous_millis_cmd = 0; -unsigned long max_inactive_time = 0; -unsigned long stepper_inactive_time = 0; - -unsigned long starttime=0; -unsigned long stoptime=0; -#ifdef SDSUPPORT -Sd2Card card; -SdVolume volume; -SdFile root; -SdFile file; -uint32_t filesize = 0; -uint32_t sdpos = 0; -bool sdmode = false; -bool sdactive = false; -bool savetosd = false; -int16_t n; -long autostart_atmillis=0; - -void initsd(){ - sdactive = false; -#if SDSS >- 1 - if(root.isOpen()) - root.close(); - if (!card.init(SPI_FULL_SPEED,SDSS)){ - //if (!card.init(SPI_HALF_SPEED,SDSS)) - Serial.println("SD init fail"); - } - else if (!volume.init(&card)) - Serial.println("volume.init failed"); - else if (!root.openRoot(&volume)) - Serial.println("openRoot failed"); - else - { - sdactive = true; - Serial.println("SD card ok"); - } -#endif //SDSS -} - -void quickinitsd(){ - sdactive=false; - autostart_atmillis=millis()+5000; -} - -inline void write_command(char *buf){ - char* begin = buf; - char* npos = 0; - char* end = buf + strlen(buf) - 1; - - file.writeError = false; - if((npos = strchr(buf, 'N')) != NULL){ - begin = strchr(npos, ' ') + 1; - end = strchr(npos, '*') - 1; - } - end[1] = '\r'; - end[2] = '\n'; - end[3] = '\0'; - //Serial.println(begin); - file.write(begin); - if (file.writeError){ - Serial.println("error writing to file"); - } -} -#endif //SDSUPPORT - - -///adds an command to the main command buffer -void enquecommand(const char *cmd) -{ - if(buflen < BUFSIZE) - { - //this is dangerous if a mixing of serial and this happsens - strcpy(&(cmdbuffer[bufindw][0]),cmd); - Serial.print("en:");Serial.println(cmdbuffer[bufindw]); - bufindw= (bufindw + 1)%BUFSIZE; - buflen += 1; - } -} - -void setup() -{ - - Serial.begin(BAUDRATE); - ECHOLN("Marlin "< -1 - SET_OUTPUT(SDPOWER); - WRITE(SDPOWER,HIGH); -#endif //SDPOWER - quickinitsd(); - -#endif //SDSUPPORT - plan_init(); // Initialize planner; - st_init(); // Initialize stepper; - tp_init(); // Initialize temperature loop - //checkautostart(); -} - -#ifdef SDSUPPORT -bool autostart_stilltocheck=true; - - -void checkautostart(bool force) -{ - //this is to delay autostart and hence the initialisaiton of the sd card to some seconds after the normal init, so the device is available quick after a reset - if(!force) - { - if(!autostart_stilltocheck) - return; - if(autostart_atmillis 0) - { - for(int i=0;i 0 && buflen < BUFSIZE) { - serial_char = Serial.read(); - if(serial_char == '\n' || serial_char == '\r' || serial_char == ':' || serial_count >= (MAX_CMD_SIZE - 1) ) - { - if(!serial_count) return; //if empty line - cmdbuffer[bufindw][serial_count] = 0; //terminate string - if(!comment_mode){ - fromsd[bufindw] = false; - if(strstr(cmdbuffer[bufindw], "N") != NULL) - { - strchr_pointer = strchr(cmdbuffer[bufindw], 'N'); - gcode_N = (strtol(&cmdbuffer[bufindw][strchr_pointer - cmdbuffer[bufindw] + 1], NULL, 10)); - if(gcode_N != gcode_LastN+1 && (strstr(cmdbuffer[bufindw], "M110") == NULL) ) { - Serial.print("Serial Error: Line Number is not Last Line Number+1, Last Line:"); - Serial.println(gcode_LastN); - //Serial.println(gcode_N); - FlushSerialRequestResend(); - serial_count = 0; - return; - } - - if(strstr(cmdbuffer[bufindw], "*") != NULL) - { - byte checksum = 0; - byte count = 0; - while(cmdbuffer[bufindw][count] != '*') checksum = checksum^cmdbuffer[bufindw][count++]; - strchr_pointer = strchr(cmdbuffer[bufindw], '*'); - - if( (int)(strtod(&cmdbuffer[bufindw][strchr_pointer - cmdbuffer[bufindw] + 1], NULL)) != checksum) { - Serial.print("Error: checksum mismatch, Last Line:"); - Serial.println(gcode_LastN); - FlushSerialRequestResend(); - serial_count = 0; - return; - } - //if no errors, continue parsing - } - else - { - Serial.print("Error: No Checksum with line number, Last Line:"); - Serial.println(gcode_LastN); - FlushSerialRequestResend(); - serial_count = 0; - return; - } - - gcode_LastN = gcode_N; - //if no errors, continue parsing - } - else // if we don't receive 'N' but still see '*' - { - if((strstr(cmdbuffer[bufindw], "*") != NULL)) - { - Serial.print("Error: No Line Number with checksum, Last Line:"); - Serial.println(gcode_LastN); - serial_count = 0; - return; - } - } - if((strstr(cmdbuffer[bufindw], "G") != NULL)){ - strchr_pointer = strchr(cmdbuffer[bufindw], 'G'); - switch((int)((strtod(&cmdbuffer[bufindw][strchr_pointer - cmdbuffer[bufindw] + 1], NULL)))){ - case 0: - case 1: -#ifdef SDSUPPORT - if(savetosd) - break; -#endif //SDSUPPORT - Serial.println("ok"); - break; - default: - break; - } - - } - bufindw = (bufindw + 1)%BUFSIZE; - buflen += 1; - - } - comment_mode = false; //for new command - serial_count = 0; //clear buffer - } - else - { - if(serial_char == ';') comment_mode = true; - if(!comment_mode) cmdbuffer[bufindw][serial_count++] = serial_char; - } - } -#ifdef SDSUPPORT - if(!sdmode || serial_count!=0){ - return; - } - while( filesize > sdpos && buflen < BUFSIZE) { - n = file.read(); - serial_char = (char)n; - if(serial_char == '\n' || serial_char == '\r' || serial_char == ':' || serial_count >= (MAX_CMD_SIZE - 1) || n == -1) - { - sdpos = file.curPosition(); - if(sdpos >= filesize){ - sdmode = false; - Serial.println("Done printing file"); - stoptime=millis(); - char time[30]; - unsigned long t=(stoptime-starttime)/1000; - int sec,min; - min=t/60; - sec=t%60; - sprintf(time,"%i min, %i sec",min,sec); - Serial.println(time); - LCD_MESSAGE(time); - checkautostart(true); - } - if(!serial_count) return; //if empty line - cmdbuffer[bufindw][serial_count] = 0; //terminate string - if(!comment_mode){ - fromsd[bufindw] = true; - buflen += 1; - bufindw = (bufindw + 1)%BUFSIZE; - } - comment_mode = false; //for new command - serial_count = 0; //clear buffer - } - else - { - if(serial_char == ';') comment_mode = true; - if(!comment_mode) cmdbuffer[bufindw][serial_count++] = serial_char; - } - } -#endif //SDSUPPORT - -} - - -inline float code_value() { - return (strtod(&cmdbuffer[bufindr][strchr_pointer - cmdbuffer[bufindr] + 1], NULL)); -} -inline long code_value_long() { - return (strtol(&cmdbuffer[bufindr][strchr_pointer - cmdbuffer[bufindr] + 1], NULL, 10)); -} -inline bool code_seen(char code_string[]) { - return (strstr(cmdbuffer[bufindr], code_string) != NULL); -} //Return True if the string was found - -inline bool code_seen(char code) -{ - strchr_pointer = strchr(cmdbuffer[bufindr], code); - return (strchr_pointer != NULL); //Return True if a character was found -} - -inline void process_commands() -{ - unsigned long codenum; //throw away variable - char *starpos = NULL; - - if(code_seen('G')) - { - switch((int)code_value()) - { - case 0: // G0 -> G1 - case 1: // G1 - get_coordinates(); // For X Y Z E F - prepare_move(); - previous_millis_cmd = millis(); - //ClearToSend(); - return; - //break; - case 4: // G4 dwell - codenum = 0; - if(code_seen('P')) codenum = code_value(); // milliseconds to wait - if(code_seen('S')) codenum = code_value() * 1000; // seconds to wait - codenum += millis(); // keep track of when we started waiting - while(millis() < codenum ){ - manage_heater(); - } - break; - case 28: //G28 Home all Axis one at a time - saved_feedrate = feedrate; - saved_feedmultiply = feedmultiply; - feedmultiply = 100; - - for(int i=0; i < NUM_AXIS; i++) { - destination[i] = current_position[i]; - } - feedrate = 0.0; - - home_all_axis = !((code_seen(axis_codes[0])) || (code_seen(axis_codes[1])) || (code_seen(axis_codes[2]))); - - if((home_all_axis) || (code_seen(axis_codes[X_AXIS]))) { - if ((X_MIN_PIN > -1 && X_HOME_DIR==-1) || (X_MAX_PIN > -1 && X_HOME_DIR==1)){ -// st_synchronize(); - current_position[X_AXIS] = 0; - plan_set_position(current_position[X_AXIS], current_position[Y_AXIS], current_position[Z_AXIS], current_position[E_AXIS]); - destination[X_AXIS] = 1.5 * X_MAX_LENGTH * X_HOME_DIR; - feedrate = homing_feedrate[X_AXIS]; - prepare_move(); - -// st_synchronize(); - current_position[X_AXIS] = 0; - plan_set_position(current_position[X_AXIS], current_position[Y_AXIS], current_position[Z_AXIS], current_position[E_AXIS]); - destination[X_AXIS] = -5 * X_HOME_DIR; - prepare_move(); - -// st_synchronize(); - destination[X_AXIS] = 10 * X_HOME_DIR; - feedrate = homing_feedrate[X_AXIS]/2 ; - prepare_move(); - -// st_synchronize(); - current_position[X_AXIS] = (X_HOME_DIR == -1) ? 0 : X_MAX_LENGTH; - plan_set_position(current_position[X_AXIS], current_position[Y_AXIS], current_position[Z_AXIS], current_position[E_AXIS]); - destination[X_AXIS] = current_position[X_AXIS]; - feedrate = 0.0; - } - } - - if((home_all_axis) || (code_seen(axis_codes[Y_AXIS]))) { - if ((Y_MIN_PIN > -1 && Y_HOME_DIR==-1) || (Y_MAX_PIN > -1 && Y_HOME_DIR==1)){ - current_position[Y_AXIS] = 0; - plan_set_position(current_position[X_AXIS], current_position[Y_AXIS], current_position[Z_AXIS], current_position[E_AXIS]); - destination[Y_AXIS] = 1.5 * Y_MAX_LENGTH * Y_HOME_DIR; - feedrate = homing_feedrate[Y_AXIS]; - prepare_move(); -// st_synchronize(); - - current_position[Y_AXIS] = 0; - plan_set_position(current_position[X_AXIS], current_position[Y_AXIS], current_position[Z_AXIS], current_position[E_AXIS]); - destination[Y_AXIS] = -5 * Y_HOME_DIR; - prepare_move(); -// st_synchronize(); - - destination[Y_AXIS] = 10 * Y_HOME_DIR; - feedrate = homing_feedrate[Y_AXIS]/2; - prepare_move(); -// st_synchronize(); - - current_position[Y_AXIS] = (Y_HOME_DIR == -1) ? 0 : Y_MAX_LENGTH; - plan_set_position(current_position[X_AXIS], current_position[Y_AXIS], current_position[Z_AXIS], current_position[E_AXIS]); - destination[Y_AXIS] = current_position[Y_AXIS]; - feedrate = 0.0; - } - } - - if((home_all_axis) || (code_seen(axis_codes[Z_AXIS]))) { - if ((Z_MIN_PIN > -1 && Z_HOME_DIR==-1) || (Z_MAX_PIN > -1 && Z_HOME_DIR==1)){ - current_position[Z_AXIS] = 0; - plan_set_position(current_position[X_AXIS], current_position[Y_AXIS], current_position[Z_AXIS], current_position[E_AXIS]); - destination[Z_AXIS] = 1.5 * Z_MAX_LENGTH * Z_HOME_DIR; - feedrate = homing_feedrate[Z_AXIS]; - prepare_move(); -// st_synchronize(); - - current_position[Z_AXIS] = 0; - plan_set_position(current_position[X_AXIS], current_position[Y_AXIS], current_position[Z_AXIS], current_position[E_AXIS]); - destination[Z_AXIS] = -2 * Z_HOME_DIR; - prepare_move(); -// st_synchronize(); - - destination[Z_AXIS] = 3 * Z_HOME_DIR; - feedrate = homing_feedrate[Z_AXIS]/2; - prepare_move(); -// st_synchronize(); - - current_position[Z_AXIS] = (Z_HOME_DIR == -1) ? 0 : Z_MAX_LENGTH; - plan_set_position(current_position[X_AXIS], current_position[Y_AXIS], current_position[Z_AXIS], current_position[E_AXIS]); - destination[Z_AXIS] = current_position[Z_AXIS]; - feedrate = 0.0; - } - } - feedrate = saved_feedrate; - feedmultiply = saved_feedmultiply; - previous_millis_cmd = millis(); - break; - case 90: // G90 - relative_mode = false; - break; - case 91: // G91 - relative_mode = true; - break; - case 92: // G92 - if(!code_seen(axis_codes[E_AXIS])) - st_synchronize(); - for(int i=0; i < NUM_AXIS; i++) { - if(code_seen(axis_codes[i])) current_position[i] = code_value(); - } - plan_set_position(current_position[X_AXIS], current_position[Y_AXIS], current_position[Z_AXIS], current_position[E_AXIS]); - break; - } - } - - else if(code_seen('M')) - { - - switch( (int)code_value() ) - { -#ifdef SDSUPPORT - - case 20: // M20 - list SD card - Serial.println("Begin file list"); - root.ls(); - Serial.println("End file list"); - break; - case 21: // M21 - init SD card - sdmode = false; - initsd(); - break; - case 22: //M22 - release SD card - sdmode = false; - sdactive = false; - break; - case 23: //M23 - Select file - if(sdactive){ - sdmode = false; - file.close(); - starpos = (strchr(strchr_pointer + 4,'*')); - if(starpos!=NULL) - *(starpos-1)='\0'; - if (file.open(&root, strchr_pointer + 4, O_READ)) { - Serial.print("File opened:"); - Serial.print(strchr_pointer + 4); - Serial.print(" Size:"); - Serial.println(file.fileSize()); - sdpos = 0; - filesize = file.fileSize(); - Serial.println("File selected"); - } - else{ - Serial.println("file.open failed"); - } - } - break; - case 24: //M24 - Start SD print - if(sdactive){ - sdmode = true; - starttime=millis(); - } - break; - case 25: //M25 - Pause SD print - if(sdmode){ - sdmode = false; - } - break; - case 26: //M26 - Set SD index - if(sdactive && code_seen('S')){ - sdpos = code_value_long(); - file.seekSet(sdpos); - } - break; - case 27: //M27 - Get SD status - if(sdactive){ - Serial.print("SD printing byte "); - Serial.print(sdpos); - Serial.print("/"); - Serial.println(filesize); - } - else{ - Serial.println("Not SD printing"); - } - break; - case 28: //M28 - Start SD write - if(sdactive){ - char* npos = 0; - file.close(); - sdmode = false; - starpos = (strchr(strchr_pointer + 4,'*')); - if(starpos != NULL){ - npos = strchr(cmdbuffer[bufindr], 'N'); - strchr_pointer = strchr(npos,' ') + 1; - *(starpos-1) = '\0'; - } - if (!file.open(&root, strchr_pointer+4, O_CREAT | O_APPEND | O_WRITE | O_TRUNC)) - { - Serial.print("open failed, File: "); - Serial.print(strchr_pointer + 4); - Serial.print("."); - } - else{ - savetosd = true; - Serial.print("Writing to file: "); - Serial.println(strchr_pointer + 4); - } - } - break; - case 29: //M29 - Stop SD write - //processed in write to file routine above - //savetosd = false; - break; - case 30: - { - stoptime=millis(); - char time[30]; - unsigned long t=(stoptime-starttime)/1000; - int sec,min; - min=t/60; - sec=t%60; - sprintf(time,"%i min, %i sec",min,sec); - Serial.println(time); - LCD_MESSAGE(time); - } - break; -#endif //SDSUPPORT - case 42: //M42 -Change pin status via gcode - if (code_seen('S')) - { - int pin_status = code_value(); - if (code_seen('P') && pin_status >= 0 && pin_status <= 255) - { - int pin_number = code_value(); - for(int i = 0; i < sizeof(sensitive_pins); i++) - { - if (sensitive_pins[i] == pin_number) - { - pin_number = -1; - break; - } - } - - if (pin_number > -1) - { - pinMode(pin_number, OUTPUT); - digitalWrite(pin_number, pin_status); - analogWrite(pin_number, pin_status); - } - } - } - break; - case 104: // M104 - if (code_seen('S')) target_raw[0] = temp2analog(code_value()); -#ifdef PIDTEMP - pid_setpoint = code_value(); -#endif //PIDTEM - #ifdef WATCHPERIOD - if(target_raw[0] > current_raw[0]){ - watchmillis = max(1,millis()); - watch_raw = current_raw[0]; - }else{ - watchmillis = 0; - } - #endif - break; - case 140: // M140 set bed temp - if (code_seen('S')) target_raw[1] = temp2analogBed(code_value()); - break; - case 105: // M105 - #if (TEMP_0_PIN > -1) || defined (HEATER_USES_AD595) - tt = analog2temp(current_raw[0]); - #endif - #if TEMP_1_PIN > -1 - bt = analog2tempBed(current_raw[1]); - #endif - #if (TEMP_0_PIN > -1) || defined (HEATER_USES_AD595) - Serial.print("ok T:"); - Serial.print(tt); -// Serial.print(", raw:"); -// Serial.print(current_raw); - #if TEMP_1_PIN > -1 -#ifdef PIDTEMP - Serial.print(" B:"); - #if TEMP_1_PIN > -1 - Serial.println(bt); - #else - Serial.println(HeaterPower); - #endif -#else - Serial.println(); -#endif - #else - Serial.println(); - #endif - #else - Serial.println("No thermistors - no temp"); - #endif - return; - //break; - case 109: {// M109 - Wait for extruder heater to reach target. - LCD_MESSAGE("Heating..."); - if (code_seen('S')) target_raw[0] = temp2analog(code_value()); - #ifdef PIDTEMP - pid_setpoint = code_value(); - #endif //PIDTEM - #ifdef WATCHPERIOD - if(target_raw[0]>current_raw[0]) { - watchmillis = max(1,millis()); - watch_raw = current_raw[0]; - } else { - watchmillis = 0; - } - #endif //WATCHPERIOD - codenum = millis(); - - /* See if we are heating up or cooling down */ - bool target_direction = (current_raw[0] < target_raw[0]); // true if heating, false if cooling - - #ifdef TEMP_RESIDENCY_TIME - long residencyStart; - residencyStart = -1; - /* continue to loop until we have reached the target temp - _and_ until TEMP_RESIDENCY_TIME hasn't passed since we reached it */ - while((target_direction ? (current_raw[0] < target_raw[0]) : (current_raw[0] > target_raw[0])) || - (residencyStart > -1 && (millis() - residencyStart) < TEMP_RESIDENCY_TIME*1000) ) { - #else - while ( target_direction ? (current_raw[0] < target_raw[0]) : (current_raw[0] > target_raw[0]) ) { - #endif //TEMP_RESIDENCY_TIME - if( (millis() - codenum) > 1000 ) { //Print Temp Reading every 1 second while heating up/cooling down - Serial.print("T:"); - Serial.println( analog2temp(current_raw[0]) ); - codenum = millis(); - } - manage_heater(); - LCD_STATUS; - #ifdef TEMP_RESIDENCY_TIME - /* start/restart the TEMP_RESIDENCY_TIME timer whenever we reach target temp for the first time - or when current temp falls outside the hysteresis after target temp was reached */ - if ((residencyStart == -1 && target_direction && current_raw[0] >= target_raw[0]) || - (residencyStart == -1 && !target_direction && current_raw[0] <= target_raw[0]) || - (residencyStart > -1 && labs(analog2temp(current_raw[0]) - analog2temp(target_raw[0])) > TEMP_HYSTERESIS) ) { - residencyStart = millis(); - } - #endif //TEMP_RESIDENCY_TIME - } - LCD_MESSAGE("Marlin ready."); - } - break; - case 190: // M190 - Wait bed for heater to reach target. - #if TEMP_1_PIN > -1 - if (code_seen('S')) target_raw[1] = temp2analog(code_value()); - codenum = millis(); - while(current_raw[1] < target_raw[1]) - { - if( (millis()-codenum) > 1000 ) //Print Temp Reading every 1 second while heating up. - { - float tt=analog2temp(current_raw[0]); - Serial.print("T:"); - Serial.println( tt ); - Serial.print("ok T:"); - Serial.print( tt ); - Serial.print(" B:"); - Serial.println( analog2temp(current_raw[1]) ); - codenum = millis(); - } - manage_heater(); - } - #endif - break; -#if FAN_PIN > -1 - case 106: //M106 Fan On - if (code_seen('S')){ - WRITE(FAN_PIN,HIGH); - fanpwm=constrain(code_value(),0,255); - analogWrite(FAN_PIN, fanpwm); - } - else { - WRITE(FAN_PIN,HIGH); - fanpwm=255; - analogWrite(FAN_PIN, fanpwm); - } - break; - case 107: //M107 Fan Off - WRITE(FAN_PIN,LOW); - analogWrite(FAN_PIN, 0); - break; -#endif -#if (PS_ON_PIN > -1) - case 80: // M80 - ATX Power On - SET_OUTPUT(PS_ON_PIN); //GND - break; - case 81: // M81 - ATX Power Off - SET_INPUT(PS_ON_PIN); //Floating - break; -#endif - case 82: - axis_relative_modes[3] = false; - break; - case 83: - axis_relative_modes[3] = true; - break; - case 18: - case 84: - if(code_seen('S')){ - stepper_inactive_time = code_value() * 1000; - } - else{ - st_synchronize(); - disable_x(); - disable_y(); - disable_z(); - disable_e(); - } - break; - case 85: // M85 - code_seen('S'); - max_inactive_time = code_value() * 1000; - break; - case 92: // M92 - for(int i=0; i < NUM_AXIS; i++) { - if(code_seen(axis_codes[i])) axis_steps_per_unit[i] = code_value(); - } - - break; - case 115: // M115 - Serial.println("FIRMWARE_NAME:Sprinter/grbl mashup for gen6 FIRMWARE_URL:http://www.mendel-parts.com PROTOCOL_VERSION:1.0 MACHINE_TYPE:Mendel EXTRUDER_COUNT:1"); - break; - case 114: // M114 - Serial.print("X:"); - Serial.print(current_position[X_AXIS]); - Serial.print("Y:"); - Serial.print(current_position[Y_AXIS]); - Serial.print("Z:"); - Serial.print(current_position[Z_AXIS]); - Serial.print("E:"); - Serial.print(current_position[E_AXIS]); - #ifdef DEBUG_STEPS - Serial.print(" Count X:"); - Serial.print(float(count_position[X_AXIS])/axis_steps_per_unit[X_AXIS]); - Serial.print("Y:"); - Serial.print(float(count_position[Y_AXIS])/axis_steps_per_unit[Y_AXIS]); - Serial.print("Z:"); - Serial.println(float(count_position[Z_AXIS])/axis_steps_per_unit[Z_AXIS]); - #endif - Serial.println(""); - break; - case 119: // M119 -#if (X_MIN_PIN > -1) - Serial.print("x_min:"); - Serial.print((READ(X_MIN_PIN)^ENDSTOPS_INVERTING)?"H ":"L "); -#endif -#if (X_MAX_PIN > -1) - Serial.print("x_max:"); - Serial.print((READ(X_MAX_PIN)^ENDSTOPS_INVERTING)?"H ":"L "); -#endif -#if (Y_MIN_PIN > -1) - Serial.print("y_min:"); - Serial.print((READ(Y_MIN_PIN)^ENDSTOPS_INVERTING)?"H ":"L "); -#endif -#if (Y_MAX_PIN > -1) - Serial.print("y_max:"); - Serial.print((READ(Y_MAX_PIN)^ENDSTOPS_INVERTING)?"H ":"L "); -#endif -#if (Z_MIN_PIN > -1) - Serial.print("z_min:"); - Serial.print((READ(Z_MIN_PIN)^ENDSTOPS_INVERTING)?"H ":"L "); -#endif -#if (Z_MAX_PIN > -1) - Serial.print("z_max:"); - Serial.print((READ(Z_MAX_PIN)^ENDSTOPS_INVERTING)?"H ":"L "); -#endif - Serial.println(""); - break; - //TODO: update for all axis, use for loop - case 201: // M201 - for(int i=0; i < NUM_AXIS; i++) { - if(code_seen(axis_codes[i])) axis_steps_per_sqr_second[i] = code_value() * axis_steps_per_unit[i]; - } - break; -#if 0 // Not used for Sprinter/grbl gen6 - case 202: // M202 - for(int i=0; i < NUM_AXIS; i++) { - if(code_seen(axis_codes[i])) axis_travel_steps_per_sqr_second[i] = code_value() * axis_steps_per_unit[i]; - } - break; -#endif - case 203: // M203 max feedrate mm/sec - for(int i=0; i < NUM_AXIS; i++) { - if(code_seen(axis_codes[i])) max_feedrate[i] = code_value()*60 ; - } - break; - case 204: // M204 acclereration S normal moves T filmanent only moves - { - if(code_seen('S')) acceleration = code_value() ; - if(code_seen('T')) retract_acceleration = code_value() ; - } - break; - case 205: //M205 advanced settings: minimum travel speed S=while printing T=travel only, B=minimum segment time X= maximum xy jerk, Z=maximum Z jerk - { - if(code_seen('S')) minimumfeedrate = code_value()*60 ; - if(code_seen('T')) mintravelfeedrate = code_value()*60 ; - if(code_seen('B')) minsegmenttime = code_value() ; - if(code_seen('X')) max_xy_jerk = code_value()*60 ; - if(code_seen('Z')) max_z_jerk = code_value()*60 ; - } - break; - case 220: // M220 S- set speed factor override percentage - { - if(code_seen('S')) - { - feedmultiply = code_value() ; - feedmultiplychanged=true; - } - } - break; -#ifdef PIDTEMP - case 301: // M301 - if(code_seen('P')) Kp = code_value(); - if(code_seen('I')) Ki = code_value()*PID_dT; - if(code_seen('D')) Kd = code_value()/PID_dT; -// ECHOLN("Kp "<<_FLOAT(Kp,2)); -// ECHOLN("Ki "<<_FLOAT(Ki/PID_dT,2)); -// ECHOLN("Kd "<<_FLOAT(Kd*PID_dT,2)); - -// temp_iState_min = 0.0; -// if (Ki!=0) { -// temp_iState_max = PID_INTEGRAL_DRIVE_MAX / (Ki/100.0); -// } -// else temp_iState_max = 1.0e10; - break; -#endif //PIDTEMP - case 500: // Store settings in EEPROM - { - StoreSettings(); - } - break; - case 501: // Read settings from EEPROM - { - RetrieveSettings(); - } - break; - case 502: // Revert to default settings - { - RetrieveSettings(true); - } - break; - - } - } - else{ - Serial.println("Unknown command:"); - Serial.println(cmdbuffer[bufindr]); - } - - ClearToSend(); -} - -void FlushSerialRequestResend() -{ - //char cmdbuffer[bufindr][100]="Resend:"; - Serial.flush(); - Serial.print("Resend:"); - Serial.println(gcode_LastN + 1); - ClearToSend(); -} - -void ClearToSend() -{ - previous_millis_cmd = millis(); -#ifdef SDSUPPORT - if(fromsd[bufindr]) - return; -#endif //SDSUPPORT - Serial.println("ok"); -} - -inline void get_coordinates() -{ - for(int i=0; i < NUM_AXIS; i++) { - if(code_seen(axis_codes[i])) destination[i] = (float)code_value() + (axis_relative_modes[i] || relative_mode)*current_position[i]; - else destination[i] = current_position[i]; //Are these else lines really needed? - } - if(code_seen('F')) { - next_feedrate = code_value(); - if(next_feedrate > 0.0) feedrate = next_feedrate; - } -} - -void prepare_move() -{ - plan_buffer_line(destination[X_AXIS], destination[Y_AXIS], destination[Z_AXIS], destination[E_AXIS], feedrate*feedmultiply/60.0/100.0); - for(int i=0; i < NUM_AXIS; i++) { - current_position[i] = destination[i]; - } -} - - - -#ifdef USE_WATCHDOG - -#include -#include - -volatile uint8_t timeout_seconds=0; - -void(* ctrlaltdelete) (void) = 0; - -ISR(WDT_vect) { //Watchdog timer interrupt, called if main program blocks >1sec - if(timeout_seconds++ >= WATCHDOG_TIMEOUT) - { - kill(); -#ifdef RESET_MANUAL - LCD_MESSAGE("Please Reset!"); - ECHOLN("echo_: Something is wrong, please turn off the printer."); -#else - LCD_MESSAGE("Timeout, resetting!"); -#endif - //disable watchdog, it will survife reboot. - WDTCSR |= (1< -1 - target_raw[0]=0; - #if HEATER_0_PIN > -1 - WRITE(HEATER_0_PIN,LOW); - #endif - #endif - #if TEMP_1_PIN > -1 - target_raw[1]=0; - #if HEATER_1_PIN > -1 - WRITE(HEATER_1_PIN,LOW); - #endif - #endif - #if TEMP_2_PIN > -1 - target_raw[2]=0; - #if HEATER_2_PIN > -1 - WRITE(HEATER_2_PIN,LOW); - #endif - #endif - disable_x(); - disable_y(); - disable_z(); - disable_e(); - - if(PS_ON_PIN > -1) pinMode(PS_ON_PIN,INPUT); - Serial.println("!! Printer halted. kill() called!!"); - while(1); // Wait for reset -} - -void manage_inactivity(byte debug) { - if( (millis()-previous_millis_cmd) > max_inactive_time ) if(max_inactive_time) kill(); - if( (millis()-previous_millis_cmd) > stepper_inactive_time ) if(stepper_inactive_time) { - disable_x(); - disable_y(); - disable_z(); - disable_e(); - } - check_axes_activity(); -} +/* + Reprap firmware based on Sprinter and grbl. + Copyright (C) 2011 Camiel Gubbels / Erik van der Zalm + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + */ + +/* + This firmware is a mashup between Sprinter and grbl. + (https://github.com/kliment/Sprinter) + (https://github.com/simen/grbl/tree) + + It has preliminary support for Matthew Roberts advance algorithm + http://reprap.org/pipermail/reprap-dev/2011-May/003323.html + */ + +#include "EEPROMwrite.h" +#include "fastio.h" +#include "Configuration.h" +#include "pins.h" +#include "Marlin.h" +#include "ultralcd.h" +#include "streaming.h" +#include "planner.h" +#include "stepper.h" +#include "temperature.h" + +#ifdef SIMPLE_LCD + #include "Simplelcd.h" +#endif + +char version_string[] = "1.0.0 Alpha 1"; + +#ifdef SDSUPPORT +#include "SdFat.h" +#endif //SDSUPPORT + + +// look here for descriptions of gcodes: http://linuxcnc.org/handbook/gcode/g-code.html +// http://objects.reprap.org/wiki/Mendel_User_Manual:_RepRapGCodes + +//Implemented Codes +//------------------- +// G0 -> G1 +// G1 - Coordinated Movement X Y Z E +// G4 - Dwell S or P +// G28 - Home all Axis +// G90 - Use Absolute Coordinates +// G91 - Use Relative Coordinates +// G92 - Set current position to cordinates given + +//RepRap M Codes +// M104 - Set extruder target temp +// M105 - Read current temp +// M106 - Fan on +// M107 - Fan off +// M109 - Wait for extruder current temp to reach target temp. +// M114 - Display current position + +//Custom M Codes +// M20 - List SD card +// M21 - Init SD card +// M22 - Release SD card +// M23 - Select SD file (M23 filename.g) +// M24 - Start/resume SD print +// M25 - Pause SD print +// M26 - Set SD position in bytes (M26 S12345) +// M27 - Report SD print status +// M28 - Start SD write (M28 filename.g) +// M29 - Stop SD write +// M42 - Change pin status via gcode +// M80 - Turn on Power Supply +// M81 - Turn off Power Supply +// M82 - Set E codes absolute (default) +// M83 - Set E codes relative while in Absolute Coordinates (G90) mode +// M84 - Disable steppers until next move, +// or use S to specify an inactivity timeout, after which the steppers will be disabled. S0 to disable the timeout. +// M85 - Set inactivity shutdown timer with parameter S. To disable set zero (default) +// M92 - Set axis_steps_per_unit - same syntax as G92 +// M115 - Capabilities string +// M140 - Set bed target temp +// M190 - Wait for bed current temp to reach target temp. +// M200 - Set filament diameter +// M201 - Set max acceleration in units/s^2 for print moves (M201 X1000 Y1000) +// 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 +// M205 - advanced settings: minimum travel speed S=while printing T=travel only, B=minimum segment time X= maximum xy jerk, Z=maximum Z jerk +// M220 - set speed factor override percentage S:factor in percent +// M301 - Set PID parameters P I and D +// M500 - stores paramters in EEPROM +// M501 - reads parameters from EEPROM (if you need reset them after you changed them temporarily). D +// M502 - reverts to the default "factory settings". You still need to store them in EEPROM afterwards if you want to. + +//Stepper Movement Variables + +char axis_codes[NUM_AXIS] = { + 'X', 'Y', 'Z', 'E'}; +float destination[NUM_AXIS] = { + 0.0, 0.0, 0.0, 0.0}; +float current_position[NUM_AXIS] = { + 0.0, 0.0, 0.0, 0.0}; +bool home_all_axis = true; +float feedrate = 1500.0, next_feedrate, saved_feedrate; +long gcode_N, gcode_LastN; + +float homing_feedrate[] = HOMING_FEEDRATE; +bool axis_relative_modes[] = AXIS_RELATIVE_MODES; + +bool relative_mode = false; //Determines Absolute or Relative Coordinates +bool relative_mode_e = false; //Determines Absolute or Relative E Codes while in Absolute Coordinates mode. E is always relative in Relative Coordinates mode. + +uint8_t fanpwm=0; + +volatile int feedmultiply=100; //100->1 200->2 +int saved_feedmultiply; +volatile bool feedmultiplychanged=false; +// comm variables +#define MAX_CMD_SIZE 96 +#define BUFSIZE 4 +char cmdbuffer[BUFSIZE][MAX_CMD_SIZE]; +bool fromsd[BUFSIZE]; +int bufindr = 0; +int bufindw = 0; +int buflen = 0; +int i = 0; +char serial_char; +int serial_count = 0; +boolean comment_mode = false; +char *strchr_pointer; // just a pointer to find chars in the cmd string like X, Y, Z, E, etc +extern float HeaterPower; + +#include "EEPROM.h" + +const int sensitive_pins[] = SENSITIVE_PINS; // Sensitive pin list for M42 + +float tt = 0, bt = 0; +#ifdef WATCHPERIOD +int watch_raw = -1000; +unsigned long watchmillis = 0; +#endif //WATCHPERIOD + +//Inactivity shutdown variables +unsigned long previous_millis_cmd = 0; +unsigned long max_inactive_time = 0; +unsigned long stepper_inactive_time = 0; + +unsigned long starttime=0; +unsigned long stoptime=0; +#ifdef SDSUPPORT +Sd2Card card; +SdVolume volume; +SdFile root; +SdFile file; +uint32_t filesize = 0; +uint32_t sdpos = 0; +bool sdmode = false; +bool sdactive = false; +bool savetosd = false; +int16_t n; +unsigned long autostart_atmillis=0; + +void initsd(){ + sdactive = false; +#if SDSS >- 1 + if(root.isOpen()) + root.close(); + if (!card.init(SPI_FULL_SPEED,SDSS)){ + //if (!card.init(SPI_HALF_SPEED,SDSS)) + Serial.println("SD init fail"); + } + else if (!volume.init(&card)) + Serial.println("volume.init failed"); + else if (!root.openRoot(&volume)) + Serial.println("openRoot failed"); + else + { + sdactive = true; + Serial.println("SD card ok"); + } +#endif //SDSS +} + +void quickinitsd(){ + sdactive=false; + autostart_atmillis=millis()+5000; +} + +inline void write_command(char *buf){ + char* begin = buf; + char* npos = 0; + char* end = buf + strlen(buf) - 1; + + file.writeError = false; + if((npos = strchr(buf, 'N')) != NULL){ + begin = strchr(npos, ' ') + 1; + end = strchr(npos, '*') - 1; + } + end[1] = '\r'; + end[2] = '\n'; + end[3] = '\0'; + //Serial.println(begin); + file.write(begin); + if (file.writeError){ + Serial.println("error writing to file"); + } +} +#endif //SDSUPPORT + + +///adds an command to the main command buffer +void enquecommand(const char *cmd) +{ + if(buflen < BUFSIZE) + { + //this is dangerous if a mixing of serial and this happsens + strcpy(&(cmdbuffer[bufindw][0]),cmd); + Serial.print("en:");Serial.println(cmdbuffer[bufindw]); + bufindw= (bufindw + 1)%BUFSIZE; + buflen += 1; + } +} + +void setup() +{ + + Serial.begin(BAUDRATE); + ECHOLN("Marlin "< -1 + SET_OUTPUT(SDPOWER); + WRITE(SDPOWER,HIGH); +#endif //SDPOWER + quickinitsd(); + +#endif //SDSUPPORT + plan_init(); // Initialize planner; + st_init(); // Initialize stepper; + tp_init(); // Initialize temperature loop + //checkautostart(); +} + +#ifdef SDSUPPORT +bool autostart_stilltocheck=true; + + +void checkautostart(bool force) +{ + //this is to delay autostart and hence the initialisaiton of the sd card to some seconds after the normal init, so the device is available quick after a reset + if(!force) + { + if(!autostart_stilltocheck) + return; + if(autostart_atmillis 0) + { + for(int i=0;i<(int)strlen((char*)p.name);i++) + p.name[i]=tolower(p.name[i]); + //Serial.print((char*)p.name); + //Serial.print(" "); + //Serial.println(autoname); + if(p.name[9]!='~') //skip safety copies + if(strncmp((char*)p.name,autoname,5)==0) + { + char cmd[30]; + + sprintf(cmd,"M23 %s",autoname); + //sprintf(cmd,"M115"); + //enquecommand("G92 Z0"); + //enquecommand("G1 Z10 F2000"); + //enquecommand("G28 X-105 Y-105"); + enquecommand(cmd); + enquecommand("M24"); + found=true; + + } + } + if(!found) + lastnr=-1; + else + lastnr++; + +} +#else + +inline void checkautostart(bool x) +{ +} +#endif + + +void loop() +{ + if(buflen<3) + get_command(); + checkautostart(false); + if(buflen) + { +#ifdef SDSUPPORT + if(savetosd){ + if(strstr(cmdbuffer[bufindr],"M29") == NULL){ + write_command(cmdbuffer[bufindr]); + Serial.println("ok"); + } + else{ + file.sync(); + file.close(); + savetosd = false; + Serial.println("Done saving file."); + } + } + else{ + process_commands(); + } +#else + process_commands(); +#endif //SDSUPPORT + buflen = (buflen-1); + bufindr = (bufindr + 1)%BUFSIZE; + } + //check heater every n milliseconds + manage_heater(); + manage_inactivity(1); + LCD_STATUS; +} + + +inline void get_command() +{ + while( Serial.available() > 0 && buflen < BUFSIZE) { + serial_char = Serial.read(); + if(serial_char == '\n' || serial_char == '\r' || serial_char == ':' || serial_count >= (MAX_CMD_SIZE - 1) ) + { + if(!serial_count) return; //if empty line + cmdbuffer[bufindw][serial_count] = 0; //terminate string + if(!comment_mode){ + fromsd[bufindw] = false; + if(strstr(cmdbuffer[bufindw], "N") != NULL) + { + strchr_pointer = strchr(cmdbuffer[bufindw], 'N'); + gcode_N = (strtol(&cmdbuffer[bufindw][strchr_pointer - cmdbuffer[bufindw] + 1], NULL, 10)); + if(gcode_N != gcode_LastN+1 && (strstr(cmdbuffer[bufindw], "M110") == NULL) ) { + Serial.print("Serial Error: Line Number is not Last Line Number+1, Last Line:"); + Serial.println(gcode_LastN); + //Serial.println(gcode_N); + FlushSerialRequestResend(); + serial_count = 0; + return; + } + + if(strstr(cmdbuffer[bufindw], "*") != NULL) + { + byte checksum = 0; + byte count = 0; + while(cmdbuffer[bufindw][count] != '*') checksum = checksum^cmdbuffer[bufindw][count++]; + strchr_pointer = strchr(cmdbuffer[bufindw], '*'); + + if( (int)(strtod(&cmdbuffer[bufindw][strchr_pointer - cmdbuffer[bufindw] + 1], NULL)) != checksum) { + Serial.print("Error: checksum mismatch, Last Line:"); + Serial.println(gcode_LastN); + FlushSerialRequestResend(); + serial_count = 0; + return; + } + //if no errors, continue parsing + } + else + { + Serial.print("Error: No Checksum with line number, Last Line:"); + Serial.println(gcode_LastN); + FlushSerialRequestResend(); + serial_count = 0; + return; + } + + gcode_LastN = gcode_N; + //if no errors, continue parsing + } + else // if we don't receive 'N' but still see '*' + { + if((strstr(cmdbuffer[bufindw], "*") != NULL)) + { + Serial.print("Error: No Line Number with checksum, Last Line:"); + Serial.println(gcode_LastN); + serial_count = 0; + return; + } + } + if((strstr(cmdbuffer[bufindw], "G") != NULL)){ + strchr_pointer = strchr(cmdbuffer[bufindw], 'G'); + switch((int)((strtod(&cmdbuffer[bufindw][strchr_pointer - cmdbuffer[bufindw] + 1], NULL)))){ + case 0: + case 1: +#ifdef SDSUPPORT + if(savetosd) + break; +#endif //SDSUPPORT + Serial.println("ok"); + break; + default: + break; + } + + } + bufindw = (bufindw + 1)%BUFSIZE; + buflen += 1; + + } + comment_mode = false; //for new command + serial_count = 0; //clear buffer + } + else + { + if(serial_char == ';') comment_mode = true; + if(!comment_mode) cmdbuffer[bufindw][serial_count++] = serial_char; + } + } +#ifdef SDSUPPORT + if(!sdmode || serial_count!=0){ + return; + } + while( filesize > sdpos && buflen < BUFSIZE) { + n = file.read(); + serial_char = (char)n; + if(serial_char == '\n' || serial_char == '\r' || serial_char == ':' || serial_count >= (MAX_CMD_SIZE - 1) || n == -1) + { + sdpos = file.curPosition(); + if(sdpos >= filesize){ + sdmode = false; + Serial.println("Done printing file"); + stoptime=millis(); + char time[30]; + unsigned long t=(stoptime-starttime)/1000; + int sec,min; + min=t/60; + sec=t%60; + sprintf(time,"%i min, %i sec",min,sec); + Serial.println(time); + LCD_MESSAGE(time); + checkautostart(true); + } + if(!serial_count) return; //if empty line + cmdbuffer[bufindw][serial_count] = 0; //terminate string + if(!comment_mode){ + fromsd[bufindw] = true; + buflen += 1; + bufindw = (bufindw + 1)%BUFSIZE; + } + comment_mode = false; //for new command + serial_count = 0; //clear buffer + } + else + { + if(serial_char == ';') comment_mode = true; + if(!comment_mode) cmdbuffer[bufindw][serial_count++] = serial_char; + } + } +#endif //SDSUPPORT + +} + + +inline float code_value() { + return (strtod(&cmdbuffer[bufindr][strchr_pointer - cmdbuffer[bufindr] + 1], NULL)); +} +inline long code_value_long() { + return (strtol(&cmdbuffer[bufindr][strchr_pointer - cmdbuffer[bufindr] + 1], NULL, 10)); +} +inline bool code_seen(char code_string[]) { + return (strstr(cmdbuffer[bufindr], code_string) != NULL); +} //Return True if the string was found + +inline bool code_seen(char code) +{ + strchr_pointer = strchr(cmdbuffer[bufindr], code); + return (strchr_pointer != NULL); //Return True if a character was found +} + +inline void process_commands() +{ + unsigned long codenum; //throw away variable + char *starpos = NULL; + + if(code_seen('G')) + { + switch((int)code_value()) + { + case 0: // G0 -> G1 + case 1: // G1 + get_coordinates(); // For X Y Z E F + prepare_move(); + previous_millis_cmd = millis(); + //ClearToSend(); + return; + //break; + case 4: // G4 dwell + codenum = 0; + if(code_seen('P')) codenum = code_value(); // milliseconds to wait + if(code_seen('S')) codenum = code_value() * 1000; // seconds to wait + codenum += millis(); // keep track of when we started waiting + while(millis() < codenum ){ + manage_heater(); + } + break; + case 28: //G28 Home all Axis one at a time + saved_feedrate = feedrate; + saved_feedmultiply = feedmultiply; + feedmultiply = 100; + + for(int i=0; i < NUM_AXIS; i++) { + destination[i] = current_position[i]; + } + feedrate = 0.0; + + home_all_axis = !((code_seen(axis_codes[0])) || (code_seen(axis_codes[1])) || (code_seen(axis_codes[2]))); + + if((home_all_axis) || (code_seen(axis_codes[X_AXIS]))) { + if ((X_MIN_PIN > -1 && X_HOME_DIR==-1) || (X_MAX_PIN > -1 && X_HOME_DIR==1)){ +// st_synchronize(); + current_position[X_AXIS] = 0; + plan_set_position(current_position[X_AXIS], current_position[Y_AXIS], current_position[Z_AXIS], current_position[E_AXIS]); + destination[X_AXIS] = 1.5 * X_MAX_LENGTH * X_HOME_DIR; + feedrate = homing_feedrate[X_AXIS]; + prepare_move(); + +// st_synchronize(); + current_position[X_AXIS] = 0; + plan_set_position(current_position[X_AXIS], current_position[Y_AXIS], current_position[Z_AXIS], current_position[E_AXIS]); + destination[X_AXIS] = -5 * X_HOME_DIR; + prepare_move(); + +// st_synchronize(); + destination[X_AXIS] = 10 * X_HOME_DIR; + feedrate = homing_feedrate[X_AXIS]/2 ; + prepare_move(); + +// st_synchronize(); + current_position[X_AXIS] = (X_HOME_DIR == -1) ? 0 : X_MAX_LENGTH; + plan_set_position(current_position[X_AXIS], current_position[Y_AXIS], current_position[Z_AXIS], current_position[E_AXIS]); + destination[X_AXIS] = current_position[X_AXIS]; + feedrate = 0.0; + } + } + + if((home_all_axis) || (code_seen(axis_codes[Y_AXIS]))) { + if ((Y_MIN_PIN > -1 && Y_HOME_DIR==-1) || (Y_MAX_PIN > -1 && Y_HOME_DIR==1)){ + current_position[Y_AXIS] = 0; + plan_set_position(current_position[X_AXIS], current_position[Y_AXIS], current_position[Z_AXIS], current_position[E_AXIS]); + destination[Y_AXIS] = 1.5 * Y_MAX_LENGTH * Y_HOME_DIR; + feedrate = homing_feedrate[Y_AXIS]; + prepare_move(); +// st_synchronize(); + + current_position[Y_AXIS] = 0; + plan_set_position(current_position[X_AXIS], current_position[Y_AXIS], current_position[Z_AXIS], current_position[E_AXIS]); + destination[Y_AXIS] = -5 * Y_HOME_DIR; + prepare_move(); +// st_synchronize(); + + destination[Y_AXIS] = 10 * Y_HOME_DIR; + feedrate = homing_feedrate[Y_AXIS]/2; + prepare_move(); +// st_synchronize(); + + current_position[Y_AXIS] = (Y_HOME_DIR == -1) ? 0 : Y_MAX_LENGTH; + plan_set_position(current_position[X_AXIS], current_position[Y_AXIS], current_position[Z_AXIS], current_position[E_AXIS]); + destination[Y_AXIS] = current_position[Y_AXIS]; + feedrate = 0.0; + } + } + + if((home_all_axis) || (code_seen(axis_codes[Z_AXIS]))) { + if ((Z_MIN_PIN > -1 && Z_HOME_DIR==-1) || (Z_MAX_PIN > -1 && Z_HOME_DIR==1)){ + current_position[Z_AXIS] = 0; + plan_set_position(current_position[X_AXIS], current_position[Y_AXIS], current_position[Z_AXIS], current_position[E_AXIS]); + destination[Z_AXIS] = 1.5 * Z_MAX_LENGTH * Z_HOME_DIR; + feedrate = homing_feedrate[Z_AXIS]; + prepare_move(); +// st_synchronize(); + + current_position[Z_AXIS] = 0; + plan_set_position(current_position[X_AXIS], current_position[Y_AXIS], current_position[Z_AXIS], current_position[E_AXIS]); + destination[Z_AXIS] = -2 * Z_HOME_DIR; + prepare_move(); +// st_synchronize(); + + destination[Z_AXIS] = 3 * Z_HOME_DIR; + feedrate = homing_feedrate[Z_AXIS]/2; + prepare_move(); +// st_synchronize(); + + current_position[Z_AXIS] = (Z_HOME_DIR == -1) ? 0 : Z_MAX_LENGTH; + plan_set_position(current_position[X_AXIS], current_position[Y_AXIS], current_position[Z_AXIS], current_position[E_AXIS]); + destination[Z_AXIS] = current_position[Z_AXIS]; + feedrate = 0.0; + } + } + feedrate = saved_feedrate; + feedmultiply = saved_feedmultiply; + previous_millis_cmd = millis(); + break; + case 90: // G90 + relative_mode = false; + break; + case 91: // G91 + relative_mode = true; + break; + case 92: // G92 + if(!code_seen(axis_codes[E_AXIS])) + st_synchronize(); + for(int i=0; i < NUM_AXIS; i++) { + if(code_seen(axis_codes[i])) current_position[i] = code_value(); + } + plan_set_position(current_position[X_AXIS], current_position[Y_AXIS], current_position[Z_AXIS], current_position[E_AXIS]); + break; + } + } + + else if(code_seen('M')) + { + + switch( (int)code_value() ) + { +#ifdef SDSUPPORT + + case 20: // M20 - list SD card + Serial.println("Begin file list"); + root.ls(); + Serial.println("End file list"); + break; + case 21: // M21 - init SD card + sdmode = false; + initsd(); + break; + case 22: //M22 - release SD card + sdmode = false; + sdactive = false; + break; + case 23: //M23 - Select file + if(sdactive){ + sdmode = false; + file.close(); + starpos = (strchr(strchr_pointer + 4,'*')); + if(starpos!=NULL) + *(starpos-1)='\0'; + if (file.open(&root, strchr_pointer + 4, O_READ)) { + Serial.print("File opened:"); + Serial.print(strchr_pointer + 4); + Serial.print(" Size:"); + Serial.println(file.fileSize()); + sdpos = 0; + filesize = file.fileSize(); + Serial.println("File selected"); + } + else{ + Serial.println("file.open failed"); + } + } + break; + case 24: //M24 - Start SD print + if(sdactive){ + sdmode = true; + starttime=millis(); + } + break; + case 25: //M25 - Pause SD print + if(sdmode){ + sdmode = false; + } + break; + case 26: //M26 - Set SD index + if(sdactive && code_seen('S')){ + sdpos = code_value_long(); + file.seekSet(sdpos); + } + break; + case 27: //M27 - Get SD status + if(sdactive){ + Serial.print("SD printing byte "); + Serial.print(sdpos); + Serial.print("/"); + Serial.println(filesize); + } + else{ + Serial.println("Not SD printing"); + } + break; + case 28: //M28 - Start SD write + if(sdactive){ + char* npos = 0; + file.close(); + sdmode = false; + starpos = (strchr(strchr_pointer + 4,'*')); + if(starpos != NULL){ + npos = strchr(cmdbuffer[bufindr], 'N'); + strchr_pointer = strchr(npos,' ') + 1; + *(starpos-1) = '\0'; + } + if (!file.open(&root, strchr_pointer+4, O_CREAT | O_APPEND | O_WRITE | O_TRUNC)) + { + Serial.print("open failed, File: "); + Serial.print(strchr_pointer + 4); + Serial.print("."); + } + else{ + savetosd = true; + Serial.print("Writing to file: "); + Serial.println(strchr_pointer + 4); + } + } + break; + case 29: //M29 - Stop SD write + //processed in write to file routine above + //savetosd = false; + break; + case 30: + { + stoptime=millis(); + char time[30]; + unsigned long t=(stoptime-starttime)/1000; + int sec,min; + min=t/60; + sec=t%60; + sprintf(time,"%i min, %i sec",min,sec); + Serial.println(time); + LCD_MESSAGE(time); + } + break; +#endif //SDSUPPORT + case 42: //M42 -Change pin status via gcode + if (code_seen('S')) + { + int pin_status = code_value(); + if (code_seen('P') && pin_status >= 0 && pin_status <= 255) + { + int pin_number = code_value(); + for(int i = 0; i < (int)sizeof(sensitive_pins); i++) + { + if (sensitive_pins[i] == pin_number) + { + pin_number = -1; + break; + } + } + + if (pin_number > -1) + { + pinMode(pin_number, OUTPUT); + digitalWrite(pin_number, pin_status); + analogWrite(pin_number, pin_status); + } + } + } + break; + case 104: // M104 + if (code_seen('S')) target_raw[TEMPSENSOR_HOTEND] = temp2analog(code_value()); +#ifdef PIDTEMP + pid_setpoint = code_value(); +#endif //PIDTEM + #ifdef WATCHPERIOD + if(target_raw[TEMPSENSOR_HOTEND] > current_raw[TEMPSENSOR_HOTEND]){ + watchmillis = max(1,millis()); + watch_raw[TEMPSENSOR_HOTEND] = current_raw[TEMPSENSOR_HOTEND]; + }else{ + watchmillis = 0; + } + #endif + break; + case 140: // M140 set bed temp + if (code_seen('S')) target_raw[TEMPSENSOR_BED] = temp2analogBed(code_value()); + break; + case 105: // M105 + #if (TEMP_0_PIN > -1) || defined (HEATER_USES_AD595) + tt = analog2temp(current_raw[TEMPSENSOR_HOTEND]); + #endif + #if TEMP_1_PIN > -1 + bt = analog2tempBed(current_raw[TEMPSENSOR_BED]); + #endif + #if (TEMP_0_PIN > -1) || defined (HEATER_USES_AD595) + Serial.print("ok T:"); + Serial.print(tt); +// Serial.print(", raw:"); +// Serial.print(current_raw); + #if TEMP_1_PIN > -1 +#ifdef PIDTEMP + Serial.print(" B:"); + #if TEMP_1_PIN > -1 + Serial.println(bt); + #else + Serial.println(HeaterPower); + #endif +#else + Serial.println(); +#endif + #else + Serial.println(); + #endif + #else + Serial.println("No thermistors - no temp"); + #endif + return; + //break; + case 109: {// M109 - Wait for extruder heater to reach target. + LCD_MESSAGE("Heating..."); + if (code_seen('S')) target_raw[TEMPSENSOR_HOTEND] = temp2analog(code_value()); + #ifdef PIDTEMP + pid_setpoint = code_value(); + #endif //PIDTEM + #ifdef WATCHPERIOD + if(target_raw[TEMPSENSOR_HOTEND]>current_raw[TEMPSENSOR_HOTEND]){ + watchmillis = max(1,millis()); + watch_raw[TEMPSENSOR_HOTEND] = current_raw[TEMPSENSOR_HOTEND]; + } else { + watchmillis = 0; + } + #endif //WATCHPERIOD + codenum = millis(); + + /* See if we are heating up or cooling down */ + bool target_direction = (current_raw[0] < target_raw[0]); // true if heating, false if cooling + + #ifdef TEMP_RESIDENCY_TIME + long residencyStart; + residencyStart = -1; + /* continue to loop until we have reached the target temp + _and_ until TEMP_RESIDENCY_TIME hasn't passed since we reached it */ + while((target_direction ? (current_raw[0] < target_raw[0]) : (current_raw[0] > target_raw[0])) || + (residencyStart > -1 && (millis() - residencyStart) < TEMP_RESIDENCY_TIME*1000) ) { + #else + while ( target_direction ? (current_raw[0] < target_raw[0]) : (current_raw[0] > target_raw[0]) ) { + #endif //TEMP_RESIDENCY_TIME + if( (millis() - codenum) > 1000 ) { //Print Temp Reading every 1 second while heating up/cooling down + Serial.print("T:"); + Serial.println( analog2temp(current_raw[TEMPSENSOR_HOTEND]) ); + codenum = millis(); + } + manage_heater(); + LCD_STATUS; + #ifdef TEMP_RESIDENCY_TIME + /* start/restart the TEMP_RESIDENCY_TIME timer whenever we reach target temp for the first time + or when current temp falls outside the hysteresis after target temp was reached */ + if ((residencyStart == -1 && target_direction && current_raw[0] >= target_raw[0]) || + (residencyStart == -1 && !target_direction && current_raw[0] <= target_raw[0]) || + (residencyStart > -1 && labs(analog2temp(current_raw[0]) - analog2temp(target_raw[0])) > TEMP_HYSTERESIS) ) { + residencyStart = millis(); + } + #endif //TEMP_RESIDENCY_TIME + } + LCD_MESSAGE("Marlin ready."); + } + break; + case 190: // M190 - Wait bed for heater to reach target. + #if TEMP_1_PIN > -1 + if (code_seen('S')) target_raw[TEMPSENSOR_BED] = temp2analog(code_value()); + codenum = millis(); + while(current_raw[TEMPSENSOR_BED] < target_raw[TEMPSENSOR_BED]) + { + if( (millis()-codenum) > 1000 ) //Print Temp Reading every 1 second while heating up. + { + float tt=analog2temp(current_raw[TEMPSENSOR_HOTEND]); + Serial.print("T:"); + Serial.println( tt ); + Serial.print("ok T:"); + Serial.print( tt ); + Serial.print(" B:"); + Serial.println( analog2temp(current_raw[TEMPSENSOR_BED]) ); + codenum = millis(); + } + manage_heater(); + } + #endif + break; +#if FAN_PIN > -1 + case 106: //M106 Fan On + if (code_seen('S')){ + WRITE(FAN_PIN,HIGH); + fanpwm=constrain(code_value(),0,255); + analogWrite(FAN_PIN, fanpwm); + } + else { + WRITE(FAN_PIN,HIGH); + fanpwm=255; + analogWrite(FAN_PIN, fanpwm); + } + break; + case 107: //M107 Fan Off + WRITE(FAN_PIN,LOW); + analogWrite(FAN_PIN, 0); + break; +#endif +#if (PS_ON_PIN > -1) + case 80: // M80 - ATX Power On + SET_OUTPUT(PS_ON_PIN); //GND + break; + case 81: // M81 - ATX Power Off + SET_INPUT(PS_ON_PIN); //Floating + break; +#endif + case 82: + axis_relative_modes[3] = false; + break; + case 83: + axis_relative_modes[3] = true; + break; + case 18: + case 84: + if(code_seen('S')){ + stepper_inactive_time = code_value() * 1000; + } + else{ + st_synchronize(); + disable_x(); + disable_y(); + disable_z(); + disable_e(); + } + break; + case 85: // M85 + code_seen('S'); + max_inactive_time = code_value() * 1000; + break; + case 92: // M92 + for(int i=0; i < NUM_AXIS; i++) { + if(code_seen(axis_codes[i])) axis_steps_per_unit[i] = code_value(); + } + + break; + case 115: // M115 + Serial.println("FIRMWARE_NAME:Sprinter/grbl mashup for gen6 FIRMWARE_URL:http://www.mendel-parts.com PROTOCOL_VERSION:1.0 MACHINE_TYPE:Mendel EXTRUDER_COUNT:1"); + break; + case 114: // M114 + Serial.print("X:"); + Serial.print(current_position[X_AXIS]); + Serial.print("Y:"); + Serial.print(current_position[Y_AXIS]); + Serial.print("Z:"); + Serial.print(current_position[Z_AXIS]); + Serial.print("E:"); + Serial.print(current_position[E_AXIS]); + #ifdef DEBUG_STEPS + Serial.print(" Count X:"); + Serial.print(float(count_position[X_AXIS])/axis_steps_per_unit[X_AXIS]); + Serial.print("Y:"); + Serial.print(float(count_position[Y_AXIS])/axis_steps_per_unit[Y_AXIS]); + Serial.print("Z:"); + Serial.println(float(count_position[Z_AXIS])/axis_steps_per_unit[Z_AXIS]); + #endif + Serial.println(""); + break; + case 119: // M119 +#if (X_MIN_PIN > -1) + Serial.print("x_min:"); + Serial.print((READ(X_MIN_PIN)^ENDSTOPS_INVERTING)?"H ":"L "); +#endif +#if (X_MAX_PIN > -1) + Serial.print("x_max:"); + Serial.print((READ(X_MAX_PIN)^ENDSTOPS_INVERTING)?"H ":"L "); +#endif +#if (Y_MIN_PIN > -1) + Serial.print("y_min:"); + Serial.print((READ(Y_MIN_PIN)^ENDSTOPS_INVERTING)?"H ":"L "); +#endif +#if (Y_MAX_PIN > -1) + Serial.print("y_max:"); + Serial.print((READ(Y_MAX_PIN)^ENDSTOPS_INVERTING)?"H ":"L "); +#endif +#if (Z_MIN_PIN > -1) + Serial.print("z_min:"); + Serial.print((READ(Z_MIN_PIN)^ENDSTOPS_INVERTING)?"H ":"L "); +#endif +#if (Z_MAX_PIN > -1) + Serial.print("z_max:"); + Serial.print((READ(Z_MAX_PIN)^ENDSTOPS_INVERTING)?"H ":"L "); +#endif + Serial.println(""); + break; + //TODO: update for all axis, use for loop + case 201: // M201 + for(int i=0; i < NUM_AXIS; i++) { + if(code_seen(axis_codes[i])) axis_steps_per_sqr_second[i] = code_value() * axis_steps_per_unit[i]; + } + break; +#if 0 // Not used for Sprinter/grbl gen6 + case 202: // M202 + for(int i=0; i < NUM_AXIS; i++) { + if(code_seen(axis_codes[i])) axis_travel_steps_per_sqr_second[i] = code_value() * axis_steps_per_unit[i]; + } + break; +#endif + case 203: // M203 max feedrate mm/sec + for(int i=0; i < NUM_AXIS; i++) { + if(code_seen(axis_codes[i])) max_feedrate[i] = code_value()*60 ; + } + break; + case 204: // M204 acclereration S normal moves T filmanent only moves + { + if(code_seen('S')) acceleration = code_value() ; + if(code_seen('T')) retract_acceleration = code_value() ; + } + break; + case 205: //M205 advanced settings: minimum travel speed S=while printing T=travel only, B=minimum segment time X= maximum xy jerk, Z=maximum Z jerk + { + if(code_seen('S')) minimumfeedrate = code_value()*60 ; + if(code_seen('T')) mintravelfeedrate = code_value()*60 ; + if(code_seen('B')) minsegmenttime = code_value() ; + if(code_seen('X')) max_xy_jerk = code_value()*60 ; + if(code_seen('Z')) max_z_jerk = code_value()*60 ; + } + break; + case 220: // M220 S- set speed factor override percentage + { + if(code_seen('S')) + { + feedmultiply = code_value() ; + feedmultiplychanged=true; + } + } + break; +#ifdef PIDTEMP + case 301: // M301 + if(code_seen('P')) Kp = code_value(); + if(code_seen('I')) Ki = code_value()*PID_dT; + if(code_seen('D')) Kd = code_value()/PID_dT; +// ECHOLN("Kp "<<_FLOAT(Kp,2)); +// ECHOLN("Ki "<<_FLOAT(Ki/PID_dT,2)); +// ECHOLN("Kd "<<_FLOAT(Kd*PID_dT,2)); + +// temp_iState_min = 0.0; +// if (Ki!=0) { +// temp_iState_max = PID_INTEGRAL_DRIVE_MAX / (Ki/100.0); +// } +// else temp_iState_max = 1.0e10; + break; +#endif //PIDTEMP + case 500: // Store settings in EEPROM + { + StoreSettings(); + } + break; + case 501: // Read settings from EEPROM + { + RetrieveSettings(); + } + break; + case 502: // Revert to default settings + { + RetrieveSettings(true); + } + break; + + } + } + else{ + Serial.println("Unknown command:"); + Serial.println(cmdbuffer[bufindr]); + } + + ClearToSend(); +} + +void FlushSerialRequestResend() +{ + //char cmdbuffer[bufindr][100]="Resend:"; + Serial.flush(); + Serial.print("Resend:"); + Serial.println(gcode_LastN + 1); + ClearToSend(); +} + +void ClearToSend() +{ + previous_millis_cmd = millis(); +#ifdef SDSUPPORT + if(fromsd[bufindr]) + return; +#endif //SDSUPPORT + Serial.println("ok"); +} + +inline void get_coordinates() +{ + for(int i=0; i < NUM_AXIS; i++) { + if(code_seen(axis_codes[i])) destination[i] = (float)code_value() + (axis_relative_modes[i] || relative_mode)*current_position[i]; + else destination[i] = current_position[i]; //Are these else lines really needed? + } + if(code_seen('F')) { + next_feedrate = code_value(); + if(next_feedrate > 0.0) feedrate = next_feedrate; + } +} + +void prepare_move() +{ + plan_buffer_line(destination[X_AXIS], destination[Y_AXIS], destination[Z_AXIS], destination[E_AXIS], feedrate*feedmultiply/60.0/100.0); + for(int i=0; i < NUM_AXIS; i++) { + current_position[i] = destination[i]; + } +} + + + +#ifdef USE_WATCHDOG + +#include +#include + +volatile uint8_t timeout_seconds=0; + +void(* ctrlaltdelete) (void) = 0; + +ISR(WDT_vect) { //Watchdog timer interrupt, called if main program blocks >1sec + if(timeout_seconds++ >= WATCHDOG_TIMEOUT) + { + kill(); +#ifdef RESET_MANUAL + LCD_MESSAGE("Please Reset!"); + ECHOLN("echo_: Something is wrong, please turn off the printer."); +#else + LCD_MESSAGE("Timeout, resetting!"); +#endif + //disable watchdog, it will survife reboot. + WDTCSR |= (1< -1 + target_raw[0]=0; + #if HEATER_0_PIN > -1 + WRITE(HEATER_0_PIN,LOW); + #endif + #endif + #if TEMP_1_PIN > -1 + target_raw[1]=0; + #if HEATER_1_PIN > -1 + WRITE(HEATER_1_PIN,LOW); + #endif + #endif + #if TEMP_2_PIN > -1 + target_raw[2]=0; + #if HEATER_2_PIN > -1 + WRITE(HEATER_2_PIN,LOW); + #endif + #endif + disable_x(); + disable_y(); + disable_z(); + disable_e(); + + if(PS_ON_PIN > -1) pinMode(PS_ON_PIN,INPUT); + Serial.println("!! Printer halted. kill() called!!"); + while(1); // Wait for reset +} + +void manage_inactivity(byte debug) { + if( (millis()-previous_millis_cmd) > max_inactive_time ) if(max_inactive_time) kill(); + if( (millis()-previous_millis_cmd) > stepper_inactive_time ) if(stepper_inactive_time) { + disable_x(); + disable_y(); + disable_z(); + disable_e(); + } + check_axes_activity(); +} diff --git a/Marlin/fastio.h b/Marlin/fastio.h index c1671ddef..2d1396252 100644 --- a/Marlin/fastio.h +++ b/Marlin/fastio.h @@ -24,12 +24,12 @@ */ /// Read a pin -#define _READ(IO) ((bool)(DIO ## IO ## _RPORT & MASK(DIO ## IO ## _PIN))) +#define _READ(IO) ((bool)(DIO ## IO ## _RPORT & MASK(DIO ## IO ## _PIN))) /// write to a pin -#define _WRITE(IO, v) do { if (v) {DIO ## IO ## _WPORT |= MASK(DIO ## IO ## _PIN); } else {DIO ## IO ## _WPORT &= ~MASK(DIO ## IO ## _PIN); }; } while (0) -//#define _WRITE(IO, v) do { #if (DIO ## IO ## _WPORT >= 0x100) CRITICAL_SECTION_START; if (v) {DIO ## IO ## _WPORT |= MASK(DIO ## IO ## _PIN); } else {DIO ## IO ## _WPORT &= ~MASK(DIO ## IO ## _PIN); };#if (DIO ## IO ## _WPORT >= 0x100) CRITICAL_SECTION_END; } while (0) +#define _WRITE(IO, v) do { if (v) {DIO ## IO ## _WPORT |= MASK(DIO ## IO ## _PIN); } else {DIO ## IO ## _WPORT &= ~MASK(DIO ## IO ## _PIN); }; } while (0) +//#define _WRITE(IO, v) do { #if (DIO ## IO ## _WPORT >= 0x100) CRITICAL_SECTION_START; if (v) {DIO ## IO ## _WPORT |= MASK(DIO ## IO ## _PIN); } else {DIO ## IO ## _WPORT &= ~MASK(DIO ## IO ## _PIN); };#if (DIO ## IO ## _WPORT >= 0x100) CRITICAL_SECTION_END; } while (0) /// toggle a pin -#define _TOGGLE(IO) do {DIO ## IO ## _RPORT = MASK(DIO ## IO ## _PIN); } while (0) +#define _TOGGLE(IO) do {DIO ## IO ## _RPORT = MASK(DIO ## IO ## _PIN); } while (0) /// set pin as input #define _SET_INPUT(IO) do {DIO ## IO ## _DDR &= ~MASK(DIO ## IO ## _PIN); } while (0) @@ -2556,4 +2556,4 @@ pins #error pins for this chip not defined in arduino.h! If you write an appropriate pin definition and have this firmware work on your chip, please submit a pull request #endif -#endif /* _ARDUINO_H */ +#endif /* _ARDUINO_H */ diff --git a/Marlin/lcd.h b/Marlin/lcd.h deleted file mode 100644 index 74057ddde..000000000 --- a/Marlin/lcd.h +++ /dev/null @@ -1,10 +0,0 @@ -#ifndef __LCDH -#define __LCDH - - - - - - - -#endif diff --git a/Marlin/lcd.pde b/Marlin/lcd.pde deleted file mode 100644 index 8b1378917..000000000 --- a/Marlin/lcd.pde +++ /dev/null @@ -1 +0,0 @@ - diff --git a/Marlin/planner.cpp b/Marlin/planner.cpp index 645384e6d..f0ca29821 100644 --- a/Marlin/planner.cpp +++ b/Marlin/planner.cpp @@ -381,13 +381,6 @@ void check_axes_activity() { // calculation the caller must also provide the physical length of the line in millimeters. void plan_buffer_line(float x, float y, float z, float e, float feed_rate) { - // The target position of the tool in absolute steps - // Calculate target position in absolute steps - long target[4]; - target[X_AXIS] = lround(x*axis_steps_per_unit[X_AXIS]); - target[Y_AXIS] = lround(y*axis_steps_per_unit[Y_AXIS]); - target[Z_AXIS] = lround(z*axis_steps_per_unit[Z_AXIS]); - target[E_AXIS] = lround(e*axis_steps_per_unit[E_AXIS]); // Calculate the buffer head after we push this byte int next_buffer_head = (block_buffer_head + 1) & (BLOCK_BUFFER_SIZE - 1); @@ -400,6 +393,15 @@ void plan_buffer_line(float x, float y, float z, float e, float feed_rate) { LCD_STATUS; } + // The target position of the tool in absolute steps + // Calculate target position in absolute steps + //this should be done after the wait, because otherwise a M92 code within the gcode disrupts this calculation somehow + long target[4]; + target[X_AXIS] = lround(x*axis_steps_per_unit[X_AXIS]); + target[Y_AXIS] = lround(y*axis_steps_per_unit[Y_AXIS]); + target[Z_AXIS] = lround(z*axis_steps_per_unit[Z_AXIS]); + target[E_AXIS] = lround(e*axis_steps_per_unit[E_AXIS]); + // Prepare to set up new block block_t *block = &block_buffer[block_buffer_head]; @@ -433,7 +435,7 @@ void plan_buffer_line(float x, float y, float z, float e, float feed_rate) { unsigned long microseconds; if (block->steps_e == 0) { - if(feed_rate. -*/ - -// This module is to be considered a sub-module of stepper.c. Please don't include -// this file from any other module. - -#ifndef planner_h -#define planner_h - -// This struct is used when buffering the setup for each linear movement "nominal" values are as specified in -// the source g-code and may never actually be reached if acceleration management is active. -typedef struct { - // Fields used by the bresenham algorithm for tracing the line - long steps_x, steps_y, steps_z, steps_e; // Step count along each axis - long step_event_count; // The number of step events required to complete this block - volatile long accelerate_until; // The index of the step event on which to stop acceleration - volatile long decelerate_after; // The index of the step event on which to start decelerating - volatile long acceleration_rate; // The acceleration rate used for acceleration calculation - unsigned char direction_bits; // The direction bit set for this block (refers to *_DIRECTION_BIT in config.h) -#ifdef ADVANCE - long advance_rate; - volatile long initial_advance; - volatile long final_advance; - float advance; -#endif - - // Fields used by the motion planner to manage acceleration - float speed_x, speed_y, speed_z, speed_e; // Nominal mm/minute for each axis - float nominal_speed; // The nominal speed for this block in mm/min - float millimeters; // The total travel of this block in mm - float entry_speed; - float acceleration; // acceleration mm/sec^2 - - // Settings for the trapezoid generator - long nominal_rate; // The nominal step rate for this block in step_events/sec - volatile long initial_rate; // The jerk-adjusted step rate at start of block - volatile long final_rate; // The minimal rate at exit - long acceleration_st; // acceleration steps/sec^2 - volatile char busy; -} block_t; - -// Initialize the motion plan subsystem -void plan_init(); - -// Add a new linear movement to the buffer. x, y and z is the signed, absolute target position in -// millimaters. Feed rate specifies the speed of the motion. -void plan_buffer_line(float x, float y, float z, float e, float feed_rate); - -// Set position. Used for G92 instructions. -void plan_set_position(float x, float y, float z, float e); - -// Called when the current block is no longer needed. Discards the block and makes the memory -// availible for new blocks. -void plan_discard_current_block(); - -// Gets the current block. Returns NULL if buffer empty -block_t *plan_get_current_block(); - -void check_axes_activity(); - -extern unsigned long minsegmenttime; -extern float max_feedrate[4]; // set the max speeds -extern float axis_steps_per_unit[4]; -extern long max_acceleration_units_per_sq_second[4]; // Use M201 to override by software -extern float minimumfeedrate; -extern float acceleration; // Normal acceleration mm/s^2 THIS IS THE DEFAULT ACCELERATION for all moves. M204 SXXXX -extern float retract_acceleration; // mm/s^2 filament pull-pack and push-forward while standing still in the other axis M204 TXXXX -extern float max_xy_jerk; //speed than can be stopped at once, if i understand correctly. -extern float max_z_jerk; -extern float mintravelfeedrate; -extern unsigned long axis_steps_per_sqr_second[NUM_AXIS]; - -#endif +/* + planner.h - buffers movement commands and manages the acceleration profile plan + Part of Grbl + + Copyright (c) 2009-2011 Simen Svale Skogsrud + + Grbl is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + Grbl is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Grbl. If not, see . +*/ + +// This module is to be considered a sub-module of stepper.c. Please don't include +// this file from any other module. + +#ifndef planner_h +#define planner_h + +#include "Configuration.h" + +// This struct is used when buffering the setup for each linear movement "nominal" values are as specified in +// the source g-code and may never actually be reached if acceleration management is active. +typedef struct { + // Fields used by the bresenham algorithm for tracing the line + long steps_x, steps_y, steps_z, steps_e; // Step count along each axis + long step_event_count; // The number of step events required to complete this block + volatile long accelerate_until; // The index of the step event on which to stop acceleration + volatile long decelerate_after; // The index of the step event on which to start decelerating + volatile long acceleration_rate; // The acceleration rate used for acceleration calculation + unsigned char direction_bits; // The direction bit set for this block (refers to *_DIRECTION_BIT in config.h) +#ifdef ADVANCE + long advance_rate; + volatile long initial_advance; + volatile long final_advance; + float advance; +#endif + + // Fields used by the motion planner to manage acceleration + float speed_x, speed_y, speed_z, speed_e; // Nominal mm/minute for each axis + float nominal_speed; // The nominal speed for this block in mm/min + float millimeters; // The total travel of this block in mm + float entry_speed; + float acceleration; // acceleration mm/sec^2 + + // Settings for the trapezoid generator + long nominal_rate; // The nominal step rate for this block in step_events/sec + volatile long initial_rate; // The jerk-adjusted step rate at start of block + volatile long final_rate; // The minimal rate at exit + long acceleration_st; // acceleration steps/sec^2 + volatile char busy; +} block_t; + +// Initialize the motion plan subsystem +void plan_init(); + +// Add a new linear movement to the buffer. x, y and z is the signed, absolute target position in +// millimaters. Feed rate specifies the speed of the motion. +void plan_buffer_line(float x, float y, float z, float e, float feed_rate); + +// Set position. Used for G92 instructions. +void plan_set_position(float x, float y, float z, float e); + +// Called when the current block is no longer needed. Discards the block and makes the memory +// availible for new blocks. +void plan_discard_current_block(); + +// Gets the current block. Returns NULL if buffer empty +block_t *plan_get_current_block(); + +void check_axes_activity(); + +extern unsigned long minsegmenttime; +extern float max_feedrate[4]; // set the max speeds +extern float axis_steps_per_unit[4]; +extern long max_acceleration_units_per_sq_second[4]; // Use M201 to override by software +extern float minimumfeedrate; +extern float acceleration; // Normal acceleration mm/s^2 THIS IS THE DEFAULT ACCELERATION for all moves. M204 SXXXX +extern float retract_acceleration; // mm/s^2 filament pull-pack and push-forward while standing still in the other axis M204 TXXXX +extern float max_xy_jerk; //speed than can be stopped at once, if i understand correctly. +extern float max_z_jerk; +extern float mintravelfeedrate; +extern unsigned long axis_steps_per_sqr_second[NUM_AXIS]; + +#endif diff --git a/Marlin/stepper.cpp b/Marlin/stepper.cpp index cd68bae0d..15f143349 100644 --- a/Marlin/stepper.cpp +++ b/Marlin/stepper.cpp @@ -115,7 +115,7 @@ asm volatile ( \ #define ENABLE_STEPPER_DRIVER_INTERRUPT() TIMSK1 |= (1<. -*/ - -#ifndef stepper_h -#define stepper_h -// Initialize and start the stepper motor subsystem -void st_init(); - -// Block until all buffered steps are executed -void st_synchronize(); - -// The stepper subsystem goes to sleep when it runs out of things to execute. Call this -// to notify the subsystem that it is time to go to work. -void st_wake_up(); - -// if DEBUG_STEPS is enabled, M114 can be used to compare two methods of determining the X,Y,Z position of the printer. -// for debugging purposes only, should be disabled by default -#ifdef DEBUG_STEPS -extern volatile long count_position[NUM_AXIS]; -extern volatile int count_direction[NUM_AXIS]; -#endif - -#endif +/* + stepper.h - stepper motor driver: executes motion plans of planner.c using the stepper motors + Part of Grbl + + Copyright (c) 2009-2011 Simen Svale Skogsrud + + Grbl is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + Grbl is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Grbl. If not, see . +*/ + +#ifndef stepper_h +#define stepper_h + +#include "planner.h" + +// Initialize and start the stepper motor subsystem +void st_init(); + +// Block until all buffered steps are executed +void st_synchronize(); + +// The stepper subsystem goes to sleep when it runs out of things to execute. Call this +// to notify the subsystem that it is time to go to work. +void st_wake_up(); + +// if DEBUG_STEPS is enabled, M114 can be used to compare two methods of determining the X,Y,Z position of the printer. +// for debugging purposes only, should be disabled by default +#ifdef DEBUG_STEPS +extern volatile long count_position[NUM_AXIS]; +extern volatile int count_direction[NUM_AXIS]; +#endif + +extern block_t *current_block; // A pointer to the block currently being traced +#endif diff --git a/Marlin/temperature.cpp b/Marlin/temperature.cpp index 7a9c56e10..5aaf6fd97 100644 --- a/Marlin/temperature.cpp +++ b/Marlin/temperature.cpp @@ -90,14 +90,15 @@ void manage_heater() float pid_input; float pid_output; - if(temp_meas_ready == true) { + if(temp_meas_ready != true) //better readability + return; CRITICAL_SECTION_START; temp_meas_ready = false; CRITICAL_SECTION_END; #ifdef PIDTEMP - pid_input = analog2temp(current_raw[0]); + pid_input = analog2temp(current_raw[TEMPSENSOR_HOTEND]); #ifndef PID_OPENLOOP pid_error = pid_setpoint - pid_input; @@ -118,10 +119,13 @@ CRITICAL_SECTION_END; temp_iState += pid_error; temp_iState = constrain(temp_iState, temp_iState_min, temp_iState_max); iTerm = Ki * temp_iState; - #define K1 0.95 + //K1 defined in Configuration.h in the PID settings #define K2 (1.0-K1) dTerm = (Kd * (pid_input - temp_dState))*K2 + (K1 * dTerm); temp_dState = pid_input; + #ifdef PID_ADD_EXTRUSION_RATE + pTerm+=Kc*current_block->speed_e; //additional heating if extrusion speed is high + #endif pid_output = constrain(pTerm + iTerm - dTerm, 0, PID_MAX); } #endif //PID_OPENLOOP @@ -157,7 +161,7 @@ CRITICAL_SECTION_END; previous_millis_bed_heater = millis(); #if TEMP_1_PIN > -1 - if(current_raw[1] >= target_raw[1]) + if(current_raw[TEMPSENSOR_BED] >= target_raw[TEMPSENSOR_BED]) { WRITE(HEATER_1_PIN,LOW); } @@ -167,7 +171,6 @@ CRITICAL_SECTION_END; } #endif } -} // Takes hot end temperature value as input and returns corresponding raw value. // For a thermistor, it uses the RepRap thermistor temp table. @@ -428,15 +431,15 @@ ISR(TIMER0_COMPB_vect) raw_temp_2_value = 0; #ifdef MAXTEMP #if (HEATER_0_PIN > -1) - if(current_raw[0] >= maxttemp) { - target_raw[0] = 0; + if(current_raw[TEMPSENSOR_HOTEND] >= maxttemp) { + target_raw[TEMPSENSOR_HOTEND] = 0; analogWrite(HEATER_0_PIN, 0); Serial.println("!! Temperature extruder 0 switched off. MAXTEMP triggered !!"); } #endif #if (HEATER_2_PIN > -1) - if(current_raw[2] >= maxttemp) { - target_raw[2] = 0; + if(current_raw[TEMPSENSOR_AUX] >= maxttemp) { + target_raw[TEMPSENSOR_AUX] = 0; analogWrite(HEATER_2_PIN, 0); Serial.println("!! Temperature extruder 1 switched off. MAXTEMP triggered !!"); } @@ -444,15 +447,15 @@ ISR(TIMER0_COMPB_vect) #endif //MAXTEMP #ifdef MINTEMP #if (HEATER_0_PIN > -1) - if(current_raw[0] <= minttemp) { - target_raw[0] = 0; + if(current_raw[TEMPSENSOR_HOTEND] <= minttemp) { + target_raw[TEMPSENSOR_HOTEND] = 0; analogWrite(HEATER_0_PIN, 0); Serial.println("!! Temperature extruder 0 switched off. MINTEMP triggered !!"); } #endif #if (HEATER_2_PIN > -1) - if(current_raw[2] <= minttemp) { - target_raw[2] = 0; + if(current_raw[TEMPSENSOR_AUX] <= minttemp) { + target_raw[TEMPSENSOR_AUX] = 0; analogWrite(HEATER_2_PIN, 0); Serial.println("!! Temperature extruder 1 switched off. MINTEMP triggered !!"); } diff --git a/Marlin/temperature.h b/Marlin/temperature.h index 986aca999..e2e6c459c 100644 --- a/Marlin/temperature.h +++ b/Marlin/temperature.h @@ -1,55 +1,58 @@ -/* - temperature.h - temperature controller - Part of Marlin - - Copyright (c) 2011 Erik van der Zalm - - Grbl is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - Grbl is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with Grbl. If not, see . -*/ - -#ifndef temperature_h -#define temperature_h - -void manage_inactivity(byte debug); - -void tp_init(); -void manage_heater(); -//int temp2analogu(int celsius, const short table[][2], int numtemps); -//float analog2tempu(int raw, const short table[][2], int numtemps); -float temp2analog(int celsius); -float temp2analogBed(int celsius); -float analog2temp(int raw); -float analog2tempBed(int raw); - -#ifdef HEATER_USES_THERMISTOR - #define HEATERSOURCE 1 -#endif -#ifdef BED_USES_THERMISTOR - #define BEDSOURCE 1 -#endif - -//#define temp2analogh( c ) temp2analogu((c),temptable,NUMTEMPS) -//#define analog2temp( c ) analog2tempu((c),temptable,NUMTEMPS - - -extern float Kp; -extern float Ki; -extern float Kd; -extern float Kc; - -extern int target_raw[3]; -extern int current_raw[3]; -extern double pid_setpoint; - -#endif +/* + temperature.h - temperature controller + Part of Marlin + + Copyright (c) 2011 Erik van der Zalm + + Grbl is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + Grbl is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Grbl. If not, see . +*/ + +#ifndef temperature_h +#define temperature_h + +#include "Marlin.h" +#ifdef PID_ADD_EXTRUSION_RATE + #include "stepper.h" +#endif +void tp_init(); +void manage_heater(); +//int temp2analogu(int celsius, const short table[][2], int numtemps); +//float analog2tempu(int raw, const short table[][2], int numtemps); +float temp2analog(int celsius); +float temp2analogBed(int celsius); +float analog2temp(int raw); +float analog2tempBed(int raw); + +#ifdef HEATER_USES_THERMISTOR + #define HEATERSOURCE 1 +#endif +#ifdef BED_USES_THERMISTOR + #define BEDSOURCE 1 +#endif + +//#define temp2analogh( c ) temp2analogu((c),temptable,NUMTEMPS) +//#define analog2temp( c ) analog2tempu((c),temptable,NUMTEMPS + + +extern float Kp; +extern float Ki; +extern float Kd; +extern float Kc; + +enum {TEMPSENSOR_HOTEND=0,TEMPSENSOR_BED=1, TEMPSENSOR_AUX=2}; +extern int target_raw[3]; +extern int current_raw[3]; +extern double pid_setpoint; + +#endif diff --git a/Marlin/thermistortables.h b/Marlin/thermistortables.h index 0ea1991dc..6d43d7273 100644 --- a/Marlin/thermistortables.h +++ b/Marlin/thermistortables.h @@ -7,67 +7,67 @@ #define NUMTEMPS_1 61 const short temptable_1[NUMTEMPS_1][2] = { -{ 23*OVERSAMPLENR , 300 }, -{ 25*OVERSAMPLENR , 295 }, -{ 27*OVERSAMPLENR , 290 }, -{ 28*OVERSAMPLENR , 285 }, -{ 31*OVERSAMPLENR , 280 }, -{ 33*OVERSAMPLENR , 275 }, -{ 35*OVERSAMPLENR , 270 }, -{ 38*OVERSAMPLENR , 265 }, -{ 41*OVERSAMPLENR , 260 }, -{ 44*OVERSAMPLENR , 255 }, -{ 48*OVERSAMPLENR , 250 }, -{ 52*OVERSAMPLENR , 245 }, -{ 56*OVERSAMPLENR , 240 }, -{ 61*OVERSAMPLENR , 235 }, -{ 66*OVERSAMPLENR , 230 }, -{ 71*OVERSAMPLENR , 225 }, -{ 78*OVERSAMPLENR , 220 }, -{ 84*OVERSAMPLENR , 215 }, -{ 92*OVERSAMPLENR , 210 }, -{ 100*OVERSAMPLENR , 205 }, -{ 109*OVERSAMPLENR , 200 }, -{ 120*OVERSAMPLENR , 195 }, -{ 131*OVERSAMPLENR , 190 }, -{ 143*OVERSAMPLENR , 185 }, -{ 156*OVERSAMPLENR , 180 }, -{ 171*OVERSAMPLENR , 175 }, -{ 187*OVERSAMPLENR , 170 }, -{ 205*OVERSAMPLENR , 165 }, -{ 224*OVERSAMPLENR , 160 }, -{ 245*OVERSAMPLENR , 155 }, -{ 268*OVERSAMPLENR , 150 }, -{ 293*OVERSAMPLENR , 145 }, -{ 320*OVERSAMPLENR , 140 }, -{ 348*OVERSAMPLENR , 135 }, -{ 379*OVERSAMPLENR , 130 }, -{ 411*OVERSAMPLENR , 125 }, -{ 445*OVERSAMPLENR , 120 }, -{ 480*OVERSAMPLENR , 115 }, -{ 516*OVERSAMPLENR , 110 }, -{ 553*OVERSAMPLENR , 105 }, -{ 591*OVERSAMPLENR , 100 }, -{ 628*OVERSAMPLENR , 95 }, -{ 665*OVERSAMPLENR , 90 }, -{ 702*OVERSAMPLENR , 85 }, -{ 737*OVERSAMPLENR , 80 }, -{ 770*OVERSAMPLENR , 75 }, -{ 801*OVERSAMPLENR , 70 }, -{ 830*OVERSAMPLENR , 65 }, -{ 857*OVERSAMPLENR , 60 }, -{ 881*OVERSAMPLENR , 55 }, -{ 903*OVERSAMPLENR , 50 }, -{ 922*OVERSAMPLENR , 45 }, -{ 939*OVERSAMPLENR , 40 }, -{ 954*OVERSAMPLENR , 35 }, -{ 966*OVERSAMPLENR , 30 }, -{ 977*OVERSAMPLENR , 25 }, -{ 985*OVERSAMPLENR , 20 }, -{ 993*OVERSAMPLENR , 15 }, -{ 999*OVERSAMPLENR , 10 }, -{ 1004*OVERSAMPLENR , 5 }, -{ 1008*OVERSAMPLENR , 0 } //safety +{ 23*OVERSAMPLENR , 300 }, +{ 25*OVERSAMPLENR , 295 }, +{ 27*OVERSAMPLENR , 290 }, +{ 28*OVERSAMPLENR , 285 }, +{ 31*OVERSAMPLENR , 280 }, +{ 33*OVERSAMPLENR , 275 }, +{ 35*OVERSAMPLENR , 270 }, +{ 38*OVERSAMPLENR , 265 }, +{ 41*OVERSAMPLENR , 260 }, +{ 44*OVERSAMPLENR , 255 }, +{ 48*OVERSAMPLENR , 250 }, +{ 52*OVERSAMPLENR , 245 }, +{ 56*OVERSAMPLENR , 240 }, +{ 61*OVERSAMPLENR , 235 }, +{ 66*OVERSAMPLENR , 230 }, +{ 71*OVERSAMPLENR , 225 }, +{ 78*OVERSAMPLENR , 220 }, +{ 84*OVERSAMPLENR , 215 }, +{ 92*OVERSAMPLENR , 210 }, +{ 100*OVERSAMPLENR , 205 }, +{ 109*OVERSAMPLENR , 200 }, +{ 120*OVERSAMPLENR , 195 }, +{ 131*OVERSAMPLENR , 190 }, +{ 143*OVERSAMPLENR , 185 }, +{ 156*OVERSAMPLENR , 180 }, +{ 171*OVERSAMPLENR , 175 }, +{ 187*OVERSAMPLENR , 170 }, +{ 205*OVERSAMPLENR , 165 }, +{ 224*OVERSAMPLENR , 160 }, +{ 245*OVERSAMPLENR , 155 }, +{ 268*OVERSAMPLENR , 150 }, +{ 293*OVERSAMPLENR , 145 }, +{ 320*OVERSAMPLENR , 140 }, +{ 348*OVERSAMPLENR , 135 }, +{ 379*OVERSAMPLENR , 130 }, +{ 411*OVERSAMPLENR , 125 }, +{ 445*OVERSAMPLENR , 120 }, +{ 480*OVERSAMPLENR , 115 }, +{ 516*OVERSAMPLENR , 110 }, +{ 553*OVERSAMPLENR , 105 }, +{ 591*OVERSAMPLENR , 100 }, +{ 628*OVERSAMPLENR , 95 }, +{ 665*OVERSAMPLENR , 90 }, +{ 702*OVERSAMPLENR , 85 }, +{ 737*OVERSAMPLENR , 80 }, +{ 770*OVERSAMPLENR , 75 }, +{ 801*OVERSAMPLENR , 70 }, +{ 830*OVERSAMPLENR , 65 }, +{ 857*OVERSAMPLENR , 60 }, +{ 881*OVERSAMPLENR , 55 }, +{ 903*OVERSAMPLENR , 50 }, +{ 922*OVERSAMPLENR , 45 }, +{ 939*OVERSAMPLENR , 40 }, +{ 954*OVERSAMPLENR , 35 }, +{ 966*OVERSAMPLENR , 30 }, +{ 977*OVERSAMPLENR , 25 }, +{ 985*OVERSAMPLENR , 20 }, +{ 993*OVERSAMPLENR , 15 }, +{ 999*OVERSAMPLENR , 10 }, +{ 1004*OVERSAMPLENR , 5 }, +{ 1008*OVERSAMPLENR , 0 } //safety }; #endif #if (THERMISTORHEATER_1 == 2) || (THERMISTORHEATER_2 == 2) || (THERMISTORBED == 2) //200k bed thermistor @@ -100,35 +100,35 @@ const short temptable_2[NUMTEMPS_2][2] = { #if (THERMISTORHEATER_1 == 3) || (THERMISTORHEATER_2 == 3) || (THERMISTORBED == 3) //mendel-parts #define NUMTEMPS_3 28 const short temptable_3[NUMTEMPS_3][2] = { - {1*OVERSAMPLENR,864}, - {21*OVERSAMPLENR,300}, - {25*OVERSAMPLENR,290}, - {29*OVERSAMPLENR,280}, - {33*OVERSAMPLENR,270}, - {39*OVERSAMPLENR,260}, - {46*OVERSAMPLENR,250}, - {54*OVERSAMPLENR,240}, - {64*OVERSAMPLENR,230}, - {75*OVERSAMPLENR,220}, - {90*OVERSAMPLENR,210}, - {107*OVERSAMPLENR,200}, - {128*OVERSAMPLENR,190}, - {154*OVERSAMPLENR,180}, - {184*OVERSAMPLENR,170}, - {221*OVERSAMPLENR,160}, - {265*OVERSAMPLENR,150}, - {316*OVERSAMPLENR,140}, - {375*OVERSAMPLENR,130}, - {441*OVERSAMPLENR,120}, - {513*OVERSAMPLENR,110}, - {588*OVERSAMPLENR,100}, - {734*OVERSAMPLENR,80}, - {856*OVERSAMPLENR,60}, - {938*OVERSAMPLENR,40}, - {986*OVERSAMPLENR,20}, - {1008*OVERSAMPLENR,0}, - {1018*OVERSAMPLENR,-20} - }; + {1*OVERSAMPLENR,864}, + {21*OVERSAMPLENR,300}, + {25*OVERSAMPLENR,290}, + {29*OVERSAMPLENR,280}, + {33*OVERSAMPLENR,270}, + {39*OVERSAMPLENR,260}, + {46*OVERSAMPLENR,250}, + {54*OVERSAMPLENR,240}, + {64*OVERSAMPLENR,230}, + {75*OVERSAMPLENR,220}, + {90*OVERSAMPLENR,210}, + {107*OVERSAMPLENR,200}, + {128*OVERSAMPLENR,190}, + {154*OVERSAMPLENR,180}, + {184*OVERSAMPLENR,170}, + {221*OVERSAMPLENR,160}, + {265*OVERSAMPLENR,150}, + {316*OVERSAMPLENR,140}, + {375*OVERSAMPLENR,130}, + {441*OVERSAMPLENR,120}, + {513*OVERSAMPLENR,110}, + {588*OVERSAMPLENR,100}, + {734*OVERSAMPLENR,80}, + {856*OVERSAMPLENR,60}, + {938*OVERSAMPLENR,40}, + {986*OVERSAMPLENR,20}, + {1008*OVERSAMPLENR,0}, + {1018*OVERSAMPLENR,-20} + }; #endif #if (THERMISTORHEATER_1 == 4) || (THERMISTORHEATER_2 == 4) || (THERMISTORBED == 4) //10k thermistor diff --git a/Marlin/ultralcd.h b/Marlin/ultralcd.h index 5f0196fa5..39cca278e 100644 --- a/Marlin/ultralcd.h +++ b/Marlin/ultralcd.h @@ -153,4 +153,4 @@ #define BLOCK ; #endif #endif //ULTRALCD - + diff --git a/Marlin/ultralcd.pde b/Marlin/ultralcd.pde index 2702af854..a6c75e0fc 100644 --- a/Marlin/ultralcd.pde +++ b/Marlin/ultralcd.pde @@ -1,1593 +1,1593 @@ -#include "ultralcd.h" - - -#ifdef ULTRA_LCD -extern volatile int feedmultiply; -extern long position[4]; - -char messagetext[LCD_WIDTH]=""; - -#include -LiquidCrystal lcd(LCD_PINS_RS, LCD_PINS_ENABLE, LCD_PINS_D4, LCD_PINS_D5,LCD_PINS_D6,LCD_PINS_D7); //RS,Enable,D4,D5,D6,D7 - -unsigned long previous_millis_lcd=0; - - - -volatile char buttons=0; //the last checked buttons in a bit array. -int encoderpos=0; -short lastenc=0; -#ifdef NEWPANEL - long blocking=0; -#else - long blocking[8]={0,0,0,0,0,0,0,0}; -#endif -MainMenu menu; - -void lcd_status(const char* message) -{ - strncpy(messagetext,message,LCD_WIDTH); -} - -void clear() -{ - //lcd.setCursor(0,0); - lcd.clear(); - //delay(1); - // lcd.begin(LCD_WIDTH,LCD_HEIGHT); - //lcd_init(); -} -long previous_millis_buttons=0; - -void lcd_init() -{ - //beep(); - byte Degree[8] = - { - B01100, - B10010, - B10010, - B01100, - B00000, - B00000, - B00000, - B00000 - }; - byte Thermometer[8] = - { - B00100, - B01010, - B01010, - B01010, - B01010, - B10001, - B10001, - B01110 - }; - byte uplevel[8]={0x04, 0x0e, 0x1f, 0x04, 0x1c, 0x00, 0x00, 0x00};//thanks joris - byte refresh[8]={0x00, 0x06, 0x19, 0x18, 0x03, 0x13, 0x0c, 0x00}; //thanks joris - lcd.begin(LCD_WIDTH, LCD_HEIGHT); - lcd.createChar(1,Degree); - lcd.createChar(2,Thermometer); - lcd.createChar(3,uplevel); - lcd.createChar(4,refresh); - LCD_MESSAGE(fillto(LCD_WIDTH,"UltiMarlin ready.")); -} - - -void beep() -{ - //return; -#ifdef ULTIPANEL - pinMode(BEEPER,OUTPUT); - for(int i=0;i<20;i++){ - WRITE(BEEPER,HIGH); - delay(5); - WRITE(BEEPER,LOW); - delay(5); - } -#endif -} - -void beepshort() -{ - //return; -#ifdef ULTIPANEL - pinMode(BEEPER,OUTPUT); - for(int i=0;i<10;i++){ - WRITE(BEEPER,HIGH); - delay(3); - WRITE(BEEPER,LOW); - delay(3); - } -#endif -} -void lcd_status() -{ -#ifdef ULTIPANEL - static uint8_t oldbuttons=0; - static long previous_millis_buttons=0; - static long previous_lcdinit=0; -// buttons_check(); // Done in temperature interrupt - //previous_millis_buttons=millis(); - - if((buttons==oldbuttons) && ((millis() - previous_millis_lcd) < LCD_UPDATE_INTERVAL) ) - return; - oldbuttons=buttons; -#else - - if(((millis() - previous_millis_lcd) < LCD_UPDATE_INTERVAL) ) - return; -#endif - - previous_millis_lcd=millis(); - menu.update(); -} -#ifdef ULTIPANEL -void buttons_init() -{ -#ifdef NEWPANEL - pinMode(BTN_EN1,INPUT); - pinMode(BTN_EN2,INPUT); - pinMode(BTN_ENC,INPUT); - pinMode(SDCARDDETECT,INPUT); - WRITE(BTN_EN1,HIGH); - WRITE(BTN_EN2,HIGH); - WRITE(BTN_ENC,HIGH); - WRITE(SDCARDDETECT,HIGH); -#else - pinMode(SHIFT_CLK,OUTPUT); - pinMode(SHIFT_LD,OUTPUT); - pinMode(SHIFT_EN,OUTPUT); - pinMode(SHIFT_OUT,INPUT); - WRITE(SHIFT_OUT,HIGH); - WRITE(SHIFT_LD,HIGH); - WRITE(SHIFT_EN,LOW); -#endif -} - - -void buttons_check() -{ -// volatile static bool busy=false; -// if(busy) -// return; -// busy=true; - -#ifdef NEWPANEL - uint8_t newbutton=0; - if(READ(BTN_EN1)==0) newbutton|=EN_A; - if(READ(BTN_EN2)==0) newbutton|=EN_B; - if((blocking>1; - if(READ(SHIFT_OUT)) - newbutton|=(1<<7); - WRITE(SHIFT_CLK,HIGH); - WRITE(SHIFT_CLK,LOW); - } - buttons=~newbutton; //invert it, because a pressed switch produces a logical 0 -#endif - char enc=0; - if(buttons&EN_A) - enc|=(1<<0); - if(buttons&EN_B) - enc|=(1<<1); - if(enc!=lastenc) - { - switch(enc) - { - case encrot0: - if(lastenc==encrot3) - encoderpos++; - else if(lastenc==encrot1) - encoderpos--; - break; - case encrot1: - if(lastenc==encrot0) - encoderpos++; - else if(lastenc==encrot2) - encoderpos--; - break; - case encrot2: - if(lastenc==encrot1) - encoderpos++; - else if(lastenc==encrot3) - encoderpos--; - break; - case encrot3: - if(lastenc==encrot2) - encoderpos++; - else if(lastenc==encrot0) - encoderpos--; - break; - default: - ; - } - } - lastenc=enc; -// busy=false; -} - -#endif - -MainMenu::MainMenu() -{ - status=Main_Status; - displayStartingRow=0; - activeline=0; - force_lcd_update=true; -#ifdef ULTIPANEL - buttons_init(); -#endif - lcd_init(); - linechanging=false; -} - -extern volatile bool feedmultiplychanged; - -void MainMenu::showStatus() -{ -#if LCD_HEIGHT==4 - static int oldcurrentraw=-1; - static int oldtargetraw=-1; - //force_lcd_update=true; - if(force_lcd_update||feedmultiplychanged) //initial display of content - { - feedmultiplychanged=false; - encoderpos=feedmultiply; - clear(); - lcd.setCursor(0,0);lcd.print("\002123/567\001 "); -#if defined BED_USES_THERMISTOR || defined BED_USES_AD595 - lcd.setCursor(10,0);lcd.print("B123/567\001 "); -#endif - } - - - if((abs(current_raw[0]-oldcurrentraw)>3)||force_lcd_update) - { - lcd.setCursor(1,0); - lcd.print(ftostr3(analog2temp(current_raw[0]))); - oldcurrentraw=current_raw[0]; - } - if((target_raw[0]!=oldtargetraw)||force_lcd_update) - { - lcd.setCursor(5,0); - lcd.print(ftostr3(analog2temp(target_raw[0]))); - oldtargetraw=target_raw[0]; - } - #if defined BED_USES_THERMISTOR || defined BED_USES_AD595 - static int oldcurrentbedraw=-1; - static int oldtargetbedraw=-1; - if((current_bed_raw!=oldcurrentbedraw)||force_lcd_update) - { - lcd.setCursor(1,0); - lcd.print(ftostr3(analog2temp(current_bed_raw))); - oldcurrentraw=current_raw[1]; - } - if((target_bed_raw!=oldtargebedtraw)||force_lcd_update) - { - lcd.setCursor(5,0); - lcd.print(ftostr3(analog2temp(target_bed_raw))); - oldtargetraw=target_bed_raw; - } - #endif - //starttime=2; - static uint16_t oldtime=0; - if(starttime!=0) - { - lcd.setCursor(0,1); - uint16_t time=millis()/60000-starttime/60000; - - if(starttime!=oldtime) - { - lcd.print(itostr2(time/60));lcd.print("h ");lcd.print(itostr2(time%60));lcd.print("m"); - oldtime=time; - } - } - static int oldzpos=0; - int currentz=current_position[2]*10; - if((currentz!=oldzpos)||force_lcd_update) - { - lcd.setCursor(10,1); - lcd.print("Z:");lcd.print(itostr31(currentz)); - oldzpos=currentz; - } - static int oldfeedmultiply=0; - int curfeedmultiply=feedmultiply; - if(encoderpos!=curfeedmultiply||force_lcd_update) - { - curfeedmultiply=encoderpos; - if(curfeedmultiply<10) - curfeedmultiply=10; - if(curfeedmultiply>999) - curfeedmultiply=999; - feedmultiply=curfeedmultiply; - encoderpos=curfeedmultiply; - } - if((curfeedmultiply!=oldfeedmultiply)||force_lcd_update) - { - oldfeedmultiply=curfeedmultiply; - lcd.setCursor(0,2); - lcd.print(itostr3(curfeedmultiply));lcd.print("% "); - } - if(messagetext[0]!='\0') - { - lcd.setCursor(0,LCD_HEIGHT-1); - lcd.print(fillto(LCD_WIDTH,messagetext)); - messagetext[0]='\0'; - } -#else //smaller LCDS---------------------------------- - static int oldcurrentraw=-1; - static int oldtargetraw=-1; - if(force_lcd_update) //initial display of content - { - encoderpos=feedmultiply; - lcd.setCursor(0,0);lcd.print("\002123/567\001 "); - #if defined BED_USES_THERMISTOR || defined BED_USES_AD595 - lcd.setCursor(10,0);lcd.print("B123/567\001 "); - #endif - } - - - if((abs(current_raw[0]-oldcurrentraw)>3)||force_lcd_update) - { - lcd.setCursor(1,0); - lcd.print(ftostr3(analog2temp(current_raw[0]))); - oldcurrentraw=current_raw[0]; - } - if((target_raw[0]!=oldtargetraw)||force_lcd_update) - { - lcd.setCursor(5,0); - lcd.print(ftostr3(analog2temp(target_raw[0]))); - oldtargetraw=target_raw[0]; - } - - if(messagetext[0]!='\0') - { - lcd.setCursor(0,LCD_HEIGHT-1); - lcd.print(fillto(LCD_WIDTH,messagetext)); - messagetext[0]='\0'; - } - -#endif -} - -enum {ItemP_exit, ItemP_home, ItemP_origin, ItemP_preheat, ItemP_extrude, ItemP_disstep}; - -void MainMenu::showPrepare() -{ - uint8_t line=0; - if(lastlineoffset!=lineoffset) - { - force_lcd_update=true; - clear(); - } - for(uint8_t i=lineoffset;i3) - { - lineoffset++; - encoderpos=3*lcdslow; - if(lineoffset>(ItemP_disstep+1-LCD_HEIGHT)) - lineoffset=ItemP_disstep+1-LCD_HEIGHT; - force_lcd_update=true; - } - //encoderpos=encoderpos%LCD_HEIGHT; - lastencoderpos=encoderpos; - activeline=encoderpos/lcdslow; - lcd.setCursor(0,activeline);lcd.print((activeline+lineoffset)?'>':'\003'); - } -} -enum { - ItemC_exit, ItemC_nozzle, - ItemC_PID_P,ItemC_PID_I,ItemC_PID_D,ItemC_PID_C, - ItemC_fan, - ItemC_acc, ItemC_xyjerk, - ItemC_vmaxx, ItemC_vmaxy, ItemC_vmaxz, ItemC_vmaxe, - ItemC_vtravmin,ItemC_vmin, - ItemC_amaxx, ItemC_amaxy, ItemC_amaxz, ItemC_amaxe, - ItemC_aret,ItemC_esteps, ItemC_store, ItemC_load,ItemC_failsafe -}; - -void MainMenu::showControl() -{ - uint8_t line=0; - if((lastlineoffset!=lineoffset)||force_lcd_update) - { - force_lcd_update=true; - clear(); - } - for(uint8_t i=lineoffset;i260) encoderpos=260; - lcd.setCursor(13,line);lcd.print(itostr3(encoderpos)); - } - } - }break; - - case ItemC_fan: - { - if(force_lcd_update) - { - lcd.setCursor(0,line);lcd.print(" Fan speed:"); - lcd.setCursor(13,line);lcd.print(ftostr3(fanpwm)); - } - - if((activeline==line) ) - { - if(CLICKED) //nalogWrite(FAN_PIN, fanpwm); - { - linechanging=!linechanging; - if(linechanging) - { - encoderpos=fanpwm; - } - else - { - fanpwm = constrain(encoderpos,0,255); - encoderpos=fanpwm; - analogWrite(FAN_PIN, fanpwm); - - beepshort(); - } - BLOCK; - } - if(linechanging) - { - if(encoderpos<0) encoderpos=0; - if(encoderpos>255) encoderpos=255; - fanpwm=encoderpos; - analogWrite(FAN_PIN, fanpwm); - lcd.setCursor(13,line);lcd.print(itostr3(encoderpos)); - } - } - }break; - case ItemC_acc: - { - if(force_lcd_update) - { - lcd.setCursor(0,line);lcd.print(" Acc:"); - lcd.setCursor(13,line);lcd.print(itostr3(acceleration/100));lcd.print("00"); - } - - if((activeline==line) ) - { - if(CLICKED) - { - linechanging=!linechanging; - if(linechanging) - { - encoderpos=(int)acceleration/100; - } - else - { - acceleration= encoderpos*100; - encoderpos=activeline*lcdslow; - } - BLOCK; - beepshort(); - } - if(linechanging) - { - if(encoderpos<5) encoderpos=5; - if(encoderpos>990) encoderpos=990; - lcd.setCursor(13,line);lcd.print(itostr3(encoderpos));lcd.print("00"); - } - } - }break; - case ItemC_xyjerk: //max_xy_jerk - { - if(force_lcd_update) - { - lcd.setCursor(0,line);lcd.print(" Vxy-jerk: "); - lcd.setCursor(13,line);lcd.print(itostr3(max_xy_jerk/60)); - } - - if((activeline==line) ) - { - if(CLICKED) - { - linechanging=!linechanging; - if(linechanging) - { - encoderpos=(int)max_xy_jerk/60; - } - else - { - max_xy_jerk= encoderpos*60; - encoderpos=activeline*lcdslow; - - } - BLOCK; - beepshort(); - } - if(linechanging) - { - if(encoderpos<1) encoderpos=1; - if(encoderpos>990) encoderpos=990; - lcd.setCursor(13,line);lcd.print(itostr3(encoderpos)); - } - } - }break; - case ItemC_PID_P: - { - if(force_lcd_update) - { - lcd.setCursor(0,line);lcd.print(" PID-P: "); - lcd.setCursor(13,line);lcd.print(itostr4(Kp)); - } - - if((activeline==line) ) - { - if(CLICKED) - { - linechanging=!linechanging; - if(linechanging) - { - encoderpos=(int)Kp/5; - } - else - { - Kp= encoderpos*5; - encoderpos=activeline*lcdslow; - - } - BLOCK; - beepshort(); - } - if(linechanging) - { - if(encoderpos<1) encoderpos=1; - if(encoderpos>9990/5) encoderpos=9990/5; - lcd.setCursor(13,line);lcd.print(itostr4(encoderpos*5)); - } - } - }break; - case ItemC_PID_I: - { - if(force_lcd_update) - { - lcd.setCursor(0,line);lcd.print(" PID-I: "); - lcd.setCursor(13,line);lcd.print(ftostr51(Ki)); - } - - if((activeline==line) ) - { - if(CLICKED) - { - linechanging=!linechanging; - if(linechanging) - { - encoderpos=(int)(Ki*10); - } - else - { - Ki= encoderpos/10.; - encoderpos=activeline*lcdslow; - - } - BLOCK; - beepshort(); - } - if(linechanging) - { - if(encoderpos<0) encoderpos=0; - if(encoderpos>9990) encoderpos=9990; - lcd.setCursor(13,line);lcd.print(ftostr51(encoderpos/10.)); - } - } - }break; - case ItemC_PID_D: - { - if(force_lcd_update) - { - lcd.setCursor(0,line);lcd.print(" PID-D: "); - lcd.setCursor(13,line);lcd.print(itostr4(Kd)); - } - - if((activeline==line) ) - { - if(CLICKED) - { - linechanging=!linechanging; - if(linechanging) - { - encoderpos=(int)Kd/5; - } - else - { - Kd= encoderpos*5; - encoderpos=activeline*lcdslow; - - } - BLOCK; - beepshort(); - } - if(linechanging) - { - if(encoderpos<0) encoderpos=0; - if(encoderpos>9990/5) encoderpos=9990/5; - lcd.setCursor(13,line);lcd.print(itostr4(encoderpos*5)); - } - } - }break; - - - - case ItemC_PID_C: - { - if(force_lcd_update) - { - lcd.setCursor(0,line);lcd.print(" PID-C: "); - lcd.setCursor(13,line);lcd.print(itostr3(Kc)); - } - - if((activeline==line) ) - { - if(CLICKED) - { - linechanging=!linechanging; - if(linechanging) - { - encoderpos=(int)Kc; - } - else - { - Kc= encoderpos; - encoderpos=activeline*lcdslow; - - } - BLOCK; - beepshort(); - } - if(linechanging) - { - if(encoderpos<0) encoderpos=0; - if(encoderpos>990) encoderpos=990; - lcd.setCursor(13,line);lcd.print(itostr3(encoderpos)); - } - } - }break; - case ItemC_vmaxx: - case ItemC_vmaxy: - case ItemC_vmaxz: - case ItemC_vmaxe: - { - if(force_lcd_update) - { - lcd.setCursor(0,line);lcd.print(" Vmax "); - if(i==ItemC_vmaxx)lcd.print("x:"); - if(i==ItemC_vmaxy)lcd.print("y:"); - if(i==ItemC_vmaxz)lcd.print("z:"); - if(i==ItemC_vmaxe)lcd.print("e:"); - lcd.setCursor(13,line);lcd.print(itostr3(max_feedrate[i-ItemC_vmaxx]/60)); - } - - if((activeline==line) ) - { - if(CLICKED) - { - linechanging=!linechanging; - if(linechanging) - { - encoderpos=(int)max_feedrate[i-ItemC_vmaxx]/60; - } - else - { - max_feedrate[i-ItemC_vmaxx]= encoderpos*60; - encoderpos=activeline*lcdslow; - - } - BLOCK; - beepshort(); - } - if(linechanging) - { - if(encoderpos<1) encoderpos=1; - if(encoderpos>990) encoderpos=990; - lcd.setCursor(13,line);lcd.print(itostr3(encoderpos)); - } - } - }break; - - case ItemC_vmin: - { - if(force_lcd_update) - { - lcd.setCursor(0,line);lcd.print(" Vmin:"); - lcd.setCursor(13,line);lcd.print(itostr3(minimumfeedrate/60)); - } - - if((activeline==line) ) - { - if(CLICKED) - { - linechanging=!linechanging; - if(linechanging) - { - encoderpos=(int)(minimumfeedrate/60.); - } - else - { - minimumfeedrate= encoderpos*60; - encoderpos=activeline*lcdslow; - - } - BLOCK; - beepshort(); - } - if(linechanging) - { - if(encoderpos<0) encoderpos=0; - if(encoderpos>990) encoderpos=990; - lcd.setCursor(13,line);lcd.print(itostr3(encoderpos)); - } - } - }break; - case ItemC_vtravmin: - { - if(force_lcd_update) - { - lcd.setCursor(0,line);lcd.print(" VTrav min:"); - lcd.setCursor(13,line);lcd.print(itostr3(mintravelfeedrate/60)); - } - - if((activeline==line) ) - { - if(CLICKED) - { - linechanging=!linechanging; - if(linechanging) - { - encoderpos=(int)mintravelfeedrate/60; - } - else - { - mintravelfeedrate= encoderpos*60; - encoderpos=activeline*lcdslow; - - } - BLOCK; - beepshort(); - } - if(linechanging) - { - if(encoderpos<0) encoderpos=0; - if(encoderpos>990) encoderpos=990; - lcd.setCursor(13,line);lcd.print(itostr3(encoderpos)); - } - } - }break; - - case ItemC_amaxx: - case ItemC_amaxy: - case ItemC_amaxz: - case ItemC_amaxe: - { - if(force_lcd_update) - { - lcd.setCursor(0,line);lcd.print(" Amax "); - if(i==ItemC_amaxx)lcd.print("x:"); - if(i==ItemC_amaxy)lcd.print("y:"); - if(i==ItemC_amaxz)lcd.print("z:"); - if(i==ItemC_amaxe)lcd.print("e:"); - lcd.setCursor(13,line);lcd.print(itostr3(max_acceleration_units_per_sq_second[i-ItemC_amaxx]/100));lcd.print("00"); - } - - if((activeline==line) ) - { - if(CLICKED) - { - linechanging=!linechanging; - if(linechanging) - { - encoderpos=(int)max_acceleration_units_per_sq_second[i-ItemC_amaxx]/100; - } - else - { - max_acceleration_units_per_sq_second[i-ItemC_amaxx]= encoderpos*100; - encoderpos=activeline*lcdslow; - } - BLOCK; - beepshort(); - } - if(linechanging) - { - if(encoderpos<1) encoderpos=1; - if(encoderpos>990) encoderpos=990; - lcd.setCursor(13,line);lcd.print(itostr3(encoderpos));lcd.print("00"); - } - } - }break; - case ItemC_aret://float retract_acceleration = 7000; - { - if(force_lcd_update) - { - lcd.setCursor(0,line);lcd.print(" A-retract:"); - lcd.setCursor(13,line);lcd.print(ftostr3(retract_acceleration/100));lcd.print("00"); - } - - if((activeline==line) ) - { - if(CLICKED) - { - linechanging=!linechanging; - if(linechanging) - { - encoderpos=(int)retract_acceleration/100; - } - else - { - retract_acceleration= encoderpos*100; - encoderpos=activeline*lcdslow; - - } - BLOCK; - beepshort(); - } - if(linechanging) - { - if(encoderpos<10) encoderpos=10; - if(encoderpos>990) encoderpos=990; - lcd.setCursor(13,line);lcd.print(itostr3(encoderpos));lcd.print("00"); - } - } - }break; - case ItemC_esteps://axis_steps_per_unit[i] = code_value(); - { - if(force_lcd_update) - { - lcd.setCursor(0,line);lcd.print(" Esteps/mm:"); - lcd.setCursor(13,line);lcd.print(itostr4(axis_steps_per_unit[3])); - } - - if((activeline==line) ) - { - if(CLICKED) - { - linechanging=!linechanging; - if(linechanging) - { - encoderpos=(int)axis_steps_per_unit[3]; - } - else - { - float factor=float(encoderpos)/float(axis_steps_per_unit[3]); - position[E_AXIS]=lround(position[E_AXIS]*factor); - //current_position[3]*=factor; - axis_steps_per_unit[E_AXIS]= encoderpos; - encoderpos=activeline*lcdslow; - - } - BLOCK; - beepshort(); - } - if(linechanging) - { - if(encoderpos<5) encoderpos=5; - if(encoderpos>9999) encoderpos=9999; - lcd.setCursor(13,line);lcd.print(itostr4(encoderpos)); - } - } - }break; - case ItemC_store: - { - if(force_lcd_update) - { - lcd.setCursor(0,line);lcd.print(" Store EPROM"); - } - if((activeline==line) && CLICKED) - { - //enquecommand("M84"); - beepshort(); - BLOCK; - StoreSettings(); - } - }break; - case ItemC_load: - { - if(force_lcd_update) - { - lcd.setCursor(0,line);lcd.print(" Load EPROM"); - } - if((activeline==line) && CLICKED) - { - //enquecommand("M84"); - beepshort(); - BLOCK; - RetrieveSettings(); - } - }break; - case ItemC_failsafe: - { - if(force_lcd_update) - { - lcd.setCursor(0,line);lcd.print(" Restore Failsafe"); - } - if((activeline==line) && CLICKED) - { - //enquecommand("M84"); - beepshort(); - BLOCK; - RetrieveSettings(true); - } - }break; - default: - break; - } - line++; - } - lastlineoffset=lineoffset; - - if(!linechanging && ((encoderpos/lcdslow!=lastencoderpos/lcdslow)||force_lcd_update)) - { - - lcd.setCursor(0,activeline);lcd.print((activeline+lineoffset)?' ':' '); - - if(encoderpos<0) - { - lineoffset--; - if(lineoffset<0) - lineoffset=0; - encoderpos=0; - force_lcd_update=true; - } - if(encoderpos/lcdslow>3) - { - lineoffset++; - encoderpos=3*lcdslow; - if(lineoffset>(ItemC_failsafe+1-LCD_HEIGHT)) - lineoffset=ItemC_failsafe+1-LCD_HEIGHT; - force_lcd_update=true; - } - //encoderpos=encoderpos%LCD_HEIGHT; - lastencoderpos=encoderpos; - activeline=encoderpos/lcdslow; - if(activeline>3) activeline=3; - lcd.setCursor(0,activeline);lcd.print((activeline+lineoffset)?'>':'\003'); - } -} - -#include "SdFat.h" - -void MainMenu::getfilename(const uint8_t nr) -{ -#ifdef SDSUPPORT - dir_t p; - root.rewind(); - uint8_t cnt=0; - filename[0]='\0'; - while (root.readDir(p) > 0) - { - if (p.name[0] == DIR_NAME_FREE) break; - if (p.name[0] == DIR_NAME_DELETED || p.name[0] == '.'|| p.name[0] == '_') continue; - if (!DIR_IS_FILE_OR_SUBDIR(&p)) continue; - if(p.name[8]!='G') continue; - if(p.name[9]=='~') continue; - if(cnt++!=nr) continue; - //Serial.println((char*)p.name); - uint8_t writepos=0; - for (uint8_t i = 0; i < 11; i++) - { - if (p.name[i] == ' ') continue; - if (i == 8) { - filename[writepos++]='.'; - } - filename[writepos++]=p.name[i]; - } - filename[writepos++]=0; - } -#endif -} - -uint8_t getnrfilenames() -{ -#ifdef SDSUPPORT - dir_t p; - root.rewind(); - uint8_t cnt=0; - while (root.readDir(p) > 0) - { - if (p.name[0] == DIR_NAME_FREE) break; - if (p.name[0] == DIR_NAME_DELETED || p.name[0] == '.'|| p.name[0] == '_') continue; - if (!DIR_IS_FILE_OR_SUBDIR(&p)) continue; - if(p.name[8]!='G') continue; - if(p.name[9]=='~') continue; - cnt++; - } - return cnt; -#endif -} - -void MainMenu::showSD() -{ - -#ifdef SDSUPPORT - uint8_t line=0; - - if(lastlineoffset!=lineoffset) - { - force_lcd_update=true; - } - static uint8_t nrfiles=0; - if(force_lcd_update) - { - clear(); - if(sdactive) - { - nrfiles=getnrfilenames(); - } - else - { - nrfiles=0; - lineoffset=0; - } - //Serial.print("Nr files:"); Serial.println((int)nrfiles); - } - - for(int8_t i=lineoffset;i3) - { - lineoffset++; - encoderpos=3*lcdslow; - if(lineoffset>(1+nrfiles+1-LCD_HEIGHT)) - lineoffset=1+nrfiles+1-LCD_HEIGHT; - force_lcd_update=true; - - } - lastencoderpos=encoderpos; - activeline=encoderpos; - if(activeline>3) - { - activeline=3; - } - if(activeline<0) - { - activeline=0; - } - if(activeline>1+nrfiles) activeline=1+nrfiles; - if(lineoffset>1+nrfiles) lineoffset=1+nrfiles; - lcd.setCursor(0,activeline);lcd.print((activeline+lineoffset)?'>':'\003'); - - } -#endif -} - -enum {ItemM_watch, ItemM_prepare, ItemM_control, ItemM_file }; -void MainMenu::showMainMenu() -{ - //if(int(encoderpos/lcdslow)!=int(lastencoderpos/lcdslow)) - // force_lcd_update=true; -#ifndef ULTIPANEL - force_lcd_update=false; -#endif - //Serial.println((int)activeline); - if(force_lcd_update) - clear(); - for(short line=0;line=LCD_HEIGHT) activeline=LCD_HEIGHT-1; - if((encoderpos!=lastencoderpos)||force_lcd_update) - { - lcd.setCursor(0,activeline);lcd.print(activeline?' ':' '); - if(encoderpos<0) encoderpos=0; - if(encoderpos>3*lcdslow) encoderpos=3*lcdslow; - activeline=abs(encoderpos/lcdslow)%LCD_HEIGHT; - if(activeline<0) activeline=0; - if(activeline>=LCD_HEIGHT) activeline=LCD_HEIGHT-1; - lastencoderpos=encoderpos; - lcd.setCursor(0,activeline);lcd.print(activeline?'>':'\003'); - } - - - -} - -void MainMenu::update() -{ - static MainStatus oldstatus=Main_Menu; //init automatically causes foce_lcd_update=true - static long timeoutToStatus=0; - static bool oldcardstatus=false; -#ifdef CARDINSERTED - if((CARDINSERTED != oldcardstatus)) - { - force_lcd_update=true; - oldcardstatus=CARDINSERTED; - //Serial.println("SD CHANGE"); - if(CARDINSERTED) - { - initsd(); - lcd_status("Card inserted"); - } - else - { - sdactive=false; - lcd_status("Card removed"); - - } - } -#endif - - if(status!=oldstatus) - { - //Serial.println(status); - //clear(); - force_lcd_update=true; - encoderpos=0; - lineoffset=0; - - oldstatus=status; - } - if( (encoderpos!=lastencoderpos) || CLICKED) - timeoutToStatus=millis()+STATUSTIMEOUT; - - switch(status) - { - case Main_Status: - { - showStatus(); - if(CLICKED) - { - linechanging=false; - BLOCK - status=Main_Menu; - timeoutToStatus=millis()+STATUSTIMEOUT; - } - }break; - case Main_Menu: - { - showMainMenu(); - linechanging=false; - }break; - case Main_Prepare: - { - showPrepare(); - }break; - case Main_Control: - { - showControl(); - }break; - case Main_SD: - { - showSD(); - }break; - } - - if(timeoutToStatus=0)?'+':'-'; - xx=abs(xx); - conv[1]=(xx/1000)%10+'0'; - conv[2]=(xx/100)%10+'0'; - conv[3]=(xx/10)%10+'0'; - conv[4]='.'; - conv[5]=(xx)%10+'0'; - conv[6]=0; - return conv; -} - -char *itostr31(const int &xx) -{ - //sprintf(conv,"%5.1f",x); - conv[0]=(xx>=0)?'+':'-'; - conv[1]=(xx/1000)%10+'0'; - conv[2]=(xx/100)%10+'0'; - conv[3]=(xx/10)%10+'0'; - conv[4]='.'; - conv[5]=(xx)%10+'0'; - conv[6]=0; - return conv; -} -char *itostr3(const int &xx) -{ - conv[0]=(xx/100)%10+'0'; - conv[1]=(xx/10)%10+'0'; - conv[2]=(xx)%10+'0'; - conv[3]=0; - return conv; -} - -char *itostr4(const int &xx) -{ - conv[0]=(xx/1000)%10+'0'; - conv[1]=(xx/100)%10+'0'; - conv[2]=(xx/10)%10+'0'; - conv[3]=(xx)%10+'0'; - conv[4]=0; - return conv; -} - -/// convert float to string with +1234.5 format -char *ftostr51(const float &x) -{ - int xx=x*10; - conv[0]=(xx>=0)?'+':'-'; - xx=abs(xx); - conv[1]=(xx/10000)%10+'0'; - conv[2]=(xx/1000)%10+'0'; - conv[3]=(xx/100)%10+'0'; - conv[4]=(xx/10)%10+'0'; - conv[5]='.'; - conv[6]=(xx)%10+'0'; - conv[7]=0; - return conv; -} - -char *fillto(int8_t n,char *c) -{ - static char ret[25]; - bool endfound=false; - for(int8_t i=0;i +LiquidCrystal lcd(LCD_PINS_RS, LCD_PINS_ENABLE, LCD_PINS_D4, LCD_PINS_D5,LCD_PINS_D6,LCD_PINS_D7); //RS,Enable,D4,D5,D6,D7 + +unsigned long previous_millis_lcd=0; + + + +volatile char buttons=0; //the last checked buttons in a bit array. +int encoderpos=0; +short lastenc=0; +#ifdef NEWPANEL + long blocking=0; +#else + long blocking[8]={0,0,0,0,0,0,0,0}; +#endif +MainMenu menu; + +void lcd_status(const char* message) +{ + strncpy(messagetext,message,LCD_WIDTH); +} + +void clear() +{ + //lcd.setCursor(0,0); + lcd.clear(); + //delay(1); + // lcd.begin(LCD_WIDTH,LCD_HEIGHT); + //lcd_init(); +} +long previous_millis_buttons=0; + +void lcd_init() +{ + //beep(); + byte Degree[8] = + { + B01100, + B10010, + B10010, + B01100, + B00000, + B00000, + B00000, + B00000 + }; + byte Thermometer[8] = + { + B00100, + B01010, + B01010, + B01010, + B01010, + B10001, + B10001, + B01110 + }; + byte uplevel[8]={0x04, 0x0e, 0x1f, 0x04, 0x1c, 0x00, 0x00, 0x00};//thanks joris + byte refresh[8]={0x00, 0x06, 0x19, 0x18, 0x03, 0x13, 0x0c, 0x00}; //thanks joris + lcd.begin(LCD_WIDTH, LCD_HEIGHT); + lcd.createChar(1,Degree); + lcd.createChar(2,Thermometer); + lcd.createChar(3,uplevel); + lcd.createChar(4,refresh); + LCD_MESSAGE(fillto(LCD_WIDTH,"UltiMarlin ready.")); +} + + +void beep() +{ + //return; +#ifdef ULTIPANEL + pinMode(BEEPER,OUTPUT); + for(int i=0;i<20;i++){ + WRITE(BEEPER,HIGH); + delay(5); + WRITE(BEEPER,LOW); + delay(5); + } +#endif +} + +void beepshort() +{ + //return; +#ifdef ULTIPANEL + pinMode(BEEPER,OUTPUT); + for(int i=0;i<10;i++){ + WRITE(BEEPER,HIGH); + delay(3); + WRITE(BEEPER,LOW); + delay(3); + } +#endif +} +void lcd_status() +{ +#ifdef ULTIPANEL + static uint8_t oldbuttons=0; + static long previous_millis_buttons=0; + static long previous_lcdinit=0; +// buttons_check(); // Done in temperature interrupt + //previous_millis_buttons=millis(); + + if((buttons==oldbuttons) && ((millis() - previous_millis_lcd) < LCD_UPDATE_INTERVAL) ) + return; + oldbuttons=buttons; +#else + + if(((millis() - previous_millis_lcd) < LCD_UPDATE_INTERVAL) ) + return; +#endif + + previous_millis_lcd=millis(); + menu.update(); +} +#ifdef ULTIPANEL +void buttons_init() +{ +#ifdef NEWPANEL + pinMode(BTN_EN1,INPUT); + pinMode(BTN_EN2,INPUT); + pinMode(BTN_ENC,INPUT); + pinMode(SDCARDDETECT,INPUT); + WRITE(BTN_EN1,HIGH); + WRITE(BTN_EN2,HIGH); + WRITE(BTN_ENC,HIGH); + WRITE(SDCARDDETECT,HIGH); +#else + pinMode(SHIFT_CLK,OUTPUT); + pinMode(SHIFT_LD,OUTPUT); + pinMode(SHIFT_EN,OUTPUT); + pinMode(SHIFT_OUT,INPUT); + WRITE(SHIFT_OUT,HIGH); + WRITE(SHIFT_LD,HIGH); + WRITE(SHIFT_EN,LOW); +#endif +} + + +void buttons_check() +{ +// volatile static bool busy=false; +// if(busy) +// return; +// busy=true; + +#ifdef NEWPANEL + uint8_t newbutton=0; + if(READ(BTN_EN1)==0) newbutton|=EN_A; + if(READ(BTN_EN2)==0) newbutton|=EN_B; + if((blocking>1; + if(READ(SHIFT_OUT)) + newbutton|=(1<<7); + WRITE(SHIFT_CLK,HIGH); + WRITE(SHIFT_CLK,LOW); + } + buttons=~newbutton; //invert it, because a pressed switch produces a logical 0 +#endif + char enc=0; + if(buttons&EN_A) + enc|=(1<<0); + if(buttons&EN_B) + enc|=(1<<1); + if(enc!=lastenc) + { + switch(enc) + { + case encrot0: + if(lastenc==encrot3) + encoderpos++; + else if(lastenc==encrot1) + encoderpos--; + break; + case encrot1: + if(lastenc==encrot0) + encoderpos++; + else if(lastenc==encrot2) + encoderpos--; + break; + case encrot2: + if(lastenc==encrot1) + encoderpos++; + else if(lastenc==encrot3) + encoderpos--; + break; + case encrot3: + if(lastenc==encrot2) + encoderpos++; + else if(lastenc==encrot0) + encoderpos--; + break; + default: + ; + } + } + lastenc=enc; +// busy=false; +} + +#endif + +MainMenu::MainMenu() +{ + status=Main_Status; + displayStartingRow=0; + activeline=0; + force_lcd_update=true; +#ifdef ULTIPANEL + buttons_init(); +#endif + lcd_init(); + linechanging=false; +} + +extern volatile bool feedmultiplychanged; + +void MainMenu::showStatus() +{ +#if LCD_HEIGHT==4 + static int oldcurrentraw=-1; + static int oldtargetraw=-1; + //force_lcd_update=true; + if(force_lcd_update||feedmultiplychanged) //initial display of content + { + feedmultiplychanged=false; + encoderpos=feedmultiply; + clear(); + lcd.setCursor(0,0);lcd.print("\002123/567\001 "); +#if defined BED_USES_THERMISTOR || defined BED_USES_AD595 + lcd.setCursor(10,0);lcd.print("B123/567\001 "); +#endif + } + + + if((abs(current_raw[TEMPSENSOR_HOTEND]-oldcurrentraw)>3)||force_lcd_update) + { + lcd.setCursor(1,0); + lcd.print(ftostr3(analog2temp(current_raw[TEMPSENSOR_HOTEND]))); + oldcurrentraw=current_raw[TEMPSENSOR_HOTEND]; + } + if((target_raw[TEMPSENSOR_HOTEND]!=oldtargetraw)||force_lcd_update) + { + lcd.setCursor(5,0); + lcd.print(ftostr3(analog2temp(target_raw[TEMPSENSOR_HOTEND]))); + oldtargetraw=target_raw[TEMPSENSOR_HOTEND]; + } + #if defined BED_USES_THERMISTOR || defined BED_USES_AD595 + static int oldcurrentbedraw=-1; + static int oldtargetbedraw=-1; + if((current_bed_raw!=oldcurrentbedraw)||force_lcd_update) + { + lcd.setCursor(1,0); + lcd.print(ftostr3(analog2temp(current_bed_raw))); + oldcurrentraw=current_raw[TEMPSENSOR_BED]; + } + if((target_bed_raw!=oldtargebedtraw)||force_lcd_update) + { + lcd.setCursor(5,0); + lcd.print(ftostr3(analog2temp(target_bed_raw))); + oldtargetraw=target_bed_raw; + } + #endif + //starttime=2; + static uint16_t oldtime=0; + if(starttime!=0) + { + lcd.setCursor(0,1); + uint16_t time=millis()/60000-starttime/60000; + + if(starttime!=oldtime) + { + lcd.print(itostr2(time/60));lcd.print("h ");lcd.print(itostr2(time%60));lcd.print("m"); + oldtime=time; + } + } + static int oldzpos=0; + int currentz=current_position[2]*10; + if((currentz!=oldzpos)||force_lcd_update) + { + lcd.setCursor(10,1); + lcd.print("Z:");lcd.print(itostr31(currentz)); + oldzpos=currentz; + } + static int oldfeedmultiply=0; + int curfeedmultiply=feedmultiply; + if(encoderpos!=curfeedmultiply||force_lcd_update) + { + curfeedmultiply=encoderpos; + if(curfeedmultiply<10) + curfeedmultiply=10; + if(curfeedmultiply>999) + curfeedmultiply=999; + feedmultiply=curfeedmultiply; + encoderpos=curfeedmultiply; + } + if((curfeedmultiply!=oldfeedmultiply)||force_lcd_update) + { + oldfeedmultiply=curfeedmultiply; + lcd.setCursor(0,2); + lcd.print(itostr3(curfeedmultiply));lcd.print("% "); + } + if(messagetext[0]!='\0') + { + lcd.setCursor(0,LCD_HEIGHT-1); + lcd.print(fillto(LCD_WIDTH,messagetext)); + messagetext[0]='\0'; + } +#else //smaller LCDS---------------------------------- + static int oldcurrentraw=-1; + static int oldtargetraw=-1; + if(force_lcd_update) //initial display of content + { + encoderpos=feedmultiply; + lcd.setCursor(0,0);lcd.print("\002123/567\001 "); + #if defined BED_USES_THERMISTOR || defined BED_USES_AD595 + lcd.setCursor(10,0);lcd.print("B123/567\001 "); + #endif + } + + + if((abs(current_raw[TEMPSENSOR_HOTEND]-oldcurrentraw)>3)||force_lcd_update) + { + lcd.setCursor(1,0); + lcd.print(ftostr3(analog2temp(current_raw[TEMPSENSOR_HOTEND]))); + oldcurrentraw=current_raw[TEMPSENSOR_HOTEND]; + } + if((target_raw[TEMPSENSOR_HOTEND]!=oldtargetraw)||force_lcd_update) + { + lcd.setCursor(5,0); + lcd.print(ftostr3(analog2temp(target_raw[TEMPSENSOR_HOTEND]))); + oldtargetraw=target_raw[TEMPSENSOR_HOTEND]; + } + + if(messagetext[0]!='\0') + { + lcd.setCursor(0,LCD_HEIGHT-1); + lcd.print(fillto(LCD_WIDTH,messagetext)); + messagetext[0]='\0'; + } + +#endif +} + +enum {ItemP_exit, ItemP_home, ItemP_origin, ItemP_preheat, ItemP_extrude, ItemP_disstep}; + +void MainMenu::showPrepare() +{ + uint8_t line=0; + if(lastlineoffset!=lineoffset) + { + force_lcd_update=true; + clear(); + } + for(uint8_t i=lineoffset;i3) + { + lineoffset++; + encoderpos=3*lcdslow; + if(lineoffset>(ItemP_disstep+1-LCD_HEIGHT)) + lineoffset=ItemP_disstep+1-LCD_HEIGHT; + force_lcd_update=true; + } + //encoderpos=encoderpos%LCD_HEIGHT; + lastencoderpos=encoderpos; + activeline=encoderpos/lcdslow; + lcd.setCursor(0,activeline);lcd.print((activeline+lineoffset)?'>':'\003'); + } +} +enum { + ItemC_exit, ItemC_nozzle, + ItemC_PID_P,ItemC_PID_I,ItemC_PID_D,ItemC_PID_C, + ItemC_fan, + ItemC_acc, ItemC_xyjerk, + ItemC_vmaxx, ItemC_vmaxy, ItemC_vmaxz, ItemC_vmaxe, + ItemC_vtravmin,ItemC_vmin, + ItemC_amaxx, ItemC_amaxy, ItemC_amaxz, ItemC_amaxe, + ItemC_aret,ItemC_esteps, ItemC_store, ItemC_load,ItemC_failsafe +}; + +void MainMenu::showControl() +{ + uint8_t line=0; + if((lastlineoffset!=lineoffset)||force_lcd_update) + { + force_lcd_update=true; + clear(); + } + for(uint8_t i=lineoffset;i260) encoderpos=260; + lcd.setCursor(13,line);lcd.print(itostr3(encoderpos)); + } + } + }break; + + case ItemC_fan: + { + if(force_lcd_update) + { + lcd.setCursor(0,line);lcd.print(" Fan speed:"); + lcd.setCursor(13,line);lcd.print(ftostr3(fanpwm)); + } + + if((activeline==line) ) + { + if(CLICKED) //nalogWrite(FAN_PIN, fanpwm); + { + linechanging=!linechanging; + if(linechanging) + { + encoderpos=fanpwm; + } + else + { + fanpwm = constrain(encoderpos,0,255); + encoderpos=fanpwm; + analogWrite(FAN_PIN, fanpwm); + + beepshort(); + } + BLOCK; + } + if(linechanging) + { + if(encoderpos<0) encoderpos=0; + if(encoderpos>255) encoderpos=255; + fanpwm=encoderpos; + analogWrite(FAN_PIN, fanpwm); + lcd.setCursor(13,line);lcd.print(itostr3(encoderpos)); + } + } + }break; + case ItemC_acc: + { + if(force_lcd_update) + { + lcd.setCursor(0,line);lcd.print(" Acc:"); + lcd.setCursor(13,line);lcd.print(itostr3(acceleration/100));lcd.print("00"); + } + + if((activeline==line) ) + { + if(CLICKED) + { + linechanging=!linechanging; + if(linechanging) + { + encoderpos=(int)acceleration/100; + } + else + { + acceleration= encoderpos*100; + encoderpos=activeline*lcdslow; + } + BLOCK; + beepshort(); + } + if(linechanging) + { + if(encoderpos<5) encoderpos=5; + if(encoderpos>990) encoderpos=990; + lcd.setCursor(13,line);lcd.print(itostr3(encoderpos));lcd.print("00"); + } + } + }break; + case ItemC_xyjerk: //max_xy_jerk + { + if(force_lcd_update) + { + lcd.setCursor(0,line);lcd.print(" Vxy-jerk: "); + lcd.setCursor(13,line);lcd.print(itostr3(max_xy_jerk/60)); + } + + if((activeline==line) ) + { + if(CLICKED) + { + linechanging=!linechanging; + if(linechanging) + { + encoderpos=(int)max_xy_jerk/60; + } + else + { + max_xy_jerk= encoderpos*60; + encoderpos=activeline*lcdslow; + + } + BLOCK; + beepshort(); + } + if(linechanging) + { + if(encoderpos<1) encoderpos=1; + if(encoderpos>990) encoderpos=990; + lcd.setCursor(13,line);lcd.print(itostr3(encoderpos)); + } + } + }break; + case ItemC_PID_P: + { + if(force_lcd_update) + { + lcd.setCursor(0,line);lcd.print(" PID-P: "); + lcd.setCursor(13,line);lcd.print(itostr4(Kp)); + } + + if((activeline==line) ) + { + if(CLICKED) + { + linechanging=!linechanging; + if(linechanging) + { + encoderpos=(int)Kp/5; + } + else + { + Kp= encoderpos*5; + encoderpos=activeline*lcdslow; + + } + BLOCK; + beepshort(); + } + if(linechanging) + { + if(encoderpos<1) encoderpos=1; + if(encoderpos>9990/5) encoderpos=9990/5; + lcd.setCursor(13,line);lcd.print(itostr4(encoderpos*5)); + } + } + }break; + case ItemC_PID_I: + { + if(force_lcd_update) + { + lcd.setCursor(0,line);lcd.print(" PID-I: "); + lcd.setCursor(13,line);lcd.print(ftostr51(Ki)); + } + + if((activeline==line) ) + { + if(CLICKED) + { + linechanging=!linechanging; + if(linechanging) + { + encoderpos=(int)(Ki*10); + } + else + { + Ki= encoderpos/10.; + encoderpos=activeline*lcdslow; + + } + BLOCK; + beepshort(); + } + if(linechanging) + { + if(encoderpos<0) encoderpos=0; + if(encoderpos>9990) encoderpos=9990; + lcd.setCursor(13,line);lcd.print(ftostr51(encoderpos/10.)); + } + } + }break; + case ItemC_PID_D: + { + if(force_lcd_update) + { + lcd.setCursor(0,line);lcd.print(" PID-D: "); + lcd.setCursor(13,line);lcd.print(itostr4(Kd)); + } + + if((activeline==line) ) + { + if(CLICKED) + { + linechanging=!linechanging; + if(linechanging) + { + encoderpos=(int)Kd/5; + } + else + { + Kd= encoderpos*5; + encoderpos=activeline*lcdslow; + + } + BLOCK; + beepshort(); + } + if(linechanging) + { + if(encoderpos<0) encoderpos=0; + if(encoderpos>9990/5) encoderpos=9990/5; + lcd.setCursor(13,line);lcd.print(itostr4(encoderpos*5)); + } + } + }break; + + + + case ItemC_PID_C: + { + if(force_lcd_update) + { + lcd.setCursor(0,line);lcd.print(" PID-C: "); + lcd.setCursor(13,line);lcd.print(itostr3(Kc)); + } + + if((activeline==line) ) + { + if(CLICKED) + { + linechanging=!linechanging; + if(linechanging) + { + encoderpos=(int)Kc; + } + else + { + Kc= encoderpos; + encoderpos=activeline*lcdslow; + + } + BLOCK; + beepshort(); + } + if(linechanging) + { + if(encoderpos<0) encoderpos=0; + if(encoderpos>990) encoderpos=990; + lcd.setCursor(13,line);lcd.print(itostr3(encoderpos)); + } + } + }break; + case ItemC_vmaxx: + case ItemC_vmaxy: + case ItemC_vmaxz: + case ItemC_vmaxe: + { + if(force_lcd_update) + { + lcd.setCursor(0,line);lcd.print(" Vmax "); + if(i==ItemC_vmaxx)lcd.print("x:"); + if(i==ItemC_vmaxy)lcd.print("y:"); + if(i==ItemC_vmaxz)lcd.print("z:"); + if(i==ItemC_vmaxe)lcd.print("e:"); + lcd.setCursor(13,line);lcd.print(itostr3(max_feedrate[i-ItemC_vmaxx]/60)); + } + + if((activeline==line) ) + { + if(CLICKED) + { + linechanging=!linechanging; + if(linechanging) + { + encoderpos=(int)max_feedrate[i-ItemC_vmaxx]/60; + } + else + { + max_feedrate[i-ItemC_vmaxx]= encoderpos*60; + encoderpos=activeline*lcdslow; + + } + BLOCK; + beepshort(); + } + if(linechanging) + { + if(encoderpos<1) encoderpos=1; + if(encoderpos>990) encoderpos=990; + lcd.setCursor(13,line);lcd.print(itostr3(encoderpos)); + } + } + }break; + + case ItemC_vmin: + { + if(force_lcd_update) + { + lcd.setCursor(0,line);lcd.print(" Vmin:"); + lcd.setCursor(13,line);lcd.print(itostr3(minimumfeedrate/60)); + } + + if((activeline==line) ) + { + if(CLICKED) + { + linechanging=!linechanging; + if(linechanging) + { + encoderpos=(int)(minimumfeedrate/60.); + } + else + { + minimumfeedrate= encoderpos*60; + encoderpos=activeline*lcdslow; + + } + BLOCK; + beepshort(); + } + if(linechanging) + { + if(encoderpos<0) encoderpos=0; + if(encoderpos>990) encoderpos=990; + lcd.setCursor(13,line);lcd.print(itostr3(encoderpos)); + } + } + }break; + case ItemC_vtravmin: + { + if(force_lcd_update) + { + lcd.setCursor(0,line);lcd.print(" VTrav min:"); + lcd.setCursor(13,line);lcd.print(itostr3(mintravelfeedrate/60)); + } + + if((activeline==line) ) + { + if(CLICKED) + { + linechanging=!linechanging; + if(linechanging) + { + encoderpos=(int)mintravelfeedrate/60; + } + else + { + mintravelfeedrate= encoderpos*60; + encoderpos=activeline*lcdslow; + + } + BLOCK; + beepshort(); + } + if(linechanging) + { + if(encoderpos<0) encoderpos=0; + if(encoderpos>990) encoderpos=990; + lcd.setCursor(13,line);lcd.print(itostr3(encoderpos)); + } + } + }break; + + case ItemC_amaxx: + case ItemC_amaxy: + case ItemC_amaxz: + case ItemC_amaxe: + { + if(force_lcd_update) + { + lcd.setCursor(0,line);lcd.print(" Amax "); + if(i==ItemC_amaxx)lcd.print("x:"); + if(i==ItemC_amaxy)lcd.print("y:"); + if(i==ItemC_amaxz)lcd.print("z:"); + if(i==ItemC_amaxe)lcd.print("e:"); + lcd.setCursor(13,line);lcd.print(itostr3(max_acceleration_units_per_sq_second[i-ItemC_amaxx]/100));lcd.print("00"); + } + + if((activeline==line) ) + { + if(CLICKED) + { + linechanging=!linechanging; + if(linechanging) + { + encoderpos=(int)max_acceleration_units_per_sq_second[i-ItemC_amaxx]/100; + } + else + { + max_acceleration_units_per_sq_second[i-ItemC_amaxx]= encoderpos*100; + encoderpos=activeline*lcdslow; + } + BLOCK; + beepshort(); + } + if(linechanging) + { + if(encoderpos<1) encoderpos=1; + if(encoderpos>990) encoderpos=990; + lcd.setCursor(13,line);lcd.print(itostr3(encoderpos));lcd.print("00"); + } + } + }break; + case ItemC_aret://float retract_acceleration = 7000; + { + if(force_lcd_update) + { + lcd.setCursor(0,line);lcd.print(" A-retract:"); + lcd.setCursor(13,line);lcd.print(ftostr3(retract_acceleration/100));lcd.print("00"); + } + + if((activeline==line) ) + { + if(CLICKED) + { + linechanging=!linechanging; + if(linechanging) + { + encoderpos=(int)retract_acceleration/100; + } + else + { + retract_acceleration= encoderpos*100; + encoderpos=activeline*lcdslow; + + } + BLOCK; + beepshort(); + } + if(linechanging) + { + if(encoderpos<10) encoderpos=10; + if(encoderpos>990) encoderpos=990; + lcd.setCursor(13,line);lcd.print(itostr3(encoderpos));lcd.print("00"); + } + } + }break; + case ItemC_esteps://axis_steps_per_unit[i] = code_value(); + { + if(force_lcd_update) + { + lcd.setCursor(0,line);lcd.print(" Esteps/mm:"); + lcd.setCursor(13,line);lcd.print(itostr4(axis_steps_per_unit[3])); + } + + if((activeline==line) ) + { + if(CLICKED) + { + linechanging=!linechanging; + if(linechanging) + { + encoderpos=(int)axis_steps_per_unit[3]; + } + else + { + float factor=float(encoderpos)/float(axis_steps_per_unit[3]); + position[E_AXIS]=lround(position[E_AXIS]*factor); + //current_position[3]*=factor; + axis_steps_per_unit[E_AXIS]= encoderpos; + encoderpos=activeline*lcdslow; + + } + BLOCK; + beepshort(); + } + if(linechanging) + { + if(encoderpos<5) encoderpos=5; + if(encoderpos>9999) encoderpos=9999; + lcd.setCursor(13,line);lcd.print(itostr4(encoderpos)); + } + } + }break; + case ItemC_store: + { + if(force_lcd_update) + { + lcd.setCursor(0,line);lcd.print(" Store EPROM"); + } + if((activeline==line) && CLICKED) + { + //enquecommand("M84"); + beepshort(); + BLOCK; + StoreSettings(); + } + }break; + case ItemC_load: + { + if(force_lcd_update) + { + lcd.setCursor(0,line);lcd.print(" Load EPROM"); + } + if((activeline==line) && CLICKED) + { + //enquecommand("M84"); + beepshort(); + BLOCK; + RetrieveSettings(); + } + }break; + case ItemC_failsafe: + { + if(force_lcd_update) + { + lcd.setCursor(0,line);lcd.print(" Restore Failsafe"); + } + if((activeline==line) && CLICKED) + { + //enquecommand("M84"); + beepshort(); + BLOCK; + RetrieveSettings(true); + } + }break; + default: + break; + } + line++; + } + lastlineoffset=lineoffset; + + if(!linechanging && ((encoderpos/lcdslow!=lastencoderpos/lcdslow)||force_lcd_update)) + { + + lcd.setCursor(0,activeline);lcd.print((activeline+lineoffset)?' ':' '); + + if(encoderpos<0) + { + lineoffset--; + if(lineoffset<0) + lineoffset=0; + encoderpos=0; + force_lcd_update=true; + } + if(encoderpos/lcdslow>3) + { + lineoffset++; + encoderpos=3*lcdslow; + if(lineoffset>(ItemC_failsafe+1-LCD_HEIGHT)) + lineoffset=ItemC_failsafe+1-LCD_HEIGHT; + force_lcd_update=true; + } + //encoderpos=encoderpos%LCD_HEIGHT; + lastencoderpos=encoderpos; + activeline=encoderpos/lcdslow; + if(activeline>3) activeline=3; + lcd.setCursor(0,activeline);lcd.print((activeline+lineoffset)?'>':'\003'); + } +} + +#include "SdFat.h" + +void MainMenu::getfilename(const uint8_t nr) +{ +#ifdef SDSUPPORT + dir_t p; + root.rewind(); + uint8_t cnt=0; + filename[0]='\0'; + while (root.readDir(p) > 0) + { + if (p.name[0] == DIR_NAME_FREE) break; + if (p.name[0] == DIR_NAME_DELETED || p.name[0] == '.'|| p.name[0] == '_') continue; + if (!DIR_IS_FILE_OR_SUBDIR(&p)) continue; + if(p.name[8]!='G') continue; + if(p.name[9]=='~') continue; + if(cnt++!=nr) continue; + //Serial.println((char*)p.name); + uint8_t writepos=0; + for (uint8_t i = 0; i < 11; i++) + { + if (p.name[i] == ' ') continue; + if (i == 8) { + filename[writepos++]='.'; + } + filename[writepos++]=p.name[i]; + } + filename[writepos++]=0; + } +#endif +} + +uint8_t getnrfilenames() +{ +#ifdef SDSUPPORT + dir_t p; + root.rewind(); + uint8_t cnt=0; + while (root.readDir(p) > 0) + { + if (p.name[0] == DIR_NAME_FREE) break; + if (p.name[0] == DIR_NAME_DELETED || p.name[0] == '.'|| p.name[0] == '_') continue; + if (!DIR_IS_FILE_OR_SUBDIR(&p)) continue; + if(p.name[8]!='G') continue; + if(p.name[9]=='~') continue; + cnt++; + } + return cnt; +#endif +} + +void MainMenu::showSD() +{ + +#ifdef SDSUPPORT + uint8_t line=0; + + if(lastlineoffset!=lineoffset) + { + force_lcd_update=true; + } + static uint8_t nrfiles=0; + if(force_lcd_update) + { + clear(); + if(sdactive) + { + nrfiles=getnrfilenames(); + } + else + { + nrfiles=0; + lineoffset=0; + } + //Serial.print("Nr files:"); Serial.println((int)nrfiles); + } + + for(int8_t i=lineoffset;i3) + { + lineoffset++; + encoderpos=3*lcdslow; + if(lineoffset>(1+nrfiles+1-LCD_HEIGHT)) + lineoffset=1+nrfiles+1-LCD_HEIGHT; + force_lcd_update=true; + + } + lastencoderpos=encoderpos; + activeline=encoderpos; + if(activeline>3) + { + activeline=3; + } + if(activeline<0) + { + activeline=0; + } + if(activeline>1+nrfiles) activeline=1+nrfiles; + if(lineoffset>1+nrfiles) lineoffset=1+nrfiles; + lcd.setCursor(0,activeline);lcd.print((activeline+lineoffset)?'>':'\003'); + + } +#endif +} + +enum {ItemM_watch, ItemM_prepare, ItemM_control, ItemM_file }; +void MainMenu::showMainMenu() +{ + //if(int(encoderpos/lcdslow)!=int(lastencoderpos/lcdslow)) + // force_lcd_update=true; +#ifndef ULTIPANEL + force_lcd_update=false; +#endif + //Serial.println((int)activeline); + if(force_lcd_update) + clear(); + for(short line=0;line=LCD_HEIGHT) activeline=LCD_HEIGHT-1; + if((encoderpos!=lastencoderpos)||force_lcd_update) + { + lcd.setCursor(0,activeline);lcd.print(activeline?' ':' '); + if(encoderpos<0) encoderpos=0; + if(encoderpos>3*lcdslow) encoderpos=3*lcdslow; + activeline=abs(encoderpos/lcdslow)%LCD_HEIGHT; + if(activeline<0) activeline=0; + if(activeline>=LCD_HEIGHT) activeline=LCD_HEIGHT-1; + lastencoderpos=encoderpos; + lcd.setCursor(0,activeline);lcd.print(activeline?'>':'\003'); + } + + + +} + +void MainMenu::update() +{ + static MainStatus oldstatus=Main_Menu; //init automatically causes foce_lcd_update=true + static long timeoutToStatus=0; + static bool oldcardstatus=false; +#ifdef CARDINSERTED + if((CARDINSERTED != oldcardstatus)) + { + force_lcd_update=true; + oldcardstatus=CARDINSERTED; + //Serial.println("SD CHANGE"); + if(CARDINSERTED) + { + initsd(); + lcd_status("Card inserted"); + } + else + { + sdactive=false; + lcd_status("Card removed"); + + } + } +#endif + + if(status!=oldstatus) + { + //Serial.println(status); + //clear(); + force_lcd_update=true; + encoderpos=0; + lineoffset=0; + + oldstatus=status; + } + if( (encoderpos!=lastencoderpos) || CLICKED) + timeoutToStatus=millis()+STATUSTIMEOUT; + + switch(status) + { + case Main_Status: + { + showStatus(); + if(CLICKED) + { + linechanging=false; + BLOCK + status=Main_Menu; + timeoutToStatus=millis()+STATUSTIMEOUT; + } + }break; + case Main_Menu: + { + showMainMenu(); + linechanging=false; + }break; + case Main_Prepare: + { + showPrepare(); + }break; + case Main_Control: + { + showControl(); + }break; + case Main_SD: + { + showSD(); + }break; + } + + if(timeoutToStatus=0)?'+':'-'; + xx=abs(xx); + conv[1]=(xx/1000)%10+'0'; + conv[2]=(xx/100)%10+'0'; + conv[3]=(xx/10)%10+'0'; + conv[4]='.'; + conv[5]=(xx)%10+'0'; + conv[6]=0; + return conv; +} + +char *itostr31(const int &xx) +{ + //sprintf(conv,"%5.1f",x); + conv[0]=(xx>=0)?'+':'-'; + conv[1]=(xx/1000)%10+'0'; + conv[2]=(xx/100)%10+'0'; + conv[3]=(xx/10)%10+'0'; + conv[4]='.'; + conv[5]=(xx)%10+'0'; + conv[6]=0; + return conv; +} +char *itostr3(const int &xx) +{ + conv[0]=(xx/100)%10+'0'; + conv[1]=(xx/10)%10+'0'; + conv[2]=(xx)%10+'0'; + conv[3]=0; + return conv; +} + +char *itostr4(const int &xx) +{ + conv[0]=(xx/1000)%10+'0'; + conv[1]=(xx/100)%10+'0'; + conv[2]=(xx/10)%10+'0'; + conv[3]=(xx)%10+'0'; + conv[4]=0; + return conv; +} + +/// convert float to string with +1234.5 format +char *ftostr51(const float &x) +{ + int xx=x*10; + conv[0]=(xx>=0)?'+':'-'; + xx=abs(xx); + conv[1]=(xx/10000)%10+'0'; + conv[2]=(xx/1000)%10+'0'; + conv[3]=(xx/100)%10+'0'; + conv[4]=(xx/10)%10+'0'; + conv[5]='.'; + conv[6]=(xx)%10+'0'; + conv[7]=0; + return conv; +} + +char *fillto(int8_t n,char *c) +{ + static char ret[25]; + bool endfound=false; + for(int8_t i=0;i Board -> Sanguino +Select Tools -> Board -> Arduino Mega 2560 Select the correct serial port in Tools ->Serial Port Open Marlin.pde -Change the printer specific setting in Configuration.h to the correct values. - -The following values are the most important: - - float axis_steps_per_unit[].... // Set the correct steps / mm in the corresponding field - - const bool ENDSTOPS_INVERTING = false; // Change if only positive moves are executed - - #define INVERT_x_DIR true // Change if the motor direction is wrong +Click the Verify/Compile button Click the Upload button If all goes well the firmware is uploading -Start pronterface - -Select the correct Serial Port. Type 250000 in the baudrate field. -Press the Connect button - -=============================================================================================== -Known issues - -On some systems we get compilation errors. - -This is caused by the "wiring_serial.c" and "wiring.c". -The simple fix is to delete these files but this may have a performance impact. - -The best workaround is to move these files to sanguino directory. -(".../arduino-0018/hardware/Sanguino/cores/arduino/" on windows systems) - +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. diff --git a/README.md b/README.md new file mode 100644 index 000000000..6cab9fa52 --- /dev/null +++ b/README.md @@ -0,0 +1,69 @@ +WARNING: THIS IN A PROCESS OF HEAVY OVERWORKING. +DO NOT USE THIS ON YOUR MACHINE UNTIL FURTHER NOTICE!!! + +=========================================== + +This RepRap firmware is a mashup between Sprinter, grbl and many original parts. + +Derived from Sprinter and Grbl by Erik van der Zalm. +Sprinters lead developers are Kliment and caru. +Grbls lead developer is Simen Svale Skogsrud. +Some features have been added by and configuration has been added by: +Bernhard Kubicek, Matthijs Keuper, Bradley Feldman, and others... + + +Features: + - 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 + - Simple LCD support (16x2) + - SD Card support + - Provisions for Bernhard Kubicek's new hardware control console and 20x4 lcd + +This firmware is optimized for Ultimaker's gen6 electronics (including the Ultimaker 1.5.x daughterboard and Arduino Mega 2560). + +The default baudrate is 115200. + + +======================================================================================== + +Configuring and compilation + + +Install the latest arduino software IDE/toolset (currently 0022) + http://www.arduino.cc/en/Main/Software + +Install Ultimaker's RepG 25 build + http://software.ultimaker.com +(or alternatively install Kliment's printrun/pronterface https://github.com/kliment/Printrun_) + +Copy the Ultimaker Marlin firmware + https:/github.com/bkubicek/Marlin + (Use the download button) + +Start the arduino IDE. +Select Tools -> Board -> Arduino Mega 2560 +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. + + + diff --git a/merging still needs.txt b/merging still needs.txt new file mode 100644 index 000000000..2d369c968 --- /dev/null +++ b/merging still needs.txt @@ -0,0 +1,58 @@ +files to compare manually: +planner.cpp +stepper.cpp +temperature.cpp + +--- +things that changed: +* planner.cpp +estimate_acc_distance now works with floats. +in calculate_trapezoid:for_block + long acceleration_rate=(long)((float)acceleration*8.388608) is gone + so is block_>acceleration_rate +void planner_reverse_pass: + some stuff I don't understand right now changed +in planner_forward_pass: + done: BLOCK_BUFFER_SIZE is now necessarily power of 2 (aka 8 16, 32). Inportant to document this somewhere. +no more inline in void plan_discard_current_block() +no more inline in plan_get_current_block() +in plan_buffer_line(...) + the long target[4]; and calculations of thoose should go after the while(block_buffer_tail==..). if the axis_steps_per_unit are changed from the gcode (M92) the calculation for the currently planned buffer move will be corrupt, because Target is calculated with one value, and the stuff afterwards with another. At least this solved the problem I had with the M92 E* changes in the code. Very sure about this, I took me 20min to find this as the solution for the bug I was hunting. +around if(feed_rate!true+return? +done #define K1 0.95 maybe in the configuration.h? +semi-done: PID-C checking needed. Untested but added. +---- + +still needed to finish the merge, before testin! + + manage_heater + ISR + movement planner + +TODO: + +remove traveling at maxpseed +remove Simplelcd + +remove DEBUG_STEPS? + +block_t +pid_dt ->0.1 whats the changes to the PID, checking needed + + +---- +second merge saturday morning: +done: PID_dt->0.1 \ No newline at end of file