Commit cf73391b authored by MagoKimbra's avatar MagoKimbra

Update 4.0.7

parents d0cc94cf 9d77c6d5
/**
* Conditionals.h
* Defines that depend on configuration but are not editable.
*/
#ifndef CONDITIONALS_H
#ifndef CONFIGURATION_LCD // Get the LCD defines which are needed first
#define CONFIGURATION_LCD
#if defined(MAKRPANEL)
#define DOGLCD
#define SDSUPPORT
#define DEFAULT_LCD_CONTRAST 17
#define ULTIPANEL
#define NEWPANEL
#endif
#if defined(miniVIKI) || defined(VIKI2)
#define ULTRA_LCD //general LCD support, also 16x2
#define DOGLCD // Support for SPI LCD 128x64 (Controller ST7565R graphic Display Family)
#define ULTIMAKERCONTROLLER //as available from the Ultimaker online store.
#ifdef miniVIKI
#define DEFAULT_LCD_CONTRAST 95
#else
#define DEFAULT_LCD_CONTRAST 40
#endif
#define ENCODER_PULSES_PER_STEP 4
#define ENCODER_STEPS_PER_MENU_ITEM 1
#endif
#ifdef PANEL_ONE
#define SDSUPPORT
#define ULTIMAKERCONTROLLER
#endif
#ifdef REPRAP_DISCOUNT_FULL_GRAPHIC_SMART_CONTROLLER
#define DOGLCD
#define U8GLIB_ST7920
#define REPRAP_DISCOUNT_SMART_CONTROLLER
#endif
#if defined(ULTIMAKERCONTROLLER) || defined(REPRAP_DISCOUNT_SMART_CONTROLLER) || defined(G3D_PANEL)
#define ULTIPANEL
#define NEWPANEL
#endif
#ifdef REPRAPWORLD_KEYPAD
#define ULTIPANEL
#define NEWPANEL
#endif
#ifdef RA_CONTROL_PANEL
#define LCD_I2C_TYPE_PCA8574
#define LCD_I2C_ADDRESS 0x27 // I2C Address of the port expander
#define ULTIPANEL
#define NEWPANEL
#endif
/**
* I2C PANELS
*/
#ifdef LCD_I2C_SAINSMART_YWROBOT
// This uses the LiquidCrystal_I2C library ( https://bitbucket.org/fmalpartida/new-liquidcrystal/wiki/Home )
// Make sure it is placed in the Arduino libraries directory.
#define LCD_I2C_TYPE_PCF8575
#define LCD_I2C_ADDRESS 0x27 // I2C Address of the port expander
#define ULTIPANEL
#define NEWPANEL
#endif
// PANELOLU2 LCD with status LEDs, separate encoder and click inputs
#ifdef LCD_I2C_PANELOLU2
// This uses the LiquidTWI2 library v1.2.3 or later ( https://github.com/lincomatic/LiquidTWI2 )
// Make sure the LiquidTWI2 directory is placed in the Arduino or Sketchbook libraries subdirectory.
// (v1.2.3 no longer requires you to define PANELOLU in the LiquidTWI2.h library header file)
// Note: The PANELOLU2 encoder click input can either be directly connected to a pin
// (if BTN_ENC defined to != -1) or read through I2C (when BTN_ENC == -1).
#define LCD_I2C_TYPE_MCP23017
#define LCD_I2C_ADDRESS 0x20 // I2C Address of the port expander
#define LCD_USE_I2C_BUZZER //comment out to disable buzzer on LCD
#ifndef ENCODER_PULSES_PER_STEP
#define ENCODER_PULSES_PER_STEP 4
#endif
#ifndef ENCODER_STEPS_PER_MENU_ITEM
#define ENCODER_STEPS_PER_MENU_ITEM 1
#endif
#ifdef LCD_USE_I2C_BUZZER
#define LCD_FEEDBACK_FREQUENCY_HZ 1000
#define LCD_FEEDBACK_FREQUENCY_DURATION_MS 100
#endif
#define ULTIPANEL
#define NEWPANEL
#endif
// Panucatt VIKI LCD with status LEDs, integrated click & L/R/U/P buttons, separate encoder inputs
#ifdef LCD_I2C_VIKI
// This uses the LiquidTWI2 library v1.2.3 or later ( https://github.com/lincomatic/LiquidTWI2 )
// Make sure the LiquidTWI2 directory is placed in the Arduino or Sketchbook libraries subdirectory.
// Note: The pause/stop/resume LCD button pin should be connected to the Arduino
// BTN_ENC pin (or set BTN_ENC to -1 if not used)
#define LCD_I2C_TYPE_MCP23017
#define LCD_I2C_ADDRESS 0x20 // I2C Address of the port expander
#define LCD_USE_I2C_BUZZER //comment out to disable buzzer on LCD (requires LiquidTWI2 v1.2.3 or later)
#define ULTIPANEL
#define NEWPANEL
#endif
// Shift register panels
// ---------------------
// 2 wire Non-latching LCD SR from:
// https://bitbucket.org/fmalpartida/new-liquidcrystal/wiki/schematics#!shiftregister-connection
#ifdef SAV_3DLCD
#define SR_LCD_2W_NL // Non latching 2 wire shiftregister
#define ULTIPANEL
#define NEWPANEL
#endif
#ifdef ULTIPANEL
#define NEWPANEL //enable this if you have a click-encoder panel
#define SDSUPPORT
#define ULTRA_LCD
#ifdef DOGLCD // Change number of lines to match the DOG graphic display
#define LCD_WIDTH 22
#define LCD_HEIGHT 5
#else
#define LCD_WIDTH 20
#define LCD_HEIGHT 4
#endif
#else //no panel but just LCD
#ifdef ULTRA_LCD
#ifdef DOGLCD // Change number of lines to match the 128x64 graphics display
#define LCD_WIDTH 22
#define LCD_HEIGHT 5
#else
#define LCD_WIDTH 16
#define LCD_HEIGHT 2
#endif
#endif
#endif
/**
* Default LCD contrast for dogm-like LCD displays
*/
#if defined(DOGLCD) && !defined(DEFAULT_LCD_CONTRAST)
#define DEFAULT_LCD_CONTRAST 32
#endif
#else // CONFIGURATION_LCD
#define CONDITIONALS_H
/**
* Firmware Test
*/
#ifdef FIRMWARE_TEST
#undef BAUDRATE
#define BAUDRATE 115200 // Baudrate setting to 115200 because serial monitor arduino function at max 115200 baudrate.
#endif
/**
* SINGLENOZZLE
*/
#ifdef SINGLENOZZLE
#define HOTENDS 1
#undef TEMP_SENSOR_1_AS_REDUNDANT
#else
#define HOTENDS EXTRUDERS
#endif
/**
* DRIVER_EXTRUDERS
*/
#if !defined(MKR4) && !defined(NPR2)
#define DRIVER_EXTRUDERS EXTRUDERS // This defines the number of Driver extruder
#endif
#ifndef AT90USB
#define HardwareSerial_h // trick to disable the standard HWserial
#endif
#if (ARDUINO >= 100)
#include "Arduino.h"
#else
#include "WProgram.h"
#endif
#include "pins.h"
/**
* Axis lengths
*/
#define X_MAX_LENGTH (X_MAX_POS - X_MIN_POS)
#define Y_MAX_LENGTH (Y_MAX_POS - Y_MIN_POS)
#define Z_MAX_LENGTH (Z_MAX_POS - Z_MIN_POS)
/**
* SCARA
*/
#ifdef SCARA
#undef SLOWDOWN
#define QUICK_HOME //SCARA needs Quickhome
#endif
/**
* DELTA
*/
#ifdef DELTA
#undef SLOWDOWN //DELTA not needs SLOWDOWN
// DELTA must have same valour for 3 axis endstop hits
#undef Y_HOME_RETRACT_MM
#undef Z_HOME_RETRACT_MM
#define Y_HOME_RETRACT_MM X_HOME_RETRACT_MM
#define Z_HOME_RETRACT_MM X_HOME_RETRACT_MM
#endif
/**
* AUTOSET LOCATIONS OF LIMIT SWITCHES
* Added by ZetaPhoenix 09-15-2012
*/
#ifdef MANUAL_HOME_POSITIONS // Use manual limit switch locations
#define X_HOME_POS MANUAL_X_HOME_POS
#define Y_HOME_POS MANUAL_Y_HOME_POS
#define Z_HOME_POS MANUAL_Z_HOME_POS
#else //!MANUAL_HOME_POSITIONS – Use home switch positions based on homing direction and travel limits
#ifdef BED_CENTER_AT_0_0
#define X_HOME_POS X_MAX_LENGTH * X_HOME_DIR * 0.5
#define Y_HOME_POS Y_MAX_LENGTH * Y_HOME_DIR * 0.5
#else
#define X_HOME_POS (X_HOME_DIR < 0 ? X_MIN_POS : X_MAX_POS)
#define Y_HOME_POS (Y_HOME_DIR < 0 ? Y_MIN_POS : Y_MAX_POS)
#endif
#define Z_HOME_POS (Z_HOME_DIR < 0 ? Z_MIN_POS : Z_MAX_POS)
#endif //!MANUAL_HOME_POSITIONS
/**
* Auto Bed Leveling
*/
#ifdef ENABLE_AUTO_BED_LEVELING
// Boundaries for probing based on set limits
#define MIN_PROBE_X (max(X_MIN_POS, X_MIN_POS + X_PROBE_OFFSET_FROM_EXTRUDER))
#define MAX_PROBE_X (min(X_MAX_POS, X_MAX_POS + X_PROBE_OFFSET_FROM_EXTRUDER))
#define MIN_PROBE_Y (max(Y_MIN_POS, Y_MIN_POS + Y_PROBE_OFFSET_FROM_EXTRUDER))
#define MAX_PROBE_Y (min(Y_MAX_POS, Y_MAX_POS + Y_PROBE_OFFSET_FROM_EXTRUDER))
#endif
/**
* MAX_STEP_FREQUENCY differs for TOSHIBA
*/
#ifdef CONFIG_STEPPERS_TOSHIBA
#define MAX_STEP_FREQUENCY 10000 // Max step frequency for Toshiba Stepper Controllers
#else
#define MAX_STEP_FREQUENCY 40000 // Max step frequency for Ultimaker (5000 pps / half step)
#endif
// MS1 MS2 Stepper Driver Microstepping mode table
#define MICROSTEP1 LOW,LOW
#define MICROSTEP2 HIGH,LOW
#define MICROSTEP4 LOW,HIGH
#define MICROSTEP8 HIGH,HIGH
#define MICROSTEP16 HIGH,HIGH
/**
* Advance calculated values
*/
#ifdef ADVANCE
#define EXTRUSION_AREA (0.25 * D_FILAMENT * D_FILAMENT * 3.14159)
#define STEPS_PER_CUBIC_MM_E (axis_steps_per_unit[E_AXIS] / EXTRUSION_AREA)
#endif
#ifdef ULTIPANEL
#undef SDCARDDETECTINVERTED
#endif
// Power Signal Control Definitions
// By default use Normal definition
#ifndef POWER_SUPPLY
#define POWER_SUPPLY 0
#endif
// 0 = Normal - 1 = ATX
#if (POWER_SUPPLY <= 1)
#define PS_ON_AWAKE LOW
#define PS_ON_ASLEEP HIGH
#endif
// 2 = X-Box 360 203W
#if (POWER_SUPPLY == 2)
#define PS_ON_AWAKE HIGH
#define PS_ON_ASLEEP LOW
#endif
/**
* Temp Sensor defines
*/
#if TEMP_SENSOR_0 == -2
#define HEATER_0_USES_MAX6675
#elif TEMP_SENSOR_0 == -1
#define HEATER_0_USES_AD595
#elif TEMP_SENSOR_0 == 0
#undef HEATER_0_MINTEMP
#undef HEATER_0_MAXTEMP
#elif TEMP_SENSOR_0 > 0
#define THERMISTORHEATER_0 TEMP_SENSOR_0
#define HEATER_0_USES_THERMISTOR
#endif
#if TEMP_SENSOR_1 == -1
#define HEATER_1_USES_AD595
#elif TEMP_SENSOR_1 == 0
#undef HEATER_1_MINTEMP
#undef HEATER_1_MAXTEMP
#elif TEMP_SENSOR_1 > 0
#define THERMISTORHEATER_1 TEMP_SENSOR_1
#define HEATER_1_USES_THERMISTOR
#endif
#if TEMP_SENSOR_2 == -1
#define HEATER_2_USES_AD595
#elif TEMP_SENSOR_2 == 0
#undef HEATER_2_MINTEMP
#undef HEATER_2_MAXTEMP
#elif TEMP_SENSOR_2 > 0
#define THERMISTORHEATER_2 TEMP_SENSOR_2
#define HEATER_2_USES_THERMISTOR
#endif
#if TEMP_SENSOR_3 == -1
#define HEATER_3_USES_AD595
#elif TEMP_SENSOR_3 == 0
#undef HEATER_3_MINTEMP
#undef HEATER_3_MAXTEMP
#elif TEMP_SENSOR_3 > 0
#define THERMISTORHEATER_3 TEMP_SENSOR_3
#define HEATER_3_USES_THERMISTOR
#endif
#if TEMP_SENSOR_BED == -1
#define BED_USES_AD595
#elif TEMP_SENSOR_BED == 0
#undef BED_MINTEMP
#undef BED_MAXTEMP
#elif TEMP_SENSOR_BED > 0
#define THERMISTORBED TEMP_SENSOR_BED
#define BED_USES_THERMISTOR
#endif
/**
* ARRAY_BY_HOTENDS based on HOTENDS
*/
#if HOTENDS > 3
#define ARRAY_BY_HOTENDS(v1, v2, v3, v4) { v1, v2, v3, v4 }
#elif HOTENDS > 2
#define ARRAY_BY_HOTENDS(v1, v2, v3, v4) { v1, v2, v3 }
#elif HOTENDS > 1
#define ARRAY_BY_HOTENDS(v1, v2, v3, v4) { v1, v2 }
#else
#define ARRAY_BY_HOTENDS(v1, v2, v3, v4) { v1 }
#endif
/**
* Shorthand for pin tests, for temperature.cpp
*/
#define HAS_TEMP_0 (defined(TEMP_0_PIN) && TEMP_0_PIN >= 0)
#define HAS_TEMP_1 (defined(TEMP_1_PIN) && TEMP_1_PIN >= 0)
#define HAS_TEMP_2 (defined(TEMP_2_PIN) && TEMP_2_PIN >= 0)
#define HAS_TEMP_3 (defined(TEMP_3_PIN) && TEMP_3_PIN >= 0)
#define HAS_TEMP_BED (defined(TEMP_BED_PIN) && TEMP_BED_PIN >= 0)
#define HAS_FILAMENT_SENSOR (defined(FILAMENT_SENSOR) && defined(FILWIDTH_PIN) && FILWIDTH_PIN >= 0)
#define HAS_POWER_CONSUMPTION_SENSOR (defined(POWER_CONSUMPTION) && defined(POWER_CONSUMPTION_PIN) && POWER_CONSUMPTION_PIN >= 0)
#define HAS_HEATER_0 (defined(HEATER_0_PIN) && HEATER_0_PIN >= 0)
#define HAS_HEATER_1 (defined(HEATER_1_PIN) && HEATER_1_PIN >= 0)
#define HAS_HEATER_2 (defined(HEATER_2_PIN) && HEATER_2_PIN >= 0)
#define HAS_HEATER_3 (defined(HEATER_3_PIN) && HEATER_3_PIN >= 0)
#define HAS_HEATER_BED (defined(HEATER_BED_PIN) && HEATER_BED_PIN >= 0)
#define HAS_AUTO_FAN_0 (defined(EXTRUDER_0_AUTO_FAN_PIN) && EXTRUDER_0_AUTO_FAN_PIN >= 0)
#define HAS_AUTO_FAN_1 (defined(EXTRUDER_1_AUTO_FAN_PIN) && EXTRUDER_1_AUTO_FAN_PIN >= 0)
#define HAS_AUTO_FAN_2 (defined(EXTRUDER_2_AUTO_FAN_PIN) && EXTRUDER_2_AUTO_FAN_PIN >= 0)
#define HAS_AUTO_FAN_3 (defined(EXTRUDER_3_AUTO_FAN_PIN) && EXTRUDER_3_AUTO_FAN_PIN >= 0)
#define HAS_AUTO_FAN HAS_AUTO_FAN_0 || HAS_AUTO_FAN_1 || HAS_AUTO_FAN_2 || HAS_AUTO_FAN_3
#define HAS_FAN (defined(FAN_PIN) && FAN_PIN >= 0)
/**
* Helper Macros for heaters and extruder fan
*/
#define WRITE_HEATER_0P(v) WRITE(HEATER_0_PIN, v)
#if HOTENDS > 1 || defined(HEATERS_PARALLEL)
#define WRITE_HEATER_1(v) WRITE(HEATER_1_PIN, v)
#if HOTENDS > 2
#define WRITE_HEATER_2(v) WRITE(HEATER_2_PIN, v)
#if HOTENDS > 3
#define WRITE_HEATER_3(v) WRITE(HEATER_3_PIN, v)
#endif
#endif
#endif
#ifdef HEATERS_PARALLEL
#define WRITE_HEATER_0(v) { WRITE_HEATER_0P(v); WRITE_HEATER_1(v); }
#else
#define WRITE_HEATER_0(v) WRITE_HEATER_0P(v)
#endif
#if HAS_HEATER_BED
#define WRITE_HEATER_BED(v) WRITE(HEATER_BED_PIN, v)
#endif
#if HAS_FAN
#define WRITE_FAN(v) WRITE(FAN_PIN, v)
#endif
#endif //CONFIGURATION_LCD
#endif //CONDITIONALS_H
......@@ -20,7 +20,7 @@
// User-specified version info of this build to display in [Pronterface, etc] terminal window during
// startup. Implementation of an idea by Prof Braino to inform user that any changes made to this
// build by the user have been successfully uploaded into firmware.
#define STRING_VERSION " 4.0.4"
#define STRING_VERSION " 4.0.7"
#define STRING_URL "reprap.org"
#define STRING_VERSION_CONFIG_H __DATE__ " " __TIME__ // build date and time
#define STRING_CONFIG_H_AUTHOR "(none, default config)" // Who made the changes.
......@@ -44,11 +44,7 @@
//#define MACHINE_UUID "00000000-0000-0000-0000-000000000000"
// If you want test the firmware uncomment below. Use Serial arduino monitor...
//#define FIRMWARE_TEST
#ifdef FIRMWARE_TEST
#undef BAUDRATE
#define BAUDRATE 115200 // Baudrate setting to 115200 because serial monitor arduino function at max 115200 baudrate.
#endif
//#define FIRMWARE_TEST // ONLY BAUDRATE 115200
/***********************************************************************\
**************************** Define type printer **********************
......@@ -75,11 +71,6 @@
// This is used for single nozzle and multiple extrusion configuration
// Uncomment below to enable (One Hotend)
//#define SINGLENOZZLE
#ifdef SINGLENOZZLE
#define HOTENDS 1
#else
#define HOTENDS EXTRUDERS
#endif
/***********************************************************************
*********************** Multiextruder MKR4 ***************************
......@@ -122,10 +113,6 @@
#endif
//**********************************************************************
#if !defined(MKR4) && !defined(NPR2)
#define DRIVER_EXTRUDERS EXTRUDERS // This defines the number of Driver extruder
#endif
// The following define selects which power supply you have. Please choose the one that matches your setup
// 0 = Normal power
......@@ -186,10 +173,6 @@
//#define TEMP_SENSOR_1_AS_REDUNDANT
#define MAX_REDUNDANT_TEMP_SENSOR_DIFF 10 // (degC)
#ifdef SINGLENOZZLE
#undef TEMP_SENSOR_1_AS_REDUNDANT
#endif
// Actual temperature must be close to target for this long before M109 returns success
#define TEMP_RESIDENCY_TIME 10 // (seconds)
#define TEMP_HYSTERESIS 3 // (degC) range of +/- temperatures considered "close" to the target one
......@@ -395,110 +378,17 @@ your extruder heater takes 2 minutes to hit the target on heating.
// REMEMBER TO INSTALL LiquidCrystal_I2C.h in your ARDUINO library folder: https://github.com/kiyoshigawa/LiquidCrystal_I2C
//#define RA_CONTROL_PANEL
//automatic expansion
#if defined (MAKRPANEL)
#define DOGLCD
#define SDSUPPORT
#define ULTIPANEL
#define NEWPANEL
#define DEFAULT_LCD_CONTRAST 17
#endif //defined (MAKRPANEL)
#if defined(miniVIKI) || defined(VIKI2)
#define ULTRA_LCD //general LCD support, also 16x2
#define DOGLCD // Support for SPI LCD 128x64 (Controller ST7565R graphic Display Family)
#define ULTIMAKERCONTROLLER //as available from the Ultimaker online store.
#ifdef miniVIKI
#define DEFAULT_LCD_CONTRAST 95
#else
#define DEFAULT_LCD_CONTRAST 40
#endif
#define ENCODER_PULSES_PER_STEP 4
#define ENCODER_STEPS_PER_MENU_ITEM 1
#endif //defined(miniVIKI) || defined(VIKI2)
#if defined (PANEL_ONE)
#define SDSUPPORT
#define ULTIMAKERCONTROLLER
#endif //defined (PANEL_ONE)
#if defined (REPRAP_DISCOUNT_FULL_GRAPHIC_SMART_CONTROLLER)
#define DOGLCD
#define U8GLIB_ST7920
#define REPRAP_DISCOUNT_SMART_CONTROLLER
#endif //defined (REPRAP_DISCOUNT_FULL_GRAPHIC_SMART_CONTROLLER)
#if defined(ULTIMAKERCONTROLLER) || defined(REPRAP_DISCOUNT_SMART_CONTROLLER) || defined(G3D_PANEL)
#define ULTIPANEL
#define NEWPANEL
#endif //defined(ULTIMAKERCONTROLLER) || defined(REPRAP_DISCOUNT_SMART_CONTROLLER) || defined(G3D_PANEL)
#if defined(REPRAPWORLD_KEYPAD)
#define NEWPANEL
#define ULTIPANEL
#endif //defined(REPRAPWORLD_KEYPAD)
#if defined(RA_CONTROL_PANEL)
#define ULTIPANEL
#define NEWPANEL
#define LCD_I2C_TYPE_PCA8574
#define LCD_I2C_ADDRESS 0x27 // I2C Address of the port expander
#endif //defined(RA_CONTROL_PANEL)
//I2C PANELS
/**
* I2C Panels
*/
//#define LCD_I2C_SAINSMART_YWROBOT
#ifdef LCD_I2C_SAINSMART_YWROBOT
// This uses the LiquidCrystal_I2C library ( https://bitbucket.org/fmalpartida/new-liquidcrystal/wiki/Home )
// Make sure it is placed in the Arduino libraries directory.
#define LCD_I2C_TYPE_PCF8575
#define LCD_I2C_ADDRESS 0x27 // I2C Address of the port expander
#define NEWPANEL
#define ULTIPANEL
#endif //LCD_I2C_SAINSMART_YWROBOT
// PANELOLU2 LCD with status LEDs, separate encoder and click inputs
//#define LCD_I2C_PANELOLU2
#ifdef LCD_I2C_PANELOLU2
// This uses the LiquidTWI2 library v1.2.3 or later ( https://github.com/lincomatic/LiquidTWI2 )
// Make sure the LiquidTWI2 directory is placed in the Arduino or Sketchbook libraries subdirectory.
// (v1.2.3 no longer requires you to define PANELOLU in the LiquidTWI2.h library header file)
// Note: The PANELOLU2 encoder click input can either be directly connected to a pin
// (if BTN_ENC defined to != -1) or read through I2C (when BTN_ENC == -1).
#define LCD_I2C_TYPE_MCP23017
#define LCD_I2C_ADDRESS 0x20 // I2C Address of the port expander
#define LCD_USE_I2C_BUZZER //comment out to disable buzzer on LCD
#define NEWPANEL
#define ULTIPANEL
#ifndef ENCODER_PULSES_PER_STEP
#define ENCODER_PULSES_PER_STEP 4
#endif
#ifndef ENCODER_STEPS_PER_MENU_ITEM
#define ENCODER_STEPS_PER_MENU_ITEM 1
#endif
#ifdef LCD_USE_I2C_BUZZER
#define LCD_FEEDBACK_FREQUENCY_HZ 1000
#define LCD_FEEDBACK_FREQUENCY_DURATION_MS 100
#endif
#endif //LCD_I2C_PANELOLU2
// Panucatt VIKI LCD with status LEDs, integrated click & L/R/U/P buttons, separate encoder inputs
//#define LCD_I2C_VIKI
#ifdef LCD_I2C_VIKI
// This uses the LiquidTWI2 library v1.2.3 or later ( https://github.com/lincomatic/LiquidTWI2 )
// Make sure the LiquidTWI2 directory is placed in the Arduino or Sketchbook libraries subdirectory.
// Note: The pause/stop/resume LCD button pin should be connected to the Arduino
// BTN_ENC pin (or set BTN_ENC to -1 if not used)
#define LCD_I2C_TYPE_MCP23017
#define LCD_I2C_ADDRESS 0x20 // I2C Address of the port expander
#define LCD_USE_I2C_BUZZER //comment out to disable buzzer on LCD (requires LiquidTWI2 v1.2.3 or later)
#define NEWPANEL
#define ULTIPANEL
#endif //LCD_I2C_VIKI
// Shift register panels
// ---------------------
......@@ -506,42 +396,6 @@ your extruder heater takes 2 minutes to hit the target on heating.
// https://bitbucket.org/fmalpartida/new-liquidcrystal/wiki/schematics#!shiftregister-connection
//#define SAV_3DLCD
#ifdef SAV_3DLCD
#define SR_LCD_2W_NL // Non latching 2 wire shiftregister
#define NEWPANEL
#define ULTIPANEL
#endif //SAV_3DLCD
#ifdef ULTIPANEL
//#define NEWPANEL //enable this if you have a click-encoder panel
#define SDSUPPORT
#define ULTRA_LCD
#ifdef DOGLCD // Change number of lines to match the DOG graphic display
#define LCD_WIDTH 22
#define LCD_HEIGHT 5
#else //NO DOGLCD
#define LCD_WIDTH 20
#define LCD_HEIGHT 4
#endif //DOGLCD
#else //no ULTIPANEL
#ifdef ULTRA_LCD
#ifdef DOGLCD // Change number of lines to match the 128x64 graphics display
#define LCD_WIDTH 22
#define LCD_HEIGHT 5
#else //NO DOGLCD
#define LCD_WIDTH 16
#define LCD_HEIGHT 2
#endif //DOGLCD
#endif //ULTRA_LCD
#endif //ULTIPANEL
// default LCD contrast for dogm-like LCD displays
#ifdef DOGLCD
#ifndef DEFAULT_LCD_CONTRAST
#define DEFAULT_LCD_CONTRAST 32
#endif
#endif //DOGLCD
// option for invert rotary switch
//#define INVERT_ROTARY_SWITCH
......@@ -584,7 +438,7 @@ your extruder heater takes 2 minutes to hit the target on heating.
//========================= Bowden Filament management ======================
//#define EASY_LOAD
#ifdef EASY_LOAD
#define BOWDEN_LENGTH 560 // mm
#define BOWDEN_LENGTH 250 // mm
#define LCD_PURGE_LENGTH 3 // mm
#define LCD_RETRACT_LENGTH 3 // mm
#define LCD_PURGE_FEEDRATE 3 // mm/s
......@@ -667,10 +521,12 @@ your extruder heater takes 2 minutes to hit the target on heating.
// Uncomment below to enable
//#define POWER_CONSUMPTION
#define POWER_VOLTAGE 12.00 //(V) The power supply OUT voltage
#define POWER_ZERO 2.5 //(V) The /\V coming out from the sensor when no current flow.
#define POWER_VOLTAGE 12.00 //(V) The power supply OUT voltage
#define POWER_ZERO 2.54459 //(V) The /\V coming out from the sensor when no current flow.
#define POWER_SENSITIVITY 0.066 //(V/A) How much increase V for 1A of increase
#define POWER_EFFICIENCY 100.0 //(%) The power efficency of the power supply
#define POWER_OFFSET 0.015 //(A) Help to get 0A when no load is connected.
#define POWER_ERROR 3.0 //(%) Ammortize measure error.
#define POWER_EFFICIENCY 100.0 //(%) The power efficency of the power supply
//When using an LCD, uncomment the line below to display the Power consumption sensor data on the last line instead of status. Status will appear for 5 sec.
//#define POWER_CONSUMPTION_LCD_DISPLAY
......
......@@ -80,10 +80,6 @@ const bool Z_MAX_ENDSTOP_INVERTING = false; // set to true to invert the log
#define Z_MIN_POS 0
#define E_MIN_POS 0
#define X_MAX_LENGTH (X_MAX_POS - X_MIN_POS)
#define Y_MAX_LENGTH (Y_MAX_POS - Y_MIN_POS)
#define Z_MAX_LENGTH (Z_MAX_POS - Z_MIN_POS)
//=====================================================================================
//============================= Bed Manual or Auto Leveling ===========================
//=====================================================================================
......@@ -151,11 +147,11 @@ const bool Z_MAX_ENDSTOP_INVERTING = false; // set to true to invert the log
#define Y_PROBE_OFFSET_FROM_EXTRUDER 0 // -front +behind
#define Z_PROBE_OFFSET_FROM_EXTRUDER -1 // -below (always!)
#define Z_RAISE_BEFORE_HOMING 10 // (in mm) Raise Z before homing (G28) for Probe Clearance.
// Be sure you have this distance over your Z_MAX_POS in case
#define Z_RAISE_BEFORE_HOMING 10 // (in mm) Raise Z before homing (G28) for Probe Clearance.
// Be sure you have this distance over your Z_MAX_POS in case
#define Z_RAISE_BEFORE_PROBING 10 //How much the extruder will be raised before travelling to the first probing point.
#define Z_RAISE_BETWEEN_PROBINGS 5 //How much the extruder will be raised when travelling from between next probing points
#define Z_RAISE_BEFORE_PROBING 10 //How much the extruder will be raised before travelling to the first probing point.
#define Z_RAISE_BETWEEN_PROBINGS 5 //How much the extruder will be raised when travelling from between next probing points
//#define Z_PROBE_SLED // turn on if you have a z-probe mounted on a sled like those designed by Charles Bell
//#define SLED_DOCKING_OFFSET 5 // the extra distance the X axis must travel to pick up the sled. 0 should be fine but you can push it further if you'd like.
......
......@@ -131,9 +131,6 @@ const bool Z_MAX_ENDSTOP_INVERTING = false; // set to true to invert the log
#define Z_MIN_POS 0
#define E_MIN_POS 0
#define X_MAX_LENGTH (X_MAX_POS - X_MIN_POS)
#define Y_MAX_LENGTH (Y_MAX_POS - Y_MIN_POS)
#define Z_MAX_LENGTH (Z_MAX_POS - Z_MIN_POS)
//// MOVEMENT SETTINGS
#define NUM_AXIS 4 // The axis order in all axis related arrays is X, Y, Z, E
......@@ -150,6 +147,12 @@ const bool Z_MAX_ENDSTOP_INVERTING = false; // set to true to invert the log
#define DEFAULT_RETRACT_ACCELERATION 2500 // X, Y, Z and E max acceleration in mm/s^2 for retracts
#define DEFAULT_TRAVEL_ACCELERATION 3000 // X, Y, Z acceleration in mm/s^2 for travel (non printing) moves
// Offset of the extruders (uncomment if using more than one and relying on firmware to position when changing).
// The offset has to be X=0, Y=0 for the extruder 0 hotend (default extruder).
// For the other hotends it is their distance from the extruder 0 hotend.
//#define HOTEND_OFFSET_X {0.0, 5.00, 0.0, 0.0} // (in mm) for each extruder, offset of the hotend on the X axis
//#define HOTEND_OFFSET_Y {0.0, 5.00, 0.0, 0.0} // (in mm) for each extruder, offset of the hotend on the Y axis
// The speed change that does not require acceleration (i.e. the software might assume it can be done instantaneously)
#define DEFAULT_XYJERK 20 // (mm/sec)
#define DEFAULT_ZJERK 20 // (mm/sec)
......
......@@ -11,6 +11,8 @@
#ifndef CONFIGURATION_ADV_H
#define CONFIGURATION_ADV_H
#include "Conditionals.h"
//===========================================================================
//=============================Thermal Settings ============================
//===========================================================================
......@@ -44,13 +46,25 @@
//The M105 command return, besides traditional information, the ADC value read from temperature sensors.
//#define SHOW_TEMP_ADC_VALUES
// extruder idle oozing prevention
//if the extruder motor is idle for more than SECONDS, and the temperature over MINTEMP, some filament is retracted. The filament retracted is re-added before the next extrusion
//or when the target temperature is less than EXTRUDE_MINTEMP and the actual temperature is greater than IDLE_OOZING_MINTEMP and less than IDLE_OOZING_FEEDRATE
//#define IDLE_OOZING_PREVENT
#define IDLE_OOZING_MINTEMP EXTRUDE_MINTEMP + 5
#define IDLE_OOZING_MAXTEMP IDLE_OOZING_MINTEMP + 5
#define IDLE_OOZING_FEEDRATE 45 //default feedrate for retracting (mm/s)
#define IDLE_OOZING_SECONDS 10
#define IDLE_OOZING_LENGTH 15 //default retract length (positive mm)
#define IDLE_OOZING_RECOVER_LENGTH 0 //default additional recover length (mm, added to retract length when recovering)
#define IDLE_OOZING_RECOVER_FEEDRATE 50 //default feedrate for recovering from retraction (mm/s)
// extruder run-out prevention.
//if the machine is idle, and the temperature over MINTEMP, every couple of SECONDS some filament is extruded
//#define EXTRUDER_RUNOUT_PREVENT
#define EXTRUDER_RUNOUT_MINTEMP 190
#define EXTRUDER_RUNOUT_SECONDS 30.
#define EXTRUDER_RUNOUT_ESTEPS 14. //mm filament
#define EXTRUDER_RUNOUT_SPEED 1500. //extrusion speed
#define EXTRUDER_RUNOUT_SECONDS 30
#define EXTRUDER_RUNOUT_ESTEPS 14 //mm filament
#define EXTRUDER_RUNOUT_SPEED 1500 //extrusion speed
#define EXTRUDER_RUNOUT_EXTRUDE 100
//These defines help to calibrate the AD595 sensor in case you get wrong temperature measurements.
......@@ -89,54 +103,6 @@
#define ENDSTOPS_ONLY_FOR_HOMING // If defined the endstops will only be used for homing
//// AUTOSET LOCATIONS OF LIMIT SWITCHES
//// Added by ZetaPhoenix 09-15-2012
#ifdef MANUAL_HOME_POSITIONS // Use manual limit switch locations
#define X_HOME_POS MANUAL_X_HOME_POS
#define Y_HOME_POS MANUAL_Y_HOME_POS
#define Z_HOME_POS MANUAL_Z_HOME_POS
#else //Set min/max homing switch positions based upon homing direction and min/max travel limits
//X axis
#if X_HOME_DIR == -1
#ifdef BED_CENTER_AT_0_0
#define X_HOME_POS X_MAX_LENGTH * -0.5
#else
#define X_HOME_POS X_MIN_POS
#endif //BED_CENTER_AT_0_0
#else
#ifdef BED_CENTER_AT_0_0
#define X_HOME_POS X_MAX_LENGTH * 0.5
#else
#define X_HOME_POS X_MAX_POS
#endif //BED_CENTER_AT_0_0
#endif //X_HOME_DIR == -1
//Y axis
#if Y_HOME_DIR == -1
#ifdef BED_CENTER_AT_0_0
#define Y_HOME_POS Y_MAX_LENGTH * -0.5
#else
#define Y_HOME_POS Y_MIN_POS
#endif //BED_CENTER_AT_0_0
#else
#ifdef BED_CENTER_AT_0_0
#define Y_HOME_POS Y_MAX_LENGTH * 0.5
#else
#define Y_HOME_POS Y_MAX_POS
#endif //BED_CENTER_AT_0_0
#endif //Y_HOME_DIR == -1
// Z axis
#if Z_HOME_DIR == -1 //BED_CENTER_AT_0_0 not used
#define Z_HOME_POS Z_MIN_POS
#else
#define Z_HOME_POS Z_MAX_POS
#endif //Z_HOME_DIR == -1
#endif //End auto min/max positions
//END AUTOSET LOCATIONS OF LIMIT SWITCHES -ZP
//#define Z_LATE_ENABLE // Enable Z the last moment. Needed if your Z driver overheats.
// A single Z stepper driver is usually used to drive 2 stepper motors.
......@@ -147,8 +113,28 @@
//#define Z_DUAL_STEPPER_DRIVERS
#ifdef Z_DUAL_STEPPER_DRIVERS
#undef EXTRUDERS
#define EXTRUDERS 1
// Z_DUAL_ENDSTOPS is a feature to enable the use of 2 endstops for both Z steppers - Let's call them Z stepper and Z2 stepper.
// That way the machine is capable to align the bed during home, since both Z steppers are homed.
// There is also an implementation of M666 (software endstops adjustment) to this feature.
// After Z homing, this adjustment is applied to just one of the steppers in order to align the bed.
// One just need to home the Z axis and measure the distance difference between both Z axis and apply the math: Z adjust = Z - Z2.
// If the Z stepper axis is closer to the bed, the measure Z > Z2 (yes, it is.. think about it) and the Z adjust would be positive.
// Play a little bit with small adjustments (0.5mm) and check the behaviour.
// The M119 (endstops report) will start reporting the Z2 Endstop as well.
#define Z_DUAL_ENDSTOPS
#ifdef Z_DUAL_ENDSTOPS
#define Z2_STEP_PIN E2_STEP_PIN // Stepper to be used to Z2 axis.
#define Z2_DIR_PIN E2_DIR_PIN
#define Z2_ENABLE_PIN E2_ENABLE_PIN
#define Z2_MAX_PIN 36 //Endstop used for Z2 axis. In this case I'm using XMAX in a Rumba Board (pin 36)
const bool Z2_MAX_ENDSTOP_INVERTING = false;
#define DISABLE_XMAX_ENDSTOP //Better to disable the XMAX to avoid conflict. Just rename "XMAX_ENDSTOP" by the endstop you are using for Z2 axis.
#endif
#endif
// Same again but for Y Axis.
......@@ -157,105 +143,81 @@
// Define if the two Y drives need to rotate in opposite directions
#define INVERT_Y2_VS_Y_DIR true
#ifdef Y_DUAL_STEPPER_DRIVERS
#undef EXTRUDERS
#define EXTRUDERS 1
#endif
#if defined (Z_DUAL_STEPPER_DRIVERS) && defined (Y_DUAL_STEPPER_DRIVERS)
#error "You cannot have dual drivers for both Y and Z"
#endif
// Enable this for dual x-carriage printers.
// A dual x-carriage design has the advantage that the inactive extruder can be parked which
// prevents hot-end ooze contaminating the print. It also reduces the weight of each x-carriage
// allowing faster printing speeds.
//#define DUAL_X_CARRIAGE
#ifdef DUAL_X_CARRIAGE
// Configuration for second X-carriage
// Note: the first x-carriage is defined as the x-carriage which homes to the minimum endstop;
// the second x-carriage always homes to the maximum endstop.
#define X2_MIN_POS 80 // set minimum to ensure second x-carriage doesn't hit the parked first X-carriage
#define X2_MAX_POS 353 // set maximum to the distance between toolheads when both heads are homed
#define X2_HOME_DIR 1 // the second X-carriage always homes to the maximum endstop position
#define X2_HOME_POS X2_MAX_POS // default home position is the maximum carriage position
// However: In this mode the EXTRUDER_OFFSET_X value for the second extruder provides a software
// override for X2_HOME_POS. This also allow recalibration of the distance between the two endstops
// without modifying the firmware (through the "M218 T1 X???" command).
// Remember: you should set the second extruder x-offset to 0 in your slicer.
// Pins for second x-carriage stepper driver (defined here to avoid further complicating pins.h)
#define X2_ENABLE_PIN 29
#define X2_STEP_PIN 25
#define X2_DIR_PIN 23
// There are a few selectable movement modes for dual x-carriages using M605 S<mode>
// Mode 0: Full control. The slicer has full control over both x-carriages and can achieve optimal travel results
// as long as it supports dual x-carriages. (M605 S0)
// Mode 1: Auto-park mode. The firmware will automatically park and unpark the x-carriages on tool changes so
// that additional slicer support is not required. (M605 S1)
// Mode 2: Duplication mode. The firmware will transparently make the second x-carriage and extruder copy all
// actions of the first x-carriage. This allows the printer to print 2 arbitrary items at
// once. (2nd extruder x offset and temp offset are set using: M605 S2 [Xnnn] [Rmmm])
// This is the default power-up mode which can be later using M605.
#define DEFAULT_DUAL_X_CARRIAGE_MODE 0
// Default settings in "Auto-park Mode"
#define TOOLCHANGE_PARK_ZLIFT 0.2 // the distance to raise Z axis when parking an extruder
#define TOOLCHANGE_UNPARK_ZLIFT 1 // the distance to raise Z axis when unparking an extruder
// Default x offset in duplication mode (typically set to half print bed width)
#define DEFAULT_DUPLICATION_X_OFFSET 100
// Configuration for second X-carriage
// Note: the first x-carriage is defined as the x-carriage which homes to the minimum endstop;
// the second x-carriage always homes to the maximum endstop.
#define X2_MIN_POS 80 // set minimum to ensure second x-carriage doesn't hit the parked first X-carriage
#define X2_MAX_POS 353 // set maximum to the distance between toolheads when both heads are homed
#define X2_HOME_DIR 1 // the second X-carriage always homes to the maximum endstop position
#define X2_HOME_POS X2_MAX_POS // default home position is the maximum carriage position
// However: In this mode the EXTRUDER_OFFSET_X value for the second extruder provides a software
// override for X2_HOME_POS. This also allow recalibration of the distance between the two endstops
// without modifying the firmware (through the "M218 T1 X???" command).
// Remember: you should set the second extruder x-offset to 0 in your slicer.
// Pins for second x-carriage stepper driver (defined here to avoid further complicating pins.h)
#define X2_ENABLE_PIN 29
#define X2_STEP_PIN 25
#define X2_DIR_PIN 23
// There are a few selectable movement modes for dual x-carriages using M605 S<mode>
// Mode 0: Full control. The slicer has full control over both x-carriages and can achieve optimal travel results
// as long as it supports dual x-carriages. (M605 S0)
// Mode 1: Auto-park mode. The firmware will automatically park and unpark the x-carriages on tool changes so
// that additional slicer support is not required. (M605 S1)
// Mode 2: Duplication mode. The firmware will transparently make the second x-carriage and extruder copy all
// actions of the first x-carriage. This allows the printer to print 2 arbitrary items at
// once. (2nd extruder x offset and temp offset are set using: M605 S2 [Xnnn] [Rmmm])
// This is the default power-up mode which can be later using M605.
#define DEFAULT_DUAL_X_CARRIAGE_MODE 0
// Default settings in "Auto-park Mode"
#define TOOLCHANGE_PARK_ZLIFT 0.2 // the distance to raise Z axis when parking an extruder
#define TOOLCHANGE_UNPARK_ZLIFT 1 // the distance to raise Z axis when unparking an extruder
// Default x offset in duplication mode (typically set to half print bed width)
#define DEFAULT_DUPLICATION_X_OFFSET 100
#endif //DUAL_X_CARRIAGE
//homing hits the endstop, then retracts by this distance, before it tries to slowly bump again:
#define X_HOME_RETRACT_MM 5
#define Y_HOME_RETRACT_MM 5
#ifdef DELTA
#define Z_HOME_RETRACT_MM 5 // deltas need the same for all three axis
#else
#define Z_HOME_RETRACT_MM 2
#endif
#define HOMING_BUMP_DIVISOR {10, 10, 2} // Re-Bump Speed Divisor (Divides the Homing Feedrate)
#define HOMING_BUMP_DIVISOR {10, 10, 5} // Re-Bump Speed Divisor (Divides the Homing Feedrate)
//#define QUICK_HOME //if this is defined, if both x and y are to be homed, a diagonal move will be performed initially.
#define AXIS_RELATIVE_MODES {false, false, false, false}
#ifdef CONFIG_STEPPERS_TOSHIBA
#define MAX_STEP_FREQUENCY 10000 // Max step frequency for Toshiba Stepper Controllers
#else
#define MAX_STEP_FREQUENCY 40000
#endif
//By default pololu step drivers require an active high signal. However, some high power drivers require an active low signal as step.
#define INVERT_X_STEP_PIN false
#define INVERT_Y_STEP_PIN false
#define INVERT_Z_STEP_PIN false
#define INVERT_E_STEP_PIN false
//default stepper release if idle. Set to 0 to deactivate.
// Default stepper release if idle. Set to 0 to deactivate.
#define DEFAULT_STEPPER_DEACTIVE_TIME 60
#define DEFAULT_MINIMUMFEEDRATE 0.0 // minimum feedrate
#define DEFAULT_MINTRAVELFEEDRATE 0.0
// Feedrates for manual moves along X, Y, Z, E from panel
#ifdef ULTIPANEL
#define MANUAL_FEEDRATE {50*60, 50*60, 4*60, 60} // set the speeds for manual moves (mm/min)
#endif
//Comment to disable setting feedrate multiplier via encoder
#ifdef ULTIPANEL
#define ULTIPANEL_FEEDMULTIPLY
#define MANUAL_FEEDRATE {50*60, 50*60, 4*60, 60} // Feedrates for manual moves along X, Y, Z, E from panel
#define ULTIPANEL_FEEDMULTIPLY // Comment to disable setting feedrate multiplier via encoder
#endif
// minimum time in microseconds that a movement needs to take if the buffer is emptied.
#define DEFAULT_MINSEGMENTTIME 20000
// If defined the movements slow down when the look ahead buffer is only half full
#ifndef DELTA
#define SLOWDOWN
#endif
// Frequency limit
// See nophead's blog for more info
......@@ -267,13 +229,6 @@
// if unwanted behavior is observed on a user's machine when running at very slow speeds.
#define MINIMUM_PLANNER_SPEED 0.05// (mm/sec)
// MS1 MS2 Stepper Driver Microstepping mode table
#define MICROSTEP1 LOW,LOW
#define MICROSTEP2 HIGH,LOW
#define MICROSTEP4 LOW,HIGH
#define MICROSTEP8 HIGH,HIGH
#define MICROSTEP16 HIGH,HIGH
// Microstep setting (Only functional when stepper driver microstep pins are connected to MCU.
#define MICROSTEP_MODES {16,16,16,16,16} // [1,2,4,8,16]
......@@ -291,9 +246,9 @@
//=============================Additional Features===========================
//===========================================================================
#define ENCODER_RATE_MULTIPLIER // If defined, certain menu edit operations automatically multiply the steps when the encoder is moved quickly
#define ENCODER_10X_STEPS_PER_SEC 75 // If the encoder steps per sec exceed this value, multiple the steps moved by ten to quickly advance the value
#define ENCODER_100X_STEPS_PER_SEC 160 // If the encoder steps per sec exceed this value, multiple the steps moved by 100 to really quickly advance the value
#define ENCODER_RATE_MULTIPLIER // If defined, certain menu edit operations automatically multiply the steps when the encoder is moved quickly
#define ENCODER_10X_STEPS_PER_SEC 75 // If the encoder steps per sec exceeds this value, multiple the steps moved by ten to quickly advance the value
#define ENCODER_100X_STEPS_PER_SEC 160 // If the encoder steps per sec exceeds this value, multiple the steps moved by 100 to really quickly advance the value
//#define ENCODER_RATE_MULTIPLIER_DEBUG // If defined, output the encoder steps per second value
//#define CHDK 4 //Pin for triggering CHDK to take a picture see how to use it here http://captain-slow.dk/2014/03/09/3d-printing-timelapses/
......@@ -316,21 +271,11 @@
// Amount of time (ms) to show the status message
#define PROGRESS_BAR_MSG_TIME 3000
// Amount of time (ms) to retain the status message (0=forever)
#define PROGRESS_BAR_MSG_EXPIRE 0
#define PROGRESS_MSG_EXPIRE 0
// Enable this to show messages for MSG_TIME then hide them
//#define PROGRESS_BAR_MSG_ONCE
#ifdef DOGLCD
#warning LCD_PROGRESS_BAR does not apply to graphical displays at this time.
#endif
#ifdef FILAMENT_LCD_DISPLAY
#error LCD_PROGRESS_BAR and FILAMENT_LCD_DISPLAY are not fully compatible. Comment out this line to use both.
#endif
#ifdef POWER_CONSUMPTION_LCD_DISPLAY
#error LCD_PROGRESS_BAR and POWER_CONSUMPTION_LCD_DISPLAY are not fully compatible. Comment out this line to use both.
#endif
//#define PROGRESS_MSG_ONCE
#endif
// The hardware watchdog should reset the microcontroller disabling all outputs, in case the firmware gets stuck and doesn't do temperature regulation.
//#define USE_WATCHDOG
......@@ -352,16 +297,6 @@
#define BABYSTEP_XY //not only z, but also XY in the menu. more clutter, more functions
#define BABYSTEP_INVERT_Z false //true for inverse movements in Z
#define BABYSTEP_Z_MULTIPLICATOR 2 //faster z movements
#ifdef COREXY
#error BABYSTEPPING not implemented for COREXY yet.
#endif
#ifdef DELTA
#ifdef BABYSTEP_XY
#error BABYSTEPPING only implemented for Z axis on deltabots.
#endif
#endif
#endif
// extruder advance constant (s2/mm3)
......@@ -375,12 +310,8 @@
#ifdef ADVANCE
#define EXTRUDER_ADVANCE_K .0
#define D_FILAMENT 2.85
#define STEPS_MM_E 836
#define EXTRUSION_AREA (0.25 * D_FILAMENT * D_FILAMENT * 3.14159)
#define STEPS_PER_CUBIC_MM_E (axis_steps_per_unit[E_AXIS]/ EXTRUSION_AREA)
#endif // ADVANCE
// Arc interpretation settings:
......@@ -395,26 +326,6 @@ const unsigned int dropsegments=5; //everything with less than this number of st
// be commented out otherwise
#define SDCARDDETECTINVERTED
#ifdef ULTIPANEL
#undef SDCARDDETECTINVERTED
#endif
// Power Signal Control Definitions
// By default use Normal definition
#ifndef POWER_SUPPLY
#define POWER_SUPPLY 0
#endif
// 0 = Normal - 1 = ATX
#if (POWER_SUPPLY <= 1)
#define PS_ON_AWAKE LOW
#define PS_ON_ASLEEP HIGH
#endif
// 2 = X-Box 360 203W
#if (POWER_SUPPLY == 2)
#define PS_ON_AWAKE HIGH
#define PS_ON_ASLEEP LOW
#endif
// Control heater 0 and heater 1 in parallel.
//#define HEATERS_PARALLEL
......@@ -424,7 +335,7 @@ const unsigned int dropsegments=5; //everything with less than this number of st
// The number of linear motions that can be in the plan at any give time.
// THE BLOCK_BUFFER_SIZE NEEDS TO BE A POWER OF 2, i.g. 8,16,32 because shifts and ors are used to do the ring-buffering.
#if defined SDSUPPORT
#ifdef SDSUPPORT
#define BLOCK_BUFFER_SIZE 16 // SD,LCD,Buttons take more memory, block buffer needs to be smaller
#else
#define BLOCK_BUFFER_SIZE 16 // maximize block buffer
......@@ -444,23 +355,23 @@ const unsigned int dropsegments=5; //everything with less than this number of st
//#define FWRETRACT //ONLY PARTIALLY TESTED
#ifdef FWRETRACT
#define MIN_RETRACT 0.1 //minimum extruded mm to accept a automatic gcode retraction attempt
#define RETRACT_LENGTH 3 //default retract length (positive mm)
#define RETRACT_LENGTH_SWAP 13 //default swap retract length (positive mm), for extruder change
#define RETRACT_FEEDRATE 45 //default feedrate for retracting (mm/s)
#define RETRACT_ZLIFT 0 //default retract Z-lift
#define RETRACT_RECOVER_LENGTH 0 //default additional recover length (mm, added to retract length when recovering)
#define RETRACT_RECOVER_LENGTH_SWAP 0 //default additional swap recover length (mm, added to retract length when recovering from extruder change)
#define RETRACT_RECOVER_FEEDRATE 80 //default feedrate for recovering from retraction (mm/s)
#define MIN_RETRACT 0.1 //minimum extruded mm to accept a automatic gcode retraction attempt
#define RETRACT_LENGTH 3 //default retract length (positive mm)
#define RETRACT_LENGTH_SWAP 13 //default swap retract length (positive mm), for extruder change
#define RETRACT_FEEDRATE 45 //default feedrate for retracting (mm/s)
#define RETRACT_ZLIFT 0 //default retract Z-lift
#define RETRACT_RECOVER_LENGTH 0 //default additional recover length (mm, added to retract length when recovering)
#define RETRACT_RECOVER_LENGTH_SWAP 0 //default additional swap recover length (mm, added to retract length when recovering from extruder change)
#define RETRACT_RECOVER_FEEDRATE 8 //default feedrate for recovering from retraction (mm/s)
#endif
//adds support for experimental filament exchange support M600; requires display
// Add support for experimental filament exchange support M600; requires display
#ifdef ULTIPANEL
#define FILAMENTCHANGEENABLE
#ifdef FILAMENTCHANGEENABLE
#define FILAMENTCHANGE_XPOS 3
#define FILAMENTCHANGE_YPOS 3
#define FILAMENTCHANGE_ZADD 5
#define FILAMENTCHANGE_ZADD 10
#define FILAMENTCHANGE_FIRSTRETRACT -2
#define FILAMENTCHANGE_FINALRETRACT -100
#endif
......@@ -606,76 +517,7 @@ const unsigned int dropsegments=5; //everything with less than this number of st
#endif
#include "Conditionals.h"
#include "SanityCheck.h"
//===========================================================================
//============================= Define Defines ============================
//===========================================================================
#if EXTRUDERS > 1 && defined TEMP_SENSOR_1_AS_REDUNDANT
#error "You cannot use TEMP_SENSOR_1_AS_REDUNDANT if EXTRUDERS > 1"
#endif
#if EXTRUDERS > 1 && defined HEATERS_PARALLEL
#error "You cannot use HEATERS_PARALLEL if EXTRUDERS > 1"
#endif
#if TEMP_SENSOR_0 > 0
#define THERMISTORHEATER_0 TEMP_SENSOR_0
#define HEATER_0_USES_THERMISTOR
#endif
#if TEMP_SENSOR_1 > 0
#define THERMISTORHEATER_1 TEMP_SENSOR_1
#define HEATER_1_USES_THERMISTOR
#endif
#if TEMP_SENSOR_2 > 0
#define THERMISTORHEATER_2 TEMP_SENSOR_2
#define HEATER_2_USES_THERMISTOR
#endif
#if TEMP_SENSOR_3 > 0
#define THERMISTORHEATER_3 TEMP_SENSOR_3
#define HEATER_3_USES_THERMISTOR
#endif
#if TEMP_SENSOR_BED > 0
#define THERMISTORBED TEMP_SENSOR_BED
#define BED_USES_THERMISTOR
#endif
#if TEMP_SENSOR_0 == -1
#define HEATER_0_USES_AD595
#endif
#if TEMP_SENSOR_1 == -1
#define HEATER_1_USES_AD595
#endif
#if TEMP_SENSOR_2 == -1
#define HEATER_2_USES_AD595
#endif
#if TEMP_SENSOR_3 == -1
#define HEATER_3_USES_AD595
#endif
#if TEMP_SENSOR_BED == -1
#define BED_USES_AD595
#endif
#if TEMP_SENSOR_0 == -2
#define HEATER_0_USES_MAX6675
#endif
#if TEMP_SENSOR_0 == 0
#undef HEATER_0_MINTEMP
#undef HEATER_0_MAXTEMP
#endif
#if TEMP_SENSOR_1 == 0
#undef HEATER_1_MINTEMP
#undef HEATER_1_MAXTEMP
#endif
#if TEMP_SENSOR_2 == 0
#undef HEATER_2_MINTEMP
#undef HEATER_2_MAXTEMP
#endif
#if TEMP_SENSOR_3 == 0
#undef HEATER_3_MINTEMP
#undef HEATER_3_MAXTEMP
#endif
#if TEMP_SENSOR_BED == 0
#undef BED_MINTEMP
#undef BED_MAXTEMP
#endif
#endif //__CONFIGURATION_ADV_H
#endif //CONFIGURATION_ADV_H
// Tonokip RepRap firmware rewrite based off of Hydra-mmm firmware.
// License: GPL
#ifndef __MARLIN_H
#define __MARLIN_H
#ifndef MARLIN_H
#define MARLIN_H
#define FORCE_INLINE __attribute__((always_inline)) inline
......@@ -22,16 +22,6 @@
#include "Configuration.h"
#include "pins.h"
#ifndef AT90USB
#define HardwareSerial_h // trick to disable the standard HWserial
#endif
#if (ARDUINO >= 100)
#include "Arduino.h"
#else
#include "WProgram.h"
#endif
#define BIT(b) (1<<(b))
#define TEST(n,b) (((n)&BIT(b))!=0)
......@@ -186,7 +176,7 @@ void manage_inactivity(bool ignore_stepper_queue=false);
#define disable_e() {disable_e0(); disable_e1(); disable_e2(); disable_e3();}
#ifdef COREXY
enum AxisEnum {X_AXIS=0, Y_AXIS=1, Z_AXIS=2, E_AXIS=3, X_HEAD=4, Y_HEAD=5};
enum AxisEnum {X_AXIS=0, Y_AXIS=1, A_AXIS=0, B_AXIS=1, Z_AXIS=2, E_AXIS=3, X_HEAD=4, Y_HEAD=5};
//X_HEAD and Y_HEAD is used for systems that don't have a 1:1 relationship between X_AXIS and X Head movement, like CoreXY bots.
#else
enum AxisEnum {X_AXIS=0, Y_AXIS=1, Z_AXIS=2, E_AXIS=3};
......@@ -234,7 +224,7 @@ void clamp_to_software_endstops(float target[3]);
void refresh_cmd_timeout(void);
#ifdef FAST_PWM_FAN
void setPwmFrequency(uint8_t pin, int val);
void setPwmFrequency(uint8_t pin, int val);
#endif
#ifndef CRITICAL_SECTION_START
......@@ -265,21 +255,19 @@ extern float home_offset[3];
#endif // HOTENDS > 1
#ifdef NPR2
extern int old_color; // old color for system NPR2
extern int old_color; // old color for system NPR2
#endif
#ifdef DELTA
extern float z_probe_offset[3];
extern float endstop_adj[3];
extern float tower_adj[6];
extern float delta_radius;
extern float delta_diagonal_rod;
//*extern float Z_MAX_POS;
//*extern float Z_MAX_LENGTH;
extern float z_probe_offset[3];
extern float endstop_adj[3];
extern float tower_adj[6];
extern float delta_radius;
extern float delta_diagonal_rod;
#endif
#ifdef SCARA
extern float axis_scaling[3]; // Build size scaling
extern float axis_scaling[3]; // Build size scaling
#endif
extern float min_pos[3];
......@@ -290,15 +278,15 @@ extern float zprobe_zoffset;
extern int fanSpeed;
#ifdef BARICUDA
extern int ValvePressure;
extern int EtoPPressure;
extern int ValvePressure;
extern int EtoPPressure;
#endif
#ifdef FAN_SOFT_PWM
extern unsigned char fanSpeedSoftPwm;
#endif
#if (defined(FILAMENT_SENSOR) && defined(FILWIDTH_PIN) && FILWIDTH_PIN >= 0)
#if defined(FILAMENT_SENSOR) && defined(FILWIDTH_PIN) && (FILWIDTH_PIN >= 0)
extern float filament_width_nominal; //holds the theoretical filament diameter ie., 3.00 or 1.75
extern bool filament_sensor; //indicates that filament sensor readings should control extrusion
extern float filament_width_meas; //holds the filament diameter as accurately measured
......@@ -309,23 +297,23 @@ extern unsigned char fanSpeedSoftPwm;
#endif
#if (defined(POWER_CONSUMPTION) && defined(POWER_CONSUMPTION_PIN) && POWER_CONSUMPTION_PIN >= 0)
extern unsigned int power_consumption_meas; //holds the power consumption as accurately measured
extern float power_consumption_meas; //holds the power consumption as accurately measured
extern unsigned long power_consumption_hour; //holds the power consumption per hour as accurately measured
#endif
#ifdef FWRETRACT
extern bool autoretract_enabled;
extern bool retracted[EXTRUDERS];
extern float retract_length, retract_length_swap, retract_feedrate, retract_zlift;
extern float retract_recover_length, retract_recover_length_swap, retract_recover_feedrate;
extern bool autoretract_enabled;
extern bool retracted[EXTRUDERS];
extern float retract_length, retract_length_swap, retract_feedrate, retract_zlift;
extern float retract_recover_length, retract_recover_length_swap, retract_recover_feedrate;
#endif
#ifdef EASY_LOAD
extern bool allow_lengthy_extrude_once; // for load/unload
extern bool allow_lengthy_extrude_once; // for load/unload
#endif
#ifdef LASERBEAM
extern int laser_ttl_modulation;
extern int laser_ttl_modulation;
#endif
extern unsigned long starttime;
......@@ -336,21 +324,20 @@ extern uint8_t active_extruder;
extern uint8_t active_driver;
#ifdef DIGIPOT_I2C
extern void digipot_i2c_set_current( int channel, float current );
extern void digipot_i2c_init();
extern void digipot_i2c_set_current( int channel, float current );
extern void digipot_i2c_init();
#endif
// Debug with repetier
extern uint8_t debugLevel;
extern inline bool debugDryrun()
{
return ((debugLevel & 8)!=0);
extern inline bool debugDryrun() {
return ((debugLevel & 8) != 0);
}
#ifdef FIRMWARE_TEST
void FirmwareTest();
void FirmwareTest();
#endif
extern void calculate_volumetric_multipliers();
#endif //__MARLIN_H
#endif //MARLIN_H
This source diff could not be displayed because it is too large. You can view the blob instead.
/**
* SanityCheck.h
*
* Test configuration values for errors at compile-time.
*/
#ifndef SANITYCHECK_H
#define SANITYCHECK_H
/**
* Dual Stepper Drivers
*/
#if defined(Z_DUAL_STEPPER_DRIVERS) && defined(Y_DUAL_STEPPER_DRIVERS)
#error You cannot have dual stepper drivers for both Y and Z.
#endif
/**
* Progress Bar
*/
#ifdef LCD_PROGRESS_BAR
#ifdef DOGLCD
#warning LCD_PROGRESS_BAR does not apply to graphical displays.
#endif
#ifdef FILAMENT_LCD_DISPLAY
#error LCD_PROGRESS_BAR and FILAMENT_LCD_DISPLAY are not fully compatible. Comment out this line to use both.
#endif
#ifdef POWER_CONSUMPTION_LCD_DISPLAY
#error LCD_PROGRESS_BAR and POWER_CONSUMPTION_LCD_DISPLAY are not fully compatible. Comment out this line to use both.
#endif
#endif
/**
* Babystepping
*/
#ifdef BABYSTEPPING
#ifdef COREXY
#error BABYSTEPPING not implemented for COREXY yet.
#endif
#ifdef SCARA
#error BABYSTEPPING is not implemented for SCARA yet.
#endif
#if defined(DELTA) && defined(BABYSTEP_XY)
#error BABYSTEPPING only implemented for Z axis on deltabots.
#endif
#endif
/**
* Filament Change with Extruder Runout Prevention
*/
#if defined(FILAMENTCHANGEENABLE) && defined(EXTRUDER_RUNOUT_PREVENT)
#error EXTRUDER_RUNOUT_PREVENT currently incompatible with FILAMENTCHANGE.
#endif
/**
* Extruder Runout Prevention
*/
#if defined(EXTRUDER_RUNOUT_PREVENT) && EXTRUDER_RUNOUT_MINTEMP < EXTRUDE_MINTEMP
#error EXTRUDER_RUNOUT_MINTEMP have to be greater than EXTRUDE_MINTEMP
#endif
/**
* Idle oozing prevent with Extruder Runout Prevention
*/
#if defined(EXTRUDER_RUNOUT_PREVENT) && defined(IDLE_OOZING_PREVENT)
#error EXTRUDER_RUNOUT_PREVENT and IDLE_OOZING_PREVENT are incopatible. Please comment one of them.
#endif
/**
* Idle oozing prevent
*/
#if defined(IDLE_OOZING_PREVENT) && IDLE_OOZING_MINTEMP < EXTRUDE_MINTEMP
#error IDLE_OOZING_MINTEMP have to be greater than EXTRUDE_MINTEMP
#endif
/**
* Options only for EXTRUDERS == 1
*/
#if EXTRUDERS > 1
#if EXTRUDERS > 4
#error The maximum number of EXTRUDERS is 4.
#endif
#ifdef TEMP_SENSOR_1_AS_REDUNDANT
#error EXTRUDERS must be 1 with TEMP_SENSOR_1_AS_REDUNDANT.
#endif
#ifdef HEATERS_PARALLEL
#error EXTRUDERS must be 1 with HEATERS_PARALLEL.
#endif
#ifdef Y_DUAL_STEPPER_DRIVERS
#error EXTRUDERS must be 1 with Y_DUAL_STEPPER_DRIVERS.
#endif
#ifdef Z_DUAL_STEPPER_DRIVERS
#error EXTRUDERS must be 1 with Z_DUAL_STEPPER_DRIVERS.
#endif
#endif // EXTRUDERS > 1
/**
* Required LCD language
*/
#if !defined(DOGLCD) && defined(ULTRA_LCD) && !defined(DISPLAY_CHARSET_HD44780_JAPAN) && !defined(DISPLAY_CHARSET_HD44780_WESTERN)
#error You must enable either DISPLAY_CHARSET_HD44780_JAPAN or DISPLAY_CHARSET_HD44780_WESTERN for your LCD controller.
#endif
/**
* Auto Bed Leveling
*/
#ifdef ENABLE_AUTO_BED_LEVELING
/**
* Require a Z Min pin
*/
#if Z_MIN_PIN == -1
#ifdef Z_PROBE_REPEATABILITY_TEST
#error You must have a Z_MIN endstop to enable Z_PROBE_REPEATABILITY_TEST.
#else
#error ENABLE_AUTO_BED_LEVELING requires a Z_MIN endstop. Z_MIN_PIN must point to a valid hardware pin.
#endif
#endif
/**
* Check if Probe_Offset * Grid Points is greater than Probing Range
*/
#ifdef AUTO_BED_LEVELING_GRID
// Make sure probing points are reachable
#if LEFT_PROBE_BED_POSITION < MIN_PROBE_X
#error The given LEFT_PROBE_BED_POSITION can't be reached by the probe.
#elif RIGHT_PROBE_BED_POSITION > MAX_PROBE_X
#error The given RIGHT_PROBE_BED_POSITION can't be reached by the probe.
#elif FRONT_PROBE_BED_POSITION < MIN_PROBE_Y
#error The given FRONT_PROBE_BED_POSITION can't be reached by the probe.
#elif BACK_PROBE_BED_POSITION > MAX_PROBE_Y
#error The given BACK_PROBE_BED_POSITION can't be reached by the probe.
#endif
#define PROBE_SIZE_X (X_PROBE_OFFSET_FROM_EXTRUDER * (AUTO_BED_LEVELING_GRID_POINTS-1))
#define PROBE_SIZE_Y (Y_PROBE_OFFSET_FROM_EXTRUDER * (AUTO_BED_LEVELING_GRID_POINTS-1))
#define PROBE_AREA_WIDTH (RIGHT_PROBE_BED_POSITION - LEFT_PROBE_BED_POSITION)
#define PROBE_AREA_DEPTH (BACK_PROBE_BED_POSITION - FRONT_PROBE_BED_POSITION)
#if X_PROBE_OFFSET_FROM_EXTRUDER < 0
#if PROBE_SIZE_X <= -PROBE_AREA_WIDTH
#define X_PROBE_ERROR
#endif
#elif PROBE_SIZE_X >= PROBE_AREA_WIDTH
#define X_PROBE_ERROR
#endif
#ifdef X_PROBE_ERROR
#error The X axis probing range is too small to fit all the points defined in AUTO_BED_LEVELING_GRID_POINTS
#endif
#if Y_PROBE_OFFSET_FROM_EXTRUDER < 0
#if PROBE_SIZE_Y <= -PROBE_AREA_DEPTH
#define Y_PROBE_ERROR
#endif
#elif PROBE_SIZE_Y >= PROBE_AREA_DEPTH
#define Y_PROBE_ERROR
#endif
#ifdef Y_PROBE_ERROR
#error The Y axis probing range is to small to fit all the points defined in AUTO_BED_LEVELING_GRID_POINTS
#endif
#undef PROBE_SIZE_X
#undef PROBE_SIZE_Y
#undef PROBE_AREA_WIDTH
#undef PROBE_AREA_DEPTH
#else // !AUTO_BED_LEVELING_GRID
// Check the triangulation points
#if ABL_PROBE_PT_1_X < MIN_PROBE_X || ABL_PROBE_PT_1_X > MAX_PROBE_X
#error "The given ABL_PROBE_PT_1_X can't be reached by the probe."
#elif ABL_PROBE_PT_2_X < MIN_PROBE_X || ABL_PROBE_PT_2_X > MAX_PROBE_X
#error "The given ABL_PROBE_PT_2_X can't be reached by the probe."
#elif ABL_PROBE_PT_3_X < MIN_PROBE_X || ABL_PROBE_PT_3_X > MAX_PROBE_X
#error "The given ABL_PROBE_PT_3_X can't be reached by the probe."
#elif ABL_PROBE_PT_1_Y < MIN_PROBE_Y || ABL_PROBE_PT_1_Y > MAX_PROBE_Y
#error "The given ABL_PROBE_PT_1_Y can't be reached by the probe."
#elif ABL_PROBE_PT_2_Y < MIN_PROBE_Y || ABL_PROBE_PT_2_Y > MAX_PROBE_Y
#error "The given ABL_PROBE_PT_2_Y can't be reached by the probe."
#elif ABL_PROBE_PT_3_Y < MIN_PROBE_Y || ABL_PROBE_PT_3_Y > MAX_PROBE_Y
#error "The given ABL_PROBE_PT_3_Y can't be reached by the probe."
#endif
#endif // !AUTO_BED_LEVELING_GRID
#endif // ENABLE_AUTO_BED_LEVELING
/**
* ULTIPANEL encoder
*/
#if defined(ULTIPANEL) && !defined(NEWPANEL) && !defined(SR_LCD_2W_NL) && !defined(SHIFT_CLK)
#error ULTIPANEL requires some kind of encoder.
#endif
/**
* Delta has limited bed leveling options
*/
#ifdef DELTA
#ifdef ENABLE_AUTO_BED_LEVELING
#ifndef AUTO_BED_LEVELING_GRID
#error Only AUTO_BED_LEVELING_GRID is supported with DELTA.
#endif
#ifdef Z_PROBE_SLED
#error You cannot use Z_PROBE_SLED with DELTA.
#endif
#ifdef Z_PROBE_REPEATABILITY_TEST
#error Z_PROBE_REPEATABILITY_TEST is not supported with DELTA yet.
#endif
#endif
#endif
/**
* Allen Key Z Probe requires Auto Bed Leveling grid and Delta
*/
#if defined(Z_PROBE_ALLEN_KEY) && !(defined(AUTO_BED_LEVELING_GRID) && defined(DELTA))
#error Invalid use of Z_PROBE_ALLEN_KEY.
#endif
/**
* Dual X Carriage requirements
*/
#ifdef DUAL_X_CARRIAGE
#if EXTRUDERS == 1 || defined(COREXY) \
|| !defined(X2_ENABLE_PIN) || !defined(X2_STEP_PIN) || !defined(X2_DIR_PIN) \
|| !defined(X2_HOME_POS) || !defined(X2_MIN_POS) || !defined(X2_MAX_POS) \
|| !defined(X_MAX_PIN) || X_MAX_PIN < 0
#error Missing or invalid definitions for DUAL_X_CARRIAGE mode.
#endif
#if X_HOME_DIR != -1 || X2_HOME_DIR != 1
#error Please use canonical x-carriage assignment.
#endif
#endif // DUAL_X_CARRIAGE
/**
* Make sure auto fan pins don't conflict with the fan pin
*/
#if HAS_AUTO_FAN && HAS_FAN
#if EXTRUDER_0_AUTO_FAN_PIN == FAN_PIN
#error You cannot set EXTRUDER_0_AUTO_FAN_PIN equal to FAN_PIN
#elif EXTRUDER_1_AUTO_FAN_PIN == FAN_PIN
#error You cannot set EXTRUDER_1_AUTO_FAN_PIN equal to FAN_PIN
#elif EXTRUDER_2_AUTO_FAN_PIN == FAN_PIN
#error You cannot set EXTRUDER_2_AUTO_FAN_PIN equal to FAN_PIN
#elif EXTRUDER_3_AUTO_FAN_PIN == FAN_PIN
#error You cannot set EXTRUDER_3_AUTO_FAN_PIN equal to FAN_PIN
#endif
#endif
/**
* Test required HEATER defines
*/
#if HOTENDS > 3
#if !HAS_HEATER_3
#error HEATER_3_PIN not defined for this board
#endif
#elif HOTENDS > 2
#if !HAS_HEATER_2
#error HEATER_2_PIN not defined for this board
#endif
#elif HOTENDS > 1 || defined(HEATERS_PARALLEL)
#if !HAS_HEATER_1
#error HEATER_1_PIN not defined for this board
#endif
#endif
#if !HAS_HEATER_0
#error HEATER_0_PIN not defined for this board
#endif
#endif //SANITYCHECK_H
......@@ -33,9 +33,7 @@ struct pin_map_t {
uint8_t bit;
};
//------------------------------------------------------------------------------
#if defined(__AVR_ATmega1280__)\
|| defined(__AVR_ATmega2560__)
// Mega
#if defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__) // Mega
// Two Wire (aka I2C) ports
uint8_t const SDA_PIN = 20; // D1
......@@ -43,6 +41,7 @@ uint8_t const SCL_PIN = 21; // D0
#undef MOSI_PIN
#undef MISO_PIN
#undef SCK_PIN
// SPI port
uint8_t const SS_PIN = 53; // B0
uint8_t const MOSI_PIN = 51; // B2
......
......@@ -14,7 +14,7 @@
#ifndef DOGM_LCD_IMPLEMENTATION_H
#define DOGM_LCD_IMPLEMENTATION_H
#define MARLIN_VERSION " 4.0.3"
#define MARLIN_VERSION " 4.0.7"
/**
* Implementation of the LCD display routines for a DOGM128 graphic display. These are common LCD 128x64 pixel graphic displays.
......@@ -267,7 +267,7 @@ static void lcd_implementation_status_screen() {
// Status line
u8g.setFont(FONT_STATUSMENU);
u8g.setPrintPos(0,63);
#if (defined(FILAMENT_SENSOR) && defined(FILWIDTH_PIN) && FILWIDTH_PIN >= 0) && defined(FILAMENT_LCD_DISPLAY) || (defined(POWER_CONSUMPTION) && defined(POWER_CONSUMPTION_PIN) && POWER_CONSUMPTION_PIN >= 0) && defined(POWER_CONSUMPTION_LCD_DISPLAY)
#if defined(FILAMENT_SENSOR) && defined(FILWIDTH_PIN) && (FILWIDTH_PIN >= 0) && defined(FILAMENT_LCD_DISPLAY) || (defined(POWER_CONSUMPTION) && defined(POWER_CONSUMPTION_PIN) && (POWER_CONSUMPTION_PIN >= 0) && defined(POWER_CONSUMPTION_LCD_DISPLAY))
if (millis() < message_millis + 5000) { //Display both Status message line and Filament display on the last line
u8g.print(lcd_status_message);
}
......@@ -279,7 +279,7 @@ static void lcd_implementation_status_screen() {
#endif
{
lcd_printPGM(PSTR("P:"));
u8g.print(itostr3(power_consumption_meas));
u8g.print(ftostr31(power_consumption_meas));
lcd_printPGM(PSTR("W C:"));
u8g.print(ltostr7(power_consumption_hour));
lcd_printPGM(PSTR("Wh"));
......
......@@ -115,6 +115,7 @@
#define MSG_Y_MAX "y_max: "
#define MSG_Z_MIN "z_min: "
#define MSG_Z_MAX "z_max: "
#define MSG_Z2_MAX "z2_max: "
#define MSG_E_MIN "e_min: "
#define MSG_PAUSE_PIN "pause pin: "
#define MSG_M119_REPORT "Reporting endstop status"
......@@ -226,8 +227,6 @@
#define STR_h3 "\263"
#define STR_Deg "\337"
#define STR_THERMOMETER "\002"
#elif defined(ULTRA_LCD)
#error You must enable either DISPLAY_CHARSET_HD44780_JAPAN or DISPLAY_CHARSET_HD44780_WESTERN for your LCD controller.
#endif
#endif
/*
......
......@@ -56,9 +56,9 @@
#define MSG_FAN_SPEED "Lüftergeschw."
#define MSG_FLOW "Fluss"
#define MSG_CONTROL "Einstellungen"
#define MSG_MIN "\002 Min"
#define MSG_MAX "\002 Max"
#define MSG_FACTOR "\002 Faktor"
#define MSG_MIN STR_THERMOMETER " Min"
#define MSG_MAX STR_THERMOMETER " Max"
#define MSG_FACTOR STR_THERMOMETER " Faktor"
#define MSG_AUTOTEMP "AutoTemp"
#define MSG_ON "Ein"
#define MSG_OFF "Aus"
......@@ -76,7 +76,7 @@
#define MSG_E "e"
#define MSG_VMIN "Vmin"
#define MSG_VTRAV_MIN "VTrav min"
#define MSG_AMAX "Amax "
#define MSG_AMAX "A max"
#define MSG_A_RETRACT "A-Retract"
#define MSG_A_TRAVEL "A-travel"
#define MSG_XSTEPS "X steps/mm"
......@@ -89,7 +89,7 @@
#define MSG_TEMPERATURE "Temperatur"
#define MSG_MOTION "Bewegung"
#define MSG_VOLUMETRIC "Filament"
#define MSG_VOLUMETRIC_ENABLED "E in mm3"
#define MSG_VOLUMETRIC_ENABLED "E in mm" STR_h3
#define MSG_FILAMENT_SIZE_EXTRUDER "Fil. Dia."
#define MSG_CONTRAST "LCD contrast"
#define MSG_STORE_EPROM "EPROM speichern"
......
......@@ -65,6 +65,9 @@
#define MSG_PID_P "PID-P"
#define MSG_PID_I "PID-I"
#define MSG_PID_D "PID-D"
#define MSG_E2 " E2"
#define MSG_E3 " E3"
#define MSG_E4 " E4"
#define MSG_ACC "Accel"
#define MSG_VXY_JERK "Vxy-jerk"
#define MSG_VZ_JERK "Vz-jerk"
......
......@@ -36,7 +36,7 @@
#define MSG_PREHEAT_GUM "Preriscalda GOMMA"
#define MSG_PREHEAT_GUM_ALL "Preri. GOMMA Tutto"
#define MSG_PREHEAT_GUM_BEDONLY "Preri. GOMMA Piatto"
#define MSG_PREHEAT_GUM_SETTINGS "Preris. GOMMA Conf"
#define MSG_PREHEAT_GUM_SETTINGS "Config. prer. GOMMA"
#define MSG_COOLDOWN "Raffredda"
#define MSG_SWITCH_PS_ON "Accendi aliment."
#define MSG_SWITCH_PS_OFF "Spegni aliment."
......@@ -65,6 +65,9 @@
#define MSG_PID_P "PID-P"
#define MSG_PID_I "PID-I"
#define MSG_PID_D "PID-D"
#define MSG_E2 " E2"
#define MSG_E3 " E3"
#define MSG_E4 " E4"
#define MSG_ACC "Accel."
#define MSG_VXY_JERK "Vxy-jerk"
#define MSG_VZ_JERK "Vz-jerk"
......
......@@ -979,9 +979,9 @@
#define SHIFT_CLK 44 // shift register
#define SHIFT_LD 42 // shift register
#elif defined(PANEL_ONE)
#define BTN_EN1 59 // AUX2 PIN 3
#define BTN_EN2 63 // AUX2 PIN 4
#define BTN_ENC 49 // AUX3 PIN 7
#define BTN_EN1 59 // AUX2 PIN 3
#define BTN_EN2 63 // AUX2 PIN 4
#define BTN_ENC 49 // AUX3 PIN 7
#else
#define BTN_EN1 37
#define BTN_EN2 35
......@@ -4450,7 +4450,7 @@ DaveX plan for Teensylu/printrboard-type pinouts (ref teensylu & sprinter) for a
************************************* FEATURE *******************************************
****************************************************************************************/
#ifdef SINGLENOZZLE
#if HOTENDS == 1
#undef HEATER_1_PIN
#undef HEATER_2_PIN
#undef HEATER_3_PIN
......@@ -4463,7 +4463,21 @@ DaveX plan for Teensylu/printrboard-type pinouts (ref teensylu & sprinter) for a
#define TEMP_1_PIN -1
#define TEMP_2_PIN -1
#define TEMP_3_PIN -1
#endif //SINGLENOZZLE
#elif HOTENDS == 2
#undef HEATER_2_PIN
#undef HEATER_3_PIN
#define HEATER_2_PIN -1
#define HEATER_3_PIN -1
#undef TEMP_2_PIN
#undef TEMP_3_PIN
#define TEMP_2_PIN -1
#define TEMP_3_PIN -1
#elif HOTENDS == 3
#undef HEATER_3_PIN
#define HEATER_3_PIN -1
#undef TEMP_3_PIN
#define TEMP_3_PIN -1
#endif
#ifdef MKR4
#if (EXTRUDERS == 2) && (DRIVER_EXTRUDERS==1) // Use this for one driver and two extruder
......
......@@ -114,39 +114,25 @@ volatile unsigned char block_buffer_tail; // Index of the block to process now
float extrude_min_temp = EXTRUDE_MINTEMP;
#endif
#ifdef XY_FREQUENCY_LIMIT
#define MAX_FREQ_TIME (1000000.0/XY_FREQUENCY_LIMIT)
// Used for the frequency limit
static unsigned char old_direction_bits = 0; // Old direction bits. Used for speed calculations
static long x_segment_time[3]={MAX_FREQ_TIME + 1,0,0}; // Segment times (in us). Used for speed calculations
static long y_segment_time[3]={MAX_FREQ_TIME + 1,0,0};
// Used for the frequency limit
#define MAX_FREQ_TIME (1000000.0/XY_FREQUENCY_LIMIT)
// Old direction bits. Used for speed calculations
static unsigned char old_direction_bits = 0;
// Segment times (in us). Used for speed calculations
static long axis_segment_time[2][3] = { {MAX_FREQ_TIME+1,0,0}, {MAX_FREQ_TIME+1,0,0} };
#endif
#if (defined(FILAMENT_SENSOR) && defined(FILWIDTH_PIN) && FILWIDTH_PIN >= 0)
static char meas_sample; //temporary variable to hold filament measurement sample
#ifdef FILAMENT_SENSOR
static char meas_sample; //temporary variable to hold filament measurement sample
#endif
// Returns the index of the next block in the ring buffer
// NOTE: Removed modulo (%) operator, which uses an expensive divide and multiplication.
static int8_t next_block_index(int8_t block_index) {
block_index++;
if (block_index == BLOCK_BUFFER_SIZE) {
block_index = 0;
}
return(block_index);
}
// Returns the index of the previous block in the ring buffer
static int8_t prev_block_index(int8_t block_index) {
if (block_index == 0) {
block_index = BLOCK_BUFFER_SIZE;
}
block_index--;
return(block_index);
}
// Get the next / previous index of the next block in the ring buffer
// NOTE: Using & here (not %) because BLOCK_BUFFER_SIZE is always a power of 2
FORCE_INLINE int8_t next_block_index(int8_t block_index) { return BLOCK_MOD(block_index + 1); }
FORCE_INLINE int8_t prev_block_index(int8_t block_index) { return BLOCK_MOD(block_index - 1); }
//===========================================================================
//=============================functions ============================
//================================ Functions ================================
//===========================================================================
// Calculates the distance (not time) it takes to accelerate from initial_rate to target_rate using the
......@@ -201,15 +187,15 @@ void calculate_trapezoid_for_block(block_t *block, float entry_factor, float exi
// block->accelerate_until = accelerate_steps;
// block->decelerate_after = accelerate_steps+plateau_steps;
CRITICAL_SECTION_START; // Fill variables used by the stepper in a critical section
if(block->busy == false) { // Don't update variables if block is busy.
if (!block->busy) { // Don't update variables if block is busy.
block->accelerate_until = accelerate_steps;
block->decelerate_after = accelerate_steps+plateau_steps;
block->initial_rate = initial_rate;
block->final_rate = final_rate;
#ifdef ADVANCE
block->initial_advance = initial_advance;
block->final_advance = final_advance;
#endif //ADVANCE
#ifdef ADVANCE
block->initial_advance = initial_advance;
block->final_advance = final_advance;
#endif //ADVANCE
}
CRITICAL_SECTION_END;
}
......@@ -217,23 +203,12 @@ void calculate_trapezoid_for_block(block_t *block, float entry_factor, float exi
// Calculates the maximum allowable speed at this point when you must be able to reach target_velocity using the
// acceleration within the allotted distance.
FORCE_INLINE float max_allowable_speed(float acceleration, float target_velocity, float distance) {
return sqrt(target_velocity*target_velocity-2*acceleration*distance);
return sqrt(target_velocity * target_velocity - 2 * acceleration * distance);
}
// "Junction jerk" in this context is the immediate change in speed at the junction of two blocks.
// This method will calculate the junction jerk as the euclidean distance between the nominal
// velocities of the respective blocks.
//inline float junction_jerk(block_t *before, block_t *after) {
// return sqrt(
// pow((before->speed_x-after->speed_x), 2)+pow((before->speed_y-after->speed_y), 2));
//}
// The kernel called by planner_recalculate() when scanning the plan from last to first entry.
void planner_reverse_pass_kernel(block_t *previous, block_t *current, block_t *next) {
if(!current) {
return;
}
if (!current) return;
if (next) {
// If entry speed is already at the maximum entry speed, no need to recheck. Block is cruising.
......@@ -243,9 +218,9 @@ void planner_reverse_pass_kernel(block_t *previous, block_t *current, block_t *n
// If nominal length true, max junction speed is guaranteed to be reached. Only compute
// for max allowable speed if block is decelerating and nominal length is false.
if ((!current->nominal_length_flag) && (current->max_entry_speed > next->entry_speed)) {
current->entry_speed = min( current->max_entry_speed,
max_allowable_speed(-current->acceleration,next->entry_speed,current->millimeters));
if (!current->nominal_length_flag && current->max_entry_speed > next->entry_speed) {
current->entry_speed = min(current->max_entry_speed,
max_allowable_speed(-current->acceleration, next->entry_speed, current->millimeters));
}
else {
current->entry_speed = current->max_entry_speed;
......@@ -263,15 +238,14 @@ void planner_reverse_pass() {
//Make a local copy of block_buffer_tail, because the interrupt can alter it
CRITICAL_SECTION_START;
unsigned char tail = block_buffer_tail;
unsigned char tail = block_buffer_tail;
CRITICAL_SECTION_END
if(((block_buffer_head-tail + BLOCK_BUFFER_SIZE) & (BLOCK_BUFFER_SIZE - 1)) > 3) {
block_index = (block_buffer_head - 3) & (BLOCK_BUFFER_SIZE - 1);
block_t *block[3] = {
NULL, NULL, NULL };
while(block_index != tail) {
block_index = prev_block_index(block_index);
if (BLOCK_MOD(block_buffer_head - tail + BLOCK_BUFFER_SIZE) > 3) { // moves queued
block_index = BLOCK_MOD(block_buffer_head - 3);
block_t *block[3] = { NULL, NULL, NULL };
while (block_index != tail) {
block_index = prev_block_index(block_index);
block[2]= block[1];
block[1]= block[0];
block[0] = &block_buffer[block_index];
......@@ -282,9 +256,7 @@ void planner_reverse_pass() {
// The kernel called by planner_recalculate() when scanning the plan from first to last entry.
void planner_forward_pass_kernel(block_t *previous, block_t *current, block_t *next) {
if(!previous) {
return;
}
if (!previous) return;
// If the previous block is an acceleration block, but it is not long enough to complete the
// full speed change within the block, we need to adjust the entry speed accordingly. Entry
......@@ -292,8 +264,8 @@ void planner_forward_pass_kernel(block_t *previous, block_t *current, block_t *n
// If nominal length is true, max junction speed is guaranteed to be reached. No need to recheck.
if (!previous->nominal_length_flag) {
if (previous->entry_speed < current->entry_speed) {
double entry_speed = min( current->entry_speed,
max_allowable_speed(-previous->acceleration,previous->entry_speed,previous->millimeters) );
double entry_speed = min(current->entry_speed,
max_allowable_speed(-previous->acceleration, previous->entry_speed, previous->millimeters));
// Check for junction speed change
if (current->entry_speed != entry_speed) {
......@@ -304,18 +276,17 @@ void planner_forward_pass_kernel(block_t *previous, block_t *current, block_t *n
}
}
// planner_recalculate() needs to go over the current plan twice. Once in reverse and once forward. This
// planner_recalculate() needs to go over the current plan twice. Once in reverse and once forward. This
// implements the forward pass.
void planner_forward_pass() {
uint8_t block_index = block_buffer_tail;
block_t *block[3] = {
NULL, NULL, NULL };
block_t *block[3] = { NULL, NULL, NULL };
while(block_index != block_buffer_head) {
while (block_index != block_buffer_head) {
block[0] = block[1];
block[1] = block[2];
block[2] = &block_buffer[block_index];
planner_forward_pass_kernel(block[0],block[1],block[2]);
planner_forward_pass_kernel(block[0], block[1], block[2]);
block_index = next_block_index(block_index);
}
planner_forward_pass_kernel(block[1], block[2], NULL);
......@@ -329,24 +300,24 @@ void planner_recalculate_trapezoids() {
block_t *current;
block_t *next = NULL;
while(block_index != block_buffer_head) {
while (block_index != block_buffer_head) {
current = next;
next = &block_buffer[block_index];
if (current) {
// Recalculate if current block entry or exit junction speed has changed.
if (current->recalculate_flag || next->recalculate_flag) {
// NOTE: Entry and exit factors always > 0 by all previous logic operations.
calculate_trapezoid_for_block(current, current->entry_speed/current->nominal_speed,
next->entry_speed/current->nominal_speed);
float nom = current->nominal_speed;
calculate_trapezoid_for_block(current, current->entry_speed / nom, next->entry_speed / nom);
current->recalculate_flag = false; // Reset current only to ensure next trapezoid is computed
}
}
block_index = next_block_index( block_index );
}
// Last/newest block in buffer. Exit speed is set with MINIMUM_PLANNER_SPEED. Always recalculated.
if(next != NULL) {
calculate_trapezoid_for_block(next, next->entry_speed/next->nominal_speed,
MINIMUM_PLANNER_SPEED/next->nominal_speed);
if (next) {
float nom = next->nominal_speed;
calculate_trapezoid_for_block(next, next->entry_speed / nom, MINIMUM_PLANNER_SPEED / nom);
next->recalculate_flag = false;
}
}
......@@ -375,161 +346,130 @@ void planner_recalculate() {
}
void plan_init() {
block_buffer_head = 0;
block_buffer_tail = 0;
block_buffer_head = block_buffer_tail = 0;
memset(position, 0, sizeof(position)); // clear position
previous_speed[0] = 0.0;
previous_speed[1] = 0.0;
previous_speed[2] = 0.0;
previous_speed[3] = 0.0;
for (int i=0; i<NUM_AXIS; i++) previous_speed[i] = 0.0;
previous_nominal_speed = 0.0;
}
#ifdef AUTOTEMP
void getHighESpeed()
{
static float oldt=0;
if(!autotemp_enabled){
return;
}
if(degTargetHotend0()+2<autotemp_min) { //probably temperature set to zero.
return; //do nothing
}
void getHighESpeed() {
static float oldt = 0;
float high=0.0;
uint8_t block_index = block_buffer_tail;
if (!autotemp_enabled) return;
if (degTargetHotend0() + 2 < autotemp_min) return; // probably temperature set to zero.
while(block_index != block_buffer_head) {
if((block_buffer[block_index].steps_x != 0) ||
(block_buffer[block_index].steps_y != 0) ||
(block_buffer[block_index].steps_z != 0)) {
float se=(float(block_buffer[block_index].steps_e)/float(block_buffer[block_index].step_event_count))*block_buffer[block_index].nominal_speed;
//se; mm/sec;
if(se>high)
{
high=se;
float high = 0.0;
uint8_t block_index = block_buffer_tail;
while (block_index != block_buffer_head) {
block_t *block = &block_buffer[block_index];
if (block->steps[X_AXIS] || block->steps[Y_AXIS] || block->steps[Z_AXIS]) {
float se = (float)block->steps[E_AXIS] / block->step_event_count * block->nominal_speed; // mm/sec;
if (se > high) high = se;
}
block_index = next_block_index(block_index);
}
block_index = (block_index+1) & (BLOCK_BUFFER_SIZE - 1);
}
float g=autotemp_min+high*autotemp_factor;
float t=g;
if(t<autotemp_min)
t=autotemp_min;
if(t>autotemp_max)
t=autotemp_max;
if(oldt>t)
{
t=AUTOTEMP_OLDWEIGHT*oldt+(1-AUTOTEMP_OLDWEIGHT)*t;
float t = autotemp_min + high * autotemp_factor;
if (t < autotemp_min) t = autotemp_min;
if (t > autotemp_max) t = autotemp_max;
if (oldt > t) t = AUTOTEMP_OLDWEIGHT * oldt + (1 - AUTOTEMP_OLDWEIGHT) * t;
oldt = t;
setTargetHotend0(t);
}
oldt=t;
setTargetHotend0(t);
}
#endif
void check_axes_activity()
{
unsigned char x_active = 0;
unsigned char y_active = 0;
unsigned char z_active = 0;
unsigned char e_active = 0;
unsigned char tail_fan_speed = fanSpeed;
void check_axes_activity() {
unsigned char axis_active[NUM_AXIS],
tail_fan_speed = fanSpeed;
#ifdef BARICUDA
unsigned char tail_valve_pressure = ValvePressure;
unsigned char tail_e_to_p_pressure = EtoPPressure;
unsigned char tail_valve_pressure = ValvePressure,
tail_e_to_p_pressure = EtoPPressure;
#endif
#ifdef LASERBEAM
unsigned char tail_laser_ttl_modulation = laser_ttl_modulation;
unsigned char tail_laser_ttl_modulation = laser_ttl_modulation;
#endif
block_t *block;
if(block_buffer_tail != block_buffer_head)
{
if (blocks_queued()) {
uint8_t block_index = block_buffer_tail;
tail_fan_speed = block_buffer[block_index].fan_speed;
#ifdef BARICUDA
tail_valve_pressure = block_buffer[block_index].valve_pressure;
tail_e_to_p_pressure = block_buffer[block_index].e_to_p_pressure;
block = &block_buffer[block_index];
tail_valve_pressure = block->valve_pressure;
tail_e_to_p_pressure = block->e_to_p_pressure;
#endif
#ifdef LASERBEAM
tail_laser_ttl_modulation = block_buffer[block_index].laser_ttlmodulation;
tail_laser_ttl_modulation = block_buffer[block_index].laser_ttlmodulation;
#endif
while(block_index != block_buffer_head)
{
while (block_index != block_buffer_head) {
block = &block_buffer[block_index];
if(block->steps_x != 0) x_active++;
if(block->steps_y != 0) y_active++;
if(block->steps_z != 0) z_active++;
if(block->steps_e != 0) e_active++;
block_index = (block_index+1) & (BLOCK_BUFFER_SIZE - 1);
for (int i=0; i<NUM_AXIS; i++) if (block->steps[i]) axis_active[i]++;
block_index = next_block_index(block_index);
}
}
if((DISABLE_X) && (x_active == 0)) disable_x();
if((DISABLE_Y) && (y_active == 0)) disable_y();
if((DISABLE_Z) && (z_active == 0)) disable_z();
if((DISABLE_E) && (e_active == 0))
{
if (DISABLE_X && !axis_active[X_AXIS]) disable_x();
if (DISABLE_Y && !axis_active[Y_AXIS]) disable_y();
if (DISABLE_Z && !axis_active[Z_AXIS]) disable_z();
if (DISABLE_E && !axis_active[E_AXIS]) {
disable_e0();
disable_e1();
disable_e2();
disable_e2();
disable_e3();
}
#if defined(FAN_PIN) && FAN_PIN > -1
#ifdef FAN_KICKSTART_TIME
static unsigned long fan_kick_end;
if (tail_fan_speed) {
if (fan_kick_end == 0) {
// Just starting up fan - run at full power.
fan_kick_end = millis() + FAN_KICKSTART_TIME;
tail_fan_speed = 255;
} else if (fan_kick_end > millis())
// Fan still spinning up.
tail_fan_speed = 255;
} else {
fan_kick_end = 0;
}
#endif//FAN_KICKSTART_TIME
#ifdef FAN_SOFT_PWM
fanSpeedSoftPwm = tail_fan_speed;
#else
analogWrite(FAN_PIN,tail_fan_speed);
#endif//!FAN_SOFT_PWM
#endif//FAN_PIN > -1
#ifdef AUTOTEMP
getHighESpeed();
#endif
#ifdef BARICUDA
#if defined(HEATER_1_PIN) && HEATER_1_PIN > -1
analogWrite(HEATER_1_PIN,tail_valve_pressure);
#if defined(FAN_PIN) && FAN_PIN > -1 // HAS_FAN
#ifdef FAN_KICKSTART_TIME
static unsigned long fan_kick_end;
if (tail_fan_speed) {
if (fan_kick_end == 0) {
// Just starting up fan - run at full power.
fan_kick_end = millis() + FAN_KICKSTART_TIME;
tail_fan_speed = 255;
} else if (fan_kick_end > millis())
// Fan still spinning up.
tail_fan_speed = 255;
} else {
fan_kick_end = 0;
}
#endif//FAN_KICKSTART_TIME
#ifdef FAN_SOFT_PWM
fanSpeedSoftPwm = tail_fan_speed;
#else
analogWrite(FAN_PIN, tail_fan_speed);
#endif //!FAN_SOFT_PWM
#endif //FAN_PIN > -1
#ifdef AUTOTEMP
getHighESpeed();
#endif
#if defined(HEATER_2_PIN) && HEATER_2_PIN > -1
#ifdef BARICUDA
#if defined(HEATER_1_PIN) && HEATER_1_PIN > -1 // HAS_HEATER_1
analogWrite(HEATER_1_PIN,tail_valve_pressure);
#endif
#if defined(HEATER_2_PIN) && HEATER_2_PIN > -1 // HAS_HEATER_2
analogWrite(HEATER_2_PIN,tail_e_to_p_pressure);
#endif
#endif
#endif
// add Laser TTL Modulation(PWM) Control
#ifdef LASERBEAM
analogWrite(LASER_TTL_PIN, tail_laser_ttl_modulation);
#endif
// add Laser TTL Modulation(PWM) Control
#ifdef LASERBEAM
analogWrite(LASER_TTL_PIN, tail_laser_ttl_modulation);
#endif
}
float junction_deviation = 0.1;
// Add a new linear movement to the buffer. steps_x, _y and _z is the absolute position in
// Add a new linear movement to the buffer. steps[X_AXIS], _y and _z is the absolute position in
// mm. Microseconds specify how many microseconds the move should take to perform. To aid acceleration
// calculation the caller must also provide the physical length of the line in millimeters.
#ifdef ENABLE_AUTO_BED_LEVELING
void plan_buffer_line(float x, float y, float z, const float &e, float feed_rate, const uint8_t &extruder, const uint8_t &driver)
void plan_buffer_line(float x, float y, float z, const float &e, float feed_rate, const uint8_t &extruder, const uint8_t &driver)
#else
void plan_buffer_line(const float &x, const float &y, const float &z, const float &e, float feed_rate, const uint8_t &extruder, const uint8_t &driver)
void plan_buffer_line(const float &x, const float &y, const float &z, const float &e, float feed_rate, const uint8_t &extruder, const uint8_t &driver)
#endif //ENABLE_AUTO_BED_LEVELING
{
// Calculate the buffer head after we push this byte
......@@ -537,68 +477,64 @@ void plan_buffer_line(const float &x, const float &y, const float &z, const floa
// If the buffer is full: good! That means we are well ahead of the robot.
// Rest here until there is room in the buffer.
while(block_buffer_tail == next_buffer_head)
{
while(block_buffer_tail == next_buffer_head) {
manage_heater();
manage_inactivity();
lcd_update();
}
#ifdef ENABLE_AUTO_BED_LEVELING
apply_rotation_xyz(plan_bed_level_matrix, x, y, z);
#endif // ENABLE_AUTO_BED_LEVELING
#ifdef ENABLE_AUTO_BED_LEVELING
apply_rotation_xyz(plan_bed_level_matrix, x, y, z);
#endif // ENABLE_AUTO_BED_LEVELING
// The target position of the tool in absolute steps
// Calculate target position in absolute steps
//this should be done after the wait, because otherwise a M92 code within the gcode disrupts this calculation somehow
long target[4];
target[X_AXIS] = lround(x*axis_steps_per_unit[X_AXIS]);
target[Y_AXIS] = lround(y*axis_steps_per_unit[Y_AXIS]);
target[Z_AXIS] = lround(z*axis_steps_per_unit[Z_AXIS]);
target[E_AXIS] = lround(e*axis_steps_per_unit[E_AXIS + active_extruder]);
#ifdef PREVENT_DANGEROUS_EXTRUDE
#ifdef NPR2
if(target[E_AXIS]!=position[E_AXIS])
{
if (active_extruder!=1)
{
if(degHotend(active_extruder)<extrude_min_temp && !debugDryrun())
{
position[E_AXIS]=target[E_AXIS]; //behave as if the move really took place, but ignore E part
SERIAL_ECHO_START;
SERIAL_ECHOLNPGM(MSG_ERR_COLD_EXTRUDE_STOP);
}
}
#else // NO NPR2
if(target[E_AXIS]!=position[E_AXIS])
{
if(degHotend(active_extruder)<extrude_min_temp && !debugDryrun())
{
position[E_AXIS]=target[E_AXIS]; //behave as if the move really took place, but ignore E part
SERIAL_ECHO_START;
SERIAL_ECHOLNPGM(MSG_ERR_COLD_EXTRUDE_STOP);
}
#endif // NPR2
#ifdef PREVENT_LENGTHY_EXTRUDE
if(labs(target[E_AXIS]-position[E_AXIS])>axis_steps_per_unit[active_extruder+3]*EXTRUDE_MAXLENGTH)
{
#ifdef EASY_LOAD
if (!allow_lengthy_extrude_once) {
#endif
position[E_AXIS]=target[E_AXIS]; //behave as if the move really took place, but ignore E part
SERIAL_ECHO_START;
SERIAL_ECHOLNPGM(MSG_ERR_LONG_EXTRUDE_STOP);
#ifdef EASY_LOAD
}
allow_lengthy_extrude_once = false;
#endif
long target[NUM_AXIS];
target[X_AXIS] = lround(x * axis_steps_per_unit[X_AXIS]);
target[Y_AXIS] = lround(y * axis_steps_per_unit[Y_AXIS]);
target[Z_AXIS] = lround(z * axis_steps_per_unit[Z_AXIS]);
target[E_AXIS] = lround(e * axis_steps_per_unit[E_AXIS + active_extruder]);
float dx = target[X_AXIS] - position[X_AXIS],
dy = target[Y_AXIS] - position[Y_AXIS],
dz = target[Z_AXIS] - position[Z_AXIS],
de = target[E_AXIS] - position[E_AXIS];
#ifdef PREVENT_DANGEROUS_EXTRUDE
if (de) {
#ifdef NPR2
if (active_extruder!=1) {
if(degHotend(active_extruder) < extrude_min_temp && !debugDryrun()) {
position[E_AXIS] = target[E_AXIS]; //behave as if the move really took place, but ignore E part
SERIAL_ECHO_START;
SERIAL_ECHOLNPGM(MSG_ERR_COLD_EXTRUDE_STOP);
}
}
#else // NO NPR2
if(degHotend(active_extruder) < extrude_min_temp && !debugDryrun()) {
position[E_AXIS] = target[E_AXIS]; //behave as if the move really took place, but ignore E part
SERIAL_ECHO_START;
SERIAL_ECHOLNPGM(MSG_ERR_COLD_EXTRUDE_STOP);
}
#endif // NPR2
#ifdef PREVENT_LENGTHY_EXTRUDE
if(labs(de) > axis_steps_per_unit[E_AXIS + active_extruder] * EXTRUDE_MAXLENGTH) {
#ifdef EASY_LOAD
if (!allow_lengthy_extrude_once) {
#endif
position[E_AXIS] = target[E_AXIS]; //behave as if the move really took place, but ignore E part
SERIAL_ECHO_START;
SERIAL_ECHOLNPGM(MSG_ERR_LONG_EXTRUDE_STOP);
#ifdef EASY_LOAD
}
allow_lengthy_extrude_once = false;
#endif
}
#endif // PREVENT_LENGTHY_EXTRUDE
}
#endif // PREVENT_LENGTHY_EXTRUDE
}
#endif // PREVENT_DANGEROUS_EXTRUDE
#endif // PREVENT_DANGEROUS_EXTRUDE
// Prepare to set up new block
block_t *block = &block_buffer[block_buffer_head];
......@@ -607,140 +543,125 @@ void plan_buffer_line(const float &x, const float &y, const float &z, const floa
block->busy = false;
// Number of steps for each axis
#ifndef COREXY
// default non-h-bot planning
block->steps_x = labs(target[X_AXIS]-position[X_AXIS]);
block->steps_y = labs(target[Y_AXIS]-position[Y_AXIS]);
#else
// corexy planning
// these equations follow the form of the dA and dB equations on http://www.corexy.com/theory.html
block->steps_x = labs((target[X_AXIS]-position[X_AXIS]) + (target[Y_AXIS]-position[Y_AXIS]));
block->steps_y = labs((target[X_AXIS]-position[X_AXIS]) - (target[Y_AXIS]-position[Y_AXIS]));
#endif
block->steps_z = labs(target[Z_AXIS]-position[Z_AXIS]);
block->steps_e = labs(target[E_AXIS]-position[E_AXIS]);
block->steps_e *= volumetric_multiplier[active_extruder];
block->steps_e *= extruder_multiplier[active_extruder];
block->steps_e /= 100;
block->step_event_count = max(block->steps_x, max(block->steps_y, max(block->steps_z, block->steps_e)));
#ifdef COREXY
// corexy planning
// these equations follow the form of the dA and dB equations on http://www.corexy.com/theory.html
block->steps[A_AXIS] = labs(dx + dy);
block->steps[B_AXIS] = labs(dx - dy);
#else
// default non-h-bot planning
block->steps[X_AXIS] = labs(dx);
block->steps[Y_AXIS] = labs(dy);
#endif
block->steps[Z_AXIS] = labs(dz);
block->steps[E_AXIS] = labs(de);
block->steps[E_AXIS] *= volumetric_multiplier[active_extruder];
block->steps[E_AXIS] *= extruder_multiplier[active_extruder];
block->steps[E_AXIS] /= 100;
block->step_event_count = max(block->steps[X_AXIS], max(block->steps[Y_AXIS], max(block->steps[Z_AXIS], block->steps[E_AXIS])));
// Bail if this is a zero-length block
if (block->step_event_count <= dropsegments)
{
return;
}
if (block->step_event_count <= dropsegments) return;
block->fan_speed = fanSpeed;
#ifdef BARICUDA
block->valve_pressure = ValvePressure;
block->e_to_p_pressure = EtoPPressure;
block->valve_pressure = ValvePressure;
block->e_to_p_pressure = EtoPPressure;
#endif
// Add update block variables for LASER BEAM control
#ifdef LASERBEAM
block->laser_ttlmodulation = laser_ttl_modulation;
block->laser_ttlmodulation = laser_ttl_modulation;
#endif
// Compute direction bits for this block
block->direction_bits = 0;
#ifndef COREXY
if (target[X_AXIS] < position[X_AXIS])
{
block->direction_bits |= BIT(X_AXIS);
}
if (target[Y_AXIS] < position[Y_AXIS])
{
block->direction_bits |= BIT(Y_AXIS);
}
#else //COREXY
if (target[X_AXIS] < position[X_AXIS])
{
block->direction_bits |= BIT(X_HEAD);
}
if (target[Y_AXIS] < position[Y_AXIS])
{
block->direction_bits |= BIT(Y_HEAD);
}
if ((target[X_AXIS]-position[X_AXIS]) + (target[Y_AXIS]-position[Y_AXIS]) < 0)
{
block->direction_bits |= BIT(X_AXIS);
}
if ((target[X_AXIS]-position[X_AXIS]) - (target[Y_AXIS]-position[Y_AXIS]) < 0)
{
block->direction_bits |= BIT(Y_AXIS);
}
#endif //COREXY
if (target[Z_AXIS] < position[Z_AXIS])
{
block->direction_bits |= BIT(Z_AXIS);
}
if (target[E_AXIS] < position[E_AXIS])
{
block->direction_bits |= BIT(E_AXIS);
}
uint8_t db = 0;
#ifdef COREXY
if (dx < 0) db |= BIT(X_HEAD); // Save the real Extruder (head) direction in X Axis
if (dy < 0) db |= BIT(Y_HEAD); // ...and Y
if (dx + dy < 0) db |= BIT(A_AXIS); // Motor A direction
if (dx - dy < 0) db |= BIT(B_AXIS); // Motor B direction
#else
if (dx < 0) db |= BIT(X_AXIS);
if (dy < 0) db |= BIT(Y_AXIS);
#endif
if (dz < 0) db |= BIT(Z_AXIS);
if (de < 0) db |= BIT(E_AXIS);
block->direction_bits = db;
block->active_driver = driver;
//enable active axes
#ifdef COREXY
if((block->steps_x != 0) || (block->steps_y != 0)) {
enable_x();
enable_y();
if (block->steps[A_AXIS] || block->steps[B_AXIS]) {
enable_x();
enable_y();
}
#else //NO COREXY
if(block->steps_x != 0) enable_x();
if(block->steps_y != 0) enable_y();
#endif //NOCOREXY
#else
if (block->steps[X_AXIS]) enable_x();
if (block->steps[Y_AXIS]) enable_y();
#endif
#ifndef Z_LATE_ENABLE
if(block->steps_z != 0) enable_z();
if (block->steps[Z_AXIS]) enable_z();
#endif
// Enable extruder(s)
if(block->steps_e != 0)
{
if (block->steps[E_AXIS]) {
#if !defined(MKR4) && !defined(NPR2)
if (DISABLE_INACTIVE_EXTRUDER) //enable only selected extruder
{
if (DISABLE_INACTIVE_EXTRUDER) { //enable only selected extruder
if(g_uc_extruder_last_move[0] > 0) g_uc_extruder_last_move[0]--;
if(g_uc_extruder_last_move[1] > 0) g_uc_extruder_last_move[1]--;
if(g_uc_extruder_last_move[2] > 0) g_uc_extruder_last_move[2]--;
if(g_uc_extruder_last_move[3] > 0) g_uc_extruder_last_move[3]--;
for (int i=0; i<EXTRUDERS; i++)
if (g_uc_extruder_last_move[i] > 0) g_uc_extruder_last_move[i]--;
switch(extruder)
{
switch(extruder) {
case 0:
enable_e0();
g_uc_extruder_last_move[0] = BLOCK_BUFFER_SIZE*2;
if(g_uc_extruder_last_move[1] == 0) disable_e1();
if(g_uc_extruder_last_move[2] == 0) disable_e2();
if(g_uc_extruder_last_move[3] == 0) disable_e3();
break;
case 1:
enable_e1();
g_uc_extruder_last_move[1] = BLOCK_BUFFER_SIZE*2;
if(g_uc_extruder_last_move[0] == 0) disable_e0();
if(g_uc_extruder_last_move[2] == 0) disable_e2();
if(g_uc_extruder_last_move[3] == 0) disable_e3();
break;
case 2:
enable_e2();
g_uc_extruder_last_move[2] = BLOCK_BUFFER_SIZE*2;
if(g_uc_extruder_last_move[0] == 0) disable_e0();
if(g_uc_extruder_last_move[1] == 0) disable_e1();
if(g_uc_extruder_last_move[3] == 0) disable_e3();
break;
case 3:
enable_e3();
g_uc_extruder_last_move[3] = BLOCK_BUFFER_SIZE*2;
if(g_uc_extruder_last_move[0] == 0) disable_e0();
if(g_uc_extruder_last_move[1] == 0) disable_e1();
if(g_uc_extruder_last_move[2] == 0) disable_e2();
g_uc_extruder_last_move[0] = BLOCK_BUFFER_SIZE * 2;
#if EXTRUDERS > 1
if (g_uc_extruder_last_move[1] == 0) disable_e1();
#if EXTRUDERS > 2
if (g_uc_extruder_last_move[2] == 0) disable_e2();
#if EXTRUDERS > 3
if (g_uc_extruder_last_move[3] == 0) disable_e3();
#endif
#endif
#endif
break;
#if EXTRUDERS > 1
case 1:
enable_e1();
g_uc_extruder_last_move[1] = BLOCK_BUFFER_SIZE*2;
if (g_uc_extruder_last_move[0] == 0) disable_e0();
#if EXTRUDERS > 2
if (g_uc_extruder_last_move[2] == 0) disable_e2();
#if EXTRUDERS > 3
if (g_uc_extruder_last_move[3] == 0) disable_e3();
#endif
#endif
break;
#if EXTRUDERS > 2
case 2:
enable_e2();
g_uc_extruder_last_move[2] = BLOCK_BUFFER_SIZE*2;
if (g_uc_extruder_last_move[0] == 0) disable_e0();
if (g_uc_extruder_last_move[1] == 0) disable_e1();
#if EXTRUDERS > 3
if (g_uc_extruder_last_move[3] == 0) disable_e3();
#endif
break;
#if EXTRUDERS > 3
case 3:
enable_e3();
g_uc_extruder_last_move[3] = BLOCK_BUFFER_SIZE*2;
if (g_uc_extruder_last_move[0] == 0) disable_e0();
if (g_uc_extruder_last_move[1] == 0) disable_e1();
if (g_uc_extruder_last_move[2] == 0) disable_e2();
break;
#endif // EXTRUDERS > 3
#endif // EXTRUDERS > 2
#endif // EXTRUDERS > 1
}
}
else //enable all
......@@ -767,133 +688,110 @@ block->steps_y = labs((target[X_AXIS]-position[X_AXIS]) - (target[Y_AXIS]-positi
break;
}
#endif //!MKR4 && !NPR2
if (feed_rate < minimumfeedrate) feed_rate = minimumfeedrate;
}
else if (feed_rate < mintravelfeedrate) feed_rate = mintravelfeedrate;
if (block->steps_e == 0)
{
if(feed_rate<mintravelfeedrate) feed_rate=mintravelfeedrate;
}
else
{
if(feed_rate<minimumfeedrate) feed_rate=minimumfeedrate;
}
/* This part of the code calculates the total length of the movement.
For cartesian bots, the X_AXIS is the real X movement and same for Y_AXIS.
But for corexy bots, that is not true. The "X_AXIS" and "Y_AXIS" motors (that should be named to A_AXIS
and B_AXIS) cannot be used for X and Y length, because A=X+Y and B=X-Y.
So we need to create other 2 "AXIS", named X_HEAD and Y_HEAD, meaning the real displacement of the Head.
Having the real displacement of the head, we can calculate the total movement length and apply the desired speed.
*/
#ifndef COREXY
float delta_mm[4];
delta_mm[X_AXIS] = (target[X_AXIS]-position[X_AXIS])/axis_steps_per_unit[X_AXIS];
delta_mm[Y_AXIS] = (target[Y_AXIS]-position[Y_AXIS])/axis_steps_per_unit[Y_AXIS];
#else
/**
* This part of the code calculates the total length of the movement.
* For cartesian bots, the X_AXIS is the real X movement and same for Y_AXIS.
* But for corexy bots, that is not true. The "X_AXIS" and "Y_AXIS" motors (that should be named to A_AXIS
* and B_AXIS) cannot be used for X and Y length, because A=X+Y and B=X-Y.
* So we need to create other 2 "AXIS", named X_HEAD and Y_HEAD, meaning the real displacement of the Head.
* Having the real displacement of the head, we can calculate the total movement length and apply the desired speed.
*/
#ifdef COREXY
float delta_mm[6];
delta_mm[X_HEAD] = (target[X_AXIS]-position[X_AXIS])/axis_steps_per_unit[X_AXIS];
delta_mm[Y_HEAD] = (target[Y_AXIS]-position[Y_AXIS])/axis_steps_per_unit[Y_AXIS];
delta_mm[X_AXIS] = ((target[X_AXIS]-position[X_AXIS]) + (target[Y_AXIS]-position[Y_AXIS]))/axis_steps_per_unit[X_AXIS];
delta_mm[Y_AXIS] = ((target[X_AXIS]-position[X_AXIS]) - (target[Y_AXIS]-position[Y_AXIS]))/axis_steps_per_unit[Y_AXIS];
delta_mm[X_HEAD] = dx / axis_steps_per_unit[A_AXIS];
delta_mm[Y_HEAD] = dy / axis_steps_per_unit[B_AXIS];
delta_mm[A_AXIS] = (dx + dy) / axis_steps_per_unit[A_AXIS];
delta_mm[B_AXIS] = (dx - dy) / axis_steps_per_unit[B_AXIS];
#else
float delta_mm[4];
delta_mm[X_AXIS] = dx / axis_steps_per_unit[X_AXIS];
delta_mm[Y_AXIS] = dy / axis_steps_per_unit[Y_AXIS];
#endif
delta_mm[Z_AXIS] = (target[Z_AXIS]-position[Z_AXIS])/axis_steps_per_unit[Z_AXIS];
delta_mm[E_AXIS] = ((target[E_AXIS]-position[E_AXIS])/axis_steps_per_unit[active_extruder+3])*volumetric_multiplier[active_extruder]*extruder_multiplier[active_extruder]/100.0;
if ( block->steps_x <=dropsegments && block->steps_y <=dropsegments && block->steps_z <=dropsegments )
{
delta_mm[Z_AXIS] = dz / axis_steps_per_unit[Z_AXIS];
delta_mm[E_AXIS] = (de / axis_steps_per_unit[E_AXIS + active_extruder]) * volumetric_multiplier[active_extruder] * extruder_multiplier[active_extruder] / 100.0;
if (block->steps[X_AXIS] <= dropsegments && block->steps[Y_AXIS] <= dropsegments && block->steps[Z_AXIS] <= dropsegments) {
block->millimeters = fabs(delta_mm[E_AXIS]);
}
else
{
#ifndef COREXY
block->millimeters = sqrt(square(delta_mm[X_AXIS]) + square(delta_mm[Y_AXIS]) + square(delta_mm[Z_AXIS]));
#else
block->millimeters = sqrt(square(delta_mm[X_HEAD]) + square(delta_mm[Y_HEAD]) + square(delta_mm[Z_AXIS]));
#endif
}
float inverse_millimeters = 1.0/block->millimeters; // Inverse millimeters to remove multiple divides
else {
block->millimeters = sqrt(
#ifdef COREXY
square(delta_mm[X_HEAD]) + square(delta_mm[Y_HEAD])
#else
square(delta_mm[X_AXIS]) + square(delta_mm[Y_AXIS])
#endif
+ square(delta_mm[Z_AXIS])
);
}
float inverse_millimeters = 1.0 / block->millimeters; // Inverse millimeters to remove multiple divides
// Calculate speed in mm/second for each axis. No divide by zero due to previous checks.
// Calculate speed in mm/second for each axis. No divide by zero due to previous checks.
float inverse_second = feed_rate * inverse_millimeters;
int moves_queued=(block_buffer_head-block_buffer_tail + BLOCK_BUFFER_SIZE) & (BLOCK_BUFFER_SIZE - 1);
int moves_queued = movesplanned();
// slow down when de buffer starts to empty, rather than wait at the corner for a buffer refill
#ifdef OLD_SLOWDOWN
if(moves_queued < (BLOCK_BUFFER_SIZE * 0.5) && moves_queued > 1)
feed_rate = feed_rate*moves_queued / (BLOCK_BUFFER_SIZE * 0.5);
#endif
bool mq = moves_queued > 1 && moves_queued < BLOCK_BUFFER_SIZE / 2;
#ifdef OLD_SLOWDOWN
if (mq) feed_rate *= 2.0 * moves_queued / BLOCK_BUFFER_SIZE;
#endif
#ifdef SLOWDOWN
// segment time im micro seconds
unsigned long segment_time = lround(1000000.0/inverse_second);
if ((moves_queued > 1) && (moves_queued < (BLOCK_BUFFER_SIZE * 0.5)))
{
if (segment_time < minsegmenttime)
{ // buffer is draining, add extra time. The amount of time added increases if the buffer is still emptied more.
inverse_second=1000000.0/(segment_time+lround(2*(minsegmenttime-segment_time)/moves_queued));
#ifdef XY_FREQUENCY_LIMIT
segment_time = lround(1000000.0/inverse_second);
#endif
#ifdef SLOWDOWN
// segment time im micro seconds
unsigned long segment_time = lround(1000000.0/inverse_second);
if (mq) {
if (segment_time < minsegmenttime) {
// buffer is draining, add extra time. The amount of time added increases if the buffer is still emptied more.
inverse_second = 1000000.0 / (segment_time + lround(2 * (minsegmenttime - segment_time) / moves_queued));
#ifdef XY_FREQUENCY_LIMIT
segment_time = lround(1000000.0 / inverse_second);
#endif
}
}
}
#endif // SLOWDOWN
// END OF SLOW DOWN SECTION
#endif // SLOWDOWN
// END OF SLOW DOWN SECTION
block->nominal_speed = block->millimeters * inverse_second; // (mm/sec) Always > 0
block->nominal_rate = ceil(block->step_event_count * inverse_second); // (step/sec) Always > 0
#if (defined(FILAMENT_SENSOR) && defined(FILWIDTH_PIN) && FILWIDTH_PIN >= 0)
//FMM update ring buffer used for delay with filament measurements
if((extruder==FILAMENT_SENSOR_EXTRUDER_NUM) && (delay_index2 > -1)) //only for extruder with filament sensor and if ring buffer is initialized
{
delay_dist = delay_dist + delta_mm[E_AXIS]; //increment counter with next move in e axis
while (delay_dist >= (10*(MAX_MEASUREMENT_DELAY+1))) //check if counter is over max buffer size in mm
delay_dist = delay_dist - 10*(MAX_MEASUREMENT_DELAY+1); //loop around the buffer
while (delay_dist<0)
delay_dist = delay_dist + 10*(MAX_MEASUREMENT_DELAY+1); //loop around the buffer
delay_index1=delay_dist/10.0; //calculate index
//ensure the number is within range of the array after converting from floating point
if(delay_index1<0)
delay_index1=0;
else if (delay_index1>MAX_MEASUREMENT_DELAY)
delay_index1=MAX_MEASUREMENT_DELAY;
if(delay_index1 != delay_index2) //moved index
{
meas_sample=widthFil_to_size_ratio()-100; //subtract off 100 to reduce magnitude - to store in a signed char
}
while( delay_index1 != delay_index2)
{
delay_index2 = delay_index2 + 1;
if(delay_index2>MAX_MEASUREMENT_DELAY)
delay_index2=delay_index2-(MAX_MEASUREMENT_DELAY+1); //loop around buffer when incrementing
if(delay_index2<0)
delay_index2=0;
else if (delay_index2>MAX_MEASUREMENT_DELAY)
delay_index2=MAX_MEASUREMENT_DELAY;
measurement_delay[delay_index2]=meas_sample;
}
}
#endif
#ifdef FILAMENT_SENSOR
//FMM update ring buffer used for delay with filament measurements
if (extruder == FILAMENT_SENSOR_EXTRUDER_NUM && delay_index2 > -1) { //only for extruder with filament sensor and if ring buffer is initialized
const int MMD = MAX_MEASUREMENT_DELAY + 1, MMD10 = MMD * 10;
delay_dist += delta_mm[E_AXIS]; // increment counter with next move in e axis
while (delay_dist >= MMD10) delay_dist -= MMD10; // loop around the buffer
while (delay_dist < 0) delay_dist += MMD10;
delay_index1 = delay_dist / 10.0; // calculate index
delay_index1 = constrain(delay_index1, 0, MAX_MEASUREMENT_DELAY); // (already constrained above)
if (delay_index1 != delay_index2) { // moved index
meas_sample = widthFil_to_size_ratio() - 100; // Subtract 100 to reduce magnitude - to store in a signed char
while (delay_index1 != delay_index2) {
// Increment and loop around buffer
if (++delay_index2 >= MMD) delay_index2 -= MMD;
delay_index2 = constrain(delay_index2, 0, MAX_MEASUREMENT_DELAY);
measurement_delay[delay_index2] = meas_sample;
}
}
}
#endif
// Calculate and limit speed in mm/sec for each axis
float current_speed[4];
float current_speed[NUM_AXIS];
float speed_factor = 1.0; //factor <=1 do decrease speed
for(int i=0; i < 3; i++)
{
for (int i = 0; i < 3; i++) {
current_speed[i] = delta_mm[i] * inverse_second;
if(fabs(current_speed[i]) > max_feedrate[i])
speed_factor = min(speed_factor, max_feedrate[i] / fabs(current_speed[i]));
float cs = fabs(current_speed[i]), mf = max_feedrate[i];
if (cs > mf) speed_factor = min(speed_factor, mf / cs);
}
current_speed[E_AXIS] = delta_mm[E_AXIS] * inverse_second;
......@@ -909,148 +807,149 @@ Having the real displacement of the head, we can calculate the total movement le
}
// Max segement time in us.
#ifdef XY_FREQUENCY_LIMIT
#define MAX_FREQ_TIME (1000000.0/XY_FREQUENCY_LIMIT)
// Check and limit the xy direction change frequency
unsigned char direction_change = block->direction_bits ^ old_direction_bits;
old_direction_bits = block->direction_bits;
segment_time = lround((float)segment_time / speed_factor);
#ifdef XY_FREQUENCY_LIMIT
#define MAX_FREQ_TIME (1000000.0 / XY_FREQUENCY_LIMIT)
// Check and limit the xy direction change frequency
unsigned char direction_change = block->direction_bits ^ old_direction_bits;
old_direction_bits = block->direction_bits;
segment_time = lround((float)segment_time / speed_factor);
if((direction_change & BIT(X_AXIS)) == 0)
{
x_segment_time[0] += segment_time;
}
else
{
x_segment_time[2] = x_segment_time[1];
x_segment_time[1] = x_segment_time[0];
x_segment_time[0] = segment_time;
}
if((direction_change & BIT(Y_AXIS)) == 0)
{
y_segment_time[0] += segment_time;
}
else
{
y_segment_time[2] = y_segment_time[1];
y_segment_time[1] = y_segment_time[0];
y_segment_time[0] = segment_time;
}
long max_x_segment_time = max(x_segment_time[0], max(x_segment_time[1], x_segment_time[2]));
long max_y_segment_time = max(y_segment_time[0], max(y_segment_time[1], y_segment_time[2]));
long min_xy_segment_time =min(max_x_segment_time, max_y_segment_time);
if(min_xy_segment_time < MAX_FREQ_TIME)
speed_factor = min(speed_factor, speed_factor * (float)min_xy_segment_time / (float)MAX_FREQ_TIME);
#endif // XY_FREQUENCY_LIMIT
long xs0 = axis_segment_time[X_AXIS][0],
xs1 = axis_segment_time[X_AXIS][1],
xs2 = axis_segment_time[X_AXIS][2],
ys0 = axis_segment_time[Y_AXIS][0],
ys1 = axis_segment_time[Y_AXIS][1],
ys2 = axis_segment_time[Y_AXIS][2];
if ((direction_change & BIT(X_AXIS)) != 0) {
xs2 = axis_segment_time[X_AXIS][2] = xs1;
xs1 = axis_segment_time[X_AXIS][1] = xs0;
xs0 = 0;
}
xs0 = axis_segment_time[X_AXIS][0] = xs0 + segment_time;
// Correct the speed
if( speed_factor < 1.0)
{
for(unsigned char i=0; i < 4; i++)
{
current_speed[i] *= speed_factor;
if ((direction_change & BIT(Y_AXIS)) != 0) {
ys2 = axis_segment_time[Y_AXIS][2] = axis_segment_time[Y_AXIS][1];
ys1 = axis_segment_time[Y_AXIS][1] = axis_segment_time[Y_AXIS][0];
ys0 = 0;
}
ys0 = axis_segment_time[Y_AXIS][0] = ys0 + segment_time;
long max_x_segment_time = max(xs0, max(xs1, xs2)),
max_y_segment_time = max(ys0, max(ys1, ys2)),
min_xy_segment_time = min(max_x_segment_time, max_y_segment_time);
if (min_xy_segment_time < MAX_FREQ_TIME) {
float low_sf = speed_factor * min_xy_segment_time / MAX_FREQ_TIME;
speed_factor = min(speed_factor, low_sf);
}
#endif // XY_FREQUENCY_LIMIT
// Correct the speed
if (speed_factor < 1.0) {
for (unsigned char i = 0; i < NUM_AXIS; i++) current_speed[i] *= speed_factor;
block->nominal_speed *= speed_factor;
block->nominal_rate *= speed_factor;
}
// Compute and limit the acceleration rate for the trapezoid generator.
float steps_per_mm = block->step_event_count/block->millimeters;
if(block->steps_x == 0 && block->steps_y == 0 && block->steps_z == 0)
{
// Compute and limit the acceleration rate for the trapezoid generator.
float steps_per_mm = block->step_event_count / block->millimeters;
long bsx = block->steps[X_AXIS], bsy = block->steps[Y_AXIS], bsz = block->steps[Z_AXIS], bse = block->steps[E_AXIS];
if (bsx == 0 && bsy == 0 && bsz == 0) {
block->acceleration_st = ceil(retract_acceleration * steps_per_mm); // convert to: acceleration steps/sec^2
}
else if(block->steps_e == 0)
{
else if (bse == 0) {
block->acceleration_st = ceil(travel_acceleration * steps_per_mm); // convert to: acceleration steps/sec^2
}
else
{
else {
block->acceleration_st = ceil(acceleration * steps_per_mm); // convert to: acceleration steps/sec^2
}
// Limit acceleration per axis
if(((float)block->acceleration_st * (float)block->steps_x / (float)block->step_event_count) > axis_steps_per_sqr_second[X_AXIS])
block->acceleration_st = axis_steps_per_sqr_second[X_AXIS];
if(((float)block->acceleration_st * (float)block->steps_y / (float)block->step_event_count) > axis_steps_per_sqr_second[Y_AXIS])
block->acceleration_st = axis_steps_per_sqr_second[Y_AXIS];
if(((float)block->acceleration_st * (float)block->steps_e / (float)block->step_event_count) > axis_steps_per_sqr_second[E_AXIS])
block->acceleration_st = axis_steps_per_sqr_second[E_AXIS];
if(((float)block->acceleration_st * (float)block->steps_z / (float)block->step_event_count ) > axis_steps_per_sqr_second[Z_AXIS])
block->acceleration_st = axis_steps_per_sqr_second[Z_AXIS];
unsigned long acc_st = block->acceleration_st,
xsteps = axis_steps_per_sqr_second[X_AXIS],
ysteps = axis_steps_per_sqr_second[Y_AXIS],
zsteps = axis_steps_per_sqr_second[Z_AXIS],
esteps = axis_steps_per_sqr_second[E_AXIS];
if ((float)acc_st * bsx / block->step_event_count > xsteps) acc_st = xsteps;
if ((float)acc_st * bsy / block->step_event_count > ysteps) acc_st = ysteps;
if ((float)acc_st * bsz / block->step_event_count > zsteps) acc_st = zsteps;
if ((float)acc_st * bse / block->step_event_count > esteps) acc_st = esteps;
block->acceleration = block->acceleration_st / steps_per_mm;
block->acceleration_rate = (long)((float)block->acceleration_st * (16777216.0 / (F_CPU / 8.0)));
#if 0 // Use old jerk for now
// Compute path unit vector
double unit_vec[3];
unit_vec[X_AXIS] = delta_mm[X_AXIS]*inverse_millimeters;
unit_vec[Y_AXIS] = delta_mm[Y_AXIS]*inverse_millimeters;
unit_vec[Z_AXIS] = delta_mm[Z_AXIS]*inverse_millimeters;
// Compute maximum allowable entry speed at junction by centripetal acceleration approximation.
// Let a circle be tangent to both previous and current path line segments, where the junction
// deviation is defined as the distance from the junction to the closest edge of the circle,
// colinear with the circle center. The circular segment joining the two paths represents the
// path of centripetal acceleration. Solve for max velocity based on max acceleration about the
// radius of the circle, defined indirectly by junction deviation. This may be also viewed as
// path width or max_jerk in the previous grbl version. This approach does not actually deviate
// from path, but used as a robust way to compute cornering speeds, as it takes into account the
// nonlinearities of both the junction angle and junction velocity.
double vmax_junction = MINIMUM_PLANNER_SPEED; // Set default max junction speed
// Skip first block or when previous_nominal_speed is used as a flag for homing and offset cycles.
if ((block_buffer_head != block_buffer_tail) && (previous_nominal_speed > 0.0)) {
// Compute cosine of angle between previous and current path. (prev_unit_vec is negative)
// NOTE: Max junction velocity is computed without sin() or acos() by trig half angle identity.
double cos_theta = - previous_unit_vec[X_AXIS] * unit_vec[X_AXIS]
- previous_unit_vec[Y_AXIS] * unit_vec[Y_AXIS]
- previous_unit_vec[Z_AXIS] * unit_vec[Z_AXIS] ;
// Skip and use default max junction speed for 0 degree acute junction.
if (cos_theta < 0.95) {
vmax_junction = min(previous_nominal_speed,block->nominal_speed);
// Skip and avoid divide by zero for straight junctions at 180 degrees. Limit to min() of nominal speeds.
if (cos_theta > -0.95) {
// Compute maximum junction velocity based on maximum acceleration and junction deviation
double sin_theta_d2 = sqrt(0.5*(1.0-cos_theta)); // Trig half angle identity. Always positive.
vmax_junction = min(vmax_junction,
sqrt(block->acceleration * junction_deviation * sin_theta_d2/(1.0-sin_theta_d2)) );
block->acceleration_st = acc_st;
block->acceleration = acc_st / steps_per_mm;
block->acceleration_rate = (long)(acc_st * 16777216.0 / (F_CPU / 8.0));
#if 0 // Use old jerk for now
// Compute path unit vector
double unit_vec[3];
unit_vec[X_AXIS] = delta_mm[X_AXIS]*inverse_millimeters;
unit_vec[Y_AXIS] = delta_mm[Y_AXIS]*inverse_millimeters;
unit_vec[Z_AXIS] = delta_mm[Z_AXIS]*inverse_millimeters;
// Compute maximum allowable entry speed at junction by centripetal acceleration approximation.
// Let a circle be tangent to both previous and current path line segments, where the junction
// deviation is defined as the distance from the junction to the closest edge of the circle,
// colinear with the circle center. The circular segment joining the two paths represents the
// path of centripetal acceleration. Solve for max velocity based on max acceleration about the
// radius of the circle, defined indirectly by junction deviation. This may be also viewed as
// path width or max_jerk in the previous grbl version. This approach does not actually deviate
// from path, but used as a robust way to compute cornering speeds, as it takes into account the
// nonlinearities of both the junction angle and junction velocity.
double vmax_junction = MINIMUM_PLANNER_SPEED; // Set default max junction speed
// Skip first block or when previous_nominal_speed is used as a flag for homing and offset cycles.
if ((block_buffer_head != block_buffer_tail) && (previous_nominal_speed > 0.0)) {
// Compute cosine of angle between previous and current path. (prev_unit_vec is negative)
// NOTE: Max junction velocity is computed without sin() or acos() by trig half angle identity.
double cos_theta = - previous_unit_vec[X_AXIS] * unit_vec[X_AXIS]
- previous_unit_vec[Y_AXIS] * unit_vec[Y_AXIS]
- previous_unit_vec[Z_AXIS] * unit_vec[Z_AXIS] ;
// Skip and use default max junction speed for 0 degree acute junction.
if (cos_theta < 0.95) {
vmax_junction = min(previous_nominal_speed,block->nominal_speed);
// Skip and avoid divide by zero for straight junctions at 180 degrees. Limit to min() of nominal speeds.
if (cos_theta > -0.95) {
// Compute maximum junction velocity based on maximum acceleration and junction deviation
double sin_theta_d2 = sqrt(0.5*(1.0-cos_theta)); // Trig half angle identity. Always positive.
vmax_junction = min(vmax_junction,
sqrt(block->acceleration * junction_deviation * sin_theta_d2/(1.0-sin_theta_d2)) );
}
}
}
}
#endif
#endif
// Start with a safe speed
float vmax_junction = max_xy_jerk/2;
float vmax_junction = max_xy_jerk / 2;
float vmax_junction_factor = 1.0;
if(fabs(current_speed[Z_AXIS]) > max_z_jerk/2)
vmax_junction = min(vmax_junction, max_z_jerk/2);
if(fabs(current_speed[E_AXIS]) > max_e_jerk/2)
vmax_junction = min(vmax_junction, max_e_jerk/2);
float mz2 = max_z_jerk / 2, me2 = max_e_jerk / 2;
float csz = current_speed[Z_AXIS], cse = current_speed[E_AXIS];
if (fabs(csz) > mz2) vmax_junction = min(vmax_junction, mz2);
if (fabs(cse) > me2) vmax_junction = min(vmax_junction, me2);
vmax_junction = min(vmax_junction, block->nominal_speed);
float safe_speed = vmax_junction;
if ((moves_queued > 1) && (previous_nominal_speed > 0.0001)) {
float jerk = sqrt(pow((current_speed[X_AXIS]-previous_speed[X_AXIS]), 2)+pow((current_speed[Y_AXIS]-previous_speed[Y_AXIS]), 2));
// if((fabs(previous_speed[X_AXIS]) > 0.0001) || (fabs(previous_speed[Y_AXIS]) > 0.0001)) {
float dx = current_speed[X_AXIS] - previous_speed[X_AXIS],
dy = current_speed[Y_AXIS] - previous_speed[Y_AXIS],
dz = fabs(csz - previous_speed[Z_AXIS]),
de = fabs(cse - previous_speed[E_AXIS]),
jerk = sqrt(dx * dx + dy * dy);
// if ((fabs(previous_speed[X_AXIS]) > 0.0001) || (fabs(previous_speed[Y_AXIS]) > 0.0001)) {
vmax_junction = block->nominal_speed;
// }
if (jerk > max_xy_jerk) {
vmax_junction_factor = (max_xy_jerk/jerk);
}
if(fabs(current_speed[Z_AXIS] - previous_speed[Z_AXIS]) > max_z_jerk) {
vmax_junction_factor= min(vmax_junction_factor, (max_z_jerk/fabs(current_speed[Z_AXIS] - previous_speed[Z_AXIS])));
}
if(fabs(current_speed[E_AXIS] - previous_speed[E_AXIS]) > max_e_jerk) {
vmax_junction_factor = min(vmax_junction_factor, (max_e_jerk/fabs(current_speed[E_AXIS] - previous_speed[E_AXIS])));
}
if (jerk > max_xy_jerk) vmax_junction_factor = max_xy_jerk / jerk;
if (dz > max_z_jerk) vmax_junction_factor = min(vmax_junction_factor, max_z_jerk / dz);
if (de > max_e_jerk) vmax_junction_factor = min(vmax_junction_factor, max_e_jerk / de);
vmax_junction = min(previous_nominal_speed, vmax_junction * vmax_junction_factor); // Limit speed to max previous speed
}
block->max_entry_speed = vmax_junction;
// Initialize block entry speed. Compute based on deceleration to user-defined MINIMUM_PLANNER_SPEED.
double v_allowable = max_allowable_speed(-block->acceleration,MINIMUM_PLANNER_SPEED,block->millimeters);
double v_allowable = max_allowable_speed(-block->acceleration, MINIMUM_PLANNER_SPEED, block->millimeters);
block->entry_speed = min(vmax_junction, v_allowable);
// Initialize planner efficiency flags
......@@ -1061,115 +960,91 @@ Having the real displacement of the head, we can calculate the total movement le
// block nominal speed limits both the current and next maximum junction speeds. Hence, in both
// the reverse and forward planners, the corresponding block junction speed will always be at the
// the maximum junction speed and may always be ignored for any speed reduction checks.
if (block->nominal_speed <= v_allowable) {
block->nominal_length_flag = true;
}
else {
block->nominal_length_flag = false;
}
block->nominal_length_flag = (block->nominal_speed <= v_allowable);
block->recalculate_flag = true; // Always calculate trapezoid for new block
// Update previous path unit_vector and nominal speed
memcpy(previous_speed, current_speed, sizeof(previous_speed)); // previous_speed[] = current_speed[]
for (int i = 0; i < NUM_AXIS; i++) previous_speed[i] = current_speed[i];
previous_nominal_speed = block->nominal_speed;
#ifdef ADVANCE
// Calculate advance rate
if((block->steps_e == 0) || (block->steps_x == 0 && block->steps_y == 0 && block->steps_z == 0)) {
block->advance_rate = 0;
block->advance = 0;
}
else {
long acc_dist = estimate_acceleration_distance(0, block->nominal_rate, block->acceleration_st);
float advance = (STEPS_PER_CUBIC_MM_E * EXTRUDER_ADVANCE_K) *
(current_speed[E_AXIS] * current_speed[E_AXIS] * EXTRUSION_AREA * EXTRUSION_AREA)*256;
block->advance = advance;
if(acc_dist == 0) {
#ifdef ADVANCE
// Calculate advance rate
if (!bse || (!bsx && !bsy && !bsz)) {
block->advance_rate = 0;
}
block->advance = 0;
}
else {
block->advance_rate = advance / (float)acc_dist;
long acc_dist = estimate_acceleration_distance(0, block->nominal_rate, block->acceleration_st);
float advance = (STEPS_PER_CUBIC_MM_E * EXTRUDER_ADVANCE_K) * (cse * cse * EXTRUSION_AREA * EXTRUSION_AREA) * 256;
block->advance = advance;
block->advance_rate = acc_dist ? advance / (float)acc_dist : 0;
}
}
/*
SERIAL_ECHO_START;
SERIAL_ECHOPGM("advance :");
SERIAL_ECHO(block->advance/256.0);
SERIAL_ECHOPGM("advance rate :");
SERIAL_ECHOLN(block->advance_rate/256.0);
*/
#endif // ADVANCE
calculate_trapezoid_for_block(block, block->entry_speed/block->nominal_speed,
safe_speed/block->nominal_speed);
/*
SERIAL_ECHO_START;
SERIAL_ECHOPGM("advance :");
SERIAL_ECHO(block->advance/256.0);
SERIAL_ECHOPGM("advance rate :");
SERIAL_ECHOLN(block->advance_rate/256.0);
*/
#endif // ADVANCE
calculate_trapezoid_for_block(block, block->entry_speed / block->nominal_speed, safe_speed / block->nominal_speed);
// Move buffer head
block_buffer_head = next_buffer_head;
// Update position
memcpy(position, target, sizeof(target)); // position[] = target[]
for (int i = 0; i < NUM_AXIS; i++) position[i] = target[i];
planner_recalculate();
st_wake_up();
}
} // plan_buffer_line()
#ifdef ENABLE_AUTO_BED_LEVELING
vector_3 plan_get_position() {
vector_3 position = vector_3(st_get_position_mm(X_AXIS), st_get_position_mm(Y_AXIS), st_get_position_mm(Z_AXIS));
vector_3 plan_get_position() {
vector_3 position = vector_3(st_get_position_mm(X_AXIS), st_get_position_mm(Y_AXIS), st_get_position_mm(Z_AXIS));
//position.debug("in plan_get position");
//plan_bed_level_matrix.debug("in plan_get bed_level");
matrix_3x3 inverse = matrix_3x3::transpose(plan_bed_level_matrix);
//inverse.debug("in plan_get inverse");
position.apply_rotation(inverse);
//position.debug("after rotation");
//position.debug("in plan_get position");
//plan_bed_level_matrix.debug("in plan_get bed_level");
matrix_3x3 inverse = matrix_3x3::transpose(plan_bed_level_matrix);
//inverse.debug("in plan_get inverse");
position.apply_rotation(inverse);
//position.debug("after rotation");
return position;
}
return position;
}
#endif // ENABLE_AUTO_BED_LEVELING
#ifdef ENABLE_AUTO_BED_LEVELING
void plan_set_position(float x, float y, float z, const float &e)
{
apply_rotation_xyz(plan_bed_level_matrix, x, y, z);
void plan_set_position(float x, float y, float z, const float &e) {
apply_rotation_xyz(plan_bed_level_matrix, x, y, z);
#else
void plan_set_position(const float &x, const float &y, const float &z, const float &e)
{
void plan_set_position(const float &x, const float &y, const float &z, const float &e) {
#endif // ENABLE_AUTO_BED_LEVELING
position[X_AXIS] = lround(x*axis_steps_per_unit[X_AXIS]);
position[Y_AXIS] = lround(y*axis_steps_per_unit[Y_AXIS]);
position[Z_AXIS] = lround(z*axis_steps_per_unit[Z_AXIS]);
position[E_AXIS] = lround(e*axis_steps_per_unit[E_AXIS + active_extruder]);
st_set_position(position[X_AXIS], position[Y_AXIS], position[Z_AXIS], position[E_AXIS]);
previous_nominal_speed = 0.0; // Resets planner junction speeds. Assumes start from rest.
previous_speed[0] = 0.0;
previous_speed[1] = 0.0;
previous_speed[2] = 0.0;
previous_speed[3] = 0.0;
}
float nx = position[X_AXIS] = lround(x * axis_steps_per_unit[X_AXIS]);
float ny = position[Y_AXIS] = lround(y * axis_steps_per_unit[Y_AXIS]);
float nz = position[Z_AXIS] = lround(z * axis_steps_per_unit[Z_AXIS]);
float ne = position[E_AXIS] = lround(e * axis_steps_per_unit[E_AXIS + active_extruder]);
st_set_position(nx, ny, nz, ne);
previous_nominal_speed = 0.0; // Resets planner junction speeds. Assumes start from rest.
void plan_set_e_position(const float &e)
{
position[E_AXIS] = lround(e*axis_steps_per_unit[E_AXIS + active_extruder]);
st_set_e_position(position[E_AXIS]);
}
for (int i=0; i<NUM_AXIS; i++) previous_speed[i] = 0.0;
}
uint8_t movesplanned()
{
return (block_buffer_head-block_buffer_tail + BLOCK_BUFFER_SIZE) & (BLOCK_BUFFER_SIZE - 1);
void plan_set_e_position(const float &e) {
position[E_AXIS] = lround(e * axis_steps_per_unit[E_AXIS + active_extruder]);
st_set_e_position(position[E_AXIS]);
}
#ifdef PREVENT_DANGEROUS_EXTRUDE
void set_extrude_min_temp(float temp) { extrude_min_temp = temp; }
void set_extrude_min_temp(float temp) { extrude_min_temp = temp; }
#endif
// Calculate the steps/s^2 acceleration rates, based on the mm/s^s
void reset_acceleration_rates()
{
for(int8_t i=0; i < 3 + EXTRUDERS; i++) {
void reset_acceleration_rates() {
for(int8_t i=0; i < E_AXIS + EXTRUDERS; i++)
axis_steps_per_sqr_second[i] = max_acceleration_units_per_sq_second[i] * axis_steps_per_unit[i];
}
}
......@@ -34,7 +34,7 @@
// the source g-code and may never actually be reached if acceleration management is active.
typedef struct {
// Fields used by the bresenham algorithm for tracing the line
long steps_x, steps_y, steps_z, steps_e; // Step count along each axis
long steps[NUM_AXIS]; // Step count along each axis
unsigned long step_event_count; // The number of step events required to complete this block
long accelerate_until; // The index of the step event on which to stop acceleration
long decelerate_after; // The index of the step event on which to start decelerating
......@@ -49,7 +49,7 @@ typedef struct {
#endif
// Fields used by the motion planner to manage acceleration
// float speed_x, speed_y, speed_z, speed_e; // Nominal mm/sec for each axis
// float speed_x, speed_y, speed_z, speed_e; // Nominal mm/sec for each axis
float nominal_speed; // The nominal speed for this block in mm/sec
float entry_speed; // Entry speed at previous-current junction in mm/sec
float max_entry_speed; // Maximum allowable junction entry speed in mm/sec
......@@ -74,40 +74,36 @@ typedef struct {
volatile char busy;
} block_t;
#ifdef ENABLE_AUTO_BED_LEVELING
// this holds the required transform to compensate for bed level
extern matrix_3x3 plan_bed_level_matrix;
#endif // #ifdef ENABLE_AUTO_BED_LEVELING
#define BLOCK_MOD(n) ((n)&(BLOCK_BUFFER_SIZE-1))
// Initialize the motion plan subsystem
void plan_init();
// Add a new linear movement to the buffer. x, y and z is the signed, absolute target position in
// millimaters. Feed rate specifies the speed of the motion.
#ifdef ENABLE_AUTO_BED_LEVELING
void plan_buffer_line(float x, float y, float z, const float &e, float feed_rate, const uint8_t &extruder, const uint8_t &driver);
void check_axes_activity();
// Get the position applying the bed level matrix if enabled
vector_3 plan_get_position();
#else
void plan_buffer_line(const float &x, const float &y, const float &z, const float &e, float feed_rate, const uint8_t &extruder, const uint8_t &driver);
#endif // ENABLE_AUTO_BED_LEVELING
// Get the number of buffered moves
extern volatile unsigned char block_buffer_head;
extern volatile unsigned char block_buffer_tail;
FORCE_INLINE uint8_t movesplanned() { return BLOCK_MOD(block_buffer_head - block_buffer_tail + BLOCK_BUFFER_SIZE); }
// Set position. Used for G92 instructions.
#ifdef ENABLE_AUTO_BED_LEVELING
void plan_set_position(float x, float y, float z, const float &e);
#include "vector_3.h"
// this holds the required transform to compensate for bed level
extern matrix_3x3 plan_bed_level_matrix;
// Get the position applying the bed level matrix if enabled
vector_3 plan_get_position();
// Add a new linear movement to the buffer. x, y and z is the signed, absolute target position in
// millimeters. Feed rate specifies the speed of the motion.
void plan_buffer_line(float x, float y, float z, const float &e, float feed_rate, const uint8_t &extruder, const uint8_t &driver);
// Set position. Used for G92 instructions.
void plan_set_position(float x, float y, float z, const float &e);
#else
void plan_set_position(const float &x, const float &y, const float &z, const float &e);
void plan_buffer_line(const float &x, const float &y, const float &z, const float &e, float feed_rate, const uint8_t &extruder, const uint8_t &driver);
void plan_set_position(const float &x, const float &y, const float &z, const float &e);
#endif // ENABLE_AUTO_BED_LEVELING
void plan_set_e_position(const float &e);
void check_axes_activity();
uint8_t movesplanned(); //return the nr of buffered moves
extern unsigned long minsegmenttime;
extern float max_feedrate[3 + EXTRUDERS]; // set the max speeds
extern float max_retraction_feedrate[EXTRUDERS]; // set the max speeds for retraction
......@@ -124,41 +120,39 @@ extern float mintravelfeedrate;
extern unsigned long axis_steps_per_sqr_second[3 + EXTRUDERS];
#ifdef AUTOTEMP
extern bool autotemp_enabled;
extern float autotemp_max;
extern float autotemp_min;
extern float autotemp_factor;
extern bool autotemp_enabled;
extern float autotemp_max;
extern float autotemp_min;
extern float autotemp_factor;
#endif
extern block_t block_buffer[BLOCK_BUFFER_SIZE]; // A ring buffer for motion instfructions
extern volatile unsigned char block_buffer_head; // Index of the next block to be pushed
extern volatile unsigned char block_buffer_tail;
// Called when the current block is no longer needed. Discards the block and makes the memory
// availible for new blocks.
FORCE_INLINE void plan_discard_current_block()
{
if (block_buffer_head != block_buffer_tail) {
block_buffer_tail = (block_buffer_tail + 1) & (BLOCK_BUFFER_SIZE - 1);
}
extern block_t block_buffer[BLOCK_BUFFER_SIZE]; // A ring buffer for motion instructions
// Returns true if the buffer has a queued block, false otherwise
FORCE_INLINE bool blocks_queued() { return (block_buffer_head != block_buffer_tail); }
// Called when the current block is no longer needed. Discards
// the block and makes the memory available for new blocks.
FORCE_INLINE void plan_discard_current_block() {
if (blocks_queued())
block_buffer_tail = BLOCK_MOD(block_buffer_tail + 1);
}
// Gets the current block. Returns NULL if buffer empty
FORCE_INLINE block_t *plan_get_current_block()
{
if (block_buffer_head == block_buffer_tail) {
return(NULL);
FORCE_INLINE block_t *plan_get_current_block() {
if (blocks_queued()) {
block_t *block = &block_buffer[block_buffer_tail];
block->busy = true;
return block;
}
block_t *block = &block_buffer[block_buffer_tail];
block->busy = true;
return(block);
else
return NULL;
}
// Returns true if the buffer has a queued block, false otherwise
FORCE_INLINE bool blocks_queued() { return (block_buffer_head != block_buffer_tail); }
#ifdef PREVENT_DANGEROUS_EXTRUDE
void set_extrude_min_temp(float temp);
void set_extrude_min_temp(float temp);
#endif
void reset_acceleration_rates();
#endif
#endif //PLANNER_H
......@@ -49,6 +49,12 @@ block_t *current_block; // A pointer to the block currently being traced
static unsigned char out_bits; // The next stepping-bits to be output
static unsigned int cleaning_buffer_counter;
#ifdef Z_DUAL_ENDSTOPS
static bool performing_homing = false,
locked_z_motor = false,
locked_z2_motor = false;
#endif
// Counter variables for the bresenham line tracer
static long counter_x, counter_y, counter_z, counter_e;
volatile static unsigned long step_events_completed; // The number of step events executed in the current block
......@@ -73,8 +79,8 @@ static volatile bool endstop_y_hit = false;
static volatile bool endstop_z_hit = false;
#ifdef NPR2
static volatile bool endstop_e_hit=false;
static bool old_e_min_endstop=false;
static volatile bool endstop_e_hit = false;
static bool old_e_min_endstop = false;
#endif
#ifdef ABORT_ON_ENDSTOP_HIT_FEATURE_ENABLED
......@@ -89,7 +95,13 @@ static bool old_x_min_endstop = false,
old_y_min_endstop = false,
old_y_max_endstop = false,
old_z_min_endstop = false,
old_z_max_endstop = false;
#ifndef Z_DUAL_ENDSTOPS
old_z_max_endstop = false;
#else
old_z_max_endstop = false,
old_z2_min_endstop = false,
old_z2_max_endstop = false;
#endif
static bool check_endstops = true;
......@@ -133,7 +145,27 @@ volatile signed char count_direction[NUM_AXIS] = { 1, 1, 1, 1 };
#ifdef Z_DUAL_STEPPER_DRIVERS
#define Z_APPLY_DIR(v,Q) { Z_DIR_WRITE(v); Z2_DIR_WRITE(v); }
<<<<<<< HEAD
#define Z_APPLY_STEP(v,Q) { Z_STEP_WRITE(v); Z2_STEP_WRITE(v); }
=======
#ifdef Z_DUAL_ENDSTOPS
#define Z_APPLY_STEP(v,Q) \
if (performing_homing) { \
if (Z_HOME_DIR > 0) {\
if (!(old_z_max_endstop && (count_direction[Z_AXIS] > 0)) && !locked_z_motor) Z_STEP_WRITE(v); \
if (!(old_z2_max_endstop && (count_direction[Z_AXIS] > 0)) && !locked_z2_motor) Z2_STEP_WRITE(v); \
} else {\
if (!(old_z_min_endstop && (count_direction[Z_AXIS] < 0)) && !locked_z_motor) Z_STEP_WRITE(v); \
if (!(old_z2_min_endstop && (count_direction[Z_AXIS] < 0)) && !locked_z2_motor) Z2_STEP_WRITE(v); \
} \
} else { \
Z_STEP_WRITE(v); \
Z2_STEP_WRITE(v); \
}
#else
#define Z_APPLY_STEP(v,Q) Z_STEP_WRITE(v), Z2_STEP_WRITE(v)
#endif
>>>>>>> origin/master
#else
#define Z_APPLY_DIR(v,Q) Z_DIR_WRITE(v)
#define Z_APPLY_STEP(v,Q) Z_STEP_WRITE(v)
......@@ -417,7 +449,7 @@ ISR(TIMER1_COMPA_vect) {
step_events_completed = 0;
#ifdef Z_LATE_ENABLE
if (current_block->steps_z > 0) {
if (current_block->steps[Z_AXIS] > 0) {
enable_z();
OCR1A = 2000; //1ms wait
return;
......@@ -458,7 +490,7 @@ ISR(TIMER1_COMPA_vect) {
#define UPDATE_ENDSTOP(axis,AXIS,minmax,MINMAX) \
bool axis ##_## minmax ##_endstop = (READ(AXIS ##_## MINMAX ##_PIN) != AXIS ##_## MINMAX ##_ENDSTOP_INVERTING); \
if (axis ##_## minmax ##_endstop && old_## axis ##_## minmax ##_endstop && (current_block->steps_## axis > 0)) { \
if (axis ##_## minmax ##_endstop && old_## axis ##_## minmax ##_endstop && (current_block->steps[AXIS ##_AXIS] > 0)) { \
endstops_trigsteps[AXIS ##_AXIS] = count_position[AXIS ##_AXIS]; \
endstop_## axis ##_hit = true; \
step_events_completed = current_block->step_event_count; \
......@@ -467,80 +499,117 @@ ISR(TIMER1_COMPA_vect) {
// Check X and Y endstops
if (check_endstops) {
#ifndef COREXY
if (TEST(out_bits, X_AXIS)) // stepping along -X axis (regular cartesians bot)
#else
#ifdef COREXY
// Head direction in -X axis for CoreXY bots.
// If DeltaX == -DeltaY, the movement is only in Y axis
if (current_block->steps_x != current_block->steps_y || (TEST(out_bits, X_AXIS) == TEST(out_bits, Y_AXIS)))
if (TEST(out_bits, X_HEAD))
if (current_block->steps[A_AXIS] != current_block->steps[B_AXIS] || (TEST(out_bits, A_AXIS) == TEST(out_bits, B_AXIS)))
if (TEST(out_bits, X_HEAD))
#else
if (TEST(out_bits, X_AXIS)) // stepping along -X axis (regular cartesians bot)
#endif
{ // -direction
#ifdef DUAL_X_CARRIAGE
// with 2 x-carriages, endstops are only checked in the homing direction for the active extruder
if ((current_block->active_extruder == 0 && X_HOME_DIR == -1) || (current_block->active_extruder != 0 && X2_HOME_DIR == -1))
#endif
{
#if defined(X_MIN_PIN) && X_MIN_PIN >= 0
UPDATE_ENDSTOP(x, X, min, MIN);
#endif
}
}
else { // +direction
#ifdef DUAL_X_CARRIAGE
// with 2 x-carriages, endstops are only checked in the homing direction for the active extruder
if ((current_block->active_driver == 0 && X_HOME_DIR == 1) || (current_block->active_extruder != 0 && X2_HOME_DIR == 1))
#endif
{
#if defined(X_MAX_PIN) && X_MAX_PIN >= 0
UPDATE_ENDSTOP(x, X, max, MAX);
#endif
}
}
#ifndef COREXY
{ // -direction
#ifdef DUAL_X_CARRIAGE
// with 2 x-carriages, endstops are only checked in the homing direction for the active extruder
if ((current_block->active_extruder == 0 && X_HOME_DIR == -1) || (current_block->active_extruder != 0 && X2_HOME_DIR == -1))
#endif
{
#if defined(X_MIN_PIN) && X_MIN_PIN >= 0
UPDATE_ENDSTOP(x, X, min, MIN);
#endif
}
}
else { // +direction
#ifdef DUAL_X_CARRIAGE
// with 2 x-carriages, endstops are only checked in the homing direction for the active extruder
if ((current_block->active_driver == 0 && X_HOME_DIR == 1) || (current_block->active_extruder != 0 && X2_HOME_DIR == 1))
#endif
{
#if defined(X_MAX_PIN) && X_MAX_PIN >= 0
UPDATE_ENDSTOP(x, X, max, MAX);
#endif
}
}
#ifdef COREXY
// Head direction in -Y axis for CoreXY bots.
// If DeltaX == DeltaY, the movement is only in X axis
if (current_block->steps[A_AXIS] != current_block->steps[B_AXIS] || (TEST(out_bits, A_AXIS) != TEST(out_bits, B_AXIS)))
if (TEST(out_bits, Y_HEAD))
#else
if (TEST(out_bits, Y_AXIS)) // -direction
#else
// Head direction in -Y axis for CoreXY bots.
// If DeltaX == DeltaY, the movement is only in X axis
if (current_block->steps_x != current_block->steps_y || (TEST(out_bits, X_AXIS) != TEST(out_bits, Y_AXIS)))
if (TEST(out_bits, Y_HEAD))
#endif
{ // -direction
#if defined(Y_MIN_PIN) && Y_MIN_PIN >= 0
UPDATE_ENDSTOP(y, Y, min, MIN);
#endif
}
else { // +direction
#if defined(Y_MAX_PIN) && Y_MAX_PIN >= 0
UPDATE_ENDSTOP(y, Y, max, MAX);
#endif
}
#endif
{ // -direction
#if defined(Y_MIN_PIN) && Y_MIN_PIN >= 0
UPDATE_ENDSTOP(y, Y, min, MIN);
#endif
}
else { // +direction
#if defined(Y_MAX_PIN) && Y_MAX_PIN >= 0
UPDATE_ENDSTOP(y, Y, max, MAX);
#endif
}
}
if (TEST(out_bits, Z_AXIS)) { // -direction
Z_DIR_WRITE(INVERT_Z_DIR);
#ifdef Z_DUAL_STEPPER_DRIVERS
Z2_DIR_WRITE(INVERT_Z_DIR);
#endif
Z_APPLY_DIR(INVERT_Z_DIR,0);
count_direction[Z_AXIS] = -1;
if (check_endstops) {
#if defined(Z_MIN_PIN) && Z_MIN_PIN >= 0
UPDATE_ENDSTOP(z, Z, min, MIN);
if (check_endstops)
{
#if defined(Z_MIN_PIN) && Z_MIN_PIN > -1
#ifndef Z_DUAL_ENDSTOPS
UPDATE_ENDSTOP(z, Z, min, MIN);
#else
bool z_min_endstop=(READ(Z_MIN_PIN) != Z_MIN_ENDSTOP_INVERTING);
#if defined(Z2_MIN_PIN) && Z2_MIN_PIN > -1
bool z2_min_endstop=(READ(Z2_MIN_PIN) != Z2_MIN_ENDSTOP_INVERTING);
#else
bool z2_min_endstop=z_min_endstop;
#endif
if(((z_min_endstop && old_z_min_endstop) || (z2_min_endstop && old_z2_min_endstop)) && (current_block->steps[Z_AXIS] > 0))
{
endstops_trigsteps[Z_AXIS] = count_position[Z_AXIS];
endstop_z_hit=true;
if (!(performing_homing) || ((performing_homing)&&(z_min_endstop && old_z_min_endstop)&&(z2_min_endstop && old_z2_min_endstop))) //if not performing home or if both endstops were trigged during homing...
{
step_events_completed = current_block->step_event_count;
}
}
old_z_min_endstop = z_min_endstop;
old_z2_min_endstop = z2_min_endstop;
#endif
#endif
}
}
else { // +direction
Z_DIR_WRITE(!INVERT_Z_DIR);
#ifdef Z_DUAL_STEPPER_DRIVERS
Z2_DIR_WRITE(!INVERT_Z_DIR);
#endif
Z_APPLY_DIR(!INVERT_Z_DIR,0);
count_direction[Z_AXIS] = 1;
if (check_endstops) {
#if defined(Z_MAX_PIN) && Z_MAX_PIN >= 0
UPDATE_ENDSTOP(z, Z, max, MAX);
#ifndef Z_DUAL_ENDSTOPS
UPDATE_ENDSTOP(z, Z, max, MAX);
#else
bool z_max_endstop=(READ(Z_MAX_PIN) != Z_MAX_ENDSTOP_INVERTING);
#if defined(Z2_MAX_PIN) && Z2_MAX_PIN > -1
bool z2_max_endstop=(READ(Z2_MAX_PIN) != Z2_MAX_ENDSTOP_INVERTING);
#else
bool z2_max_endstop=z_max_endstop;
#endif
if(((z_max_endstop && old_z_max_endstop) || (z2_max_endstop && old_z2_max_endstop)) && (current_block->steps[Z_AXIS] > 0))
{
endstops_trigsteps[Z_AXIS] = count_position[Z_AXIS];
endstop_z_hit=true;
// if (z_max_endstop && old_z_max_endstop) SERIAL_ECHOLN("z_max_endstop = true");
// if (z2_max_endstop && old_z2_max_endstop) SERIAL_ECHOLN("z2_max_endstop = true");
if (!(performing_homing) || ((performing_homing)&&(z_max_endstop && old_z_max_endstop)&&(z2_max_endstop && old_z2_max_endstop))) //if not performing home or if both endstops were trigged during homing...
{
step_events_completed = current_block->step_event_count;
}
}
old_z_max_endstop = z_max_endstop;
old_z2_max_endstop = z2_max_endstop;
#endif
#endif
}
}
......@@ -553,9 +622,9 @@ ISR(TIMER1_COMPA_vect) {
if (check_endstops) {
#if defined(E_MIN_PIN) && E_MIN_PIN > -1
bool e_min_endstop=(READ(E_MIN_PIN) != E_MIN_ENDSTOP_INVERTING);
if (e_min_endstop && old_e_min_endstop && (current_block->steps_e > 0)) {
if (e_min_endstop && old_e_min_endstop && (current_block->steps[E_AXIS] > 0)) {
endstops_trigsteps[E_AXIS] = count_position[E_AXIS];
endstop_e_hit=true;
endstop_e_hit = true;
step_events_completed = current_block->step_event_count;
}
old_e_min_endstop = e_min_endstop;
......@@ -576,7 +645,7 @@ ISR(TIMER1_COMPA_vect) {
#endif
#ifdef ADVANCE
counter_e += current_block->steps_e;
counter_e += current_block->steps[E_AXIS];
if (counter_e > 0) {
counter_e -= current_block->step_event_count;
e_steps[current_block->active_driver] += TEST(out_bits, E_AXIS) ? -1 : 1;
......@@ -590,15 +659,14 @@ ISR(TIMER1_COMPA_vect) {
* instead of doing each in turn. The extra tests add enough
* lag to allow it work with without needing NOPs
*/
counter_x += current_block->steps_x;
if (counter_x > 0) X_STEP_WRITE(HIGH);
counter_y += current_block->steps_y;
if (counter_y > 0) Y_STEP_WRITE(HIGH);
counter_z += current_block->steps_z;
if (counter_z > 0) Z_STEP_WRITE(HIGH);
#define STEP_ADD(axis, AXIS) \
counter_## axis += current_block->steps[AXIS ##_AXIS]; \
if (counter_## axis > 0) { AXIS ##_STEP_WRITE(HIGH); }
STEP_ADD(x,X);
STEP_ADD(y,Y);
STEP_ADD(z,Z);
#ifndef ADVANCE
counter_e += current_block->steps_e;
if (counter_e > 0) E_STEP_WRITE(HIGH);
STEP_ADD(e,E);
#endif
#define STEP_IF_COUNTER(axis, AXIS) \
......@@ -618,7 +686,7 @@ ISR(TIMER1_COMPA_vect) {
#else // !CONFIG_STEPPERS_TOSHIBA
#define APPLY_MOVEMENT(axis, AXIS) \
counter_## axis += current_block->steps_## axis; \
counter_## axis += current_block->steps[AXIS ##_AXIS]; \
if (counter_## axis > 0) { \
AXIS ##_APPLY_STEP(!INVERT_## AXIS ##_STEP_PIN,0); \
counter_## axis -= current_block->step_event_count; \
......@@ -931,6 +999,13 @@ void st_init() {
#endif
#endif
#if defined(Z2_MAX_PIN) && Z2_MAX_PIN >= 0
SET_INPUT(Z2_MAX_PIN);
#ifdef ENDSTOPPULLUP_ZMAX
WRITE(Z2_MAX_PIN,HIGH);
#endif
#endif
#define AXIS_INIT(axis, AXIS, PIN) \
AXIS ##_STEP_INIT; \
AXIS ##_STEP_WRITE(INVERT_## PIN ##_STEP_PIN); \
......@@ -1275,3 +1350,9 @@ void microstep_readings() {
SERIAL_PROTOCOLLN(digitalRead(E1_MS2_PIN));
#endif
}
#ifdef Z_DUAL_ENDSTOPS
void In_Homing_Process(bool state) { performing_homing = state; }
void Lock_z_motor(bool state) { locked_z_motor = state; }
void Lock_z2_motor(bool state) { locked_z2_motor = state; }
#endif
......@@ -97,6 +97,12 @@ void digipot_current(uint8_t driver, int current);
void microstep_init();
void microstep_readings();
#ifdef Z_DUAL_ENDSTOPS
void In_Homing_Process(bool state);
void Lock_z_motor(bool state);
void Lock_z2_motor(bool state);
#endif
#ifdef BABYSTEPPING
void babystep(const uint8_t axis,const bool direction); // perform a short step with a single stepper motor, outside of any convention
#endif //BABYSTEPPING
......
......@@ -41,6 +41,7 @@
//================================== macros =================================
//===========================================================================
<<<<<<< HEAD
#if HOTENDS > 4
#error Unsupported number of hotends
#elif HOTENDS > 3
......@@ -71,11 +72,21 @@
#define HAS_AUTO_FAN_3 (defined(EXTRUDER_3_AUTO_FAN_PIN) && EXTRUDER_3_AUTO_FAN_PIN >= 0)
#define HAS_AUTO_FAN HAS_AUTO_FAN_0 || HAS_AUTO_FAN_1 || HAS_AUTO_FAN_2 || HAS_AUTO_FAN_3
#define HAS_FAN (defined(FAN_PIN) && FAN_PIN >= 0)
=======
#ifdef K1 // Defined in Configuration.h in the PID settings
#define K2 (1.0 - K1)
#endif
#if defined(PIDTEMPBED) || defined(PIDTEMP)
#define PID_dT ((OVERSAMPLENR * 14.0)/(F_CPU / 64.0 / 256.0))
#endif
>>>>>>> origin/master
//===========================================================================
//============================= public variables ============================
//===========================================================================
<<<<<<< HEAD
// Sampling period of the temperature routine
#ifdef PID_dT
#undef PID_dT
......@@ -86,16 +97,24 @@ int target_temperature[HOTENDS] = { 0 };
int current_temperature_raw[HOTENDS] = { 0 };
float current_temperature[HOTENDS] = { 0.0 };
=======
int target_temperature[HOTENDS] = { 0 };
>>>>>>> origin/master
int target_temperature_bed = 0;
int current_temperature_raw[HOTENDS] = { 0 };
float current_temperature[HOTENDS] = { 0.0 };
int current_temperature_bed_raw = 0;
float current_temperature_bed = 0.0;
#ifdef TEMP_SENSOR_1_AS_REDUNDANT
int redundant_temperature_raw = 0;
float redundant_temperature = 0.0;
#endif
<<<<<<< HEAD
#ifdef PIDTEMP
float Kp[HOTENDS],Ki[HOTENDS],Kd[HOTENDS];
#endif //PIDTEMP
=======
>>>>>>> origin/master
#ifdef PIDTEMPBED
float bedKp=DEFAULT_bedKp;
......@@ -119,6 +138,7 @@ unsigned char soft_pwm_bed;
#if HAS_POWER_CONSUMPTION_SENSOR
int current_raw_powconsumption = 0; //Holds measured power consumption
static unsigned long raw_powconsumption_value = 0;
#endif
//===========================================================================
......@@ -162,11 +182,18 @@ static unsigned char soft_pwm[HOTENDS];
#if HAS_AUTO_FAN
static unsigned long extruder_autofan_last_check;
#endif
#ifdef PIDTEMP
float Kp[HOTENDS], Ki[HOTENDS], Kd[HOTENDS];
#endif //PIDTEMP
// Init min and max temp with extreme values to prevent false errors during startup
static int minttemp_raw[HOTENDS] = ARRAY_BY_HOTENDS( HEATER_0_RAW_LO_TEMP , HEATER_1_RAW_LO_TEMP , HEATER_2_RAW_LO_TEMP, HEATER_3_RAW_LO_TEMP);
static int maxttemp_raw[HOTENDS] = ARRAY_BY_HOTENDS( HEATER_0_RAW_HI_TEMP , HEATER_1_RAW_HI_TEMP , HEATER_2_RAW_HI_TEMP, HEATER_3_RAW_HI_TEMP);
<<<<<<< HEAD
static int minttemp[HOTENDS] = ARRAY_BY_HOTENDS( 0, 0, 0, 0 );
=======
static int minttemp[HOTENDS] = { 0 };
>>>>>>> origin/master
static int maxttemp[HOTENDS] = ARRAY_BY_HOTENDS( 16383, 16383, 16383, 16383 );
//static int bed_minttemp_raw = HEATER_BED_RAW_LO_TEMP; /* No bed mintemp error implemented?!? */
......@@ -187,8 +214,13 @@ static float analog2tempBed(int raw);
static void updateTemperaturesFromRawValues();
#ifdef WATCH_TEMP_PERIOD
<<<<<<< HEAD
int watch_start_temp[HOTENDS] = ARRAY_BY_HOTENDS(0,0,0,0);
unsigned long watchmillis[HOTENDS] = ARRAY_BY_HOTENDS(0,0,0,0);
=======
int watch_start_temp[HOTENDS] = { 0 };
unsigned long watchmillis[HOTENDS] = { 0 };
>>>>>>> origin/master
#endif //WATCH_TEMP_PERIOD
#ifndef SOFT_PWM_SCALE
......@@ -204,7 +236,7 @@ static void updateTemperaturesFromRawValues();
#endif
//===========================================================================
//============================= functions ============================
//============================= Functions ============================
//===========================================================================
void PID_autotune(float temp, int hotend, int ncycles)
......@@ -367,7 +399,11 @@ void PID_autotune(float temp, int hotend, int ncycles)
void updatePID() {
#ifdef PIDTEMP
for (int e = 0; e < HOTENDS; e++) {
<<<<<<< HEAD
temp_iState_max[e] = PID_INTEGRAL_DRIVE_MAX / Ki[e];
=======
temp_iState_max[e] = PID_INTEGRAL_DRIVE_MAX / PID_PARAM(Ki,e);
>>>>>>> origin/master
}
#endif
#ifdef PIDTEMPBED
......@@ -380,6 +416,7 @@ int getHeaterPower(int heater) {
}
#if HAS_AUTO_FAN
<<<<<<< HEAD
#if HAS_FAN
#if EXTRUDER_0_AUTO_FAN_PIN == FAN_PIN
#error "You cannot set EXTRUDER_0_AUTO_FAN_PIN equal to FAN_PIN"
......@@ -467,11 +504,88 @@ int getHeaterPower(int heater) {
setExtruderAutoFanState(EXTRUDER_3_AUTO_FAN_PIN, (fanState & 8) != 0);
#endif
}
=======
void setExtruderAutoFanState(int pin, bool state)
{
unsigned char newFanSpeed = (state != 0) ? EXTRUDER_AUTO_FAN_SPEED : 0;
// this idiom allows both digital and PWM fan outputs (see M42 handling).
pinMode(pin, OUTPUT);
digitalWrite(pin, newFanSpeed);
analogWrite(pin, newFanSpeed);
}
void checkExtruderAutoFans()
{
uint8_t fanState = 0;
// which fan pins need to be turned on?
#if HAS_AUTO_FAN_0
if (current_temperature[0] > EXTRUDER_AUTO_FAN_TEMPERATURE)
fanState |= 1;
#endif
#if HAS_AUTO_FAN_1
if (current_temperature[1] > EXTRUDER_AUTO_FAN_TEMPERATURE)
{
if (EXTRUDER_1_AUTO_FAN_PIN == EXTRUDER_0_AUTO_FAN_PIN)
fanState |= 1;
else
fanState |= 2;
}
#endif
#if HAS_AUTO_FAN_2
if (current_temperature[2] > EXTRUDER_AUTO_FAN_TEMPERATURE)
{
if (EXTRUDER_2_AUTO_FAN_PIN == EXTRUDER_0_AUTO_FAN_PIN)
fanState |= 1;
else if (EXTRUDER_2_AUTO_FAN_PIN == EXTRUDER_1_AUTO_FAN_PIN)
fanState |= 2;
else
fanState |= 4;
}
#endif
#if HAS_AUTO_FAN_3
if (current_temperature[3] > EXTRUDER_AUTO_FAN_TEMPERATURE)
{
if (EXTRUDER_3_AUTO_FAN_PIN == EXTRUDER_0_AUTO_FAN_PIN)
fanState |= 1;
else if (EXTRUDER_3_AUTO_FAN_PIN == EXTRUDER_1_AUTO_FAN_PIN)
fanState |= 2;
else if (EXTRUDER_3_AUTO_FAN_PIN == EXTRUDER_2_AUTO_FAN_PIN)
fanState |= 4;
else
fanState |= 8;
}
#endif
// update extruder auto fan states
#if HAS_AUTO_FAN_0
setExtruderAutoFanState(EXTRUDER_0_AUTO_FAN_PIN, (fanState & 1) != 0);
#endif
#if HAS_AUTO_FAN_1
if (EXTRUDER_1_AUTO_FAN_PIN != EXTRUDER_0_AUTO_FAN_PIN)
setExtruderAutoFanState(EXTRUDER_1_AUTO_FAN_PIN, (fanState & 2) != 0);
#endif
#if HAS_AUTO_FAN_2
if (EXTRUDER_2_AUTO_FAN_PIN != EXTRUDER_0_AUTO_FAN_PIN
&& EXTRUDER_2_AUTO_FAN_PIN != EXTRUDER_1_AUTO_FAN_PIN)
setExtruderAutoFanState(EXTRUDER_2_AUTO_FAN_PIN, (fanState & 4) != 0);
#endif
#if HAS_AUTO_FAN_3
if (EXTRUDER_3_AUTO_FAN_PIN != EXTRUDER_0_AUTO_FAN_PIN
&& EXTRUDER_3_AUTO_FAN_PIN != EXTRUDER_1_AUTO_FAN_PIN
&& EXTRUDER_3_AUTO_FAN_PIN != EXTRUDER_2_AUTO_FAN_PIN)
setExtruderAutoFanState(EXTRUDER_3_AUTO_FAN_PIN, (fanState & 8) != 0);
#endif
}
>>>>>>> origin/master
#endif // any extruder auto fan pins set
//
// Error checking and Write Routines
// Temperature Error Handlers
//
<<<<<<< HEAD
#if HOTENDS > 0
#if !HAS_HEATER_0
#error HEATER_0_PIN not defined for this board
......@@ -510,6 +624,8 @@ int getHeaterPower(int heater) {
#define WRITE_FAN(v) WRITE(FAN_PIN, v)
#endif
=======
>>>>>>> origin/master
inline void _temp_error(int e, const char *msg1, const char *msg2) {
if (!IsStopped()) {
SERIAL_ERROR_START;
......@@ -540,12 +656,117 @@ void bed_max_temp_error(void) {
_temp_error(-1, PSTR(MSG_MAXTEMP_BED_OFF), PSTR(MSG_ERR_MAXTEMP_BED));
}
float get_pid_output(int e) {
float pid_output;
#ifdef PIDTEMP
#ifndef PID_OPENLOOP
pid_error[e] = target_temperature[e] - current_temperature[e];
if (pid_error[e] > PID_FUNCTIONAL_RANGE) {
pid_output = BANG_MAX;
pid_reset[e] = true;
}
else if (pid_error[e] < -PID_FUNCTIONAL_RANGE || target_temperature[e] == 0) {
pid_output = 0;
pid_reset[e] = true;
}
else {
if (pid_reset[e]) {
temp_iState[e] = 0.0;
pid_reset[e] = false;
}
pTerm[e] = PID_PARAM(Kp,e) * pid_error[e];
temp_iState[e] += pid_error[e];
temp_iState[e] = constrain(temp_iState[e], temp_iState_min[e], temp_iState_max[e]);
iTerm[e] = PID_PARAM(Ki,e) * temp_iState[e];
dTerm[e] = K2 * PID_PARAM(Kd,e) * (current_temperature[e] - temp_dState[e]) + K1 * dTerm[e];
pid_output = pTerm[e] + iTerm[e] - dTerm[e];
if (pid_output > PID_MAX) {
if (pid_error[e] > 0) temp_iState[e] -= pid_error[e]; // conditional un-integration
pid_output = PID_MAX;
}
else if (pid_output < 0) {
if (pid_error[e] < 0) temp_iState[e] -= pid_error[e]; // conditional un-integration
pid_output = 0;
}
}
temp_dState[e] = current_temperature[e];
#else
pid_output = constrain(target_temperature[e], 0, PID_MAX);
#endif //PID_OPENLOOP
#ifdef PID_DEBUG
SERIAL_ECHO_START;
SERIAL_ECHO(MSG_PID_DEBUG);
SERIAL_ECHO(e);
SERIAL_ECHO(MSG_PID_DEBUG_INPUT);
SERIAL_ECHO(current_temperature[e]);
SERIAL_ECHO(MSG_PID_DEBUG_OUTPUT);
SERIAL_ECHO(pid_output);
SERIAL_ECHO(MSG_PID_DEBUG_PTERM);
SERIAL_ECHO(pTerm[e]);
SERIAL_ECHO(MSG_PID_DEBUG_ITERM);
SERIAL_ECHO(iTerm[e]);
SERIAL_ECHO(MSG_PID_DEBUG_DTERM);
SERIAL_ECHOLN(dTerm[e]);
#endif //PID_DEBUG
#else /* PID off */
pid_output = (current_temperature[e] < target_temperature[e]) ? PID_MAX : 0;
#endif
return pid_output;
}
#ifdef PIDTEMPBED
float get_pid_output_bed() {
float pid_output;
#ifndef PID_OPENLOOP
pid_error_bed = target_temperature_bed - current_temperature_bed;
pTerm_bed = bedKp * pid_error_bed;
temp_iState_bed += pid_error_bed;
temp_iState_bed = constrain(temp_iState_bed, temp_iState_min_bed, temp_iState_max_bed);
iTerm_bed = bedKi * temp_iState_bed;
dTerm_bed = K2 * bedKd * (current_temperature_bed - temp_dState_bed) + K1 * dTerm_bed;
temp_dState_bed = current_temperature_bed;
pid_output = pTerm_bed + iTerm_bed - dTerm_bed;
if (pid_output > MAX_BED_POWER) {
if (pid_error_bed > 0) temp_iState_bed -= pid_error_bed; // conditional un-integration
pid_output = MAX_BED_POWER;
}
else if (pid_output < 0) {
if (pid_error_bed < 0) temp_iState_bed -= pid_error_bed; // conditional un-integration
pid_output = 0;
}
#else
pid_output = constrain(target_temperature_bed, 0, MAX_BED_POWER);
#endif // PID_OPENLOOP
#ifdef PID_BED_DEBUG
SERIAL_ECHO_START;
SERIAL_ECHO(" PID_BED_DEBUG ");
SERIAL_ECHO(": Input ");
SERIAL_ECHO(current_temperature_bed);
SERIAL_ECHO(" Output ");
SERIAL_ECHO(pid_output);
SERIAL_ECHO(" pTerm ");
SERIAL_ECHO(pTerm_bed);
SERIAL_ECHO(" iTerm ");
SERIAL_ECHO(iTerm_bed);
SERIAL_ECHO(" dTerm ");
SERIAL_ECHOLN(dTerm_bed);
#endif //PID_BED_DEBUG
return pid_output;
}
#endif
void manage_heater() {
if (!temp_meas_ready) return;
float pid_input, pid_output;
updateTemperaturesFromRawValues();
#ifdef HEATER_0_USES_MAX6675
......@@ -557,74 +778,18 @@ void manage_heater() {
unsigned long ms = millis();
// Loop through all hotends
<<<<<<< HEAD
for (int e = 0; e < HOTENDS; e++)
{
=======
for (int e = 0; e < HOTENDS; e++) {
>>>>>>> origin/master
#if defined (THERMAL_RUNAWAY_PROTECTION_PERIOD) && THERMAL_RUNAWAY_PROTECTION_PERIOD > 0
thermal_runaway_protection(&thermal_runaway_state_machine[e], &thermal_runaway_timer[e], current_temperature[e], target_temperature[e], e, THERMAL_RUNAWAY_PROTECTION_PERIOD, THERMAL_RUNAWAY_PROTECTION_HYSTERESIS);
#endif
#ifdef PIDTEMP
pid_input = current_temperature[e];
#ifndef PID_OPENLOOP
pid_error[e] = target_temperature[e] - pid_input;
if (pid_error[e] > PID_FUNCTIONAL_RANGE) {
pid_output = BANG_MAX;
pid_reset[e] = true;
}
else if (pid_error[e] < -PID_FUNCTIONAL_RANGE || target_temperature[e] == 0) {
pid_output = 0;
pid_reset[e] = true;
}
else {
if (pid_reset[e] == true) {
temp_iState[e] = 0.0;
pid_reset[e] = false;
}
pTerm[e] = Kp[e] * pid_error[e];
temp_iState[e] += pid_error[e];
temp_iState[e] = constrain(temp_iState[e], temp_iState_min[e], temp_iState_max[e]);
iTerm[e] = Ki[e] * temp_iState[e];
//K1 defined in Configuration.h in the PID settings
#define K2 (1.0-K1)
dTerm[e] = (Kd[e] * (pid_input - temp_dState[e])) * K2 + (K1 * dTerm[e]);
pid_output = pTerm[e] + iTerm[e] - dTerm[e];
if (pid_output > PID_MAX) {
if (pid_error[e] > 0) temp_iState[e] -= pid_error[e]; // conditional un-integration
pid_output = PID_MAX;
}
else if (pid_output < 0) {
if (pid_error[e] < 0) temp_iState[e] -= pid_error[e]; // conditional un-integration
pid_output = 0;
}
}
temp_dState[e] = pid_input;
#else
pid_output = constrain(target_temperature[e], 0, PID_MAX);
#endif //PID_OPENLOOP
#ifdef PID_DEBUG
SERIAL_ECHO_START;
SERIAL_ECHO(MSG_PID_DEBUG);
SERIAL_ECHO(e);
SERIAL_ECHO(MSG_PID_DEBUG_INPUT);
SERIAL_ECHO(pid_input);
SERIAL_ECHO(MSG_PID_DEBUG_OUTPUT);
SERIAL_ECHO(pid_output);
SERIAL_ECHO(MSG_PID_DEBUG_PTERM);
SERIAL_ECHO(pTerm[e]);
SERIAL_ECHO(MSG_PID_DEBUG_ITERM);
SERIAL_ECHO(iTerm[e]);
SERIAL_ECHO(MSG_PID_DEBUG_DTERM);
SERIAL_ECHOLN(dTerm[e]);
#endif //PID_DEBUG
#else /* PID off */
pid_output = 0;
if (current_temperature[e] < target_temperature[e]) pid_output = PID_MAX;
#endif //PIDTEMP
float pid_output = get_pid_output(e);
// Check if temperature is within the correct range
soft_pwm[e] = current_temperature[e] > minttemp[e] && current_temperature[e] < maxttemp[e] ? (int)pid_output >> 1 : 0;
......@@ -646,9 +811,13 @@ void manage_heater() {
#ifdef TEMP_SENSOR_1_AS_REDUNDANT
if (fabs(current_temperature[0] - redundant_temperature) > MAX_REDUNDANT_TEMP_SENSOR_DIFF) {
disable_heater();
_temp_error(-1, MSG_EXTRUDER_SWITCHED_OFF, MSG_ERR_REDUNDANT_TEMP);
_temp_error(0, PSTR(MSG_EXTRUDER_SWITCHED_OFF), PSTR(MSG_ERR_REDUNDANT_TEMP));
}
#endif //TEMP_SENSOR_1_AS_REDUNDANT
<<<<<<< HEAD
=======
>>>>>>> origin/master
} // Hotends Loop
#if HAS_AUTO_FAN
......@@ -670,48 +839,7 @@ void manage_heater() {
#endif
#ifdef PIDTEMPBED
pid_input = current_temperature_bed;
#ifndef PID_OPENLOOP
pid_error_bed = target_temperature_bed - pid_input;
pTerm_bed = bedKp * pid_error_bed;
temp_iState_bed += pid_error_bed;
temp_iState_bed = constrain(temp_iState_bed, temp_iState_min_bed, temp_iState_max_bed);
iTerm_bed = bedKi * temp_iState_bed;
//K1 defined in Configuration.h in the PID settings
#define K2 (1.0-K1)
dTerm_bed = (bedKd * (pid_input - temp_dState_bed))*K2 + (K1 * dTerm_bed);
temp_dState_bed = pid_input;
pid_output = pTerm_bed + iTerm_bed - dTerm_bed;
if (pid_output > MAX_BED_POWER) {
if (pid_error_bed > 0) temp_iState_bed -= pid_error_bed; // conditional un-integration
pid_output = MAX_BED_POWER;
}
else if (pid_output < 0) {
if (pid_error_bed < 0) temp_iState_bed -= pid_error_bed; // conditional un-integration
pid_output = 0;
}
#else
pid_output = constrain(target_temperature_bed, 0, MAX_BED_POWER);
#endif //PID_OPENLOOP
#ifdef PID_BED_DEBUG
SERIAL_ECHO_START;
SERIAL_ECHO(" PID_BED_DEBUG ");
SERIAL_ECHO(": Input ");
SERIAL_ECHO(pid_input);
SERIAL_ECHO(" Output ");
SERIAL_ECHO(pid_output);
SERIAL_ECHO(" pTerm ");
SERIAL_ECHO(pTerm_bed);
SERIAL_ECHO(" iTerm ");
SERIAL_ECHO(iTerm_bed);
SERIAL_ECHO(" dTerm ");
SERIAL_ECHOLN(dTerm_bed);
#endif //PID_BED_DEBUG
float pid_output = get_pid_output_bed();
soft_pwm_bed = current_temperature_bed > BED_MINTEMP && current_temperature_bed < BED_MAXTEMP ? (int)pid_output >> 1 : 0;
......@@ -759,11 +887,11 @@ void manage_heater() {
// Derived from RepRap FiveD extruder::getTemperature()
// For hot end temperature measurement.
static float analog2temp(int raw, uint8_t e) {
#ifdef TEMP_SENSOR_1_AS_REDUNDANT
if (e > EXTRUDERS)
#else
if (e >= EXTRUDERS)
#endif
#ifdef TEMP_SENSOR_1_AS_REDUNDANT
if (e > EXTRUDERS)
#else
if (e >= EXTRUDERS)
#endif
{
SERIAL_ERROR_START;
SERIAL_ERROR((int)e);
......@@ -801,7 +929,7 @@ static float analog2temp(int raw, uint8_t e) {
return celsius;
}
return ((raw * ((5.0 * 100) / 1024) / OVERSAMPLENR) * TEMP_SENSOR_AD595_GAIN) + TEMP_SENSOR_AD595_OFFSET;
return ((raw * ((5.0 * 100.0) / 1024.0) / OVERSAMPLENR) * TEMP_SENSOR_AD595_GAIN) + TEMP_SENSOR_AD595_OFFSET;
}
// Derived from RepRap FiveD extruder::getTemperature()
......@@ -828,7 +956,7 @@ static float analog2tempBed(int raw) {
return celsius;
#elif defined BED_USES_AD595
return ((raw * ((5.0 * 100) / 1024) / OVERSAMPLENR) * TEMP_SENSOR_AD595_GAIN) + TEMP_SENSOR_AD595_OFFSET;
return ((raw * ((5.0 * 100.0) / 1024.0) / OVERSAMPLENR) * TEMP_SENSOR_AD595_GAIN) + TEMP_SENSOR_AD595_OFFSET;
#else //NO BED_USES_THERMISTOR
return 0;
#endif //BED_USES_THERMISTOR
......@@ -840,9 +968,13 @@ static void updateTemperaturesFromRawValues() {
#ifdef HEATER_0_USES_MAX6675
current_temperature_raw[0] = read_max6675();
#endif
<<<<<<< HEAD
for (int e = 0; e < HOTENDS; e++)
{
=======
for (int e = 0; e < HOTENDS; e++) {
>>>>>>> origin/master
current_temperature[e] = analog2temp(current_temperature_raw[e], e);
}
current_temperature_bed = analog2tempBed(current_temperature_bed_raw);
......@@ -856,10 +988,10 @@ static void updateTemperaturesFromRawValues() {
static float watt_overflow = 0.0;
static unsigned long last_power_update = millis();
unsigned long temp_last_power_update = millis();
float power_temp = analog2power();
power_consumption_meas = (unsigned int)power_temp;
watt_overflow += (power_temp*(temp_last_power_update-last_power_update))/3600000.0;
if(watt_overflow >= 1.0) {
power_consumption_meas = analog2power();
//MYSERIAL.println(analog2current(),3);
watt_overflow += (power_consumption_meas * (temp_last_power_update - last_power_update)) / 3600000.0;
if (watt_overflow >= 1.0) {
power_consumption_hour++;
watt_overflow--;
}
......@@ -875,9 +1007,10 @@ static void updateTemperaturesFromRawValues() {
#if HAS_FILAMENT_SENSOR
// Convert raw Filament Width to millimeters
float analog2widthFil() {
return current_raw_filwidth / (1024 * OVERSAMPLENR) * 5.0;
return current_raw_filwidth / (1023 * OVERSAMPLENR) * 5.0;
//return current_raw_filwidth;
}
......@@ -895,8 +1028,13 @@ static void updateTemperaturesFromRawValues() {
=======
#if HAS_POWER_CONSUMPTION_SENSOR
// Convert raw Power Consumption to watt
float analog2current() {
float temp = (((5.0 * current_raw_powconsumption) / (1023 * OVERSAMPLENR)) - POWER_ZERO) / POWER_SENSITIVITY;
temp = ((100 - POWER_ERROR) / 100) * (temp + (temp / 100)) - POWER_OFFSET;
return temp > 0 ? temp : 0;
}
float analog2power() {
return (((((5.0 * current_raw_powconsumption) / (1024.0 * OVERSAMPLENR)) - POWER_ZERO) * (POWER_VOLTAGE * 100.0)) / (POWER_SENSITIVITY * POWER_EFFICIENCY));
return (analog2current() * POWER_VOLTAGE * 100) / POWER_EFFICIENCY;
}
#endif
>>>>>>> origin/master
......@@ -910,13 +1048,17 @@ void tp_init()
#endif
// Finish init of mult hotends arrays
<<<<<<< HEAD
for (int e = 0; e < HOTENDS; e++)
{
=======
for (int e = 0; e < HOTENDS; e++) {
>>>>>>> origin/master
// populate with the first value
maxttemp[e] = maxttemp[0];
#ifdef PIDTEMP
temp_iState_min[e] = 0.0;
temp_iState_max[e] = PID_INTEGRAL_DRIVE_MAX / Ki[e];
temp_iState_max[e] = PID_INTEGRAL_DRIVE_MAX / PID_PARAM(Ki,e);
#endif //PIDTEMP
#ifdef PIDTEMPBED
temp_iState_min_bed = 0.0;
......@@ -958,7 +1100,7 @@ void tp_init()
#else
pinMode(SS_PIN, OUTPUT);
digitalWrite(SS_PIN, HIGH);
#endif //SDSUPPORT
#endif
OUT_WRITE(MAX6675_SS,HIGH);
......@@ -1080,14 +1222,18 @@ void tp_init()
void setWatch() {
#ifdef WATCH_TEMP_PERIOD
unsigned long ms = millis();
<<<<<<< HEAD
for (int e = 0; e < HOTENDS; e++)
{
=======
for (int e = 0; e < HOTENDS; e++) {
>>>>>>> origin/master
if (degHotend(e) < degTargetHotend(e) - (WATCH_TEMP_INCREASE * 2)) {
watch_start_temp[e] = degHotend(e);
watchmillis[e] = ms;
}
}
#endif //WATCH_TEMP_PERIOD
#endif
}
#if defined(THERMAL_RUNAWAY_PROTECTION_PERIOD) && THERMAL_RUNAWAY_PROTECTION_PERIOD > 0
......@@ -1156,16 +1302,28 @@ void thermal_runaway_protection(int *state, unsigned long *timer, float temperat
void disable_heater() {
<<<<<<< HEAD
for (int e = 0; e < HOTENDS; e++)
setTargetHotend(0, e);
=======
for (int i = 0; i < HOTENDS; i++) setTargetHotend(0, i);
>>>>>>> origin/master
setTargetBed(0);
#define DISABLE_HEATER(NR) { \
target_temperature[NR] = 0; \
soft_pwm[NR] = 0; \
WRITE_HEATER_ ## NR (LOW); \
}
#if HAS_TEMP_0
target_temperature[0] = 0;
soft_pwm[0] = 0;
WRITE_HEATER_0P(LOW); // If HEATERS_PARALLEL should apply, change to WRITE_HEATER_0
WRITE_HEATER_0P(LOW); // Should HEATERS_PARALLEL apply here? Then change to DISABLE_HEATER(0)
#endif
#if HOTENDS > 1 && HAS_TEMP_1
<<<<<<< HEAD
target_temperature[1] = 0;
soft_pwm[1] = 0;
WRITE_HEATER_1(LOW);
......@@ -1181,6 +1339,17 @@ void disable_heater() {
target_temperature[3] = 0;
soft_pwm[3] = 0;
WRITE_HEATER_3(LOW);
=======
DISABLE_HEATER(1);
#endif
#if HOTENDS > 2 && HAS_TEMP_2
DISABLE_HEATER(2);
#endif
#if HOTENDS > 3 && HAS_TEMP_3
DISABLE_HEATER(3);
>>>>>>> origin/master
#endif
#if HAS_TEMP_BED
......@@ -1245,9 +1414,12 @@ void disable_heater() {
return max6675_temp;
}
#endif //HEATER_0_USES_MAX6675
//Stages in the ISR loop
/**
* Stages in the ISR loop
*/
enum TempState {
PrepareTemp_0,
MeasureTemp_0,
......@@ -1266,12 +1438,50 @@ enum TempState {
StartupDelay // Startup, delay initial temp reading a tiny bit so the hardware can settle
};
#ifdef TEMP_SENSOR_1_AS_REDUNDANT
#define TEMP_SENSOR_COUNT 2
#else
#define TEMP_SENSOR_COUNT HOTENDS
#endif
static unsigned long raw_temp_value[TEMP_SENSOR_COUNT] = { 0 };
static unsigned long raw_temp_bed_value = 0;
static void set_current_temp_raw() {
#ifndef HEATER_0_USES_MAX6675
current_temperature_raw[0] = raw_temp_value[0];
#endif
#if HOTENDS > 1
current_temperature_raw[1] = raw_temp_value[1];
#if HOTENDS > 2
current_temperature_raw[2] = raw_temp_value[2];
#if HOTENDS > 3
current_temperature_raw[3] = raw_temp_value[3];
#endif
#endif
#endif
#ifdef TEMP_SENSOR_1_AS_REDUNDANT
redundant_temperature_raw = raw_temp_value[1];
#endif
current_temperature_bed_raw = raw_temp_bed_value;
#if HAS_POWER_CONSUMPTION_SENSOR
float power_zero_raw = (POWER_ZERO * 1023 * OVERSAMPLENR) / 5.0;
current_raw_powconsumption = (raw_powconsumption_value < power_zero_raw) ? (2 * power_zero_raw - raw_powconsumption_value) : (raw_powconsumption_value);
#endif
}
//
// Timer 0 is shared with millies
//
ISR(TIMER0_COMPB_vect) {
//these variables are only accessible from the ISR, but static, so they don't lose their value
static unsigned char temp_count = 0;
<<<<<<< HEAD
static unsigned long raw_temp_value[HOTENDS] = { 0 };
static unsigned long raw_temp_bed_value = 0;
=======
>>>>>>> origin/master
static TempState temp_state = StartupDelay;
static unsigned char pwm_count = BIT(SOFT_PWM_SCALE);
......@@ -1305,11 +1515,7 @@ ISR(TIMER0_COMPB_vect) {
#if HAS_FILAMENT_SENSOR
static unsigned long raw_filwidth_value = 0;
#endif
#if HAS_POWER_CONSUMPTION_SENSOR
static unsigned long raw_powconsumption_value = 0;
#endif
#ifndef SLOW_PWM_HEATERS
/**
* standard PWM modulation
......@@ -1345,7 +1551,10 @@ ISR(TIMER0_COMPB_vect) {
}
if (soft_pwm_0 < pwm_count) { WRITE_HEATER_0(0); }
<<<<<<< HEAD
=======
>>>>>>> origin/master
#if HOTENDS > 1
if (soft_pwm_1 < pwm_count) WRITE_HEATER_1(0);
#if HOTENDS > 2
......@@ -1495,6 +1704,7 @@ ISR(TIMER0_COMPB_vect) {
#endif
temp_state = PrepareTemp_BED;
break;
case PrepareTemp_BED:
#if HAS_TEMP_BED
START_ADC(TEMP_BED_PIN);
......@@ -1508,6 +1718,7 @@ ISR(TIMER0_COMPB_vect) {
#endif
temp_state = PrepareTemp_1;
break;
case PrepareTemp_1:
#if HAS_TEMP_1
START_ADC(TEMP_1_PIN);
......@@ -1521,6 +1732,7 @@ ISR(TIMER0_COMPB_vect) {
#endif
temp_state = PrepareTemp_2;
break;
case PrepareTemp_2:
#if HAS_TEMP_2
START_ADC(TEMP_2_PIN);
......@@ -1534,6 +1746,7 @@ ISR(TIMER0_COMPB_vect) {
#endif
temp_state = PrepareTemp_3;
break;
case PrepareTemp_3:
#if HAS_TEMP_3
START_ADC(TEMP_3_PIN);
......@@ -1547,6 +1760,7 @@ ISR(TIMER0_COMPB_vect) {
#endif
temp_state = Prepare_FILWIDTH;
break;
case Prepare_FILWIDTH:
#if HAS_FILAMENT_SENSOR
START_ADC(FILWIDTH_PIN);
......@@ -1563,7 +1777,8 @@ ISR(TIMER0_COMPB_vect) {
}
#endif
temp_state = Prepare_POWCONSUMPTION;
break;
break;
case Prepare_POWCONSUMPTION:
#if HAS_POWER_CONSUMPTION_SENSOR
START_ADC(POWER_CONSUMPTION_PIN);
......@@ -1573,13 +1788,12 @@ ISR(TIMER0_COMPB_vect) {
break;
case Measure_POWCONSUMPTION:
#if HAS_POWER_CONSUMPTION_SENSOR
// raw_powconsumption_value += ADC; //remove to use an IIR filter approach
raw_powconsumption_value -= (raw_powconsumption_value>>7); //multiply raw_powconsumption_value by 127/128
raw_powconsumption_value += ((unsigned long)((ADC < (POWER_ZERO*1024)/5.0) ? (1024 - ADC) : (ADC))<<7); //add new ADC reading
raw_powconsumption_value += ADC;
#endif
temp_state = PrepareTemp_0;
temp_count++;
break;
case StartupDelay:
temp_state = PrepareTemp_0;
break;
......@@ -1589,9 +1803,10 @@ ISR(TIMER0_COMPB_vect) {
// SERIAL_ERRORLNPGM("Temp measurement error!");
// break;
} // switch(temp_state)
if (temp_count >= OVERSAMPLENR) { // 12 * 16 * 1/(16000000/64/256) = 164ms.
if (temp_count >= OVERSAMPLENR) { // 14 * 16 * 1/(16000000/64/256)
if (!temp_meas_ready) { //Only update the raw values if they have been read. Else we could be updating them during reading.
<<<<<<< HEAD
#ifndef HEATER_0_USES_MAX6675
current_temperature_raw[0] = raw_temp_value[0];
#endif
......@@ -1609,19 +1824,19 @@ ISR(TIMER0_COMPB_vect) {
redundant_temperature_raw = raw_temp_value[1];
#endif
current_temperature_bed_raw = raw_temp_bed_value;
=======
set_current_temp_raw();
>>>>>>> origin/master
} //!temp_meas_ready
// Filament Sensor - can be read any time since IIR filtering is used
#if HAS_FILAMENT_SENSOR
current_raw_filwidth = raw_filwidth_value >> 10; // Divide to get to 0-16384 range since we used 1/128 IIR filter approach
#endif
// Power Sensor - can be read any time since IIR filtering is used
#if HAS_POWER_CONSUMPTION_SENSOR
current_raw_powconsumption = raw_powconsumption_value >> 10; // Divide to get to 0-16384 range since we used 1/128 IIR filter approach
#endif
temp_meas_ready = true;
temp_count = 0;
<<<<<<< HEAD
for (int i = 0; i < HOTENDS; i++) raw_temp_value[i] = 0;
raw_temp_bed_value = 0;
......@@ -1631,6 +1846,13 @@ ISR(TIMER0_COMPB_vect) {
#else
#define GE0 >=
#define LE0 <=
=======
for (int i = 0; i < TEMP_SENSOR_COUNT; i++) raw_temp_value[i] = 0;
raw_temp_bed_value = 0;
#if HAS_POWER_CONSUMPTION_SENSOR
raw_powconsumption_value = 0;
>>>>>>> origin/master
#endif
if (current_temperature_raw[0] GE0 maxttemp_raw[0]) max_temp_error(0);
if (current_temperature_raw[0] LE0 minttemp_raw[0]) min_temp_error(0);
......@@ -1669,6 +1891,7 @@ ISR(TIMER0_COMPB_vect) {
#endif // HOTENDS > 2
#endif // HOTENDS > 1
<<<<<<< HEAD
#if defined(BED_MAXTEMP) && (TEMP_SENSOR_BED != 0)
#if HEATER_BED_RAW_LO_TEMP > HEATER_BED_RAW_HI_TEMP
#define GEBED <=
......@@ -1676,12 +1899,61 @@ ISR(TIMER0_COMPB_vect) {
#else
#define GEBED >=
#define LEBED <=
=======
#ifndef HEATER_0_USES_MAX6675
#if HEATER_0_RAW_LO_TEMP > HEATER_0_RAW_HI_TEMP
#define GE0 <=
#else
#define GE0 >=
#endif
if (current_temperature_raw[0] GE0 maxttemp_raw[0]) max_temp_error(0);
if (minttemp_raw[0] GE0 current_temperature_raw[0]) min_temp_error(0);
#endif
#if HOTENDS > 1
#if HEATER_1_RAW_LO_TEMP > HEATER_1_RAW_HI_TEMP
#define GE1 <=
#else
#define GE1 >=
#endif
if (current_temperature_raw[1] GE1 maxttemp_raw[1]) max_temp_error(1);
if (minttemp_raw[1] GE0 current_temperature_raw[1]) min_temp_error(1);
#if HOTENDS > 2
#if HEATER_2_RAW_LO_TEMP > HEATER_2_RAW_HI_TEMP
#define GE2 <=
#else
#define GE2 >=
#endif
if (current_temperature_raw[2] GE2 maxttemp_raw[2]) max_temp_error(2);
if (minttemp_raw[2] GE0 current_temperature_raw[2]) min_temp_error(2);
#if HOTENDS > 3
#if HEATER_3_RAW_LO_TEMP > HEATER_3_RAW_HI_TEMP
#define GE3 <=
#else
#define GE3 >=
#endif
if (current_temperature_raw[3] GE3 maxttemp_raw[3]) max_temp_error(3);
if (minttemp_raw[3] GE0 current_temperature_raw[3]) min_temp_error(3);
#endif // HOTENDS > 3
#endif // HOTENDS > 2
#endif // HOTENDS > 1
#if defined(BED_MAXTEMP) && (TEMP_SENSOR_BED != 0)
#if HEATER_BED_RAW_LO_TEMP > HEATER_BED_RAW_HI_TEMP
#define GEBED <=
#else
#define GEBED >=
>>>>>>> origin/master
#endif
if (current_temperature_bed_raw GEBED bed_maxttemp_raw) {
target_temperature_bed = 0;
bed_max_temp_error();
}
#endif
} // temp_count >= OVERSAMPLENR
#ifdef BABYSTEPPING
......
......@@ -40,6 +40,7 @@ void manage_heater(); //it is critical that this is called periodically.
#if (defined(POWER_CONSUMPTION) && defined(POWER_CONSUMPTION_PIN) && POWER_CONSUMPTION_PIN >= 0)
// For converting raw Power Consumption to watt
float analog2current();
float analog2power();
#endif
......@@ -63,7 +64,12 @@ extern float current_temperature_bed;
#endif
#ifdef PIDTEMP
<<<<<<< HEAD
extern float Kp[HOTENDS],Ki[HOTENDS],Kd[HOTENDS];
=======
extern float Kp[HOTENDS], Ki[HOTENDS], Kd[HOTENDS];
#define PID_PARAM(param,e) param[e] // use macro to point to array value
>>>>>>> origin/master
float scalePID_i(float i);
float scalePID_d(float d);
float unscalePID_i(float i);
......@@ -93,7 +99,7 @@ FORCE_INLINE float degBed() { return current_temperature_bed; }
#ifdef SHOW_TEMP_ADC_VALUES
FORCE_INLINE float rawHotendTemp(uint8_t hotend) { return current_temperature_raw[HOTEND_ARG]; }
FORCE_INLINE float rawBedTemp() { return current_temperature_bed_raw; }
#endif //SHOW_TEMP_ADC_VALUES
#endif
FORCE_INLINE float degTargetHotend(uint8_t hotend) { return target_temperature[HOTEND_ARG]; }
......@@ -144,7 +150,11 @@ FORCE_INLINE bool isCoolingBed() { return target_temperature_bed < current_tempe
#define setTargetHotend3(_celsius) do{}while(0)
#endif
#if HOTENDS > 4
<<<<<<< HEAD
#error Invalid number of hotend
=======
#error Invalid number of hotends
>>>>>>> origin/master
#endif
int getHeaterPower(int heater);
......
......@@ -51,14 +51,13 @@ uint8_t lcd_status_message_level;
char lcd_status_message[LCD_WIDTH+1] = WELCOME_MSG;
#ifdef DOGLCD
#include "dogm_lcd_implementation.h"
#include "dogm_lcd_implementation.h"
#define LCD_Printpos(x, y) u8g.setPrintPos(x, y)
#else
#include "ultralcd_implementation_hitachi_HD44780.h"
#include "ultralcd_implementation_hitachi_HD44780.h"
#define LCD_Printpos(x, y) lcd.setCursor(x, y)
#endif
void copy_and_scalePID_i();
void copy_and_scalePID_d();
/* Different menus */
static void lcd_status_screen();
#ifdef ULTIPANEL
......@@ -215,7 +214,11 @@ static void menu_action_setting_edit_callback_long5(const char* pstr, unsigned l
#define MENU_MULTIPLIER_ITEM_EDIT_CALLBACK(type, label, args...) MENU_ITEM(setting_edit_callback_ ## type, label, PSTR(label), ## args)
#endif //!ENCODER_RATE_MULTIPLIER
#define END_MENU() \
<<<<<<< HEAD
if (encoderLine >= _menuItemNr) encoderPosition = _menuItemNr * ENCODER_STEPS_PER_MENU_ITEM - 1; encoderLine = encoderPosition / ENCODER_STEPS_PER_MENU_ITEM;\
=======
if (encoderLine >= _menuItemNr) { encoderPosition = _menuItemNr * ENCODER_STEPS_PER_MENU_ITEM - 1; encoderLine = encoderPosition / ENCODER_STEPS_PER_MENU_ITEM; }\
>>>>>>> origin/master
if (encoderLine >= currentMenuViewOffset + LCD_HEIGHT) { currentMenuViewOffset = encoderLine - LCD_HEIGHT + 1; lcdDrawUpdate = 1; _lineNr = currentMenuViewOffset - 1; _drawLineNr = -1; } \
} } while(0)
......@@ -275,17 +278,17 @@ static void lcd_status_screen()
encoderRateMultiplierEnabled = false;
#if defined(LCD_PROGRESS_BAR) && defined(SDSUPPORT) && !defined(DOGLCD)
uint16_t mil = millis();
#ifndef PROGRESS_BAR_MSG_ONCE
#ifndef PROGRESS_MSG_ONCE
if (mil > progressBarTick + PROGRESS_BAR_MSG_TIME + PROGRESS_BAR_BAR_TIME) {
progressBarTick = mil;
}
#endif
#if PROGRESS_BAR_MSG_EXPIRE > 0
#if PROGRESS_MSG_EXPIRE > 0
// keep the message alive if paused, count down otherwise
if (messageTick > 0) {
if (card.isFileOpen()) {
if (IS_SD_PRINTING) {
if ((mil-messageTick) >= PROGRESS_BAR_MSG_EXPIRE) {
if ((mil-messageTick) >= PROGRESS_MSG_EXPIRE) {
lcd_status_message[0] = '\0';
messageTick = 0;
}
......@@ -311,12 +314,6 @@ static void lcd_status_screen()
lcd_status_update_delay = 10; /* redraw the main screen every second. This is easier then trying keep track of all things that change on the screen */
}
#if (defined(FILAMENT_SENSOR) && defined(FILWIDTH_PIN) && FILWIDTH_PIN >= 0) && defined(FILAMENT_LCD_DISPLAY) || (defined(POWER_CONSUMPTION) && defined(POWER_CONSUMPTION_PIN) && POWER_CONSUMPTION_PIN >= 0) && defined(POWER_CONSUMPTION_LCD_DISPLAY)
if (millis() > message_millis + 15000) message_millis = millis();
#else
if (millis() > message_millis + 10000) message_millis = millis();
#endif
#ifdef ULTIPANEL
bool current_click = LCD_CLICKED;
......@@ -339,12 +336,22 @@ static void lcd_status_screen()
if (current_click)
{
lcd_goto_menu(lcd_main_menu);
lcd_implementation_init( // to maybe revive the LCD if static electricity killed it.
#if defined(LCD_PROGRESS_BAR) && defined(SDSUPPORT) && !defined(DOGLCD)
currentMenu == lcd_status_screen
#endif
);
lcd_goto_menu(lcd_main_menu);
lcd_implementation_init( // to maybe revive the LCD if static electricity killed it.
#if defined(LCD_PROGRESS_BAR) && defined(SDSUPPORT) && !defined(DOGLCD)
currentMenu == lcd_status_screen
#endif
);
#if (defined(FILAMENT_SENSOR) && defined(FILWIDTH_PIN) && FILWIDTH_PIN >= 0) && defined(FILAMENT_LCD_DISPLAY) || (defined(POWER_CONSUMPTION) && defined(POWER_CONSUMPTION_PIN) && POWER_CONSUMPTION_PIN >= 0) && defined(POWER_CONSUMPTION_LCD_DISPLAY)
#if (defined(FILAMENT_SENSOR) && defined(FILWIDTH_PIN) && FILWIDTH_PIN >= 0) && defined(FILAMENT_LCD_DISPLAY) && (defined(POWER_CONSUMPTION) && defined(POWER_CONSUMPTION_PIN) && POWER_CONSUMPTION_PIN >= 0) && defined(POWER_CONSUMPTION_LCD_DISPLAY)
if (millis() > message_millis + 15000)
#else
if (millis() > message_millis + 10000)
#endif
{
message_millis = millis();
}
#endif
}
#ifdef ULTIPANEL_FEEDMULTIPLY
......@@ -690,86 +697,73 @@ void config_lcd_level_bed()
void lcd_level_bed()
{
if(ChangeScreen) {
lcd.clear();
lcd_implementation_clear;
switch(pageShowInfo) {
case 0:
{
lcd.setCursor(0, 1);
{
LCD_Printpos(0, 1);
lcd_printPGM(PSTR(MSG_LP_INTRO));
currentMenu = lcd_level_bed;
ChangeScreen=false;
currentMenu = lcd_level_bed;
ChangeScreen=false;
}
break;
break;
case 1:
{
lcd.setCursor(0, 1);
{
LCD_Printpos(0, 1);
lcd_printPGM(PSTR(MSG_LP_1));
currentMenu = lcd_level_bed;
ChangeScreen=false;
currentMenu = lcd_level_bed;
ChangeScreen=false;
}
break;
break;
case 2:
{
lcd.setCursor(0, 1);
{
LCD_Printpos(0, 1);
lcd_printPGM(PSTR(MSG_LP_2));
currentMenu = lcd_level_bed;
ChangeScreen=false;
ChangeScreen=false;
}
break;
break;
case 3:
{
lcd.setCursor(0, 1);
{
LCD_Printpos(0, 1);
lcd_printPGM(PSTR(MSG_LP_3));
currentMenu = lcd_level_bed;
ChangeScreen=false;
currentMenu = lcd_level_bed;
ChangeScreen=false;
}
break;
case 4:
{
lcd.setCursor(0, 1);
break;
case 4:
{
LCD_Printpos(0, 1);
lcd_printPGM(PSTR(MSG_LP_4));
currentMenu = lcd_level_bed;
ChangeScreen=false;
currentMenu = lcd_level_bed;
ChangeScreen=false;
}
break;
case 5:
{
lcd.setCursor(0, 1);
break;
case 5:
{
LCD_Printpos(0, 1);
lcd_printPGM(PSTR(MSG_LP_5));
currentMenu = lcd_level_bed;
ChangeScreen=false;
currentMenu = lcd_level_bed;
ChangeScreen=false;
}
break;
case 6:
break;
case 6:
{
lcd.setCursor(2, 2);
lcd_printPGM(PSTR(MSG_LP_6));
LCD_Printpos(2, 2);
lcd_printPGM(PSTR(MSG_LP_6));
ChangeScreen=false;
delay(1200);
delay(1200);
encoderPosition = 0;
lcd.clear();
lcd_implementation_clear();
currentMenu = lcd_status_screen;
lcd_status_screen();
pageShowInfo=0;
}
break;
break;
}
}
}
}
static void lcd_prepare_menu() {
START_MENU();
MENU_ITEM(back, MSG_MAIN, lcd_main_menu);
......@@ -969,6 +963,35 @@ static void lcd_config_menu() {
END_MENU();
}
#ifdef PIDTEMP
// Helpers for editing PID Ki & Kd values
// grab the PID value out of the temp variable; scale it; then update the PID driver
void copy_and_scalePID_i(int e) {
PID_PARAM(Ki, e) = scalePID_i(raw_Ki);
updatePID();
}
void copy_and_scalePID_d(int e) {
PID_PARAM(Kd, e) = scalePID_d(raw_Kd);
updatePID();
}
void copy_and_scalePID_i_E1() { copy_and_scalePID_i(0); }
void copy_and_scalePID_d_E1() { copy_and_scalePID_d(0); }
#if HOTENDS > 1
void copy_and_scalePID_i_E2() { copy_and_scalePID_i(1); }
void copy_and_scalePID_d_E2() { copy_and_scalePID_d(1); }
#if HOTENDS > 2
void copy_and_scalePID_i_E3() { copy_and_scalePID_i(2); }
void copy_and_scalePID_d_E3() { copy_and_scalePID_d(2); }
#if HOTENDS > 3
void copy_and_scalePID_i_E4() { copy_and_scalePID_i(3); }
void copy_and_scalePID_d_E4() { copy_and_scalePID_d(3); }
#endif //HOTENDS > 3
#endif //HOTENDS > 2
#endif //HOTENDS > 1
#endif //PIDTEMP
static void lcd_control_temperature_menu() {
START_MENU();
MENU_ITEM(back, MSG_CONTROL, lcd_control_menu);
......@@ -1002,6 +1025,7 @@ static void lcd_control_temperature_menu() {
#endif
#ifdef PIDTEMP
// set up temp variables - undo the default scaling
<<<<<<< HEAD
raw_Ki = unscalePID_i(Ki[0]);
raw_Kd = unscalePID_d(Kd[0]);
MENU_ITEM_EDIT(float52, MSG_PID_P, &Kp[0], 1, 9990);
......@@ -1035,6 +1059,41 @@ static void lcd_control_temperature_menu() {
MENU_ITEM_EDIT_CALLBACK(float52, MSG_PID_I " E4", &raw_Ki, 0.01, 9990, copy_and_scalePID_i);
MENU_ITEM_EDIT_CALLBACK(float52, MSG_PID_D " E4", &raw_Kd, 1, 9990, copy_and_scalePID_d);
#endif //HOTENDS > 2
=======
raw_Ki = unscalePID_i(PID_PARAM(Ki,0));
raw_Kd = unscalePID_d(PID_PARAM(Kd,0));
MENU_ITEM_EDIT(float52, MSG_PID_P, &PID_PARAM(Kp,0), 1, 9990);
// i is typically a small value so allows values below 1
MENU_ITEM_EDIT_CALLBACK(float52, MSG_PID_I, &raw_Ki, 0.01, 9990, copy_and_scalePID_i_E1);
MENU_ITEM_EDIT_CALLBACK(float52, MSG_PID_D, &raw_Kd, 1, 9990, copy_and_scalePID_d_E1);
#if HOTENDS > 1
// set up temp variables - undo the default scaling
raw_Ki = unscalePID_i(PID_PARAM(Ki,1));
raw_Kd = unscalePID_d(PID_PARAM(Kd,1));
MENU_ITEM_EDIT(float52, MSG_PID_P MSG_E2, &PID_PARAM(Kp,1), 1, 9990);
// i is typically a small value so allows values below 1
MENU_ITEM_EDIT_CALLBACK(float52, MSG_PID_I MSG_E2, &raw_Ki, 0.01, 9990, copy_and_scalePID_i_E2);
MENU_ITEM_EDIT_CALLBACK(float52, MSG_PID_D MSG_E2, &raw_Kd, 1, 9990, copy_and_scalePID_d_E2);
#if HOTENDS > 2
// set up temp variables - undo the default scaling
raw_Ki = unscalePID_i(PID_PARAM(Ki,2));
raw_Kd = unscalePID_d(PID_PARAM(Kd,2));
MENU_ITEM_EDIT(float52, MSG_PID_P MSG_E3, &PID_PARAM(Kp,2), 1, 9990);
// i is typically a small value so allows values below 1
MENU_ITEM_EDIT_CALLBACK(float52, MSG_PID_I MSG_E3, &raw_Ki, 0.01, 9990, copy_and_scalePID_i_E3);
MENU_ITEM_EDIT_CALLBACK(float52, MSG_PID_D MSG_E3, &raw_Kd, 1, 9990, copy_and_scalePID_d_E3);
#if HOTENDS > 3
// set up temp variables - undo the default scaling
raw_Ki = unscalePID_i(PID_PARAM(Ki,3));
raw_Kd = unscalePID_d(PID_PARAM(Kd,3));
MENU_ITEM_EDIT(float52, MSG_PID_P MSG_E4, &PID_PARAM(Kp,3), 1, 9990);
// i is typically a small value so allows values below 1
MENU_ITEM_EDIT_CALLBACK(float52, MSG_PID_I MSG_E4, &raw_Ki, 0.01, 9990, copy_and_scalePID_i_E4);
MENU_ITEM_EDIT_CALLBACK(float52, MSG_PID_D MSG_E4, &raw_Kd, 1, 9990, copy_and_scalePID_d_E4);
#endif //HOTENDS > 3
#endif //HOTENDS > 2
#endif //HOTENDS > 1
>>>>>>> origin/master
#endif //PIDTEMP
MENU_ITEM(submenu, MSG_PREHEAT_PLA_SETTINGS, lcd_control_temperature_preheat_pla_settings_menu);
MENU_ITEM(submenu, MSG_PREHEAT_ABS_SETTINGS, lcd_control_temperature_preheat_abs_settings_menu);
......@@ -1094,9 +1153,9 @@ static void lcd_control_motion_menu() {
START_MENU();
MENU_ITEM(back, MSG_CONTROL, lcd_control_menu);
#ifdef ENABLE_AUTO_BED_LEVELING
MENU_ITEM_EDIT(float32, MSG_ZPROBE_ZOFFSET, &zprobe_zoffset, 0.5, 50);
MENU_ITEM_EDIT(float32, MSG_ZPROBE_ZOFFSET, &zprobe_zoffset, 0.0, 50);
#endif
MENU_ITEM_EDIT(float5, MSG_ACC, &acceleration, 500, 99000);
MENU_ITEM_EDIT(float5, MSG_ACC, &acceleration, 10, 99000);
MENU_ITEM_EDIT(float3, MSG_VXY_JERK, &max_xy_jerk, 1, 990);
MENU_ITEM_EDIT(float52, MSG_VZ_JERK, &max_z_jerk, 0.1, 990);
MENU_ITEM_EDIT(float3, MSG_VE_JERK, &max_e_jerk, 1, 990);
......@@ -1108,7 +1167,7 @@ static void lcd_control_motion_menu() {
MENU_ITEM_EDIT(float3, MSG_VTRAV_MIN, &mintravelfeedrate, 0, 999);
MENU_ITEM_EDIT_CALLBACK(long5, MSG_AMAX MSG_X, &max_acceleration_units_per_sq_second[X_AXIS], 100, 99000, reset_acceleration_rates);
MENU_ITEM_EDIT_CALLBACK(long5, MSG_AMAX MSG_Y, &max_acceleration_units_per_sq_second[Y_AXIS], 100, 99000, reset_acceleration_rates);
MENU_ITEM_EDIT_CALLBACK(long5, MSG_AMAX MSG_Z, &max_acceleration_units_per_sq_second[Z_AXIS], 100, 99000, reset_acceleration_rates);
MENU_ITEM_EDIT_CALLBACK(long5, MSG_AMAX MSG_Z, &max_acceleration_units_per_sq_second[Z_AXIS], 10, 99000, reset_acceleration_rates);
MENU_ITEM_EDIT_CALLBACK(long5, MSG_AMAX MSG_E, &max_acceleration_units_per_sq_second[E_AXIS], 100, 99000, reset_acceleration_rates);
MENU_ITEM_EDIT(float5, MSG_A_RETRACT, &retract_acceleration, 100, 99000);
MENU_ITEM_EDIT(float5, MSG_A_TRAVEL, &travel_acceleration, 100, 99000);
......@@ -1391,10 +1450,6 @@ void lcd_init() {
WRITE(SHIFT_OUT,HIGH);
WRITE(SHIFT_LD,HIGH);
WRITE(SHIFT_EN,LOW);
#else
#ifdef ULTIPANEL
#error ULTIPANEL requires an encoder
#endif
#endif // SR_LCD_2W_NL
#endif//!NEWPANEL
......@@ -1569,7 +1624,7 @@ void lcd_finishstatus() {
}
lcd_status_message[LCD_WIDTH] = '\0';
#if defined(LCD_PROGRESS_BAR) && defined(SDSUPPORT) && !defined(DOGLCD)
#if PROGRESS_BAR_MSG_EXPIRE > 0
#if PROGRESS_MSG_EXPIRE > 0
messageTick =
#endif
progressBarTick = millis();
......@@ -2006,24 +2061,4 @@ char *ftostr52(const float &x)
return conv;
}
// Callback for after editing PID i value
// grab the PID i value out of the temp variable; scale it; then update the PID driver
void copy_and_scalePID_i()
{
#ifdef PIDTEMP
Ki[active_extruder] = scalePID_i(raw_Ki);
updatePID();
#endif
}
// Callback for after editing PID d value
// grab the PID d value out of the temp variable; scale it; then update the PID driver
void copy_and_scalePID_d()
{
#ifdef PIDTEMP
Kd[active_extruder] = scalePID_d(raw_Kd);
updatePID();
#endif
}
#endif //ULTRA_LCD
......@@ -33,32 +33,30 @@
#define LCD_TIMEOUT_TO_STATUS 15000
#ifdef ULTIPANEL
void lcd_buttons_update();
extern volatile uint8_t buttons; //the last checked buttons in a bit array.
#ifdef REPRAPWORLD_KEYPAD
extern volatile uint8_t buttons_reprapworld_keypad; // to store the keypad shift register values
#endif
void lcd_buttons_update();
extern volatile uint8_t buttons; //the last checked buttons in a bit array.
#ifdef REPRAPWORLD_KEYPAD
extern volatile uint8_t buttons_reprapworld_keypad; // to store the keypad shift register values
#endif
#else
FORCE_INLINE void lcd_buttons_update() {}
FORCE_INLINE void lcd_buttons_update() {}
#endif
extern int plaPreheatHotendTemp;
extern int plaPreheatHPBTemp;
extern int plaPreheatFanSpeed;
extern int absPreheatHotendTemp;
extern int absPreheatHPBTemp;
extern int absPreheatFanSpeed;
extern int gumPreheatHotendTemp;
extern int gumPreheatHPBTemp;
extern int gumPreheatFanSpeed;
extern bool cancel_heatup;
#if (defined(FILAMENT_SENSOR) && defined(FILWIDTH_PIN) && FILWIDTH_PIN >= 0) && defined(FILAMENT_LCD_DISPLAY) || (defined(POWER_CONSUMPTION) && defined(POWER_CONSUMPTION_PIN) && POWER_CONSUMPTION_PIN >= 0) && defined(POWER_CONSUMPTION_LCD_DISPLAY)
extern unsigned long message_millis;
#endif
#if (defined(FILAMENT_SENSOR) && defined(FILWIDTH_PIN) && FILWIDTH_PIN >= 0) && defined(FILAMENT_LCD_DISPLAY) || (defined(POWER_CONSUMPTION) && defined(POWER_CONSUMPTION_PIN) && POWER_CONSUMPTION_PIN >= 0) && defined(POWER_CONSUMPTION_LCD_DISPLAY)
extern unsigned long message_millis;
#endif
void lcd_buzz(long duration,uint16_t freq);
bool lcd_clicked();
......
......@@ -200,7 +200,7 @@
#if defined(LCD_PROGRESS_BAR) && defined(SDSUPPORT)
static uint16_t progressBarTick = 0;
#if PROGRESS_BAR_MSG_EXPIRE > 0
#if PROGRESS_MSG_EXPIRE > 0
static uint16_t messageTick = 0;
#endif
#define LCD_STR_PROGRESS "\x03\x04\x05"
......@@ -382,16 +382,16 @@ static void lcd_set_custom_characters(
static void lcd_implementation_init (
#if defined(LCD_PROGRESS_BAR) && defined(SDSUPPORT)
bool progress_bar_set = true
bool progress_bar_set=true
#endif
){
) {
#if defined(LCD_I2C_TYPE_PCF8575)
lcd.begin(LCD_WIDTH, LCD_HEIGHT);
#ifdef LCD_I2C_PIN_BL
lcd.setBacklightPin(LCD_I2C_PIN_BL,POSITIVE);
lcd.setBacklight(HIGH);
#endif
#ifdef LCD_I2C_PIN_BL
lcd.setBacklightPin(LCD_I2C_PIN_BL,POSITIVE);
lcd.setBacklight(HIGH);
#endif
#elif defined(LCD_I2C_TYPE_MCP23017)
lcd.setMCPType(LTI_TYPE_MCP23017);
......@@ -408,9 +408,9 @@ static void lcd_implementation_init (
#endif
lcd_set_custom_characters(
#if defined(LCD_PROGRESS_BAR) && defined(SDSUPPORT)
progress_bar_set
#endif
#if defined(LCD_PROGRESS_BAR) && defined(SDSUPPORT)
progress_bar_set
#endif
);
lcd.clear();
......@@ -421,7 +421,8 @@ static void lcd_implementation_clear() {
}
/* Arduino < 1.0.0 is missing a function to print PROGMEM strings, so we need to implement our own */
static void lcd_printPGM(const char* str) {
static void lcd_printPGM(const char* str)
{
char c;
while((c = pgm_read_byte(str++)) != '\0')
{
......@@ -458,7 +459,8 @@ Possible status screens:
|Status line.........|
*/
static void lcd_implementation_status_screen() {
static void lcd_implementation_status_screen()
{
int tHotend=int(degHotend(0) + 0.5);
int tTarget=int(degTargetHotend(0) + 0.5);
......@@ -468,6 +470,7 @@ static void lcd_implementation_status_screen() {
lcd.print('/');
lcd.print(itostr3left(tTarget));
<<<<<<< HEAD
<<<<<<< HEAD
#if HOTENDS > 1 || TEMP_SENSOR_BED != 0
//If we have an 2nd extruder or heated bed, show that in the top right corner
......@@ -478,6 +481,12 @@ static void lcd_implementation_status_screen() {
//If we have an 2nd extruder or heated bed, show that in the top right corner
lcd.setCursor(8, 0);
#if EXTRUDERS > 1 && !defined(SINGLENOZZLE)
>>>>>>> origin/master
=======
#if HOTENDS > 1 || TEMP_SENSOR_BED != 0
//If we have an 2nd extruder or heated bed, show that in the top right corner
lcd.setCursor(8, 0);
#if HOTENDS > 1
>>>>>>> origin/master
tHotend = int(degHotend(1) + 0.5);
tTarget = int(degTargetHotend(1) + 0.5);
......@@ -490,11 +499,15 @@ static void lcd_implementation_status_screen() {
lcd.print(itostr3(tHotend));
lcd.print('/');
lcd.print(itostr3left(tTarget));
<<<<<<< HEAD
<<<<<<< HEAD
#endif //HOTENDS > 1 || TEMP_SENSOR_BED != 0
=======
#endif //(EXTRUDERS > 1 && !defined(SINGLENOZZLE)) || TEMP_SENSOR_BED != 0
>>>>>>> origin/master
=======
#endif //HOTENDS > 1 || TEMP_SENSOR_BED != 0
>>>>>>> origin/master
#else//LCD_WIDTH > 19
lcd.setCursor(0, 0);
......@@ -505,6 +518,7 @@ static void lcd_implementation_status_screen() {
lcd_printPGM(PSTR(LCD_STR_DEGREE " "));
if (tTarget < 10) lcd.print(' ');
<<<<<<< HEAD
<<<<<<< HEAD
#if HOTENDS > 1 || TEMP_SENSOR_BED != 0
//If we have an 2nd extruder or heated bed, show that in the top right corner
......@@ -515,6 +529,12 @@ static void lcd_implementation_status_screen() {
//If we have an 2nd extruder or heated bed, show that in the top right corner
lcd.setCursor(10, 0);
#if EXTRUDERS > 1 && !defined(SINGLENOZZLE)
>>>>>>> origin/master
=======
#if HOTENDS > 1 || TEMP_SENSOR_BED != 0
//If we have an 2nd extruder or heated bed, show that in the top right corner
lcd.setCursor(10, 0);
#if HOTENDS > 1
>>>>>>> origin/master
tHotend = int(degHotend(1) + 0.5);
tTarget = int(degTargetHotend(1) + 0.5);
......@@ -529,6 +549,7 @@ static void lcd_implementation_status_screen() {
lcd.print(itostr3left(tTarget));
lcd_printPGM(PSTR(LCD_STR_DEGREE " "));
if (tTarget < 10) lcd.print(' ');
<<<<<<< HEAD
<<<<<<< HEAD
#endif//HOTENDS > 1 || TEMP_SENSOR_BED != 0
#endif//LCD_WIDTH > 19
......@@ -630,6 +651,57 @@ static void lcd_implementation_status_screen() {
#endif//LCD_HEIGHT > 2
#if LCD_HEIGHT > 3
>>>>>>> origin/master
=======
#endif//HOTENDS > 1 || TEMP_SENSOR_BED != 0
#endif//LCD_WIDTH > 19
#if LCD_HEIGHT > 2
//Lines 2 for 4 line LCD
#if LCD_WIDTH < 20
#ifdef SDSUPPORT
lcd.setCursor(0, 2);
lcd_printPGM(PSTR("SD"));
if (IS_SD_PRINTING)
lcd.print(itostr3(card.percentDone()));
else
lcd_printPGM(PSTR("---"));
lcd.print('%');
#endif//SDSUPPORT
#else //LCD_WIDTH > 19
#if HOTENDS > 1 && TEMP_SENSOR_BED != 0
//If we both have a 2nd extruder and a heated bed, show the heated bed temp on the 2nd line on the left, as the first line is filled with extruder temps
tHotend=int(degBed() + 0.5);
tTarget=int(degTargetBed() + 0.5);
lcd.setCursor(0, 1);
lcd.print(LCD_STR_BEDTEMP[0]);
lcd.print(itostr3(tHotend));
lcd.print('/');
lcd.print(itostr3left(tTarget));
lcd_printPGM(PSTR(LCD_STR_DEGREE " "));
if (tTarget < 10) lcd.print(' ');
#else
lcd.setCursor(0,1);
#ifdef DELTA
lcd.print('X');
lcd.print(ftostr30(current_position[X_AXIS]));
lcd_printPGM(PSTR(" Y"));
lcd.print(ftostr30(current_position[Y_AXIS]));
#else
lcd.print('X');
lcd.print(ftostr3(current_position[X_AXIS]));
lcd_printPGM(PSTR(" Y"));
lcd.print(ftostr3(current_position[Y_AXIS]));
#endif // DELTA
#endif //HOTENDS > 1 || TEMP_SENSOR_BED != 0
#endif //LCD_WIDTH > 19
lcd.setCursor(LCD_WIDTH - 8, 1);
lcd.print('Z');
lcd.print(ftostr32sp(current_position[Z_AXIS] + 0.00001));
#endif //LCD_HEIGHT > 2
#if LCD_HEIGHT > 3
>>>>>>> origin/master
lcd.setCursor(0, 2);
lcd.print(LCD_STR_FEEDRATE[0]);
......@@ -703,21 +775,21 @@ static void lcd_implementation_status_screen() {
lcd.print(lcd_status_message);
>>>>>>> origin/master
}
#if (defined(POWER_CONSUMPTION) && defined(POWER_CONSUMPTION_PIN) && POWER_CONSUMPTION_PIN >= 0) && defined(POWER_CONSUMPTION_LCD_DISPLAY)
#if (defined(FILAMENT_SENSOR) && defined(FILWIDTH_PIN) && FILWIDTH_PIN >= 0) && defined(FILAMENT_LCD_DISPLAY)
#if defined(POWER_CONSUMPTION) && defined(POWER_CONSUMPTION_PIN) && (POWER_CONSUMPTION_PIN >= 0) && defined(POWER_CONSUMPTION_LCD_DISPLAY)
#if defined(FILAMENT_SENSOR) && defined(FILWIDTH_PIN) && (FILWIDTH_PIN >= 0) && defined(FILAMENT_LCD_DISPLAY)
else if (millis() < message_millis + 10000)
#else
else
#endif
{
lcd_printPGM(PSTR("P:"));
lcd.print(itostr3(power_consumption_meas));
lcd.print(ftostr31(power_consumption_meas));
lcd_printPGM(PSTR("W C:"));
lcd.print(ltostr7(power_consumption_hour));
lcd_printPGM(PSTR("Wh"));
}
#endif
#if (defined(FILAMENT_SENSOR) && defined(FILWIDTH_PIN) && FILWIDTH_PIN >= 0) && defined(FILAMENT_LCD_DISPLAY)
#if defined(FILAMENT_SENSOR) && defined(FILWIDTH_PIN) && (FILWIDTH_PIN >= 0) && defined(FILAMENT_LCD_DISPLAY)
else {
lcd_printPGM(PSTR("D:"));
lcd.print(ftostr12ns(filament_width_meas));
......@@ -726,7 +798,8 @@ static void lcd_implementation_status_screen() {
lcd.print('%');
return;
}
#else
#endif
#else
lcd.print(lcd_status_message);
#endif
}
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment