Corrected temp variables.

This commit is contained in:
Erik van der Zalm 2011-11-05 20:21:09 +01:00
parent 04d3b5537f
commit 2e8e8878e5
5 changed files with 2052 additions and 2050 deletions

View file

@ -1,245 +1,245 @@
#ifndef CONFIGURATION_H #ifndef CONFIGURATION_H
#define CONFIGURATION_H #define CONFIGURATION_H
//#define DEBUG_STEPS //#define DEBUG_STEPS
// BASIC SETTINGS: select your board type, thermistor type, axis scaling, and endstop configuration // 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 //// The following define selects which electronics board you have. Please choose the one that matches your setup
// MEGA/RAMPS up to 1.2 = 3, // MEGA/RAMPS up to 1.2 = 3,
// RAMPS 1.3 = 33 // RAMPS 1.3 = 33
// Gen6 = 5, // Gen6 = 5,
// Sanguinololu 1.2 and above = 62 // Sanguinololu 1.2 and above = 62
// Ultimaker = 7, // Ultimaker = 7,
#define MOTHERBOARD 7 #define MOTHERBOARD 7
//#define MOTHERBOARD 5 //#define MOTHERBOARD 5
//// Thermistor settings: //// Thermistor settings:
// 1 is 100k thermistor // 1 is 100k thermistor
// 2 is 200k thermistor // 2 is 200k thermistor
// 3 is mendel-parts thermistor // 3 is mendel-parts thermistor
// 4 is 10k thermistor // 4 is 10k thermistor
// 5 is ParCan supplied 104GT-2 100K // 5 is ParCan supplied 104GT-2 100K
// 6 is EPCOS 100k // 6 is EPCOS 100k
// 7 is 100k Honeywell thermistor 135-104LAG-J01 // 7 is 100k Honeywell thermistor 135-104LAG-J01
#define THERMISTORHEATER_1 3 #define THERMISTORHEATER_1 3
#define THERMISTORHEATER_2 3 #define THERMISTORHEATER_2 3
#define THERMISTORBED 3 #define THERMISTORBED 3
//#define HEATER_0_USES_THERMISTOR //#define HEATER_0_USES_THERMISTOR
//#define HEATER_1_USES_THERMISTOR //#define HEATER_1_USES_THERMISTOR
#define HEATER_0_USES_AD595 #define HEATER_0_USES_AD595
//#define HEATER_1_USES_AD595 //#define HEATER_1_USES_AD595
// Select one of these only to define how the bed temp is read. // Select one of these only to define how the bed temp is read.
//#define BED_USES_THERMISTOR //#define BED_USES_THERMISTOR
//#define BED_USES_AD595 //#define BED_USES_AD595
#define HEATER_CHECK_INTERVAL 50 #define HEATER_CHECK_INTERVAL 50
#define BED_CHECK_INTERVAL 5000 #define BED_CHECK_INTERVAL 5000
//// Endstop Settings //// Endstop Settings
#define ENDSTOPPULLUPS // Comment this out (using // at the start of the line) to disable the endstop pullup resistors #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. // 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. 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 // For optos H21LOB set to true, for Mendel-Parts newer optos TCST2103 set to false
// This determines the communication speed of the printer // This determines the communication speed of the printer
#define BAUDRATE 250000 #define BAUDRATE 250000
//#define BAUDRATE 115200 //#define BAUDRATE 115200
//#define BAUDRATE 230400 //#define BAUDRATE 230400
// Comment out (using // at the start of the line) to disable SD support: // Comment out (using // at the start of the line) to disable SD support:
// #define ULTRA_LCD //any lcd // #define ULTRA_LCD //any lcd
#define ULTIPANEL #define ULTIPANEL
#define ULTIPANEL #define ULTIPANEL
#ifdef ULTIPANEL #ifdef ULTIPANEL
//#define NEWPANEL //enable this if you have a click-encoder panel //#define NEWPANEL //enable this if you have a click-encoder panel
#define SDSUPPORT #define SDSUPPORT
#define ULTRA_LCD #define ULTRA_LCD
#define LCD_WIDTH 20 #define LCD_WIDTH 20
#define LCD_HEIGHT 4 #define LCD_HEIGHT 4
#else //no panel but just lcd #else //no panel but just lcd
#ifdef ULTRA_LCD #ifdef ULTRA_LCD
#define LCD_WIDTH 16 #define LCD_WIDTH 16
#define LCD_HEIGHT 2 #define LCD_HEIGHT 2
#endif #endif
#endif #endif
//#define SDSUPPORT // Enable SD Card Support in Hardware Console //#define SDSUPPORT // Enable SD Card Support in Hardware Console
const int dropsegments=5; //everything with this number of steps will be ignored as move const int dropsegments=5; //everything with this number of steps will be ignored as move
//// ADVANCED SETTINGS - to tweak parameters //// ADVANCED SETTINGS - to tweak parameters
#include "thermistortables.h" #include "thermistortables.h"
// For Inverting Stepper Enable Pins (Active Low) use 0, Non Inverting (Active High) use 1 // For Inverting Stepper Enable Pins (Active Low) use 0, Non Inverting (Active High) use 1
#define X_ENABLE_ON 0 #define X_ENABLE_ON 0
#define Y_ENABLE_ON 0 #define Y_ENABLE_ON 0
#define Z_ENABLE_ON 0 #define Z_ENABLE_ON 0
#define E_ENABLE_ON 0 #define E_ENABLE_ON 0
// Disables axis when it's not being used. // Disables axis when it's not being used.
#define DISABLE_X false #define DISABLE_X false
#define DISABLE_Y false #define DISABLE_Y false
#define DISABLE_Z false #define DISABLE_Z false
#define DISABLE_E false #define DISABLE_E false
// Inverting axis direction // Inverting axis direction
#define INVERT_X_DIR true // for Mendel set to false, for Orca set to true #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_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_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 #define INVERT_E_DIR false // for direct drive extruder v9 set to true, for geared extruder set to false
//// ENDSTOP SETTINGS: //// ENDSTOP SETTINGS:
// Sets direction of endstops when homing; 1=MAX, -1=MIN // Sets direction of endstops when homing; 1=MAX, -1=MIN
#define X_HOME_DIR -1 #define X_HOME_DIR -1
#define Y_HOME_DIR -1 #define Y_HOME_DIR -1
#define Z_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 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 max_software_endstops false //If true, axis won't move to coordinates greater than the defined lengths below.
#define X_MAX_LENGTH 210 #define X_MAX_LENGTH 210
#define Y_MAX_LENGTH 210 #define Y_MAX_LENGTH 210
#define Z_MAX_LENGTH 210 #define Z_MAX_LENGTH 210
//// MOVEMENT SETTINGS //// MOVEMENT SETTINGS
#define NUM_AXIS 4 // The axis order in all axis related arrays is X, Y, Z, E #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. //note: on bernhards ultimaker 200 200 12 are working well.
#define HOMING_FEEDRATE {50*60, 50*60, 12*60, 0} // set the homing speeds #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. //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. //!!!!!!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 // 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 TRAVELING_AT_MAXSPEED
#define AXIS_RELATIVE_MODES {false, false, false, false} #define AXIS_RELATIVE_MODES {false, false, false, false}
#define MAX_STEP_FREQUENCY 40000 // Max step frequency for Ultimaker (5000 pps / half step) #define MAX_STEP_FREQUENCY 40000 // Max step frequency for Ultimaker (5000 pps / half step)
// default settings // default settings
#define DEFAULT_AXIS_STEPS_PER_UNIT {79.87220447,79.87220447,200*8/3,14} // default steps per unit for ultimaker #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_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_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_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_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_MINIMUMFEEDRATE 10 // minimum feedrate
#define DEFAULT_MINTRAVELFEEDRATE 10 #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. // 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_MINSEGMENTTIME 20000
#define DEFAULT_XYJERK 30.0*60 #define DEFAULT_XYJERK 30.0*60
#define DEFAULT_ZJERK 10.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 // The watchdog waits for the watchperiod in milliseconds whenever an M104 or M109 increases the target temperature
//this enables the watchdog interrupt. //this enables the watchdog interrupt.
#define USE_WATCHDOG #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: //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 RESET_MANUAL
#define WATCHDOG_TIMEOUT 4 #define WATCHDOG_TIMEOUT 4
//// Experimental watchdog and minimal temp //// Experimental watchdog and minimal temp
// The watchdog waits for the watchperiod in milliseconds whenever an M104 or M109 increases the target temperature // 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 // 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 //#define WATCHPERIOD 5000 //5 seconds
// Actual temperature must be close to target for this long before M109 returns success // Actual temperature must be close to target for this long before M109 returns success
//#define TEMP_RESIDENCY_TIME 20 // (seconds) //#define TEMP_RESIDENCY_TIME 20 // (seconds)
//#define TEMP_HYSTERESIS 5 // (C°) range of +/- temperatures considered "close" to the target one //#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 //// The minimal temperature defines the temperature below which the heater will not be enabled
#define HEATER_0_MINTEMP 5 #define HEATER_0_MINTEMP 5
//#define HEATER_1_MINTEMP 5 //#define HEATER_1_MINTEMP 5
//#define BED_MINTEMP 5 //#define BED_MINTEMP 5
// When temperature exceeds max temp, your heater will be switched off. // 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! // 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. // You should use MINTEMP for thermistor short/failure protection.
#define HEATER_0_MAXTEMP 275 #define HEATER_0_MAXTEMP 275
//#define_HEATER_1_MAXTEMP 275 //#define_HEATER_1_MAXTEMP 275
//#define BED_MAXTEMP 150 //#define BED_MAXTEMP 150
#define PIDTEMP #define PIDTEMP
#ifdef PIDTEMP #ifdef PIDTEMP
/// PID settings: /// PID settings:
// Uncomment the following line to enable PID support. // Uncomment the following line to enable PID support.
//#define SMOOTHING //#define SMOOTHING
//#define SMOOTHFACTOR 5.0 //#define SMOOTHFACTOR 5.0
//float current_raw_average=0; //float current_raw_average=0;
#define K1 0.95 //smoothing of the PID #define K1 0.95 //smoothing of the PID
//#define PID_DEBUG // Sends debug data to the serial port. //#define PID_DEBUG // Sends debug data to the serial port.
//#define PID_OPENLOOP 1 // Puts PID in open loop. M104 sets the output power in % //#define PID_OPENLOOP 1 // Puts PID in open loop. M104 sets the output power in %
#define PID_MAX 255 // limits current to nozzle #define PID_MAX 255 // limits current to nozzle
#define PID_INTEGRAL_DRIVE_MAX 255 #define PID_INTEGRAL_DRIVE_MAX 255
#define PID_dT 0.1 #define PID_dT 0.1
//machine with red silicon: 1950:45 second ; with fan fully blowin 3000:47 //machine with red silicon: 1950:45 second ; with fan fully blowin 3000:47
#define PID_CRITIAL_GAIN 3000 #define PID_CRITIAL_GAIN 3000
#define PID_SWING_AT_CRITIAL 45 //seconds #define PID_SWING_AT_CRITIAL 45 //seconds
#define PIDIADD 5 #define PIDIADD 5
/* /*
//PID according to Ziegler-Nichols method //PID according to Ziegler-Nichols method
float Kp = 0.6*PID_CRITIAL_GAIN; float Kp = 0.6*PID_CRITIAL_GAIN;
float Ki =PIDIADD+2*Kp/PID_SWING_AT_CRITIAL*PID_dT; float Ki =PIDIADD+2*Kp/PID_SWING_AT_CRITIAL*PID_dT;
float Kd = Kp*PID_SWING_AT_CRITIAL/8./PID_dT; float Kd = Kp*PID_SWING_AT_CRITIAL/8./PID_dT;
*/ */
//PI according to Ziegler-Nichols method //PI according to Ziegler-Nichols method
#define DEFAULT_Kp (PID_CRITIAL_GAIN/2.2) #define DEFAULT_Kp (PID_CRITIAL_GAIN/2.2)
#define DEFAULT_Ki (1.2*Kp/PID_SWING_AT_CRITIAL*PID_dT) #define DEFAULT_Ki (1.2*Kp/PID_SWING_AT_CRITIAL*PID_dT)
#define DEFAULT_Kd (0) #define DEFAULT_Kd (0)
#define PID_ADD_EXTRUSION_RATE #define PID_ADD_EXTRUSION_RATE
#ifdef PID_ADD_EXTRUSION_RATE #ifdef PID_ADD_EXTRUSION_RATE
#define DEFAULT_Kc (5) //heatingpower=Kc*(e_speed) #define DEFAULT_Kc (5) //heatingpower=Kc*(e_speed)
#endif #endif
#endif // PIDTEMP #endif // PIDTEMP
// extruder advance constant (s2/mm3) // extruder advance constant (s2/mm3)
// //
// advance (steps) = STEPS_PER_CUBIC_MM_E * EXTUDER_ADVANCE_K * cubic mm per second ^ 2 // advance (steps) = STEPS_PER_CUBIC_MM_E * EXTUDER_ADVANCE_K * cubic mm per second ^ 2
// //
// hooke's law says: force = k * distance // hooke's law says: force = k * distance
// bernoulli's priniciple says: v ^ 2 / 2 + g . h + pressure / density = constant // 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 // so: v ^ 2 is proportional to number of steps we advance the extruder
//#define ADVANCE //#define ADVANCE
#ifdef ADVANCE #ifdef ADVANCE
#define EXTRUDER_ADVANCE_K .3 #define EXTRUDER_ADVANCE_K .3
#define D_FILAMENT 1.7 #define D_FILAMENT 1.7
#define STEPS_MM_E 65 #define STEPS_MM_E 65
#define EXTRUTION_AREA (0.25 * D_FILAMENT * D_FILAMENT * 3.14159) #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) #define STEPS_PER_CUBIC_MM_E (axis_steps_per_unit[E_AXIS]/ EXTRUTION_AREA)
#endif // ADVANCE #endif // ADVANCE
// THE BLOCK_BUFFER_SIZE NEEDS TO BE A POWER OF 2, e.g. 8,16,32 // THE BLOCK_BUFFER_SIZE NEEDS TO BE A POWER OF 2, e.g. 8,16,32
#if defined SDSUPPORT #if defined SDSUPPORT
// The number of linear motions that can be in the plan at any give time. // 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 #define BLOCK_BUFFER_SIZE 16 // SD,LCD,Buttons take more memory, block buffer needs to be smaller
#else #else
#define BLOCK_BUFFER_SIZE 16 // maximize block buffer #define BLOCK_BUFFER_SIZE 16 // maximize block buffer
#endif #endif
#endif #endif

View file

@ -1,1235 +1,1235 @@
/* /*
Reprap firmware based on Sprinter and grbl. Reprap firmware based on Sprinter and grbl.
Copyright (C) 2011 Camiel Gubbels / Erik van der Zalm Copyright (C) 2011 Camiel Gubbels / Erik van der Zalm
This program is free software: you can redistribute it and/or modify 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 it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or the Free Software Foundation, either version 3 of the License, or
(at your option) any later version. (at your option) any later version.
This program is distributed in the hope that it will be useful, This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details. GNU General Public License for more details.
You should have received a copy of the GNU General Public License You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>. along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
/* /*
This firmware is a mashup between Sprinter and grbl. This firmware is a mashup between Sprinter and grbl.
(https://github.com/kliment/Sprinter) (https://github.com/kliment/Sprinter)
(https://github.com/simen/grbl/tree) (https://github.com/simen/grbl/tree)
It has preliminary support for Matthew Roberts advance algorithm It has preliminary support for Matthew Roberts advance algorithm
http://reprap.org/pipermail/reprap-dev/2011-May/003323.html http://reprap.org/pipermail/reprap-dev/2011-May/003323.html
*/ */
#include "EEPROMwrite.h" #include "EEPROMwrite.h"
#include "fastio.h" #include "fastio.h"
#include "Configuration.h" #include "Configuration.h"
#include "pins.h" #include "pins.h"
#include "Marlin.h" #include "Marlin.h"
#include "ultralcd.h" #include "ultralcd.h"
#include "streaming.h" #include "streaming.h"
#include "planner.h" #include "planner.h"
#include "stepper.h" #include "stepper.h"
#include "temperature.h" #include "temperature.h"
#ifdef SIMPLE_LCD #ifdef SIMPLE_LCD
#include "Simplelcd.h" #include "Simplelcd.h"
#endif #endif
char version_string[] = "1.0.0 Alpha 1"; char version_string[] = "1.0.0 Alpha 1";
#ifdef SDSUPPORT #ifdef SDSUPPORT
#include "SdFat.h" #include "SdFat.h"
#endif //SDSUPPORT #endif //SDSUPPORT
// look here for descriptions of gcodes: http://linuxcnc.org/handbook/gcode/g-code.html // look here for descriptions of gcodes: http://linuxcnc.org/handbook/gcode/g-code.html
// http://objects.reprap.org/wiki/Mendel_User_Manual:_RepRapGCodes // http://objects.reprap.org/wiki/Mendel_User_Manual:_RepRapGCodes
//Implemented Codes //Implemented Codes
//------------------- //-------------------
// G0 -> G1 // G0 -> G1
// G1 - Coordinated Movement X Y Z E // G1 - Coordinated Movement X Y Z E
// G2 - CW ARC // G2 - CW ARC
// G3 - CCW ARC // G3 - CCW ARC
// G4 - Dwell S<seconds> or P<milliseconds> // G4 - Dwell S<seconds> or P<milliseconds>
// G28 - Home all Axis // G28 - Home all Axis
// G90 - Use Absolute Coordinates // G90 - Use Absolute Coordinates
// G91 - Use Relative Coordinates // G91 - Use Relative Coordinates
// G92 - Set current position to cordinates given // G92 - Set current position to cordinates given
//RepRap M Codes //RepRap M Codes
// M104 - Set extruder target temp // M104 - Set extruder target temp
// M105 - Read current temp // M105 - Read current temp
// M106 - Fan on // M106 - Fan on
// M107 - Fan off // M107 - Fan off
// M109 - Wait for extruder current temp to reach target temp. // M109 - Wait for extruder current temp to reach target temp.
// M114 - Display current position // M114 - Display current position
//Custom M Codes //Custom M Codes
// M20 - List SD card // M20 - List SD card
// M21 - Init SD card // M21 - Init SD card
// M22 - Release SD card // M22 - Release SD card
// M23 - Select SD file (M23 filename.g) // M23 - Select SD file (M23 filename.g)
// M24 - Start/resume SD print // M24 - Start/resume SD print
// M25 - Pause SD print // M25 - Pause SD print
// M26 - Set SD position in bytes (M26 S12345) // M26 - Set SD position in bytes (M26 S12345)
// M27 - Report SD print status // M27 - Report SD print status
// M28 - Start SD write (M28 filename.g) // M28 - Start SD write (M28 filename.g)
// M29 - Stop SD write // M29 - Stop SD write
// M42 - Change pin status via gcode // M42 - Change pin status via gcode
// M80 - Turn on Power Supply // M80 - Turn on Power Supply
// M81 - Turn off Power Supply // M81 - Turn off Power Supply
// M82 - Set E codes absolute (default) // M82 - Set E codes absolute (default)
// M83 - Set E codes relative while in Absolute Coordinates (G90) mode // M83 - Set E codes relative while in Absolute Coordinates (G90) mode
// M84 - Disable steppers until next move, // M84 - Disable steppers until next move,
// or use S<seconds> to specify an inactivity timeout, after which the steppers will be disabled. S0 to disable the timeout. // or use S<seconds> 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<seconds>. To disable set zero (default) // M85 - Set inactivity shutdown timer with parameter S<seconds>. To disable set zero (default)
// M92 - Set axis_steps_per_unit - same syntax as G92 // M92 - Set axis_steps_per_unit - same syntax as G92
// M115 - Capabilities string // M115 - Capabilities string
// M140 - Set bed target temp // M140 - Set bed target temp
// M190 - Wait for bed current temp to reach target temp. // M190 - Wait for bed current temp to reach target temp.
// M200 - Set filament diameter // M200 - Set filament diameter
// M201 - Set max acceleration in units/s^2 for print moves (M201 X1000 Y1000) // 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!! // 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 // 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 // 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 // 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 // M220 - set speed factor override percentage S:factor in percent
// M301 - Set PID parameters P I and D // M301 - Set PID parameters P I and D
// M500 - stores paramters in EEPROM // M500 - stores paramters in EEPROM
// M501 - reads parameters from EEPROM (if you need reset them after you changed them temporarily). D // 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. // M502 - reverts to the default "factory settings". You still need to store them in EEPROM afterwards if you want to.
//Stepper Movement Variables //Stepper Movement Variables
char axis_codes[NUM_AXIS] = { char axis_codes[NUM_AXIS] = {
'X', 'Y', 'Z', 'E'}; 'X', 'Y', 'Z', 'E'};
float destination[NUM_AXIS] = { float destination[NUM_AXIS] = {
0.0, 0.0, 0.0, 0.0}; 0.0, 0.0, 0.0, 0.0};
float current_position[NUM_AXIS] = { float current_position[NUM_AXIS] = {
0.0, 0.0, 0.0, 0.0}; 0.0, 0.0, 0.0, 0.0};
bool home_all_axis = true; bool home_all_axis = true;
float feedrate = 1500.0, next_feedrate, saved_feedrate; float feedrate = 1500.0, next_feedrate, saved_feedrate;
long gcode_N, gcode_LastN; long gcode_N, gcode_LastN;
float homing_feedrate[] = HOMING_FEEDRATE; float homing_feedrate[] = HOMING_FEEDRATE;
bool axis_relative_modes[] = AXIS_RELATIVE_MODES; bool axis_relative_modes[] = AXIS_RELATIVE_MODES;
bool relative_mode = false; //Determines Absolute or Relative Coordinates 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. 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; uint8_t fanpwm=0;
volatile int feedmultiply=100; //100->1 200->2 volatile int feedmultiply=100; //100->1 200->2
int saved_feedmultiply; int saved_feedmultiply;
volatile bool feedmultiplychanged=false; volatile bool feedmultiplychanged=false;
// comm variables // comm variables
#define MAX_CMD_SIZE 96 #define MAX_CMD_SIZE 96
#define BUFSIZE 4 #define BUFSIZE 4
char cmdbuffer[BUFSIZE][MAX_CMD_SIZE]; char cmdbuffer[BUFSIZE][MAX_CMD_SIZE];
bool fromsd[BUFSIZE]; bool fromsd[BUFSIZE];
int bufindr = 0; int bufindr = 0;
int bufindw = 0; int bufindw = 0;
int buflen = 0; int buflen = 0;
int i = 0; int i = 0;
char serial_char; char serial_char;
int serial_count = 0; int serial_count = 0;
boolean comment_mode = false; boolean comment_mode = false;
char *strchr_pointer; // just a pointer to find chars in the cmd string like X, Y, Z, E, etc char *strchr_pointer; // just a pointer to find chars in the cmd string like X, Y, Z, E, etc
extern float HeaterPower; extern float HeaterPower;
#include "EEPROM.h" #include "EEPROM.h"
const int sensitive_pins[] = SENSITIVE_PINS; // Sensitive pin list for M42 const int sensitive_pins[] = SENSITIVE_PINS; // Sensitive pin list for M42
float tt = 0, bt = 0; float tt = 0, bt = 0;
#ifdef WATCHPERIOD #ifdef WATCHPERIOD
int watch_raw = -1000; int watch_raw = -1000;
unsigned long watchmillis = 0; unsigned long watchmillis = 0;
#endif //WATCHPERIOD #endif //WATCHPERIOD
//Inactivity shutdown variables //Inactivity shutdown variables
unsigned long previous_millis_cmd = 0; unsigned long previous_millis_cmd = 0;
unsigned long max_inactive_time = 0; unsigned long max_inactive_time = 0;
unsigned long stepper_inactive_time = 0; unsigned long stepper_inactive_time = 0;
unsigned long starttime=0; unsigned long starttime=0;
unsigned long stoptime=0; unsigned long stoptime=0;
#ifdef SDSUPPORT #ifdef SDSUPPORT
Sd2Card card; Sd2Card card;
SdVolume volume; SdVolume volume;
SdFile root; SdFile root;
SdFile file; SdFile file;
uint32_t filesize = 0; uint32_t filesize = 0;
uint32_t sdpos = 0; uint32_t sdpos = 0;
bool sdmode = false; bool sdmode = false;
bool sdactive = false; bool sdactive = false;
bool savetosd = false; bool savetosd = false;
int16_t n; int16_t n;
unsigned long autostart_atmillis=0; unsigned long autostart_atmillis=0;
void initsd(){ void initsd(){
sdactive = false; sdactive = false;
#if SDSS >- 1 #if SDSS >- 1
if(root.isOpen()) if(root.isOpen())
root.close(); root.close();
if (!card.init(SPI_FULL_SPEED,SDSS)){ if (!card.init(SPI_FULL_SPEED,SDSS)){
//if (!card.init(SPI_HALF_SPEED,SDSS)) //if (!card.init(SPI_HALF_SPEED,SDSS))
Serial.println("SD init fail"); Serial.println("SD init fail");
} }
else if (!volume.init(&card)) else if (!volume.init(&card))
Serial.println("volume.init failed"); Serial.println("volume.init failed");
else if (!root.openRoot(&volume)) else if (!root.openRoot(&volume))
Serial.println("openRoot failed"); Serial.println("openRoot failed");
else else
{ {
sdactive = true; sdactive = true;
Serial.println("SD card ok"); Serial.println("SD card ok");
} }
#endif //SDSS #endif //SDSS
} }
void quickinitsd(){ void quickinitsd(){
sdactive=false; sdactive=false;
autostart_atmillis=millis()+5000; autostart_atmillis=millis()+5000;
} }
inline void write_command(char *buf){ inline void write_command(char *buf){
char* begin = buf; char* begin = buf;
char* npos = 0; char* npos = 0;
char* end = buf + strlen(buf) - 1; char* end = buf + strlen(buf) - 1;
file.writeError = false; file.writeError = false;
if((npos = strchr(buf, 'N')) != NULL){ if((npos = strchr(buf, 'N')) != NULL){
begin = strchr(npos, ' ') + 1; begin = strchr(npos, ' ') + 1;
end = strchr(npos, '*') - 1; end = strchr(npos, '*') - 1;
} }
end[1] = '\r'; end[1] = '\r';
end[2] = '\n'; end[2] = '\n';
end[3] = '\0'; end[3] = '\0';
//Serial.println(begin); //Serial.println(begin);
file.write(begin); file.write(begin);
if (file.writeError){ if (file.writeError){
Serial.println("error writing to file"); Serial.println("error writing to file");
} }
} }
#endif //SDSUPPORT #endif //SDSUPPORT
///adds an command to the main command buffer ///adds an command to the main command buffer
void enquecommand(const char *cmd) void enquecommand(const char *cmd)
{ {
if(buflen < BUFSIZE) if(buflen < BUFSIZE)
{ {
//this is dangerous if a mixing of serial and this happsens //this is dangerous if a mixing of serial and this happsens
strcpy(&(cmdbuffer[bufindw][0]),cmd); strcpy(&(cmdbuffer[bufindw][0]),cmd);
Serial.print("en:");Serial.println(cmdbuffer[bufindw]); Serial.print("en:");Serial.println(cmdbuffer[bufindw]);
bufindw= (bufindw + 1)%BUFSIZE; bufindw= (bufindw + 1)%BUFSIZE;
buflen += 1; buflen += 1;
} }
} }
void setup() void setup()
{ {
Serial.begin(BAUDRATE); Serial.begin(BAUDRATE);
ECHOLN("Marlin "<<version_string); ECHOLN("Marlin "<<version_string);
Serial.println("start"); Serial.println("start");
#if defined FANCY_LCD || defined SIMPLE_LCD #if defined FANCY_LCD || defined SIMPLE_LCD
lcd_init(); lcd_init();
#endif #endif
for(int i = 0; i < BUFSIZE; i++){ for(int i = 0; i < BUFSIZE; i++){
fromsd[i] = false; fromsd[i] = false;
} }
RetrieveSettings(); // loads data from EEPROM if available RetrieveSettings(); // loads data from EEPROM if available
for(int i=0; i < NUM_AXIS; i++){ for(int i=0; i < NUM_AXIS; i++){
axis_steps_per_sqr_second[i] = max_acceleration_units_per_sq_second[i] * axis_steps_per_unit[i]; axis_steps_per_sqr_second[i] = max_acceleration_units_per_sq_second[i] * axis_steps_per_unit[i];
} }
#ifdef SDSUPPORT #ifdef SDSUPPORT
//power to SD reader //power to SD reader
#if SDPOWER > -1 #if SDPOWER > -1
SET_OUTPUT(SDPOWER); SET_OUTPUT(SDPOWER);
WRITE(SDPOWER,HIGH); WRITE(SDPOWER,HIGH);
#endif //SDPOWER #endif //SDPOWER
quickinitsd(); quickinitsd();
#endif //SDSUPPORT #endif //SDSUPPORT
plan_init(); // Initialize planner; plan_init(); // Initialize planner;
st_init(); // Initialize stepper; st_init(); // Initialize stepper;
tp_init(); // Initialize temperature loop tp_init(); // Initialize temperature loop
//checkautostart(); //checkautostart();
} }
#ifdef SDSUPPORT #ifdef SDSUPPORT
bool autostart_stilltocheck=true; bool autostart_stilltocheck=true;
void checkautostart(bool force) 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 //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(!force)
{ {
if(!autostart_stilltocheck) if(!autostart_stilltocheck)
return; return;
if(autostart_atmillis<millis()) if(autostart_atmillis<millis())
return; return;
} }
autostart_stilltocheck=false; autostart_stilltocheck=false;
if(!sdactive) if(!sdactive)
{ {
initsd(); initsd();
if(!sdactive) //fail if(!sdactive) //fail
return; return;
} }
static int lastnr=0; static int lastnr=0;
char autoname[30]; char autoname[30];
sprintf(autoname,"auto%i.g",lastnr); sprintf(autoname,"auto%i.g",lastnr);
for(int i=0;i<(int)strlen(autoname);i++) for(int i=0;i<(int)strlen(autoname);i++)
autoname[i]=tolower(autoname[i]); autoname[i]=tolower(autoname[i]);
dir_t p; dir_t p;
root.rewind(); root.rewind();
//char filename[11]; //char filename[11];
//int cnt=0; //int cnt=0;
bool found=false; bool found=false;
while (root.readDir(p) > 0) while (root.readDir(p) > 0)
{ {
for(int i=0;i<(int)strlen((char*)p.name);i++) for(int i=0;i<(int)strlen((char*)p.name);i++)
p.name[i]=tolower(p.name[i]); p.name[i]=tolower(p.name[i]);
//Serial.print((char*)p.name); //Serial.print((char*)p.name);
//Serial.print(" "); //Serial.print(" ");
//Serial.println(autoname); //Serial.println(autoname);
if(p.name[9]!='~') //skip safety copies if(p.name[9]!='~') //skip safety copies
if(strncmp((char*)p.name,autoname,5)==0) if(strncmp((char*)p.name,autoname,5)==0)
{ {
char cmd[30]; char cmd[30];
sprintf(cmd,"M23 %s",autoname); sprintf(cmd,"M23 %s",autoname);
//sprintf(cmd,"M115"); //sprintf(cmd,"M115");
//enquecommand("G92 Z0"); //enquecommand("G92 Z0");
//enquecommand("G1 Z10 F2000"); //enquecommand("G1 Z10 F2000");
//enquecommand("G28 X-105 Y-105"); //enquecommand("G28 X-105 Y-105");
enquecommand(cmd); enquecommand(cmd);
enquecommand("M24"); enquecommand("M24");
found=true; found=true;
} }
} }
if(!found) if(!found)
lastnr=-1; lastnr=-1;
else else
lastnr++; lastnr++;
} }
#else #else
inline void checkautostart(bool x) inline void checkautostart(bool x)
{ {
} }
#endif #endif
void loop() void loop()
{ {
if(buflen<3) if(buflen<3)
get_command(); get_command();
checkautostart(false); checkautostart(false);
if(buflen) if(buflen)
{ {
#ifdef SDSUPPORT #ifdef SDSUPPORT
if(savetosd){ if(savetosd){
if(strstr(cmdbuffer[bufindr],"M29") == NULL){ if(strstr(cmdbuffer[bufindr],"M29") == NULL){
write_command(cmdbuffer[bufindr]); write_command(cmdbuffer[bufindr]);
Serial.println("ok"); Serial.println("ok");
} }
else{ else{
file.sync(); file.sync();
file.close(); file.close();
savetosd = false; savetosd = false;
Serial.println("Done saving file."); Serial.println("Done saving file.");
} }
} }
else{ else{
process_commands(); process_commands();
} }
#else #else
process_commands(); process_commands();
#endif //SDSUPPORT #endif //SDSUPPORT
buflen = (buflen-1); buflen = (buflen-1);
bufindr = (bufindr + 1)%BUFSIZE; bufindr = (bufindr + 1)%BUFSIZE;
} }
//check heater every n milliseconds //check heater every n milliseconds
manage_heater(); manage_heater();
manage_inactivity(1); manage_inactivity(1);
LCD_STATUS; LCD_STATUS;
} }
inline void get_command() inline void get_command()
{ {
while( Serial.available() > 0 && buflen < BUFSIZE) { while( Serial.available() > 0 && buflen < BUFSIZE) {
serial_char = Serial.read(); serial_char = Serial.read();
if(serial_char == '\n' || serial_char == '\r' || serial_char == ':' || serial_count >= (MAX_CMD_SIZE - 1) ) if(serial_char == '\n' || serial_char == '\r' || serial_char == ':' || serial_count >= (MAX_CMD_SIZE - 1) )
{ {
if(!serial_count) return; //if empty line if(!serial_count) return; //if empty line
cmdbuffer[bufindw][serial_count] = 0; //terminate string cmdbuffer[bufindw][serial_count] = 0; //terminate string
if(!comment_mode){ if(!comment_mode){
fromsd[bufindw] = false; fromsd[bufindw] = false;
if(strstr(cmdbuffer[bufindw], "N") != NULL) if(strstr(cmdbuffer[bufindw], "N") != NULL)
{ {
strchr_pointer = strchr(cmdbuffer[bufindw], 'N'); strchr_pointer = strchr(cmdbuffer[bufindw], 'N');
gcode_N = (strtol(&cmdbuffer[bufindw][strchr_pointer - cmdbuffer[bufindw] + 1], NULL, 10)); gcode_N = (strtol(&cmdbuffer[bufindw][strchr_pointer - cmdbuffer[bufindw] + 1], NULL, 10));
if(gcode_N != gcode_LastN+1 && (strstr(cmdbuffer[bufindw], "M110") == NULL) ) { 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.print("Serial Error: Line Number is not Last Line Number+1, Last Line:");
Serial.println(gcode_LastN); Serial.println(gcode_LastN);
//Serial.println(gcode_N); //Serial.println(gcode_N);
FlushSerialRequestResend(); FlushSerialRequestResend();
serial_count = 0; serial_count = 0;
return; return;
} }
if(strstr(cmdbuffer[bufindw], "*") != NULL) if(strstr(cmdbuffer[bufindw], "*") != NULL)
{ {
byte checksum = 0; byte checksum = 0;
byte count = 0; byte count = 0;
while(cmdbuffer[bufindw][count] != '*') checksum = checksum^cmdbuffer[bufindw][count++]; while(cmdbuffer[bufindw][count] != '*') checksum = checksum^cmdbuffer[bufindw][count++];
strchr_pointer = strchr(cmdbuffer[bufindw], '*'); strchr_pointer = strchr(cmdbuffer[bufindw], '*');
if( (int)(strtod(&cmdbuffer[bufindw][strchr_pointer - cmdbuffer[bufindw] + 1], NULL)) != checksum) { if( (int)(strtod(&cmdbuffer[bufindw][strchr_pointer - cmdbuffer[bufindw] + 1], NULL)) != checksum) {
Serial.print("Error: checksum mismatch, Last Line:"); Serial.print("Error: checksum mismatch, Last Line:");
Serial.println(gcode_LastN); Serial.println(gcode_LastN);
FlushSerialRequestResend(); FlushSerialRequestResend();
serial_count = 0; serial_count = 0;
return; return;
} }
//if no errors, continue parsing //if no errors, continue parsing
} }
else else
{ {
Serial.print("Error: No Checksum with line number, Last Line:"); Serial.print("Error: No Checksum with line number, Last Line:");
Serial.println(gcode_LastN); Serial.println(gcode_LastN);
FlushSerialRequestResend(); FlushSerialRequestResend();
serial_count = 0; serial_count = 0;
return; return;
} }
gcode_LastN = gcode_N; gcode_LastN = gcode_N;
//if no errors, continue parsing //if no errors, continue parsing
} }
else // if we don't receive 'N' but still see '*' else // if we don't receive 'N' but still see '*'
{ {
if((strstr(cmdbuffer[bufindw], "*") != NULL)) if((strstr(cmdbuffer[bufindw], "*") != NULL))
{ {
Serial.print("Error: No Line Number with checksum, Last Line:"); Serial.print("Error: No Line Number with checksum, Last Line:");
Serial.println(gcode_LastN); Serial.println(gcode_LastN);
serial_count = 0; serial_count = 0;
return; return;
} }
} }
if((strstr(cmdbuffer[bufindw], "G") != NULL)){ if((strstr(cmdbuffer[bufindw], "G") != NULL)){
strchr_pointer = strchr(cmdbuffer[bufindw], 'G'); strchr_pointer = strchr(cmdbuffer[bufindw], 'G');
switch((int)((strtod(&cmdbuffer[bufindw][strchr_pointer - cmdbuffer[bufindw] + 1], NULL)))){ switch((int)((strtod(&cmdbuffer[bufindw][strchr_pointer - cmdbuffer[bufindw] + 1], NULL)))){
case 0: case 0:
case 1: case 1:
#ifdef SDSUPPORT #ifdef SDSUPPORT
if(savetosd) if(savetosd)
break; break;
#endif //SDSUPPORT #endif //SDSUPPORT
Serial.println("ok"); Serial.println("ok");
break; break;
default: default:
break; break;
} }
} }
bufindw = (bufindw + 1)%BUFSIZE; bufindw = (bufindw + 1)%BUFSIZE;
buflen += 1; buflen += 1;
} }
comment_mode = false; //for new command comment_mode = false; //for new command
serial_count = 0; //clear buffer serial_count = 0; //clear buffer
} }
else else
{ {
if(serial_char == ';') comment_mode = true; if(serial_char == ';') comment_mode = true;
if(!comment_mode) cmdbuffer[bufindw][serial_count++] = serial_char; if(!comment_mode) cmdbuffer[bufindw][serial_count++] = serial_char;
} }
} }
#ifdef SDSUPPORT #ifdef SDSUPPORT
if(!sdmode || serial_count!=0){ if(!sdmode || serial_count!=0){
return; return;
} }
while( filesize > sdpos && buflen < BUFSIZE) { while( filesize > sdpos && buflen < BUFSIZE) {
n = file.read(); n = file.read();
serial_char = (char)n; serial_char = (char)n;
if(serial_char == '\n' || serial_char == '\r' || serial_char == ':' || serial_count >= (MAX_CMD_SIZE - 1) || n == -1) if(serial_char == '\n' || serial_char == '\r' || serial_char == ':' || serial_count >= (MAX_CMD_SIZE - 1) || n == -1)
{ {
sdpos = file.curPosition(); sdpos = file.curPosition();
if(sdpos >= filesize){ if(sdpos >= filesize){
sdmode = false; sdmode = false;
Serial.println("Done printing file"); Serial.println("Done printing file");
stoptime=millis(); stoptime=millis();
char time[30]; char time[30];
unsigned long t=(stoptime-starttime)/1000; unsigned long t=(stoptime-starttime)/1000;
int sec,min; int sec,min;
min=t/60; min=t/60;
sec=t%60; sec=t%60;
sprintf(time,"%i min, %i sec",min,sec); sprintf(time,"%i min, %i sec",min,sec);
Serial.println(time); Serial.println(time);
LCD_MESSAGE(time); LCD_MESSAGE(time);
checkautostart(true); checkautostart(true);
} }
if(!serial_count) return; //if empty line if(!serial_count) return; //if empty line
cmdbuffer[bufindw][serial_count] = 0; //terminate string cmdbuffer[bufindw][serial_count] = 0; //terminate string
if(!comment_mode){ if(!comment_mode){
fromsd[bufindw] = true; fromsd[bufindw] = true;
buflen += 1; buflen += 1;
bufindw = (bufindw + 1)%BUFSIZE; bufindw = (bufindw + 1)%BUFSIZE;
} }
comment_mode = false; //for new command comment_mode = false; //for new command
serial_count = 0; //clear buffer serial_count = 0; //clear buffer
} }
else else
{ {
if(serial_char == ';') comment_mode = true; if(serial_char == ';') comment_mode = true;
if(!comment_mode) cmdbuffer[bufindw][serial_count++] = serial_char; if(!comment_mode) cmdbuffer[bufindw][serial_count++] = serial_char;
} }
} }
#endif //SDSUPPORT #endif //SDSUPPORT
} }
inline float code_value() { inline float code_value() {
return (strtod(&cmdbuffer[bufindr][strchr_pointer - cmdbuffer[bufindr] + 1], NULL)); return (strtod(&cmdbuffer[bufindr][strchr_pointer - cmdbuffer[bufindr] + 1], NULL));
} }
inline long code_value_long() { inline long code_value_long() {
return (strtol(&cmdbuffer[bufindr][strchr_pointer - cmdbuffer[bufindr] + 1], NULL, 10)); return (strtol(&cmdbuffer[bufindr][strchr_pointer - cmdbuffer[bufindr] + 1], NULL, 10));
} }
inline bool code_seen(char code_string[]) { inline bool code_seen(char code_string[]) {
return (strstr(cmdbuffer[bufindr], code_string) != NULL); return (strstr(cmdbuffer[bufindr], code_string) != NULL);
} //Return True if the string was found } //Return True if the string was found
inline bool code_seen(char code) inline bool code_seen(char code)
{ {
strchr_pointer = strchr(cmdbuffer[bufindr], code); strchr_pointer = strchr(cmdbuffer[bufindr], code);
return (strchr_pointer != NULL); //Return True if a character was found return (strchr_pointer != NULL); //Return True if a character was found
} }
inline void process_commands() inline void process_commands()
{ {
unsigned long codenum; //throw away variable unsigned long codenum; //throw away variable
char *starpos = NULL; char *starpos = NULL;
if(code_seen('G')) if(code_seen('G'))
{ {
switch((int)code_value()) switch((int)code_value())
{ {
case 0: // G0 -> G1 case 0: // G0 -> G1
case 1: // G1 case 1: // G1
get_coordinates(); // For X Y Z E F get_coordinates(); // For X Y Z E F
prepare_move(); prepare_move();
previous_millis_cmd = millis(); previous_millis_cmd = millis();
//ClearToSend(); //ClearToSend();
return; return;
//break; //break;
case 4: // G4 dwell case 4: // G4 dwell
codenum = 0; codenum = 0;
if(code_seen('P')) codenum = code_value(); // milliseconds to wait if(code_seen('P')) codenum = code_value(); // milliseconds to wait
if(code_seen('S')) codenum = code_value() * 1000; // seconds to wait if(code_seen('S')) codenum = code_value() * 1000; // seconds to wait
codenum += millis(); // keep track of when we started waiting codenum += millis(); // keep track of when we started waiting
while(millis() < codenum ){ while(millis() < codenum ){
manage_heater(); manage_heater();
} }
break; break;
case 28: //G28 Home all Axis one at a time case 28: //G28 Home all Axis one at a time
saved_feedrate = feedrate; saved_feedrate = feedrate;
saved_feedmultiply = feedmultiply; saved_feedmultiply = feedmultiply;
feedmultiply = 100; feedmultiply = 100;
for(int i=0; i < NUM_AXIS; i++) { for(int i=0; i < NUM_AXIS; i++) {
destination[i] = current_position[i]; destination[i] = current_position[i];
} }
feedrate = 0.0; feedrate = 0.0;
home_all_axis = !((code_seen(axis_codes[0])) || (code_seen(axis_codes[1])) || (code_seen(axis_codes[2]))); 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((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)){ if ((X_MIN_PIN > -1 && X_HOME_DIR==-1) || (X_MAX_PIN > -1 && X_HOME_DIR==1)){
// st_synchronize(); // st_synchronize();
current_position[X_AXIS] = 0; current_position[X_AXIS] = 0;
plan_set_position(current_position[X_AXIS], current_position[Y_AXIS], current_position[Z_AXIS], current_position[E_AXIS]); 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; destination[X_AXIS] = 1.5 * X_MAX_LENGTH * X_HOME_DIR;
feedrate = homing_feedrate[X_AXIS]; feedrate = homing_feedrate[X_AXIS];
prepare_move(); prepare_move();
// st_synchronize(); // st_synchronize();
current_position[X_AXIS] = 0; current_position[X_AXIS] = 0;
plan_set_position(current_position[X_AXIS], current_position[Y_AXIS], current_position[Z_AXIS], current_position[E_AXIS]); 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; destination[X_AXIS] = -5 * X_HOME_DIR;
prepare_move(); prepare_move();
// st_synchronize(); // st_synchronize();
destination[X_AXIS] = 10 * X_HOME_DIR; destination[X_AXIS] = 10 * X_HOME_DIR;
feedrate = homing_feedrate[X_AXIS]/2 ; feedrate = homing_feedrate[X_AXIS]/2 ;
prepare_move(); prepare_move();
// st_synchronize(); // st_synchronize();
current_position[X_AXIS] = (X_HOME_DIR == -1) ? 0 : X_MAX_LENGTH; 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]); 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]; destination[X_AXIS] = current_position[X_AXIS];
feedrate = 0.0; feedrate = 0.0;
} }
} }
if((home_all_axis) || (code_seen(axis_codes[Y_AXIS]))) { 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)){ if ((Y_MIN_PIN > -1 && Y_HOME_DIR==-1) || (Y_MAX_PIN > -1 && Y_HOME_DIR==1)){
current_position[Y_AXIS] = 0; current_position[Y_AXIS] = 0;
plan_set_position(current_position[X_AXIS], current_position[Y_AXIS], current_position[Z_AXIS], current_position[E_AXIS]); 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; destination[Y_AXIS] = 1.5 * Y_MAX_LENGTH * Y_HOME_DIR;
feedrate = homing_feedrate[Y_AXIS]; feedrate = homing_feedrate[Y_AXIS];
prepare_move(); prepare_move();
// st_synchronize(); // st_synchronize();
current_position[Y_AXIS] = 0; current_position[Y_AXIS] = 0;
plan_set_position(current_position[X_AXIS], current_position[Y_AXIS], current_position[Z_AXIS], current_position[E_AXIS]); 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; destination[Y_AXIS] = -5 * Y_HOME_DIR;
prepare_move(); prepare_move();
// st_synchronize(); // st_synchronize();
destination[Y_AXIS] = 10 * Y_HOME_DIR; destination[Y_AXIS] = 10 * Y_HOME_DIR;
feedrate = homing_feedrate[Y_AXIS]/2; feedrate = homing_feedrate[Y_AXIS]/2;
prepare_move(); prepare_move();
// st_synchronize(); // st_synchronize();
current_position[Y_AXIS] = (Y_HOME_DIR == -1) ? 0 : Y_MAX_LENGTH; 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]); 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]; destination[Y_AXIS] = current_position[Y_AXIS];
feedrate = 0.0; feedrate = 0.0;
} }
} }
if((home_all_axis) || (code_seen(axis_codes[Z_AXIS]))) { 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)){ if ((Z_MIN_PIN > -1 && Z_HOME_DIR==-1) || (Z_MAX_PIN > -1 && Z_HOME_DIR==1)){
current_position[Z_AXIS] = 0; current_position[Z_AXIS] = 0;
plan_set_position(current_position[X_AXIS], current_position[Y_AXIS], current_position[Z_AXIS], current_position[E_AXIS]); 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; destination[Z_AXIS] = 1.5 * Z_MAX_LENGTH * Z_HOME_DIR;
feedrate = homing_feedrate[Z_AXIS]; feedrate = homing_feedrate[Z_AXIS];
prepare_move(); prepare_move();
// st_synchronize(); // st_synchronize();
current_position[Z_AXIS] = 0; current_position[Z_AXIS] = 0;
plan_set_position(current_position[X_AXIS], current_position[Y_AXIS], current_position[Z_AXIS], current_position[E_AXIS]); 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; destination[Z_AXIS] = -2 * Z_HOME_DIR;
prepare_move(); prepare_move();
// st_synchronize(); // st_synchronize();
destination[Z_AXIS] = 3 * Z_HOME_DIR; destination[Z_AXIS] = 3 * Z_HOME_DIR;
feedrate = homing_feedrate[Z_AXIS]/2; feedrate = homing_feedrate[Z_AXIS]/2;
prepare_move(); prepare_move();
// st_synchronize(); // st_synchronize();
current_position[Z_AXIS] = (Z_HOME_DIR == -1) ? 0 : Z_MAX_LENGTH; 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]); 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]; destination[Z_AXIS] = current_position[Z_AXIS];
feedrate = 0.0; feedrate = 0.0;
} }
} }
feedrate = saved_feedrate; feedrate = saved_feedrate;
feedmultiply = saved_feedmultiply; feedmultiply = saved_feedmultiply;
previous_millis_cmd = millis(); previous_millis_cmd = millis();
break; break;
case 90: // G90 case 90: // G90
relative_mode = false; relative_mode = false;
break; break;
case 91: // G91 case 91: // G91
relative_mode = true; relative_mode = true;
break; break;
case 92: // G92 case 92: // G92
if(!code_seen(axis_codes[E_AXIS])) if(!code_seen(axis_codes[E_AXIS]))
st_synchronize(); st_synchronize();
for(int i=0; i < NUM_AXIS; i++) { for(int i=0; i < NUM_AXIS; i++) {
if(code_seen(axis_codes[i])) current_position[i] = code_value(); 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]); plan_set_position(current_position[X_AXIS], current_position[Y_AXIS], current_position[Z_AXIS], current_position[E_AXIS]);
break; break;
} }
} }
else if(code_seen('M')) else if(code_seen('M'))
{ {
switch( (int)code_value() ) switch( (int)code_value() )
{ {
#ifdef SDSUPPORT #ifdef SDSUPPORT
case 20: // M20 - list SD card case 20: // M20 - list SD card
Serial.println("Begin file list"); Serial.println("Begin file list");
root.ls(); root.ls();
Serial.println("End file list"); Serial.println("End file list");
break; break;
case 21: // M21 - init SD card case 21: // M21 - init SD card
sdmode = false; sdmode = false;
initsd(); initsd();
break; break;
case 22: //M22 - release SD card case 22: //M22 - release SD card
sdmode = false; sdmode = false;
sdactive = false; sdactive = false;
break; break;
case 23: //M23 - Select file case 23: //M23 - Select file
if(sdactive){ if(sdactive){
sdmode = false; sdmode = false;
file.close(); file.close();
starpos = (strchr(strchr_pointer + 4,'*')); starpos = (strchr(strchr_pointer + 4,'*'));
if(starpos!=NULL) if(starpos!=NULL)
*(starpos-1)='\0'; *(starpos-1)='\0';
if (file.open(&root, strchr_pointer + 4, O_READ)) { if (file.open(&root, strchr_pointer + 4, O_READ)) {
Serial.print("File opened:"); Serial.print("File opened:");
Serial.print(strchr_pointer + 4); Serial.print(strchr_pointer + 4);
Serial.print(" Size:"); Serial.print(" Size:");
Serial.println(file.fileSize()); Serial.println(file.fileSize());
sdpos = 0; sdpos = 0;
filesize = file.fileSize(); filesize = file.fileSize();
Serial.println("File selected"); Serial.println("File selected");
} }
else{ else{
Serial.println("file.open failed"); Serial.println("file.open failed");
} }
} }
break; break;
case 24: //M24 - Start SD print case 24: //M24 - Start SD print
if(sdactive){ if(sdactive){
sdmode = true; sdmode = true;
starttime=millis(); starttime=millis();
} }
break; break;
case 25: //M25 - Pause SD print case 25: //M25 - Pause SD print
if(sdmode){ if(sdmode){
sdmode = false; sdmode = false;
} }
break; break;
case 26: //M26 - Set SD index case 26: //M26 - Set SD index
if(sdactive && code_seen('S')){ if(sdactive && code_seen('S')){
sdpos = code_value_long(); sdpos = code_value_long();
file.seekSet(sdpos); file.seekSet(sdpos);
} }
break; break;
case 27: //M27 - Get SD status case 27: //M27 - Get SD status
if(sdactive){ if(sdactive){
Serial.print("SD printing byte "); Serial.print("SD printing byte ");
Serial.print(sdpos); Serial.print(sdpos);
Serial.print("/"); Serial.print("/");
Serial.println(filesize); Serial.println(filesize);
} }
else{ else{
Serial.println("Not SD printing"); Serial.println("Not SD printing");
} }
break; break;
case 28: //M28 - Start SD write case 28: //M28 - Start SD write
if(sdactive){ if(sdactive){
char* npos = 0; char* npos = 0;
file.close(); file.close();
sdmode = false; sdmode = false;
starpos = (strchr(strchr_pointer + 4,'*')); starpos = (strchr(strchr_pointer + 4,'*'));
if(starpos != NULL){ if(starpos != NULL){
npos = strchr(cmdbuffer[bufindr], 'N'); npos = strchr(cmdbuffer[bufindr], 'N');
strchr_pointer = strchr(npos,' ') + 1; strchr_pointer = strchr(npos,' ') + 1;
*(starpos-1) = '\0'; *(starpos-1) = '\0';
} }
if (!file.open(&root, strchr_pointer+4, O_CREAT | O_APPEND | O_WRITE | O_TRUNC)) if (!file.open(&root, strchr_pointer+4, O_CREAT | O_APPEND | O_WRITE | O_TRUNC))
{ {
Serial.print("open failed, File: "); Serial.print("open failed, File: ");
Serial.print(strchr_pointer + 4); Serial.print(strchr_pointer + 4);
Serial.print("."); Serial.print(".");
} }
else{ else{
savetosd = true; savetosd = true;
Serial.print("Writing to file: "); Serial.print("Writing to file: ");
Serial.println(strchr_pointer + 4); Serial.println(strchr_pointer + 4);
} }
} }
break; break;
case 29: //M29 - Stop SD write case 29: //M29 - Stop SD write
//processed in write to file routine above //processed in write to file routine above
//savetosd = false; //savetosd = false;
break; break;
case 30: case 30:
{ {
stoptime=millis(); stoptime=millis();
char time[30]; char time[30];
unsigned long t=(stoptime-starttime)/1000; unsigned long t=(stoptime-starttime)/1000;
int sec,min; int sec,min;
min=t/60; min=t/60;
sec=t%60; sec=t%60;
sprintf(time,"%i min, %i sec",min,sec); sprintf(time,"%i min, %i sec",min,sec);
Serial.println(time); Serial.println(time);
LCD_MESSAGE(time); LCD_MESSAGE(time);
} }
break; break;
#endif //SDSUPPORT #endif //SDSUPPORT
case 42: //M42 -Change pin status via gcode case 42: //M42 -Change pin status via gcode
if (code_seen('S')) if (code_seen('S'))
{ {
int pin_status = code_value(); int pin_status = code_value();
if (code_seen('P') && pin_status >= 0 && pin_status <= 255) if (code_seen('P') && pin_status >= 0 && pin_status <= 255)
{ {
int pin_number = code_value(); int pin_number = code_value();
for(int i = 0; i < (int)sizeof(sensitive_pins); i++) for(int i = 0; i < (int)sizeof(sensitive_pins); i++)
{ {
if (sensitive_pins[i] == pin_number) if (sensitive_pins[i] == pin_number)
{ {
pin_number = -1; pin_number = -1;
break; break;
} }
} }
if (pin_number > -1) if (pin_number > -1)
{ {
pinMode(pin_number, OUTPUT); pinMode(pin_number, OUTPUT);
digitalWrite(pin_number, pin_status); digitalWrite(pin_number, pin_status);
analogWrite(pin_number, pin_status); analogWrite(pin_number, pin_status);
} }
} }
} }
break; break;
case 104: // M104 case 104: // M104
if (code_seen('S')) target_raw[TEMPSENSOR_HOTEND] = temp2analog(code_value()); if (code_seen('S')) target_raw[TEMPSENSOR_HOTEND_0] = temp2analog(code_value());
#ifdef PIDTEMP #ifdef PIDTEMP
pid_setpoint = code_value(); pid_setpoint = code_value();
#endif //PIDTEM #endif //PIDTEM
#ifdef WATCHPERIOD #ifdef WATCHPERIOD
if(target_raw[TEMPSENSOR_HOTEND] > current_raw[TEMPSENSOR_HOTEND]){ if(target_raw[TEMPSENSOR_HOTEND_0] > current_raw[TEMPSENSOR_HOTEND_0]){
watchmillis = max(1,millis()); watchmillis = max(1,millis());
watch_raw[TEMPSENSOR_HOTEND] = current_raw[TEMPSENSOR_HOTEND]; watch_raw[TEMPSENSOR_HOTEND_0] = current_raw[TEMPSENSOR_HOTEND_0];
}else{ }else{
watchmillis = 0; watchmillis = 0;
} }
#endif #endif
break; break;
case 140: // M140 set bed temp case 140: // M140 set bed temp
if (code_seen('S')) target_raw[TEMPSENSOR_BED] = temp2analogBed(code_value()); if (code_seen('S')) target_raw[TEMPSENSOR_BED] = temp2analogBed(code_value());
break; break;
case 105: // M105 case 105: // M105
#if (TEMP_0_PIN > -1) || defined (HEATER_USES_AD595) #if (TEMP_0_PIN > -1) || defined (HEATER_USES_AD595)
tt = analog2temp(current_raw[TEMPSENSOR_HOTEND]); tt = analog2temp(current_raw[TEMPSENSOR_HOTEND_0]);
#endif #endif
#if TEMP_1_PIN > -1 #if TEMP_1_PIN > -1
bt = analog2tempBed(current_raw[TEMPSENSOR_BED]); bt = analog2tempBed(current_raw[TEMPSENSOR_BED]);
#endif #endif
#if (TEMP_0_PIN > -1) || defined (HEATER_USES_AD595) #if (TEMP_0_PIN > -1) || defined (HEATER_USES_AD595)
Serial.print("ok T:"); Serial.print("ok T:");
Serial.print(tt); Serial.print(tt);
// Serial.print(", raw:"); // Serial.print(", raw:");
// Serial.print(current_raw); // Serial.print(current_raw);
#if TEMP_1_PIN > -1 #if TEMP_1_PIN > -1
#ifdef PIDTEMP #ifdef PIDTEMP
Serial.print(" B:"); Serial.print(" B:");
#if TEMP_1_PIN > -1 #if TEMP_1_PIN > -1
Serial.println(bt); Serial.println(bt);
#else #else
Serial.println(HeaterPower); Serial.println(HeaterPower);
#endif #endif
#else #else
Serial.println(); Serial.println();
#endif #endif
#else #else
Serial.println(); Serial.println();
#endif #endif
#else #else
Serial.println("No thermistors - no temp"); Serial.println("No thermistors - no temp");
#endif #endif
return; return;
//break; //break;
case 109: {// M109 - Wait for extruder heater to reach target. case 109: {// M109 - Wait for extruder heater to reach target.
LCD_MESSAGE("Heating..."); LCD_MESSAGE("Heating...");
if (code_seen('S')) target_raw[TEMPSENSOR_HOTEND] = temp2analog(code_value()); if (code_seen('S')) target_raw[TEMPSENSOR_HOTEND_0] = temp2analog(code_value());
#ifdef PIDTEMP #ifdef PIDTEMP
pid_setpoint = code_value(); pid_setpoint = code_value();
#endif //PIDTEM #endif //PIDTEM
#ifdef WATCHPERIOD #ifdef WATCHPERIOD
if(target_raw[TEMPSENSOR_HOTEND]>current_raw[TEMPSENSOR_HOTEND]){ if(target_raw[TEMPSENSOR_HOTEND_0]>current_raw[TEMPSENSOR_HOTEND_0]){
watchmillis = max(1,millis()); watchmillis = max(1,millis());
watch_raw[TEMPSENSOR_HOTEND] = current_raw[TEMPSENSOR_HOTEND]; watch_raw[TEMPSENSOR_HOTEND_0] = current_raw[TEMPSENSOR_HOTEND_0];
} else { } else {
watchmillis = 0; watchmillis = 0;
} }
#endif //WATCHPERIOD #endif //WATCHPERIOD
codenum = millis(); codenum = millis();
/* See if we are heating up or cooling down */ /* See if we are heating up or cooling down */
bool target_direction = (current_raw[0] < target_raw[0]); // true if heating, false if cooling bool target_direction = (current_raw[TEMPSENSOR_HOTEND_0] < target_raw[TEMPSENSOR_HOTEND_0]); // true if heating, false if cooling
#ifdef TEMP_RESIDENCY_TIME #ifdef TEMP_RESIDENCY_TIME
long residencyStart; long residencyStart;
residencyStart = -1; residencyStart = -1;
/* continue to loop until we have reached the target temp /* continue to loop until we have reached the target temp
_and_ until TEMP_RESIDENCY_TIME hasn't passed since we reached it */ _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])) || while((target_direction ? (current_raw[TEMPSENSOR_HOTEND_0] < target_raw[TEMPSENSOR_HOTEND_0]) : (current_raw[TEMPSENSOR_HOTEND_0] > target_raw[TEMPSENSOR_HOTEND_0])) ||
(residencyStart > -1 && (millis() - residencyStart) < TEMP_RESIDENCY_TIME*1000) ) { (residencyStart > -1 && (millis() - residencyStart) < TEMP_RESIDENCY_TIME*1000) ) {
#else #else
while ( target_direction ? (current_raw[0] < target_raw[0]) : (current_raw[0] > target_raw[0]) ) { while ( target_direction ? (current_raw[TEMPSENSOR_HOTEND_0] < target_raw[TEMPSENSOR_HOTEND_0]) : (current_raw[TEMPSENSOR_HOTEND_0] > target_raw[TEMPSENSOR_HOTEND_0]) ) {
#endif //TEMP_RESIDENCY_TIME #endif //TEMP_RESIDENCY_TIME
if( (millis() - codenum) > 1000 ) { //Print Temp Reading every 1 second while heating up/cooling down if( (millis() - codenum) > 1000 ) { //Print Temp Reading every 1 second while heating up/cooling down
Serial.print("T:"); Serial.print("T:");
Serial.println( analog2temp(current_raw[TEMPSENSOR_HOTEND]) ); Serial.println( analog2temp(current_raw[TEMPSENSOR_HOTEND_0]) );
codenum = millis(); codenum = millis();
} }
manage_heater(); manage_heater();
LCD_STATUS; LCD_STATUS;
#ifdef TEMP_RESIDENCY_TIME #ifdef TEMP_RESIDENCY_TIME
/* start/restart the TEMP_RESIDENCY_TIME timer whenever we reach target temp for the first 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 */ or when current temp falls outside the hysteresis after target temp was reached */
if ((residencyStart == -1 && target_direction && current_raw[0] >= target_raw[0]) || if ((residencyStart == -1 && target_direction && current_raw[TEMPSENSOR_HOTEND_0] >= target_raw[TEMPSENSOR_HOTEND_0]) ||
(residencyStart == -1 && !target_direction && current_raw[0] <= target_raw[0]) || (residencyStart == -1 && !target_direction && current_raw[TEMPSENSOR_HOTEND_0] <= target_raw[TEMPSENSOR_HOTEND_0]) ||
(residencyStart > -1 && labs(analog2temp(current_raw[0]) - analog2temp(target_raw[0])) > TEMP_HYSTERESIS) ) { (residencyStart > -1 && labs(analog2temp(current_raw[TEMPSENSOR_HOTEND_0]) - analog2temp(target_raw[TEMPSENSOR_HOTEND_0])) > TEMP_HYSTERESIS) ) {
residencyStart = millis(); residencyStart = millis();
} }
#endif //TEMP_RESIDENCY_TIME #endif //TEMP_RESIDENCY_TIME
} }
LCD_MESSAGE("Marlin ready."); LCD_MESSAGE("Marlin ready.");
} }
break; break;
case 190: // M190 - Wait bed for heater to reach target. case 190: // M190 - Wait bed for heater to reach target.
#if TEMP_1_PIN > -1 #if TEMP_1_PIN > -1
if (code_seen('S')) target_raw[TEMPSENSOR_BED] = temp2analog(code_value()); if (code_seen('S')) target_raw[TEMPSENSOR_BED] = temp2analog(code_value());
codenum = millis(); codenum = millis();
while(current_raw[TEMPSENSOR_BED] < target_raw[TEMPSENSOR_BED]) while(current_raw[TEMPSENSOR_BED] < target_raw[TEMPSENSOR_BED])
{ {
if( (millis()-codenum) > 1000 ) //Print Temp Reading every 1 second while heating up. if( (millis()-codenum) > 1000 ) //Print Temp Reading every 1 second while heating up.
{ {
float tt=analog2temp(current_raw[TEMPSENSOR_HOTEND]); float tt=analog2temp(current_raw[TEMPSENSOR_HOTEND_0]);
Serial.print("T:"); Serial.print("T:");
Serial.println( tt ); Serial.println( tt );
Serial.print("ok T:"); Serial.print("ok T:");
Serial.print( tt ); Serial.print( tt );
Serial.print(" B:"); Serial.print(" B:");
Serial.println( analog2temp(current_raw[TEMPSENSOR_BED]) ); Serial.println( analog2temp(current_raw[TEMPSENSOR_BED]) );
codenum = millis(); codenum = millis();
} }
manage_heater(); manage_heater();
} }
#endif #endif
break; break;
#if FAN_PIN > -1 #if FAN_PIN > -1
case 106: //M106 Fan On case 106: //M106 Fan On
if (code_seen('S')){ if (code_seen('S')){
WRITE(FAN_PIN,HIGH); WRITE(FAN_PIN,HIGH);
fanpwm=constrain(code_value(),0,255); fanpwm=constrain(code_value(),0,255);
analogWrite(FAN_PIN, fanpwm); analogWrite(FAN_PIN, fanpwm);
} }
else { else {
WRITE(FAN_PIN,HIGH); WRITE(FAN_PIN,HIGH);
fanpwm=255; fanpwm=255;
analogWrite(FAN_PIN, fanpwm); analogWrite(FAN_PIN, fanpwm);
} }
break; break;
case 107: //M107 Fan Off case 107: //M107 Fan Off
WRITE(FAN_PIN,LOW); WRITE(FAN_PIN,LOW);
analogWrite(FAN_PIN, 0); analogWrite(FAN_PIN, 0);
break; break;
#endif #endif
#if (PS_ON_PIN > -1) #if (PS_ON_PIN > -1)
case 80: // M80 - ATX Power On case 80: // M80 - ATX Power On
SET_OUTPUT(PS_ON_PIN); //GND SET_OUTPUT(PS_ON_PIN); //GND
break; break;
case 81: // M81 - ATX Power Off case 81: // M81 - ATX Power Off
SET_INPUT(PS_ON_PIN); //Floating SET_INPUT(PS_ON_PIN); //Floating
break; break;
#endif #endif
case 82: case 82:
axis_relative_modes[3] = false; axis_relative_modes[3] = false;
break; break;
case 83: case 83:
axis_relative_modes[3] = true; axis_relative_modes[3] = true;
break; break;
case 18: case 18:
case 84: case 84:
if(code_seen('S')){ if(code_seen('S')){
stepper_inactive_time = code_value() * 1000; stepper_inactive_time = code_value() * 1000;
} }
else{ else{
st_synchronize(); st_synchronize();
disable_x(); disable_x();
disable_y(); disable_y();
disable_z(); disable_z();
disable_e(); disable_e();
} }
break; break;
case 85: // M85 case 85: // M85
code_seen('S'); code_seen('S');
max_inactive_time = code_value() * 1000; max_inactive_time = code_value() * 1000;
break; break;
case 92: // M92 case 92: // M92
for(int i=0; i < NUM_AXIS; i++) { for(int i=0; i < NUM_AXIS; i++) {
if(code_seen(axis_codes[i])) axis_steps_per_unit[i] = code_value(); if(code_seen(axis_codes[i])) axis_steps_per_unit[i] = code_value();
} }
break; break;
case 115: // M115 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"); 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; break;
case 114: // M114 case 114: // M114
Serial.print("X:"); Serial.print("X:");
Serial.print(current_position[X_AXIS]); Serial.print(current_position[X_AXIS]);
Serial.print("Y:"); Serial.print("Y:");
Serial.print(current_position[Y_AXIS]); Serial.print(current_position[Y_AXIS]);
Serial.print("Z:"); Serial.print("Z:");
Serial.print(current_position[Z_AXIS]); Serial.print(current_position[Z_AXIS]);
Serial.print("E:"); Serial.print("E:");
Serial.print(current_position[E_AXIS]); Serial.print(current_position[E_AXIS]);
#ifdef DEBUG_STEPS #ifdef DEBUG_STEPS
Serial.print(" Count X:"); Serial.print(" Count X:");
Serial.print(float(count_position[X_AXIS])/axis_steps_per_unit[X_AXIS]); Serial.print(float(count_position[X_AXIS])/axis_steps_per_unit[X_AXIS]);
Serial.print("Y:"); Serial.print("Y:");
Serial.print(float(count_position[Y_AXIS])/axis_steps_per_unit[Y_AXIS]); Serial.print(float(count_position[Y_AXIS])/axis_steps_per_unit[Y_AXIS]);
Serial.print("Z:"); Serial.print("Z:");
Serial.println(float(count_position[Z_AXIS])/axis_steps_per_unit[Z_AXIS]); Serial.println(float(count_position[Z_AXIS])/axis_steps_per_unit[Z_AXIS]);
#endif #endif
Serial.println(""); Serial.println("");
break; break;
case 119: // M119 case 119: // M119
#if (X_MIN_PIN > -1) #if (X_MIN_PIN > -1)
Serial.print("x_min:"); Serial.print("x_min:");
Serial.print((READ(X_MIN_PIN)^ENDSTOPS_INVERTING)?"H ":"L "); Serial.print((READ(X_MIN_PIN)^ENDSTOPS_INVERTING)?"H ":"L ");
#endif #endif
#if (X_MAX_PIN > -1) #if (X_MAX_PIN > -1)
Serial.print("x_max:"); Serial.print("x_max:");
Serial.print((READ(X_MAX_PIN)^ENDSTOPS_INVERTING)?"H ":"L "); Serial.print((READ(X_MAX_PIN)^ENDSTOPS_INVERTING)?"H ":"L ");
#endif #endif
#if (Y_MIN_PIN > -1) #if (Y_MIN_PIN > -1)
Serial.print("y_min:"); Serial.print("y_min:");
Serial.print((READ(Y_MIN_PIN)^ENDSTOPS_INVERTING)?"H ":"L "); Serial.print((READ(Y_MIN_PIN)^ENDSTOPS_INVERTING)?"H ":"L ");
#endif #endif
#if (Y_MAX_PIN > -1) #if (Y_MAX_PIN > -1)
Serial.print("y_max:"); Serial.print("y_max:");
Serial.print((READ(Y_MAX_PIN)^ENDSTOPS_INVERTING)?"H ":"L "); Serial.print((READ(Y_MAX_PIN)^ENDSTOPS_INVERTING)?"H ":"L ");
#endif #endif
#if (Z_MIN_PIN > -1) #if (Z_MIN_PIN > -1)
Serial.print("z_min:"); Serial.print("z_min:");
Serial.print((READ(Z_MIN_PIN)^ENDSTOPS_INVERTING)?"H ":"L "); Serial.print((READ(Z_MIN_PIN)^ENDSTOPS_INVERTING)?"H ":"L ");
#endif #endif
#if (Z_MAX_PIN > -1) #if (Z_MAX_PIN > -1)
Serial.print("z_max:"); Serial.print("z_max:");
Serial.print((READ(Z_MAX_PIN)^ENDSTOPS_INVERTING)?"H ":"L "); Serial.print((READ(Z_MAX_PIN)^ENDSTOPS_INVERTING)?"H ":"L ");
#endif #endif
Serial.println(""); Serial.println("");
break; break;
//TODO: update for all axis, use for loop //TODO: update for all axis, use for loop
case 201: // M201 case 201: // M201
for(int i=0; i < NUM_AXIS; i++) { 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]; if(code_seen(axis_codes[i])) axis_steps_per_sqr_second[i] = code_value() * axis_steps_per_unit[i];
} }
break; break;
#if 0 // Not used for Sprinter/grbl gen6 #if 0 // Not used for Sprinter/grbl gen6
case 202: // M202 case 202: // M202
for(int i=0; i < NUM_AXIS; i++) { 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]; if(code_seen(axis_codes[i])) axis_travel_steps_per_sqr_second[i] = code_value() * axis_steps_per_unit[i];
} }
break; break;
#endif #endif
case 203: // M203 max feedrate mm/sec case 203: // M203 max feedrate mm/sec
for(int i=0; i < NUM_AXIS; i++) { for(int i=0; i < NUM_AXIS; i++) {
if(code_seen(axis_codes[i])) max_feedrate[i] = code_value()*60 ; if(code_seen(axis_codes[i])) max_feedrate[i] = code_value()*60 ;
} }
break; break;
case 204: // M204 acclereration S normal moves T filmanent only moves case 204: // M204 acclereration S normal moves T filmanent only moves
{ {
if(code_seen('S')) acceleration = code_value() ; if(code_seen('S')) acceleration = code_value() ;
if(code_seen('T')) retract_acceleration = code_value() ; if(code_seen('T')) retract_acceleration = code_value() ;
} }
break; 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 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('S')) minimumfeedrate = code_value()*60 ;
if(code_seen('T')) mintravelfeedrate = code_value()*60 ; if(code_seen('T')) mintravelfeedrate = code_value()*60 ;
if(code_seen('B')) minsegmenttime = code_value() ; if(code_seen('B')) minsegmenttime = code_value() ;
if(code_seen('X')) max_xy_jerk = code_value()*60 ; if(code_seen('X')) max_xy_jerk = code_value()*60 ;
if(code_seen('Z')) max_z_jerk = code_value()*60 ; if(code_seen('Z')) max_z_jerk = code_value()*60 ;
} }
break; break;
case 220: // M220 S<factor in percent>- set speed factor override percentage case 220: // M220 S<factor in percent>- set speed factor override percentage
{ {
if(code_seen('S')) if(code_seen('S'))
{ {
feedmultiply = code_value() ; feedmultiply = code_value() ;
feedmultiplychanged=true; feedmultiplychanged=true;
} }
} }
break; break;
#ifdef PIDTEMP #ifdef PIDTEMP
case 301: // M301 case 301: // M301
if(code_seen('P')) Kp = code_value(); if(code_seen('P')) Kp = code_value();
if(code_seen('I')) Ki = code_value()*PID_dT; if(code_seen('I')) Ki = code_value()*PID_dT;
if(code_seen('D')) Kd = code_value()/PID_dT; if(code_seen('D')) Kd = code_value()/PID_dT;
// ECHOLN("Kp "<<_FLOAT(Kp,2)); // ECHOLN("Kp "<<_FLOAT(Kp,2));
// ECHOLN("Ki "<<_FLOAT(Ki/PID_dT,2)); // ECHOLN("Ki "<<_FLOAT(Ki/PID_dT,2));
// ECHOLN("Kd "<<_FLOAT(Kd*PID_dT,2)); // ECHOLN("Kd "<<_FLOAT(Kd*PID_dT,2));
// temp_iState_min = 0.0; // temp_iState_min = 0.0;
// if (Ki!=0) { // if (Ki!=0) {
// temp_iState_max = PID_INTEGRAL_DRIVE_MAX / (Ki/100.0); // temp_iState_max = PID_INTEGRAL_DRIVE_MAX / (Ki/100.0);
// } // }
// else temp_iState_max = 1.0e10; // else temp_iState_max = 1.0e10;
break; break;
#endif //PIDTEMP #endif //PIDTEMP
case 500: // Store settings in EEPROM case 500: // Store settings in EEPROM
{ {
StoreSettings(); StoreSettings();
} }
break; break;
case 501: // Read settings from EEPROM case 501: // Read settings from EEPROM
{ {
RetrieveSettings(); RetrieveSettings();
} }
break; break;
case 502: // Revert to default settings case 502: // Revert to default settings
{ {
RetrieveSettings(true); RetrieveSettings(true);
} }
break; break;
} }
} }
else{ else{
Serial.println("Unknown command:"); Serial.println("Unknown command:");
Serial.println(cmdbuffer[bufindr]); Serial.println(cmdbuffer[bufindr]);
} }
ClearToSend(); ClearToSend();
} }
void FlushSerialRequestResend() void FlushSerialRequestResend()
{ {
//char cmdbuffer[bufindr][100]="Resend:"; //char cmdbuffer[bufindr][100]="Resend:";
Serial.flush(); Serial.flush();
Serial.print("Resend:"); Serial.print("Resend:");
Serial.println(gcode_LastN + 1); Serial.println(gcode_LastN + 1);
ClearToSend(); ClearToSend();
} }
void ClearToSend() void ClearToSend()
{ {
previous_millis_cmd = millis(); previous_millis_cmd = millis();
#ifdef SDSUPPORT #ifdef SDSUPPORT
if(fromsd[bufindr]) if(fromsd[bufindr])
return; return;
#endif //SDSUPPORT #endif //SDSUPPORT
Serial.println("ok"); Serial.println("ok");
} }
inline void get_coordinates() inline void get_coordinates()
{ {
for(int i=0; i < NUM_AXIS; i++) { 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]; 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? else destination[i] = current_position[i]; //Are these else lines really needed?
} }
if(code_seen('F')) { if(code_seen('F')) {
next_feedrate = code_value(); next_feedrate = code_value();
if(next_feedrate > 0.0) feedrate = next_feedrate; if(next_feedrate > 0.0) feedrate = next_feedrate;
} }
} }
void prepare_move() void prepare_move()
{ {
plan_buffer_line(destination[X_AXIS], destination[Y_AXIS], destination[Z_AXIS], destination[E_AXIS], feedrate*feedmultiply/60.0/100.0); 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++) { for(int i=0; i < NUM_AXIS; i++) {
current_position[i] = destination[i]; current_position[i] = destination[i];
} }
} }
#ifdef USE_WATCHDOG #ifdef USE_WATCHDOG
#include <avr/wdt.h> #include <avr/wdt.h>
#include <avr/interrupt.h> #include <avr/interrupt.h>
volatile uint8_t timeout_seconds=0; volatile uint8_t timeout_seconds=0;
void(* ctrlaltdelete) (void) = 0; void(* ctrlaltdelete) (void) = 0;
ISR(WDT_vect) { //Watchdog timer interrupt, called if main program blocks >1sec ISR(WDT_vect) { //Watchdog timer interrupt, called if main program blocks >1sec
if(timeout_seconds++ >= WATCHDOG_TIMEOUT) if(timeout_seconds++ >= WATCHDOG_TIMEOUT)
{ {
kill(); kill();
#ifdef RESET_MANUAL #ifdef RESET_MANUAL
LCD_MESSAGE("Please Reset!"); LCD_MESSAGE("Please Reset!");
ECHOLN("echo_: Something is wrong, please turn off the printer."); ECHOLN("echo_: Something is wrong, please turn off the printer.");
#else #else
LCD_MESSAGE("Timeout, resetting!"); LCD_MESSAGE("Timeout, resetting!");
#endif #endif
//disable watchdog, it will survife reboot. //disable watchdog, it will survife reboot.
WDTCSR |= (1<<WDCE) | (1<<WDE); WDTCSR |= (1<<WDCE) | (1<<WDE);
WDTCSR = 0; WDTCSR = 0;
#ifdef RESET_MANUAL #ifdef RESET_MANUAL
while(1); //wait for user or serial reset while(1); //wait for user or serial reset
#else #else
ctrlaltdelete(); ctrlaltdelete();
#endif #endif
} }
} }
/// intialise watch dog with a 1 sec interrupt time /// intialise watch dog with a 1 sec interrupt time
void wd_init() { void wd_init() {
WDTCSR = (1<<WDCE )|(1<<WDE ); //allow changes WDTCSR = (1<<WDCE )|(1<<WDE ); //allow changes
WDTCSR = (1<<WDIF)|(1<<WDIE)| (1<<WDCE )|(1<<WDE )| (1<<WDP2 )|(1<<WDP1)|(0<<WDP0); WDTCSR = (1<<WDIF)|(1<<WDIE)| (1<<WDCE )|(1<<WDE )| (1<<WDP2 )|(1<<WDP1)|(0<<WDP0);
} }
/// reset watchdog. MUST be called every 1s after init or avr will reset. /// reset watchdog. MUST be called every 1s after init or avr will reset.
void wd_reset() { void wd_reset() {
wdt_reset(); wdt_reset();
timeout_seconds=0; //reset counter for resets timeout_seconds=0; //reset counter for resets
} }
#endif /* USE_WATCHDOG */ #endif /* USE_WATCHDOG */
inline void kill() inline void kill()
{ {
#if TEMP_0_PIN > -1 #if TEMP_0_PIN > -1
target_raw[0]=0; target_raw[0]=0;
#if HEATER_0_PIN > -1 #if HEATER_0_PIN > -1
WRITE(HEATER_0_PIN,LOW); WRITE(HEATER_0_PIN,LOW);
#endif #endif
#endif #endif
#if TEMP_1_PIN > -1 #if TEMP_1_PIN > -1
target_raw[1]=0; target_raw[1]=0;
#if HEATER_1_PIN > -1 #if HEATER_1_PIN > -1
WRITE(HEATER_1_PIN,LOW); WRITE(HEATER_1_PIN,LOW);
#endif #endif
#endif #endif
#if TEMP_2_PIN > -1 #if TEMP_2_PIN > -1
target_raw[2]=0; target_raw[2]=0;
#if HEATER_2_PIN > -1 #if HEATER_2_PIN > -1
WRITE(HEATER_2_PIN,LOW); WRITE(HEATER_2_PIN,LOW);
#endif #endif
#endif #endif
disable_x(); disable_x();
disable_y(); disable_y();
disable_z(); disable_z();
disable_e(); disable_e();
if(PS_ON_PIN > -1) pinMode(PS_ON_PIN,INPUT); if(PS_ON_PIN > -1) pinMode(PS_ON_PIN,INPUT);
Serial.println("!! Printer halted. kill() called!!"); Serial.println("!! Printer halted. kill() called!!");
while(1); // Wait for reset while(1); // Wait for reset
} }
void manage_inactivity(byte debug) { void manage_inactivity(byte debug) {
if( (millis()-previous_millis_cmd) > max_inactive_time ) if(max_inactive_time) kill(); 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) { if( (millis()-previous_millis_cmd) > stepper_inactive_time ) if(stepper_inactive_time) {
disable_x(); disable_x();
disable_y(); disable_y();
disable_z(); disable_z();
disable_e(); disable_e();
} }
check_axes_activity(); check_axes_activity();
} }

View file

@ -1,501 +1,503 @@
/* /*
temperature.c - temperature control temperature.c - temperature control
Part of Marlin Part of Marlin
Copyright (C) 2011 Camiel Gubbels / Erik van der Zalm Copyright (C) 2011 Camiel Gubbels / Erik van der Zalm
This program is free software: you can redistribute it and/or modify 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 it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or the Free Software Foundation, either version 3 of the License, or
(at your option) any later version. (at your option) any later version.
This program is distributed in the hope that it will be useful, This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details. GNU General Public License for more details.
You should have received a copy of the GNU General Public License You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>. along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
/* /*
This firmware is a mashup between Sprinter and grbl. This firmware is a mashup between Sprinter and grbl.
(https://github.com/kliment/Sprinter) (https://github.com/kliment/Sprinter)
(https://github.com/simen/grbl/tree) (https://github.com/simen/grbl/tree)
It has preliminary support for Matthew Roberts advance algorithm It has preliminary support for Matthew Roberts advance algorithm
http://reprap.org/pipermail/reprap-dev/2011-May/003323.html http://reprap.org/pipermail/reprap-dev/2011-May/003323.html
This firmware is optimized for gen6 electronics. This firmware is optimized for gen6 electronics.
*/ */
#include "fastio.h" #include "fastio.h"
#include "Configuration.h" #include "Configuration.h"
#include "pins.h" #include "pins.h"
#include "Marlin.h" #include "Marlin.h"
#include "ultralcd.h" #include "ultralcd.h"
#include "streaming.h" #include "streaming.h"
#include "temperature.h" #include "temperature.h"
int target_bed_raw = 0; int target_bed_raw = 0;
int current_bed_raw = 0; int current_bed_raw = 0;
int target_raw[3] = {0, 0, 0}; int target_raw[3] = {0, 0, 0};
int current_raw[3] = {0, 0, 0}; int current_raw[3] = {0, 0, 0};
unsigned char temp_meas_ready = false; unsigned char temp_meas_ready = false;
unsigned long previous_millis_heater, previous_millis_bed_heater; unsigned long previous_millis_heater, previous_millis_bed_heater;
#ifdef PIDTEMP #ifdef PIDTEMP
double temp_iState = 0; double temp_iState = 0;
double temp_dState = 0; double temp_dState = 0;
double pTerm; double pTerm;
double iTerm; double iTerm;
double dTerm; double dTerm;
//int output; //int output;
double pid_error; double pid_error;
double temp_iState_min; double temp_iState_min;
double temp_iState_max; double temp_iState_max;
double pid_setpoint = 0.0; double pid_setpoint = 0.0;
double pid_input; double pid_input;
double pid_output; double pid_output;
bool pid_reset; bool pid_reset;
float HeaterPower; float HeaterPower;
float Kp=DEFAULT_Kp; float Kp=DEFAULT_Kp;
float Ki=DEFAULT_Ki; float Ki=DEFAULT_Ki;
float Kd=DEFAULT_Kd; float Kd=DEFAULT_Kd;
float Kc=DEFAULT_Kc; float Kc=DEFAULT_Kc;
#endif //PIDTEMP #endif //PIDTEMP
#ifdef HEATER_0_MINTEMP #ifdef HEATER_0_MINTEMP
int minttemp_0 = temp2analog(HEATER_0_MINTEMP); int minttemp_0 = temp2analog(HEATER_0_MINTEMP);
#endif //MINTEMP #endif //MINTEMP
#ifdef HEATER_0_MAXTEMP #ifdef HEATER_0_MAXTEMP
int maxttemp_0 = temp2analog(HEATER_0_MAXTEMP); int maxttemp_0 = temp2analog(HEATER_0_MAXTEMP);
#endif //MAXTEMP #endif //MAXTEMP
#ifdef HEATER_1_MINTEMP #ifdef HEATER_1_MINTEMP
int minttemp_1 = temp2analog(HEATER_1_MINTEMP); int minttemp_1 = temp2analog(HEATER_1_MINTEMP);
#endif //MINTEMP #endif //MINTEMP
#ifdef HEATER_1_MAXTEMP #ifdef HEATER_1_MAXTEMP
int maxttemp_1 = temp2analog(HEATER_1_MAXTEMP); int maxttemp_1 = temp2analog(HEATER_1_MAXTEMP);
#endif //MAXTEMP #endif //MAXTEMP
#ifdef BED_MINTEMP #ifdef BED_MINTEMP
int bed_minttemp = temp2analog(BED_MINTEMP); int bed_minttemp = temp2analog(BED_MINTEMP);
#endif //BED_MINTEMP #endif //BED_MINTEMP
#ifdef BED_MAXTEMP #ifdef BED_MAXTEMP
int bed_maxttemp = temp2analog(BED_MAXTEMP); int bed_maxttemp = temp2analog(BED_MAXTEMP);
#endif //BED_MAXTEMP #endif //BED_MAXTEMP
void manage_heater() void manage_heater()
{ {
#ifdef USE_WATCHDOG #ifdef USE_WATCHDOG
wd_reset(); wd_reset();
#endif #endif
float pid_input; float pid_input;
float pid_output; float pid_output;
if(temp_meas_ready != true) //better readability if(temp_meas_ready != true) //better readability
return; return;
CRITICAL_SECTION_START; CRITICAL_SECTION_START;
temp_meas_ready = false; temp_meas_ready = false;
CRITICAL_SECTION_END; CRITICAL_SECTION_END;
#ifdef PIDTEMP #ifdef PIDTEMP
pid_input = analog2temp(current_raw[TEMPSENSOR_HOTEND]); pid_input = analog2temp(current_raw[TEMPSENSOR_HOTEND_0]);
#ifndef PID_OPENLOOP #ifndef PID_OPENLOOP
pid_error = pid_setpoint - pid_input; pid_error = pid_setpoint - pid_input;
if(pid_error > 10){ if(pid_error > 10){
pid_output = PID_MAX; pid_output = PID_MAX;
pid_reset = true; pid_reset = true;
} }
else if(pid_error < -10) { else if(pid_error < -10) {
pid_output = 0; pid_output = 0;
pid_reset = true; pid_reset = true;
} }
else { else {
if(pid_reset == true) { if(pid_reset == true) {
temp_iState = 0.0; temp_iState = 0.0;
pid_reset = false; pid_reset = false;
} }
pTerm = Kp * pid_error; pTerm = Kp * pid_error;
temp_iState += pid_error; temp_iState += pid_error;
temp_iState = constrain(temp_iState, temp_iState_min, temp_iState_max); temp_iState = constrain(temp_iState, temp_iState_min, temp_iState_max);
iTerm = Ki * temp_iState; iTerm = Ki * temp_iState;
//K1 defined in Configuration.h in the PID settings //K1 defined in Configuration.h in the PID settings
#define K2 (1.0-K1) #define K2 (1.0-K1)
dTerm = (Kd * (pid_input - temp_dState))*K2 + (K1 * dTerm); dTerm = (Kd * (pid_input - temp_dState))*K2 + (K1 * dTerm);
temp_dState = pid_input; temp_dState = pid_input;
#ifdef PID_ADD_EXTRUSION_RATE #ifdef PID_ADD_EXTRUSION_RATE
pTerm+=Kc*current_block->speed_e; //additional heating if extrusion speed is high pTerm+=Kc*current_block->speed_e; //additional heating if extrusion speed is high
#endif #endif
pid_output = constrain(pTerm + iTerm - dTerm, 0, PID_MAX); pid_output = constrain(pTerm + iTerm - dTerm, 0, PID_MAX);
} }
#endif //PID_OPENLOOP #endif //PID_OPENLOOP
#ifdef PID_DEBUG #ifdef PID_DEBUG
Serial.print(" Input "); Serial.print(" Input ");
Serial.print(pid_input); Serial.print(pid_input);
Serial.print(" Output "); Serial.print(" Output ");
Serial.print(pid_output); Serial.print(pid_output);
Serial.print(" pTerm "); Serial.print(" pTerm ");
Serial.print(pTerm); Serial.print(pTerm);
Serial.print(" iTerm "); Serial.print(" iTerm ");
Serial.print(iTerm); Serial.print(iTerm);
Serial.print(" dTerm "); Serial.print(" dTerm ");
Serial.print(dTerm); Serial.print(dTerm);
Serial.println(); Serial.println();
#endif //PID_DEBUG #endif //PID_DEBUG
analogWrite(HEATER_0_PIN, pid_output); analogWrite(HEATER_0_PIN, pid_output);
#endif //PIDTEMP #endif //PIDTEMP
#ifndef PIDTEMP #ifndef PIDTEMP
if(current_raw[0] >= target_raw[0]) if(current_raw[0] >= target_raw[0])
{ {
WRITE(HEATER_0_PIN,LOW); WRITE(HEATER_0_PIN,LOW);
} }
else else
{ {
WRITE(HEATER_0_PIN,HIGH); WRITE(HEATER_0_PIN,HIGH);
} }
#endif #endif
if(millis() - previous_millis_bed_heater < BED_CHECK_INTERVAL) if(millis() - previous_millis_bed_heater < BED_CHECK_INTERVAL)
return; return;
previous_millis_bed_heater = millis(); previous_millis_bed_heater = millis();
#if TEMP_1_PIN > -1 #if TEMP_1_PIN > -1
if(current_raw[TEMPSENSOR_BED] >= target_raw[TEMPSENSOR_BED]) if(current_raw[TEMPSENSOR_BED] >= target_raw[TEMPSENSOR_BED])
{ {
WRITE(HEATER_1_PIN,LOW); WRITE(HEATER_1_PIN,LOW);
} }
else else
{ {
WRITE(HEATER_1_PIN,HIGH); WRITE(HEATER_1_PIN,HIGH);
} }
#endif #endif
} }
// Takes hot end temperature value as input and returns corresponding raw value. // Takes hot end temperature value as input and returns corresponding raw value.
// For a thermistor, it uses the RepRap thermistor temp table. // For a thermistor, it uses the RepRap thermistor temp table.
// This is needed because PID in hydra firmware hovers around a given analog value, not a temp value. // This is needed because PID in hydra firmware hovers around a given analog value, not a temp value.
// This function is derived from inversing the logic from a portion of getTemperature() in FiveD RepRap firmware. // This function is derived from inversing the logic from a portion of getTemperature() in FiveD RepRap firmware.
int temp2analog(int celsius) { int temp2analog(int celsius) {
#ifdef HEATER_0_USES_THERMISTOR #ifdef HEATER_0_USES_THERMISTOR
int raw = 0; int raw = 0;
byte i; byte i;
for (i=1; i<NUMTEMPS_HEATER_0; i++) for (i=1; i<NUMTEMPS_HEATER_0; i++)
{ {
if (heater_0_temptable[i][1] < celsius) if (heater_0_temptable[i][1] < celsius)
{ {
raw = heater_0_temptable[i-1][0] + raw = heater_0_temptable[i-1][0] +
(celsius - heater_0_temptable[i-1][1]) * (celsius - heater_0_temptable[i-1][1]) *
(heater_0_temptable[i][0] - heater_0_temptable[i-1][0]) / (heater_0_temptable[i][0] - heater_0_temptable[i-1][0]) /
(heater_0_temptable[i][1] - heater_0_temptable[i-1][1]); (heater_0_temptable[i][1] - heater_0_temptable[i-1][1]);
break; break;
} }
} }
// Overflow: Set to last value in the table // Overflow: Set to last value in the table
if (i == NUMTEMPS_0) raw = heater_0_temptable[i-1][0]; if (i == NUMTEMPS_0) raw = heater_0_temptable[i-1][0];
return (1023 * OVERSAMPLENR) - raw; return (1023 * OVERSAMPLENR) - raw;
#elif defined HEATER_0_USES_AD595 #elif defined HEATER_0_USES_AD595
return celsius * (1024.0 / (5.0 * 100.0) ) * OVERSAMPLENR; return celsius * (1024.0 / (5.0 * 100.0) ) * OVERSAMPLENR;
#endif #endif
} }
// Takes bed temperature value as input and returns corresponding raw value. // Takes bed temperature value as input and returns corresponding raw value.
// For a thermistor, it uses the RepRap thermistor temp table. // For a thermistor, it uses the RepRap thermistor temp table.
// This is needed because PID in hydra firmware hovers around a given analog value, not a temp value. // This is needed because PID in hydra firmware hovers around a given analog value, not a temp value.
// This function is derived from inversing the logic from a portion of getTemperature() in FiveD RepRap firmware. // This function is derived from inversing the logic from a portion of getTemperature() in FiveD RepRap firmware.
int temp2analogBed(int celsius) { int temp2analogBed(int celsius) {
#ifdef BED_USES_THERMISTOR #ifdef BED_USES_THERMISTOR
int raw = 0; int raw = 0;
byte i; byte i;
for (i=1; i<BNUMTEMPS; i++) for (i=1; i<BNUMTEMPS; i++)
{ {
if (bedtemptable[i][1] < celsius) if (bedtemptable[i][1] < celsius)
{ {
raw = bedtemptable[i-1][0] + raw = bedtemptable[i-1][0] +
(celsius - bedtemptable[i-1][1]) * (celsius - bedtemptable[i-1][1]) *
(bedtemptable[i][0] - bedtemptable[i-1][0]) / (bedtemptable[i][0] - bedtemptable[i-1][0]) /
(bedtemptable[i][1] - bedtemptable[i-1][1]); (bedtemptable[i][1] - bedtemptable[i-1][1]);
break; break;
} }
} }
// Overflow: Set to last value in the table // Overflow: Set to last value in the table
if (i == BNUMTEMPS) raw = bedtemptable[i-1][0]; if (i == BNUMTEMPS) raw = bedtemptable[i-1][0];
return (1023 * OVERSAMPLENR) - raw; return (1023 * OVERSAMPLENR) - raw;
#elif defined BED_USES_AD595 #elif defined BED_USES_AD595
return celsius * (1024.0 / (5.0 * 100.0) ) * OVERSAMPLENR; return celsius * (1024.0 / (5.0 * 100.0) ) * OVERSAMPLENR;
#endif #endif
} }
// Derived from RepRap FiveD extruder::getTemperature() // Derived from RepRap FiveD extruder::getTemperature()
// For hot end temperature measurement. // For hot end temperature measurement.
float analog2temp(int raw) { float analog2temp(int raw) {
#ifdef HEATER_0_USES_THERMISTOR #ifdef HEATER_0_USES_THERMISTOR
float celsius = 0; float celsius = 0;
byte i; byte i;
raw = (1023 * OVERSAMPLENR) - raw; raw = (1023 * OVERSAMPLENR) - raw;
for (i=1; i<NUMTEMPS_HEATER_0; i++) for (i=1; i<NUMTEMPS_HEATER_0; i++)
{ {
if (heater_0_temptable[i][0] > raw) if (heater_0_temptable[i][0] > raw)
{ {
celsius = heater_0_temptable[i-1][1] + celsius = heater_0_temptable[i-1][1] +
(raw - heater_0_temptable[i-1][0]) * (raw - heater_0_temptable[i-1][0]) *
(float)(heater_0_temptable[i][1] - heater_0_temptable[i-1][1]) / (float)(heater_0_temptable[i][1] - heater_0_temptable[i-1][1]) /
(float)(heater_0_temptable[i][0] - heater_0_temptable[i-1][0]); (float)(heater_0_temptable[i][0] - heater_0_temptable[i-1][0]);
break; break;
} }
} }
// Overflow: Set to last value in the table // Overflow: Set to last value in the table
if (i == NUMTEMPS_HEATER_0) celsius = heater_0_temptable[i-1][1]; if (i == NUMTEMPS_HEATER_0) celsius = heater_0_temptable[i-1][1];
return celsius; return celsius;
#elif defined HEATER_0_USES_AD595 #elif defined HEATER_0_USES_AD595
return raw * ((5.0 * 100.0) / 1024.0) / OVERSAMPLENR; return raw * ((5.0 * 100.0) / 1024.0) / OVERSAMPLENR;
#endif #endif
} }
// Derived from RepRap FiveD extruder::getTemperature() // Derived from RepRap FiveD extruder::getTemperature()
// For bed temperature measurement. // For bed temperature measurement.
float analog2tempBed(int raw) { float analog2tempBed(int raw) {
#ifdef BED_USES_THERMISTOR #ifdef BED_USES_THERMISTOR
int celsius = 0; int celsius = 0;
byte i; byte i;
raw = (1023 * OVERSAMPLENR) - raw; raw = (1023 * OVERSAMPLENR) - raw;
for (i=1; i<BNUMTEMPS; i++) for (i=1; i<BNUMTEMPS; i++)
{ {
if (bedtemptable[i][0] > raw) if (bedtemptable[i][0] > raw)
{ {
celsius = bedtemptable[i-1][1] + celsius = bedtemptable[i-1][1] +
(raw - bedtemptable[i-1][0]) * (raw - bedtemptable[i-1][0]) *
(bedtemptable[i][1] - bedtemptable[i-1][1]) / (bedtemptable[i][1] - bedtemptable[i-1][1]) /
(bedtemptable[i][0] - bedtemptable[i-1][0]); (bedtemptable[i][0] - bedtemptable[i-1][0]);
break; break;
} }
} }
// Overflow: Set to last value in the table // Overflow: Set to last value in the table
if (i == BNUMTEMPS) celsius = bedtemptable[i-1][1]; if (i == BNUMTEMPS) celsius = bedtemptable[i-1][1];
return celsius; return celsius;
#elif defined BED_USES_AD595 #elif defined BED_USES_AD595
return raw * ((5.0 * 100.0) / 1024.0) / OVERSAMPLENR; return raw * ((5.0 * 100.0) / 1024.0) / OVERSAMPLENR;
#endif #endif
} }
void tp_init() void tp_init()
{ {
#if (HEATER_0_PIN > -1) #if (HEATER_0_PIN > -1)
SET_OUTPUT(HEATER_0_PIN); SET_OUTPUT(HEATER_0_PIN);
#endif #endif
#if (HEATER_1_PIN > -1) #if (HEATER_1_PIN > -1)
SET_OUTPUT(HEATER_1_PIN); SET_OUTPUT(HEATER_1_PIN);
#endif #endif
#if (HEATER_2_PIN > -1) #if (HEATER_2_PIN > -1)
SET_OUTPUT(HEATER_2_PIN); SET_OUTPUT(HEATER_2_PIN);
#endif #endif
#ifdef PIDTEMP #ifdef PIDTEMP
temp_iState_min = 0.0; temp_iState_min = 0.0;
temp_iState_max = PID_INTEGRAL_DRIVE_MAX / Ki; temp_iState_max = PID_INTEGRAL_DRIVE_MAX / Ki;
#endif //PIDTEMP #endif //PIDTEMP
// Set analog inputs // Set analog inputs
ADCSRA = 1<<ADEN | 1<<ADSC | 1<<ADIF | 0x07; ADCSRA = 1<<ADEN | 1<<ADSC | 1<<ADIF | 0x07;
// Use timer0 for temperature measurement // Use timer0 for temperature measurement
// Interleave temperature interrupt with millies interrupt // Interleave temperature interrupt with millies interrupt
OCR0B = 128; OCR0B = 128;
TIMSK0 |= (1<<OCIE0B); TIMSK0 |= (1<<OCIE0B);
} }
// Timer 0 is shared with millies // Timer 0 is shared with millies
ISR(TIMER0_COMPB_vect) ISR(TIMER0_COMPB_vect)
{ {
//these variables are only accesible from the ISR, but static, so they don't loose their value //these variables are only accesible from the ISR, but static, so they don't loose their value
static unsigned char temp_count = 0; static unsigned char temp_count = 0;
static unsigned long raw_temp_0_value = 0; static unsigned long raw_temp_0_value = 0;
static unsigned long raw_temp_1_value = 0; static unsigned long raw_temp_1_value = 0;
static unsigned long raw_temp_2_value = 0; static unsigned long raw_temp_2_value = 0;
static unsigned char temp_state = 0; static unsigned char temp_state = 0;
switch(temp_state) { switch(temp_state) {
case 0: // Prepare TEMP_0 case 0: // Prepare TEMP_0
#if (TEMP_0_PIN > -1) #if (TEMP_0_PIN > -1)
#if TEMP_0_PIN < 8 #if TEMP_0_PIN < 8
DIDR0 = 1 << TEMP_0_PIN; DIDR0 = 1 << TEMP_0_PIN;
#else #else
DIDR2 = 1<<(TEMP_0_PIN - 8); DIDR2 = 1<<(TEMP_0_PIN - 8);
ADCSRB = 1<<MUX5; ADCSRB = 1<<MUX5;
#endif #endif
ADMUX = ((1 << REFS0) | (TEMP_0_PIN & 0x07)); ADMUX = ((1 << REFS0) | (TEMP_0_PIN & 0x07));
ADCSRA |= 1<<ADSC; // Start conversion ADCSRA |= 1<<ADSC; // Start conversion
#endif #endif
#ifdef ULTIPANEL #ifdef ULTIPANEL
buttons_check(); buttons_check();
#endif #endif
temp_state = 1; temp_state = 1;
break; break;
case 1: // Measure TEMP_0 case 1: // Measure TEMP_0
#if (TEMP_0_PIN > -1) #if (TEMP_0_PIN > -1)
raw_temp_0_value += ADC; raw_temp_0_value += ADC;
#endif #endif
temp_state = 2; temp_state = 2;
break; break;
case 2: // Prepare TEMP_1 case 2: // Prepare TEMP_1
#if (TEMP_1_PIN > -1) #if (TEMP_1_PIN > -1)
#if TEMP_1_PIN < 7 #if TEMP_1_PIN < 7
DIDR0 = 1<<TEMP_1_PIN; DIDR0 = 1<<TEMP_1_PIN;
#else #else
DIDR2 = 1<<(TEMP_1_PIN - 8); DIDR2 = 1<<(TEMP_1_PIN - 8);
ADCSRB = 1<<MUX5; ADCSRB = 1<<MUX5;
#endif #endif
ADMUX = ((1 << REFS0) | (TEMP_1_PIN & 0x07)); ADMUX = ((1 << REFS0) | (TEMP_1_PIN & 0x07));
ADCSRA |= 1<<ADSC; // Start conversion ADCSRA |= 1<<ADSC; // Start conversion
#endif #endif
#ifdef ULTIPANEL #ifdef ULTIPANEL
buttons_check(); buttons_check();
#endif #endif
temp_state = 3; temp_state = 3;
break; break;
case 3: // Measure TEMP_1 case 3: // Measure TEMP_1
#if (TEMP_1_PIN > -1) #if (TEMP_1_PIN > -1)
raw_temp_1_value += ADC; raw_temp_1_value += ADC;
#endif #endif
temp_state = 4; temp_state = 4;
break; break;
case 4: // Prepare TEMP_2 case 4: // Prepare TEMP_2
#if (TEMP_2_PIN > -1) #if (TEMP_2_PIN > -1)
#if TEMP_2_PIN < 7 #if TEMP_2_PIN < 7
DIDR0 = 1 << TEMP_2_PIN; DIDR0 = 1 << TEMP_2_PIN;
#else #else
DIDR2 = 1<<(TEMP_2_PIN - 8); DIDR2 = 1<<(TEMP_2_PIN - 8);
ADCSRB = 1<<MUX5; ADCSRB = 1<<MUX5;
#endif #endif
ADMUX = ((1 << REFS0) | (TEMP_2_PIN & 0x07)); ADMUX = ((1 << REFS0) | (TEMP_2_PIN & 0x07));
ADCSRA |= 1<<ADSC; // Start conversion ADCSRA |= 1<<ADSC; // Start conversion
#endif #endif
#ifdef ULTIPANEL #ifdef ULTIPANEL
buttons_check(); buttons_check();
#endif #endif
temp_state = 5; temp_state = 5;
break; break;
case 5: // Measure TEMP_2 case 5: // Measure TEMP_2
#if (TEMP_2_PIN > -1) #if (TEMP_2_PIN > -1)
raw_temp_2_value += ADC; raw_temp_2_value += ADC;
#endif #endif
temp_state = 0; temp_state = 0;
temp_count++; temp_count++;
break; break;
default: default:
Serial.println("!! Temp measurement error !!"); Serial.println("!! Temp measurement error !!");
break; break;
} }
if(temp_count >= 16) // 6 ms * 16 = 96ms. if(temp_count >= 16) // 6 ms * 16 = 96ms.
{ {
#ifdef HEATER_0_USES_AD595 #ifdef HEATER_0_USES_AD595
current_raw[0] = raw_temp_0_value; current_raw[0] = raw_temp_0_value;
#else #else
current_raw[0] = 16383 - raw_temp_0_value; current_raw[0] = 16383 - raw_temp_0_value;
#endif #endif
#ifdef HEATER_1_USES_AD595 #ifdef HEATER_1_USES_AD595
current_raw[2] = raw_temp_2_value; current_raw[2] = raw_temp_2_value;
#else #else
current_raw[2] = 16383 - raw_temp_2_value; current_raw[2] = 16383 - raw_temp_2_value;
#endif #endif
#ifdef BED_USES_AD595 #ifdef BED_USES_AD595
current_raw[1] = raw_temp_1_value; current_raw[1] = raw_temp_1_value;
#else #else
current_raw[1] = 16383 - raw_temp_1_value; current_raw[1] = 16383 - raw_temp_1_value;
#endif #endif
temp_meas_ready = true; temp_meas_ready = true;
temp_count = 0; temp_count = 0;
raw_temp_0_value = 0; raw_temp_0_value = 0;
raw_temp_1_value = 0; raw_temp_1_value = 0;
raw_temp_2_value = 0; raw_temp_2_value = 0;
#ifdef HEATER_0_MAXTEMP #ifdef HEATER_0_MAXTEMP
#if (HEATER_0_PIN > -1) #if (HEATER_0_PIN > -1)
if(current_raw[TEMPSENSOR_HOTEND] >= maxttemp) { if(current_raw[TEMPSENSOR_HOTEND_0] >= maxttemp_0) {
target_raw[TEMPSENSOR_HOTEND] = 0; target_raw[TEMPSENSOR_HOTEND_0] = 0;
analogWrite(HEATER_0_PIN, 0); analogWrite(HEATER_0_PIN, 0);
Serial.println("!! Temperature extruder 0 switched off. MAXTEMP triggered !!"); Serial.println("!! Temperature extruder 0 switched off. MAXTEMP triggered !!");
kill(); kill();
} }
#endif #endif
#endif #endif
if(current_raw[TEMPSENSOR_AUX] >= maxttemp) { #ifdef HEATER_1_MAXTEMP
target_raw[TEMPSENSOR_AUX] = 0; #if (HEATER_1_PIN > -1)
if(current_raw[2] >= maxttemp_1) { if(current_raw[TEMPSENSOR_HOTEND_1] >= maxttemp_1) {
analogWrite(HEATER_2_PIN, 0); target_raw[TEMPSENSOR_HOTEND_1] = 0;
Serial.println("!! Temperature extruder 1 switched off. MAXTEMP triggered !!"); if(current_raw[2] >= maxttemp_1) {
kill() analogWrite(HEATER_2_PIN, 0);
} Serial.println("!! Temperature extruder 1 switched off. MAXTEMP triggered !!");
#endif kill()
#endif //MAXTEMP }
#ifdef HEATER_0_MINTEMP #endif
#if (HEATER_0_PIN > -1) #endif //MAXTEMP
if(current_raw[TEMPSENSOR_HOTEND] <= minttemp) { #ifdef HEATER_0_MINTEMP
target_raw[TEMPSENSOR_HOTEND] = 0; #if (HEATER_0_PIN > -1)
analogWrite(HEATER_0_PIN, 0); if(current_raw[TEMPSENSOR_HOTEND_0] <= minttemp_0) {
Serial.println("!! Temperature extruder 0 switched off. MINTEMP triggered !!"); target_raw[TEMPSENSOR_HOTEND_0] = 0;
kill(); analogWrite(HEATER_0_PIN, 0);
} Serial.println("!! Temperature extruder 0 switched off. MINTEMP triggered !!");
#endif kill();
#endif }
#ifdef HEATER_1_MINTEMP #endif
#if (HEATER_2_PIN > -1) #endif
if(current_raw[TEMPSENSOR_AUX] <= minttemp) { #ifdef HEATER_1_MINTEMP
target_raw[TEMPSENSOR_AUX] = 0; #if (HEATER_2_PIN > -1)
analogWrite(HEATER_2_PIN, 0); if(current_raw[TEMPSENSOR_HOTEND_1] <= minttemp_1) {
Serial.println("!! Temperature extruder 1 switched off. MINTEMP triggered !!"); target_raw[TEMPSENSOR_HOTEND_1] = 0;
kill(); analogWrite(HEATER_2_PIN, 0);
} Serial.println("!! Temperature extruder 1 switched off. MINTEMP triggered !!");
#endif kill();
#endif //MAXTEMP }
#ifdef BED_MINTEMP #endif
#if (HEATER_1_PIN > -1) #endif //MAXTEMP
if(current_raw[1] <= bed_minttemp) { #ifdef BED_MINTEMP
target_raw[1] = 0; #if (HEATER_1_PIN > -1)
WRITE(HEATER_1_PIN, 0); if(current_raw[1] <= bed_minttemp) {
Serial.println("!! Temperatur heated bed switched off. MINTEMP triggered !!"); target_raw[1] = 0;
kill(); WRITE(HEATER_1_PIN, 0);
} Serial.println("!! Temperatur heated bed switched off. MINTEMP triggered !!");
#endif kill();
#endif }
#ifdef BED_MAXTEMP #endif
#if (HEATER_1_PIN > -1) #endif
if(current_raw[1] >= bed_maxttemp) { #ifdef BED_MAXTEMP
target_raw[1] = 0; #if (HEATER_1_PIN > -1)
WRITE(HEATER_1_PIN, 0); if(current_raw[1] >= bed_maxttemp) {
Serial.println("!! Temperature heated bed switched off. MAXTEMP triggered !!"); target_raw[1] = 0;
kill(); WRITE(HEATER_1_PIN, 0);
} Serial.println("!! Temperature heated bed switched off. MAXTEMP triggered !!");
#endif kill();
#endif }
} #endif
} #endif
}
}

View file

@ -1,58 +1,58 @@
/* /*
temperature.h - temperature controller temperature.h - temperature controller
Part of Marlin Part of Marlin
Copyright (c) 2011 Erik van der Zalm Copyright (c) 2011 Erik van der Zalm
Grbl is free software: you can redistribute it and/or modify Grbl is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or the Free Software Foundation, either version 3 of the License, or
(at your option) any later version. (at your option) any later version.
Grbl is distributed in the hope that it will be useful, Grbl is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details. GNU General Public License for more details.
You should have received a copy of the GNU General Public License You should have received a copy of the GNU General Public License
along with Grbl. If not, see <http://www.gnu.org/licenses/>. along with Grbl. If not, see <http://www.gnu.org/licenses/>.
*/ */
#ifndef temperature_h #ifndef temperature_h
#define temperature_h #define temperature_h
#include "Marlin.h" #include "Marlin.h"
#ifdef PID_ADD_EXTRUSION_RATE #ifdef PID_ADD_EXTRUSION_RATE
#include "stepper.h" #include "stepper.h"
#endif #endif
void tp_init(); void tp_init();
void manage_heater(); void manage_heater();
//int temp2analogu(int celsius, const short table[][2], int numtemps); //int temp2analogu(int celsius, const short table[][2], int numtemps);
//float analog2tempu(int raw, const short table[][2], int numtemps); //float analog2tempu(int raw, const short table[][2], int numtemps);
int temp2analog(int celsius); int temp2analog(int celsius);
int temp2analogBed(int celsius); int temp2analogBed(int celsius);
float analog2temp(int raw); float analog2temp(int raw);
float analog2tempBed(int raw); float analog2tempBed(int raw);
#ifdef HEATER_USES_THERMISTOR #ifdef HEATER_0_USES_THERMISTOR
#define HEATERSOURCE 1 #define HEATERSOURCE 1
#endif #endif
#ifdef BED_USES_THERMISTOR #ifdef BED_USES_THERMISTOR
#define BEDSOURCE 1 #define BEDSOURCE 1
#endif #endif
//#define temp2analogh( c ) temp2analogu((c),temptable,NUMTEMPS) //#define temp2analogh( c ) temp2analogu((c),temptable,NUMTEMPS)
//#define analog2temp( c ) analog2tempu((c),temptable,NUMTEMPS //#define analog2temp( c ) analog2tempu((c),temptable,NUMTEMPS
extern float Kp; extern float Kp;
extern float Ki; extern float Ki;
extern float Kd; extern float Kd;
extern float Kc; extern float Kc;
enum {TEMPSENSOR_HOTEND=0,TEMPSENSOR_BED=1, TEMPSENSOR_AUX=2}; enum {TEMPSENSOR_HOTEND_0=0,TEMPSENSOR_BED=1, TEMPSENSOR_HOTEND_1=2};
extern int target_raw[3]; extern int target_raw[3];
extern int current_raw[3]; extern int current_raw[3];
extern double pid_setpoint; extern double pid_setpoint;
#endif #endif

View file

@ -253,17 +253,17 @@ void MainMenu::showStatus()
} }
if((abs(current_raw[TEMPSENSOR_HOTEND]-oldcurrentraw)>3)||force_lcd_update) if((abs(current_raw[TEMPSENSOR_HOTEND_0]-oldcurrentraw)>3)||force_lcd_update)
{ {
lcd.setCursor(1,0); lcd.setCursor(1,0);
lcd.print(ftostr3(analog2temp(current_raw[TEMPSENSOR_HOTEND]))); lcd.print(ftostr3(analog2temp(current_raw[TEMPSENSOR_HOTEND_0])));
oldcurrentraw=current_raw[TEMPSENSOR_HOTEND]; oldcurrentraw=current_raw[TEMPSENSOR_HOTEND_0];
} }
if((target_raw[TEMPSENSOR_HOTEND]!=oldtargetraw)||force_lcd_update) if((target_raw[TEMPSENSOR_HOTEND_0]!=oldtargetraw)||force_lcd_update)
{ {
lcd.setCursor(5,0); lcd.setCursor(5,0);
lcd.print(ftostr3(analog2temp(target_raw[TEMPSENSOR_HOTEND]))); lcd.print(ftostr3(analog2temp(target_raw[TEMPSENSOR_HOTEND_0])));
oldtargetraw=target_raw[TEMPSENSOR_HOTEND]; oldtargetraw=target_raw[TEMPSENSOR_HOTEND_0];
} }
#if defined BED_USES_THERMISTOR || defined BED_USES_AD595 #if defined BED_USES_THERMISTOR || defined BED_USES_AD595
static int oldcurrentbedraw=-1; static int oldcurrentbedraw=-1;
@ -426,7 +426,7 @@ void MainMenu::showPrepare()
if((activeline==line) && CLICKED) if((activeline==line) && CLICKED)
{ {
BLOCK BLOCK
target_raw[TEMPSENSOR_HOTEND] = temp2analog(170); target_raw[TEMPSENSOR_HOTEND_0] = temp2analog(170);
beepshort(); beepshort();
} }
}break; }break;
@ -531,7 +531,7 @@ void MainMenu::showControl()
if(force_lcd_update) if(force_lcd_update)
{ {
lcd.setCursor(0,line);lcd.print(" \002Nozzle:"); lcd.setCursor(0,line);lcd.print(" \002Nozzle:");
lcd.setCursor(13,line);lcd.print(ftostr3(analog2temp(target_raw[TEMPSENSOR_HOTEND]))); lcd.setCursor(13,line);lcd.print(ftostr3(analog2temp(target_raw[TEMPSENSOR_HOTEND_0])));
} }
if((activeline==line) ) if((activeline==line) )
@ -541,11 +541,11 @@ void MainMenu::showControl()
linechanging=!linechanging; linechanging=!linechanging;
if(linechanging) if(linechanging)
{ {
encoderpos=(int)analog2temp(target_raw[TEMPSENSOR_HOTEND]); encoderpos=(int)analog2temp(target_raw[TEMPSENSOR_HOTEND_0]);
} }
else else
{ {
target_raw[TEMPSENSOR_HOTEND] = temp2analog(encoderpos); target_raw[TEMPSENSOR_HOTEND_0] = temp2analog(encoderpos);
encoderpos=activeline*lcdslow; encoderpos=activeline*lcdslow;
beepshort(); beepshort();
} }
@ -1590,4 +1590,4 @@ char *fillto(int8_t n,char *c)
#else #else
inline void lcd_status() {}; inline void lcd_status() {};
#endif #endif