From 0ce35766855c53c95df9d7e065f774534937df96 Mon Sep 17 00:00:00 2001 From: alexborro Date: Tue, 24 Mar 2015 14:06:44 -0300 Subject: [PATCH 01/13] New Feature: Z_DUAL_ENDSTOPS 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. --- Marlin/ConfigurationStore.cpp | 22 +++++++ Marlin/Configuration_adv.h | 27 ++++++++- Marlin/Marlin.h | 2 + Marlin/Marlin_main.cpp | 51 +++++++++++++++- Marlin/language.h | 1 + Marlin/pins.h | 29 +++++++++ Marlin/stepper.cpp | 109 +++++++++++++++++++++++++++++----- Marlin/stepper.h | 6 ++ 8 files changed, 228 insertions(+), 19 deletions(-) diff --git a/Marlin/ConfigurationStore.cpp b/Marlin/ConfigurationStore.cpp index 29cc0412ae..fc485e2262 100644 --- a/Marlin/ConfigurationStore.cpp +++ b/Marlin/ConfigurationStore.cpp @@ -67,6 +67,9 @@ * * filament_size (x4) * + * Z_DUAL_ENDSTOPS + * z_endstop_adj + * */ #include "Marlin.h" #include "language.h" @@ -165,6 +168,10 @@ void Config_StoreSettings() { EEPROM_WRITE_VAR(i, delta_radius); // 1 float EEPROM_WRITE_VAR(i, delta_diagonal_rod); // 1 float EEPROM_WRITE_VAR(i, delta_segments_per_second); // 1 float + #elif defined(Z_DUAL_ENDSTOPS) + EEPROM_WRITE_VAR(i, z_endstop_adj); // 1 floats + dummy = 0.0f; + for (int q=5; q--;) EEPROM_WRITE_VAR(i, dummy); #else dummy = 0.0f; for (int q=6; q--;) EEPROM_WRITE_VAR(i, dummy); @@ -326,7 +333,12 @@ void Config_RetrieveSettings() { EEPROM_READ_VAR(i, delta_radius); // 1 float EEPROM_READ_VAR(i, delta_diagonal_rod); // 1 float EEPROM_READ_VAR(i, delta_segments_per_second); // 1 float + #elif defined(Z_DUAL_ENDSTOPS) + EEPROM_READ_VAR(i, z_endstop_adj); + dummy = 0.0f; + for (int q=5; q--;) EEPROM_READ_VAR(i, dummy); #else + dummy = 0.0f; for (int q=6; q--;) EEPROM_READ_VAR(i, dummy); #endif @@ -459,6 +471,8 @@ void Config_ResetDefault() { delta_diagonal_rod = DELTA_DIAGONAL_ROD; delta_segments_per_second = DELTA_SEGMENTS_PER_SECOND; recalc_delta_settings(delta_radius, delta_diagonal_rod); + #elif defined(Z_DUAL_ENDSTOPS) + z_endstop_adj = 0; #endif #ifdef ULTIPANEL @@ -629,6 +643,14 @@ void Config_PrintSettings(bool forReplay) { SERIAL_ECHOPAIR(" R", delta_radius ); SERIAL_ECHOPAIR(" S", delta_segments_per_second ); SERIAL_EOL; + #elif defined(Z_DUAL_ENDSTOPS) + SERIAL_ECHO_START; + if (!forReplay) { + SERIAL_ECHOLNPGM("Z2 Endstop adjustement (mm):"); + SERIAL_ECHO_START; + } + SERIAL_ECHOPAIR(" M666 Z", z_endstop_adj ); + SERIAL_EOL; #endif // DELTA #ifdef PIDTEMP diff --git a/Marlin/Configuration_adv.h b/Marlin/Configuration_adv.h index 7d6182bf58..721074e23c 100644 --- a/Marlin/Configuration_adv.h +++ b/Marlin/Configuration_adv.h @@ -98,7 +98,32 @@ // Only a few motherboards support this, like RAMPS, which have dual extruder support (the 2nd, often unused, extruder driver is used // to control the 2nd Z axis stepper motor). The pins are currently only defined for a RAMPS motherboards. // On a RAMPS (or other 5 driver) motherboard, using this feature will limit you to using 1 extruder. -//#define Z_DUAL_STEPPER_DRIVERS +#define Z_DUAL_STEPPER_DRIVERS + +#ifdef Z_DUAL_STEPPER_DRIVERS + +// 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. //#define Y_DUAL_STEPPER_DRIVERS diff --git a/Marlin/Marlin.h b/Marlin/Marlin.h index cc1f111188..bbd7ac3dbb 100644 --- a/Marlin/Marlin.h +++ b/Marlin/Marlin.h @@ -242,6 +242,8 @@ extern float home_offset[3]; extern float delta_diagonal_rod; extern float delta_segments_per_second; void recalc_delta_settings(float radius, float diagonal_rod); +#elif defined(Z_DUAL_ENDSTOPS) +extern float z_endstop_adj; #endif #ifdef SCARA extern float axis_scaling[3]; // Build size scaling diff --git a/Marlin/Marlin_main.cpp b/Marlin/Marlin_main.cpp index 5109118190..3316862add 100644 --- a/Marlin/Marlin_main.cpp +++ b/Marlin/Marlin_main.cpp @@ -248,6 +248,8 @@ float current_position[NUM_AXIS] = { 0.0, 0.0, 0.0, 0.0 }; float home_offset[3] = { 0, 0, 0 }; #ifdef DELTA float endstop_adj[3] = { 0, 0, 0 }; +#elif defined(Z_DUAL_ENDSTOPS) + float z_endstop_adj = 0; #endif float min_pos[3] = { X_MIN_POS, Y_MIN_POS, Z_MIN_POS }; @@ -973,7 +975,7 @@ XYZ_CONSTS_FROM_CONFIG(signed char, home_dir, HOME_DIR); static float x_home_pos(int extruder) { if (extruder == 0) - return base_home_pos(X_AXIS) + add_homing[X_AXIS]; + return base_home_pos(X_AXIS) + home_offset[X_AXIS]; else // In dual carriage mode the extruder offset provides an override of the // second X-carriage offset when homed - otherwise X2_HOME_POS is used. @@ -1487,6 +1489,9 @@ static void homeaxis(int axis) { } #endif #endif // Z_PROBE_SLED + #ifdef Z_DUAL_ENDSTOPS + if (axis==Z_AXIS) In_Homing_Process(true); + #endif destination[axis] = 1.5 * max_length(axis) * axis_home_dir; feedrate = homing_feedrate[axis]; plan_buffer_line(destination[X_AXIS], destination[Y_AXIS], destination[Z_AXIS], destination[E_AXIS], feedrate/60, active_extruder); @@ -1512,6 +1517,27 @@ static void homeaxis(int axis) { plan_buffer_line(destination[X_AXIS], destination[Y_AXIS], destination[Z_AXIS], destination[E_AXIS], feedrate/60, active_extruder); st_synchronize(); + #ifdef Z_DUAL_ENDSTOPS + if (axis==Z_AXIS) + { + feedrate = homing_feedrate[axis]; + plan_set_position(current_position[X_AXIS], current_position[Y_AXIS], current_position[Z_AXIS], current_position[E_AXIS]); + if (axis_home_dir > 0) + { + destination[axis] = (-1) * fabs(z_endstop_adj); + if (z_endstop_adj > 0) Lock_z_motor(true); else Lock_z2_motor(true); + } else { + destination[axis] = fabs(z_endstop_adj); + if (z_endstop_adj < 0) Lock_z_motor(true); else Lock_z2_motor(true); + } + plan_buffer_line(destination[X_AXIS], destination[Y_AXIS], destination[Z_AXIS], destination[E_AXIS], feedrate/60, active_extruder); + st_synchronize(); + Lock_z_motor(false); + Lock_z2_motor(false); + In_Homing_Process(false); + } + #endif + #ifdef DELTA // retrace by the amount specified in endstop_adj if (endstop_adj[axis] * axis_home_dir < 0) { @@ -1754,7 +1780,7 @@ inline void gcode_G28() { enable_endstops(true); - for (int i = X_AXIS; i <= Z_AXIS; i++) destination[i] = current_position[i]; + for (int i = X_AXIS; i <= NUM_AXIS; i++) destination[i] = current_position[i]; feedrate = 0.0; @@ -1944,7 +1970,7 @@ inline void gcode_G28() { if (code_seen(axis_codes[Z_AXIS]) && code_value_long() != 0) current_position[Z_AXIS] = code_value() + home_offset[Z_AXIS]; - #ifdef ENABLE_AUTO_BED_LEVELING + #if defined(ENABLE_AUTO_BED_LEVELING) && (Z_HOME_DIR < 0) if (home_all_axis || code_seen(axis_codes[Z_AXIS])) current_position[Z_AXIS] += zprobe_zoffset; //Add Z_Probe offset (the distance is negative) #endif @@ -3452,6 +3478,11 @@ inline void gcode_M119() { SERIAL_PROTOCOLPGM(MSG_Z_MAX); SERIAL_PROTOCOLLN(((READ(Z_MAX_PIN)^Z_MAX_ENDSTOP_INVERTING)?MSG_ENDSTOP_HIT:MSG_ENDSTOP_OPEN)); #endif + #if defined(Z2_MAX_PIN) && Z2_MAX_PIN > -1 + SERIAL_PROTOCOLPGM(MSG_Z2_MAX); + SERIAL_PROTOCOLLN(((READ(Z2_MAX_PIN)^Z2_MAX_ENDSTOP_INVERTING)?MSG_ENDSTOP_HIT:MSG_ENDSTOP_OPEN)); + #endif + } /** @@ -3645,6 +3676,16 @@ inline void gcode_M206() { } } } +#elif defined(Z_DUAL_ENDSTOPS) + /** + * M666: For Z Dual Endstop setup, set z axis offset to the z2 axis. + */ + inline void gcode_M666() { + if (code_seen('Z')) z_endstop_adj = code_value(); + SERIAL_ECHOPAIR("Z Endstop Adjustment set to (mm):", z_endstop_adj ); + SERIAL_EOL; + } + #endif // DELTA #ifdef FWRETRACT @@ -4894,6 +4935,10 @@ void process_commands() { case 666: // M666 set delta endstop adjustment gcode_M666(); break; + #elif defined(Z_DUAL_ENDSTOPS) + case 666: // M666 set delta endstop adjustment + gcode_M666(); + break; #endif // DELTA #ifdef FWRETRACT diff --git a/Marlin/language.h b/Marlin/language.h index 387e1e3ef0..9e348c929f 100644 --- a/Marlin/language.h +++ b/Marlin/language.h @@ -128,6 +128,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_M119_REPORT "Reporting endstop status" #define MSG_ENDSTOP_HIT "TRIGGERED" #define MSG_ENDSTOP_OPEN "open" diff --git a/Marlin/pins.h b/Marlin/pins.h index 88c5cc78cb..939dab5e66 100644 --- a/Marlin/pins.h +++ b/Marlin/pins.h @@ -178,6 +178,35 @@ #define Z_MIN_PIN -1 #endif +#ifdef DISABLE_XMAX_ENDSTOP + #undef X_MAX_PIN + #define X_MAX_PIN -1 +#endif + +#ifdef DISABLE_XMIN_ENDSTOP + #undef X_MIN_PIN + #define X_MIN_PIN -1 +#endif + +#ifdef DISABLE_YMAX_ENDSTOP + #define Y_MAX_PIN -1 +#endif + +#ifdef DISABLE_YMIN_ENDSTOP + #undef Y_MIN_PIN + #define Y_MIN_PIN -1 +#endif + +#ifdef DISABLE_ZMAX_ENDSTOP + #undef Z_MAX_PIN + #define Z_MAX_PIN -1 +#endif + +#ifdef DISABLE_ZMIN_ENDSTOP + #undef Z_MIN_PIN + #define Z_MIN_PIN -1 +#endif + #define SENSITIVE_PINS { 0, 1, X_STEP_PIN, X_DIR_PIN, X_ENABLE_PIN, X_MIN_PIN, X_MAX_PIN, Y_STEP_PIN, Y_DIR_PIN, Y_ENABLE_PIN, Y_MIN_PIN, Y_MAX_PIN, Z_STEP_PIN, Z_DIR_PIN, Z_ENABLE_PIN, Z_MIN_PIN, Z_MAX_PIN, PS_ON_PIN, \ HEATER_BED_PIN, FAN_PIN, \ _E0_PINS _E1_PINS _E2_PINS _E3_PINS \ diff --git a/Marlin/stepper.cpp b/Marlin/stepper.cpp index d3651b6b41..8be4b98af4 100644 --- a/Marlin/stepper.cpp +++ b/Marlin/stepper.cpp @@ -48,6 +48,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 @@ -84,7 +90,13 @@ static bool old_x_min_endstop = false, old_y_min_endstop = false, old_y_max_endstop = false, old_z_min_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; @@ -128,7 +140,23 @@ 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); } - #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 #else #define Z_APPLY_DIR(v,Q) Z_DIR_WRITE(v) #define Z_APPLY_STEP(v,Q) Z_STEP_WRITE(v) @@ -465,28 +493,66 @@ ISR(TIMER1_COMPA_vect) { } 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 } } @@ -845,6 +911,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); \ @@ -1174,3 +1247,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 diff --git a/Marlin/stepper.h b/Marlin/stepper.h index a1f2916090..d6c17d60f6 100644 --- a/Marlin/stepper.h +++ b/Marlin/stepper.h @@ -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 From c2ba5d0c094000617f37e57552090399eee64459 Mon Sep 17 00:00:00 2001 From: alexborro Date: Tue, 24 Mar 2015 15:50:31 -0300 Subject: [PATCH 02/13] Fix ZigZag and Topograph table MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ZigZag: Inverted Behavior.. If T supplied, it does not zigzag. Topograph table: The table was rotated 90ยบ clockwise. --- Marlin/Marlin_main.cpp | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/Marlin/Marlin_main.cpp b/Marlin/Marlin_main.cpp index 3316862add..b3235f5595 100644 --- a/Marlin/Marlin_main.cpp +++ b/Marlin/Marlin_main.cpp @@ -2274,13 +2274,11 @@ inline void gcode_G28() { xStart = 0; xStop = auto_bed_leveling_grid_points; xInc = 1; - zig = false; } else { xStart = auto_bed_leveling_grid_points - 1; xStop = -1; xInc = -1; - zig = true; } #ifndef DELTA @@ -2367,7 +2365,7 @@ inline void gcode_G28() { SERIAL_PROTOCOLPGM("+-----------+\n"); for (int yy = auto_bed_leveling_grid_points - 1; yy >= 0; yy--) { - for (int xx = auto_bed_leveling_grid_points - 1; xx >= 0; xx--) { + for (int xx = 0; xx < auto_bed_leveling_grid_points; xx++) { int ind = yy * auto_bed_leveling_grid_points + xx; float diff = eqnBVector[ind] - mean; if (diff >= 0.0) From 8848b7e9ef17c8e6ce2c1f8418416d54f48fe4df Mon Sep 17 00:00:00 2001 From: AnHardt Date: Wed, 25 Mar 2015 09:48:21 +0100 Subject: [PATCH 03/13] Add the missed {} to END_MENU in ultralcd.cpp what caused an extra update of encoderLine most of the time. --- Marlin/ultralcd.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Marlin/ultralcd.cpp b/Marlin/ultralcd.cpp index 0c27e7d500..f6af156d53 100644 --- a/Marlin/ultralcd.cpp +++ b/Marlin/ultralcd.cpp @@ -204,7 +204,7 @@ 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() \ - 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; }\ if (encoderLine >= currentMenuViewOffset + LCD_HEIGHT) { currentMenuViewOffset = encoderLine - LCD_HEIGHT + 1; lcdDrawUpdate = 1; _lineNr = currentMenuViewOffset - 1; _drawLineNr = -1; } \ } } while(0) From dd0067afa6966cf0243ad9eb38accc8ed6a5aafa Mon Sep 17 00:00:00 2001 From: AnHardt Date: Wed, 25 Mar 2015 11:08:24 +0100 Subject: [PATCH 04/13] Fix MAX6675 again and introduce set_current_temp_raw() to make the temperature-code work again with Arduino 1.0.6. Sorry could not make an extra block on base level. --- Marlin/temperature.cpp | 65 +++++++++++++++++++++++------------------- 1 file changed, 36 insertions(+), 29 deletions(-) diff --git a/Marlin/temperature.cpp b/Marlin/temperature.cpp index 713d0312f6..e236afee9a 100644 --- a/Marlin/temperature.cpp +++ b/Marlin/temperature.cpp @@ -576,6 +576,12 @@ void manage_heater() { updateTemperaturesFromRawValues(); + #ifdef HEATER_0_USES_MAX6675 + float ct = current_temperature[0]; + if (ct > min(HEATER_0_MAXTEMP, 1023)) max_temp_error(0); + if (ct < max(HEATER_0_MINTEMP, 0.01)) min_temp_error(0); + #endif //HEATER_0_USES_MAX6675 + unsigned long ms = millis(); // Loop through all extruders @@ -1162,20 +1168,40 @@ 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 EXTRUDERS +#endif + +unsigned long raw_temp_value[TEMP_SENSOR_COUNT] = { 0 }; +unsigned long raw_temp_bed_value = 0; + +void set_current_temp_raw() { + #ifndef HEATER_0_USES_MAX6675 + current_temperature_raw[0] = raw_temp_value[0]; + #endif + #if EXTRUDERS > 1 + current_temperature_raw[1] = raw_temp_value[1]; + #if EXTRUDERS > 2 + current_temperature_raw[2] = raw_temp_value[2]; + #if EXTRUDERS > 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; +} + // // Timer 0 is shared with millies // ISR(TIMER0_COMPB_vect) { - #ifdef TEMP_SENSOR_1_AS_REDUNDANT - #define TEMP_SENSOR_COUNT 2 - #else - #define TEMP_SENSOR_COUNT EXTRUDERS - #endif - //these variables are only accesible from the ISR, but static, so they don't lose their value static unsigned char temp_count = 0; - static unsigned long raw_temp_value[TEMP_SENSOR_COUNT] = { 0 }; - static unsigned long raw_temp_bed_value = 0; static TempState temp_state = StartupDelay; static unsigned char pwm_count = BIT(SOFT_PWM_SCALE); @@ -1478,22 +1504,7 @@ ISR(TIMER0_COMPB_vect) { if (temp_count >= OVERSAMPLENR) { // 10 * 16 * 1/(16000000/64/256) = 164ms. if (!temp_meas_ready) { //Only update the raw values if they have been read. Else we could be updating them during reading. - #ifndef HEATER_0_USES_MAX6675 - current_temperature_raw[0] = raw_temp_value[0]; - #endif - #if EXTRUDERS > 1 - current_temperature_raw[1] = raw_temp_value[1]; - #if EXTRUDERS > 2 - current_temperature_raw[2] = raw_temp_value[2]; - #if EXTRUDERS > 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; + set_current_temp_raw(); } //!temp_meas_ready // Filament Sensor - can be read any time since IIR filtering is used @@ -1506,11 +1517,7 @@ ISR(TIMER0_COMPB_vect) { for (int i = 0; i < TEMP_SENSOR_COUNT; i++) raw_temp_value[i] = 0; raw_temp_bed_value = 0; - #ifdef HEATER_0_USES_MAX6675 - float ct = current_temperature[0]; - if (ct > min(HEATER_0_MAXTEMP, 1023)) max_temp_error(0); - if (ct < max(HEATER_0_MINTEMP, 0.01)) min_temp_error(0); - #else + #ifndef HEATER_0_USES_MAX6675 #if HEATER_0_RAW_LO_TEMP > HEATER_0_RAW_HI_TEMP #define GE0 <= #else From 94330705c7e48ef2d4462368c01ea74281c63db4 Mon Sep 17 00:00:00 2001 From: AnHardt Date: Wed, 25 Mar 2015 11:51:41 +0100 Subject: [PATCH 05/13] Move definition of PIDdT back to temperature.h make it unconditional remove all definitions in the 'Configuration.h's remove form 'Conditionals.h' --- Marlin/Conditionals.h | 11 ----------- Marlin/Configuration.h | 3 +-- Marlin/configurator/config/Configuration.h | 3 +-- Marlin/example_configurations/Felix/Configuration.h | 3 +-- .../example_configurations/Felix/Configuration_DUAL.h | 3 +-- .../example_configurations/Hephestos/Configuration.h | 3 +-- Marlin/example_configurations/K8200/Configuration.h | 3 +-- Marlin/example_configurations/SCARA/Configuration.h | 3 +-- Marlin/example_configurations/WITBOX/Configuration.h | 3 +-- .../delta/generic/Configuration.h | 3 +-- .../delta/kossel_mini/Configuration.h | 3 +-- Marlin/example_configurations/makibox/Configuration.h | 3 +-- .../tvrrug/Round2/Configuration.h | 3 +-- Marlin/temperature.cpp | 4 ++++ 14 files changed, 16 insertions(+), 35 deletions(-) diff --git a/Marlin/Conditionals.h b/Marlin/Conditionals.h index fc6d6573ea..c471ec4366 100644 --- a/Marlin/Conditionals.h +++ b/Marlin/Conditionals.h @@ -390,16 +390,5 @@ #define WRITE_FAN(v) WRITE(FAN_PIN, v) #endif - /** - * Sampling period of the temperature routine - * This override comes originally from temperature.cpp - * The Configuration.h option is basically ignored. - */ - #ifdef PID_dT - #undef PID_dT - #endif - #define PID_dT ((OVERSAMPLENR * 12.0)/(F_CPU / 64.0 / 256.0)) - - #endif //CONFIGURATION_LCD #endif //CONDITIONALS_H diff --git a/Marlin/Configuration.h b/Marlin/Configuration.h index f5a36e6b9c..c02392be48 100644 --- a/Marlin/Configuration.h +++ b/Marlin/Configuration.h @@ -184,7 +184,6 @@ Here are some standard links for getting your machine calibrated: // is more then PID_FUNCTIONAL_RANGE then the PID will be shut off and the heater will be set to min/max. #define PID_INTEGRAL_DRIVE_MAX PID_MAX //limit for the integral term #define K1 0.95 //smoothing factor within the PID - #define PID_dT ((OVERSAMPLENR * 10.0)/(F_CPU / 64.0 / 256.0)) //sampling period of the temperature routine // If you are using a pre-configured hotend then you can use one of the value sets by uncommenting it // Ultimaker @@ -209,7 +208,7 @@ Here are some standard links for getting your machine calibrated: // Select PID or bang-bang with PIDTEMPBED. If bang-bang, BED_LIMIT_SWITCHING will enable hysteresis // // Uncomment this to enable PID on the bed. It uses the same frequency PWM as the extruder. -// If your PID_dT above is the default, and correct for your hardware/configuration, that means 7.689Hz, +// If your PID_dT is the default, and correct for your hardware/configuration, that means 7.689Hz, // which is fine for driving a square wave into a resistive load and does not significantly impact you FET heating. // This also works fine on a Fotek SSR-10DA Solid State Relay into a 250W heater. // If your configuration is significantly different than this and you don't understand the issues involved, you probably diff --git a/Marlin/configurator/config/Configuration.h b/Marlin/configurator/config/Configuration.h index 71cbdebaec..bfc62f5789 100644 --- a/Marlin/configurator/config/Configuration.h +++ b/Marlin/configurator/config/Configuration.h @@ -193,7 +193,6 @@ Here are some standard links for getting your machine calibrated: // is more then PID_FUNCTIONAL_RANGE then the PID will be shut off and the heater will be set to min/max. #define PID_INTEGRAL_DRIVE_MAX PID_MAX //limit for the integral term #define K1 0.95 //smoothing factor within the PID - #define PID_dT ((OVERSAMPLENR * 10.0)/(F_CPU / 64.0 / 256.0)) //sampling period of the temperature routine // If you are using a pre-configured hotend then you can use one of the value sets by uncommenting it // Ultimaker @@ -218,7 +217,7 @@ Here are some standard links for getting your machine calibrated: // Select PID or bang-bang with PIDTEMPBED. If bang-bang, BED_LIMIT_SWITCHING will enable hysteresis // // Uncomment this to enable PID on the bed. It uses the same frequency PWM as the extruder. -// If your PID_dT above is the default, and correct for your hardware/configuration, that means 7.689Hz, +// If your PID_dT is the default, and correct for your hardware/configuration, that means 7.689Hz, // which is fine for driving a square wave into a resistive load and does not significantly impact you FET heating. // This also works fine on a Fotek SSR-10DA Solid State Relay into a 250W heater. // If your configuration is significantly different than this and you don't understand the issues involved, you probably diff --git a/Marlin/example_configurations/Felix/Configuration.h b/Marlin/example_configurations/Felix/Configuration.h index e9801813f8..865a551677 100644 --- a/Marlin/example_configurations/Felix/Configuration.h +++ b/Marlin/example_configurations/Felix/Configuration.h @@ -184,7 +184,6 @@ Here are some standard links for getting your machine calibrated: // is more then PID_FUNCTIONAL_RANGE then the PID will be shut off and the heater will be set to min/max. #define PID_INTEGRAL_DRIVE_MAX PID_MAX //limit for the integral term #define K1 0.95 //smoothing factor within the PID - #define PID_dT ((OVERSAMPLENR * 10.0)/(F_CPU / 64.0 / 256.0)) //sampling period of the temperature routine // Felix 2.0+ electronics with v4 Hotend #define DEFAULT_Kp 12 @@ -199,7 +198,7 @@ Here are some standard links for getting your machine calibrated: // Select PID or bang-bang with PIDTEMPBED. If bang-bang, BED_LIMIT_SWITCHING will enable hysteresis // // Uncomment this to enable PID on the bed. It uses the same frequency PWM as the extruder. -// If your PID_dT above is the default, and correct for your hardware/configuration, that means 7.689Hz, +// If your PID_dT is the default, and correct for your hardware/configuration, that means 7.689Hz, // which is fine for driving a square wave into a resistive load and does not significantly impact you FET heating. // This also works fine on a Fotek SSR-10DA Solid State Relay into a 250W heater. // If your configuration is significantly different than this and you don't understand the issues involved, you probably diff --git a/Marlin/example_configurations/Felix/Configuration_DUAL.h b/Marlin/example_configurations/Felix/Configuration_DUAL.h index e9e4623cab..e9e0adba41 100644 --- a/Marlin/example_configurations/Felix/Configuration_DUAL.h +++ b/Marlin/example_configurations/Felix/Configuration_DUAL.h @@ -184,7 +184,6 @@ Here are some standard links for getting your machine calibrated: // is more then PID_FUNCTIONAL_RANGE then the PID will be shut off and the heater will be set to min/max. #define PID_INTEGRAL_DRIVE_MAX PID_MAX //limit for the integral term #define K1 0.95 //smoothing factor within the PID - #define PID_dT ((OVERSAMPLENR * 10.0)/(F_CPU / 64.0 / 256.0)) //sampling period of the temperature routine // Felix 2.0+ electronics with v4 Hotend #define DEFAULT_Kp 12 @@ -199,7 +198,7 @@ Here are some standard links for getting your machine calibrated: // Select PID or bang-bang with PIDTEMPBED. If bang-bang, BED_LIMIT_SWITCHING will enable hysteresis // // Uncomment this to enable PID on the bed. It uses the same frequency PWM as the extruder. -// If your PID_dT above is the default, and correct for your hardware/configuration, that means 7.689Hz, +// If your PID_dT is the default, and correct for your hardware/configuration, that means 7.689Hz, // which is fine for driving a square wave into a resistive load and does not significantly impact you FET heating. // This also works fine on a Fotek SSR-10DA Solid State Relay into a 250W heater. // If your configuration is significantly different than this and you don't understand the issues involved, you probably diff --git a/Marlin/example_configurations/Hephestos/Configuration.h b/Marlin/example_configurations/Hephestos/Configuration.h index c5b0243d57..5c426a5da7 100644 --- a/Marlin/example_configurations/Hephestos/Configuration.h +++ b/Marlin/example_configurations/Hephestos/Configuration.h @@ -184,7 +184,6 @@ Here are some standard links for getting your machine calibrated: // is more then PID_FUNCTIONAL_RANGE then the PID will be shut off and the heater will be set to min/max. #define PID_INTEGRAL_DRIVE_MAX PID_MAX //limit for the integral term #define K1 0.95 //smoothing factor within the PID - #define PID_dT ((OVERSAMPLENR * 10.0)/(F_CPU / 64.0 / 256.0)) //sampling period of the temperature routine // If you are using a pre-configured hotend then you can use one of the value sets by uncommenting it // Ultimaker @@ -215,7 +214,7 @@ Here are some standard links for getting your machine calibrated: // Select PID or bang-bang with PIDTEMPBED. If bang-bang, BED_LIMIT_SWITCHING will enable hysteresis // // Uncomment this to enable PID on the bed. It uses the same frequency PWM as the extruder. -// If your PID_dT above is the default, and correct for your hardware/configuration, that means 7.689Hz, +// If your PID_dT is the default, and correct for your hardware/configuration, that means 7.689Hz, // which is fine for driving a square wave into a resistive load and does not significantly impact you FET heating. // This also works fine on a Fotek SSR-10DA Solid State Relay into a 250W heater. // If your configuration is significantly different than this and you don't understand the issues involved, you probably diff --git a/Marlin/example_configurations/K8200/Configuration.h b/Marlin/example_configurations/K8200/Configuration.h index bc0f3e5dfe..96a261caf3 100644 --- a/Marlin/example_configurations/K8200/Configuration.h +++ b/Marlin/example_configurations/K8200/Configuration.h @@ -184,7 +184,6 @@ Here are some standard links for getting your machine calibrated: // is more then PID_FUNCTIONAL_RANGE then the PID will be shut off and the heater will be set to min/max. #define PID_INTEGRAL_DRIVE_MAX PID_MAX //limit for the integral term #define K1 0.95 //smoothing factor within the PID - #define PID_dT ((OVERSAMPLENR * 10.0)/(F_CPU / 64.0 / 256.0)) //sampling period of the temperature routine // If you are using a pre-configured hotend then you can use one of the value sets by uncommenting it // Ultimaker @@ -214,7 +213,7 @@ Here are some standard links for getting your machine calibrated: // Select PID or bang-bang with PIDTEMPBED. If bang-bang, BED_LIMIT_SWITCHING will enable hysteresis // // Uncomment this to enable PID on the bed. It uses the same frequency PWM as the extruder. -// If your PID_dT above is the default, and correct for your hardware/configuration, that means 7.689Hz, +// If your PID_dT is the default, and correct for your hardware/configuration, that means 7.689Hz, // which is fine for driving a square wave into a resistive load and does not significantly impact you FET heating. // This also works fine on a Fotek SSR-10DA Solid State Relay into a 250W heater. // If your configuration is significantly different than this and you don't understand the issues involved, you probably diff --git a/Marlin/example_configurations/SCARA/Configuration.h b/Marlin/example_configurations/SCARA/Configuration.h index d42bebe3af..30dc731840 100644 --- a/Marlin/example_configurations/SCARA/Configuration.h +++ b/Marlin/example_configurations/SCARA/Configuration.h @@ -202,7 +202,6 @@ Here are some standard links for getting your machine calibrated: // is more then PID_FUNCTIONAL_RANGE then the PID will be shut off and the heater will be set to min/max. #define PID_INTEGRAL_DRIVE_MAX PID_MAX //limit for the integral term #define K1 0.95 //smoothing factor within the PID - #define PID_dT ((OVERSAMPLENR * 10.0)/(F_CPU / 64.0 / 256.0)) //sampling period of the temperature routine // If you are using a pre-configured hotend then you can use one of the value sets by uncommenting it // Ultimaker @@ -238,7 +237,7 @@ Here are some standard links for getting your machine calibrated: // Select PID or bang-bang with PIDTEMPBED. If bang-bang, BED_LIMIT_SWITCHING will enable hysteresis // // Uncomment this to enable PID on the bed. It uses the same frequency PWM as the extruder. -// If your PID_dT above is the default, and correct for your hardware/configuration, that means 7.689Hz, +// If your PID_dT is the default, and correct for your hardware/configuration, that means 7.689Hz, // which is fine for driving a square wave into a resistive load and does not significantly impact you FET heating. // This also works fine on a Fotek SSR-10DA Solid State Relay into a 250W heater. // If your configuration is significantly different than this and you don't understand the issues involved, you probably diff --git a/Marlin/example_configurations/WITBOX/Configuration.h b/Marlin/example_configurations/WITBOX/Configuration.h index 481b591255..7a395d012d 100644 --- a/Marlin/example_configurations/WITBOX/Configuration.h +++ b/Marlin/example_configurations/WITBOX/Configuration.h @@ -184,7 +184,6 @@ Here are some standard links for getting your machine calibrated: // is more then PID_FUNCTIONAL_RANGE then the PID will be shut off and the heater will be set to min/max. #define PID_INTEGRAL_DRIVE_MAX PID_MAX //limit for the integral term #define K1 0.95 //smoothing factor within the PID - #define PID_dT ((OVERSAMPLENR * 10.0)/(F_CPU / 64.0 / 256.0)) //sampling period of the temperature routine // If you are using a pre-configured hotend then you can use one of the value sets by uncommenting it // Ultimaker @@ -214,7 +213,7 @@ Here are some standard links for getting your machine calibrated: // Select PID or bang-bang with PIDTEMPBED. If bang-bang, BED_LIMIT_SWITCHING will enable hysteresis // // Uncomment this to enable PID on the bed. It uses the same frequency PWM as the extruder. -// If your PID_dT above is the default, and correct for your hardware/configuration, that means 7.689Hz, +// If your PID_dT is the default, and correct for your hardware/configuration, that means 7.689Hz, // which is fine for driving a square wave into a resistive load and does not significantly impact you FET heating. // This also works fine on a Fotek SSR-10DA Solid State Relay into a 250W heater. // If your configuration is significantly different than this and you don't understand the issues involved, you probably diff --git a/Marlin/example_configurations/delta/generic/Configuration.h b/Marlin/example_configurations/delta/generic/Configuration.h index 0baf7de1c0..fb78c269da 100644 --- a/Marlin/example_configurations/delta/generic/Configuration.h +++ b/Marlin/example_configurations/delta/generic/Configuration.h @@ -217,7 +217,6 @@ Here are some standard links for getting your machine calibrated: // is more then PID_FUNCTIONAL_RANGE then the PID will be shut off and the heater will be set to min/max. #define PID_INTEGRAL_DRIVE_MAX PID_MAX //limit for the integral term #define K1 0.95 //smoothing factor within the PID - #define PID_dT ((OVERSAMPLENR * 10.0)/(F_CPU / 64.0 / 256.0)) //sampling period of the temperature routine // If you are using a pre-configured hotend then you can use one of the value sets by uncommenting it // Ultimaker @@ -242,7 +241,7 @@ Here are some standard links for getting your machine calibrated: // Select PID or bang-bang with PIDTEMPBED. If bang-bang, BED_LIMIT_SWITCHING will enable hysteresis // // Uncomment this to enable PID on the bed. It uses the same frequency PWM as the extruder. -// If your PID_dT above is the default, and correct for your hardware/configuration, that means 7.689Hz, +// If your PID_dT is the default, and correct for your hardware/configuration, that means 7.689Hz, // which is fine for driving a square wave into a resistive load and does not significantly impact you FET heating. // This also works fine on a Fotek SSR-10DA Solid State Relay into a 250W heater. // If your configuration is significantly different than this and you don't understand the issues involved, you probably diff --git a/Marlin/example_configurations/delta/kossel_mini/Configuration.h b/Marlin/example_configurations/delta/kossel_mini/Configuration.h index 9f5f89ca5a..556a98bf3b 100644 --- a/Marlin/example_configurations/delta/kossel_mini/Configuration.h +++ b/Marlin/example_configurations/delta/kossel_mini/Configuration.h @@ -218,7 +218,6 @@ Here are some standard links for getting your machine calibrated: // is more then PID_FUNCTIONAL_RANGE then the PID will be shut off and the heater will be set to min/max. #define PID_INTEGRAL_DRIVE_MAX PID_MAX //limit for the integral term #define K1 0.95 //smoothing factor within the PID - #define PID_dT ((OVERSAMPLENR * 10.0)/(F_CPU / 64.0 / 256.0)) //sampling period of the temperature routine // If you are using a pre-configured hotend then you can use one of the value sets by uncommenting it // Ultimaker @@ -243,7 +242,7 @@ Here are some standard links for getting your machine calibrated: // Select PID or bang-bang with PIDTEMPBED. If bang-bang, BED_LIMIT_SWITCHING will enable hysteresis // // Uncomment this to enable PID on the bed. It uses the same frequency PWM as the extruder. -// If your PID_dT above is the default, and correct for your hardware/configuration, that means 7.689Hz, +// If your PID_dT is the default, and correct for your hardware/configuration, that means 7.689Hz, // which is fine for driving a square wave into a resistive load and does not significantly impact you FET heating. // This also works fine on a Fotek SSR-10DA Solid State Relay into a 250W heater. // If your configuration is significantly different than this and you don't understand the issues involved, you probably diff --git a/Marlin/example_configurations/makibox/Configuration.h b/Marlin/example_configurations/makibox/Configuration.h index f6561b3af8..3e8c07fe46 100644 --- a/Marlin/example_configurations/makibox/Configuration.h +++ b/Marlin/example_configurations/makibox/Configuration.h @@ -184,7 +184,6 @@ Here are some standard links for getting your machine calibrated: // is more then PID_FUNCTIONAL_RANGE then the PID will be shut off and the heater will be set to min/max. #define PID_INTEGRAL_DRIVE_MAX PID_MAX //limit for the integral term #define K1 0.95 //smoothing factor within the PID - #define PID_dT ((OVERSAMPLENR * 10.0)/(F_CPU / 64.0 / 256.0)) //sampling period of the temperature routine // If you are using a pre-configured hotend then you can use one of the value sets by uncommenting it // Ultimaker @@ -209,7 +208,7 @@ Here are some standard links for getting your machine calibrated: // Select PID or bang-bang with PIDTEMPBED. If bang-bang, BED_LIMIT_SWITCHING will enable hysteresis // // Uncomment this to enable PID on the bed. It uses the same frequency PWM as the extruder. -// If your PID_dT above is the default, and correct for your hardware/configuration, that means 7.689Hz, +// If your PID_dT is the default, and correct for your hardware/configuration, that means 7.689Hz, // which is fine for driving a square wave into a resistive load and does not significantly impact you FET heating. // This also works fine on a Fotek SSR-10DA Solid State Relay into a 250W heater. // If your configuration is significantly different than this and you don't understand the issues involved, you probably diff --git a/Marlin/example_configurations/tvrrug/Round2/Configuration.h b/Marlin/example_configurations/tvrrug/Round2/Configuration.h index 17928b536b..22e16e4eeb 100644 --- a/Marlin/example_configurations/tvrrug/Round2/Configuration.h +++ b/Marlin/example_configurations/tvrrug/Round2/Configuration.h @@ -184,7 +184,6 @@ Here are some standard links for getting your machine calibrated: // is more then PID_FUNCTIONAL_RANGE then the PID will be shut off and the heater will be set to min/max. #define PID_INTEGRAL_DRIVE_MAX PID_MAX //limit for the integral term #define K1 0.95 //smoothing factor within the PID - #define PID_dT ((OVERSAMPLENR * 10.0)/(F_CPU / 64.0 / 256.0)) //sampling period of the temperature routine // If you are using a pre-configured hotend then you can use one of the value sets by uncommenting it // J-Head Mk V-B @@ -214,7 +213,7 @@ Here are some standard links for getting your machine calibrated: // Select PID or bang-bang with PIDTEMPBED. If bang-bang, BED_LIMIT_SWITCHING will enable hysteresis // // Uncomment this to enable PID on the bed. It uses the same frequency PWM as the extruder. -// If your PID_dT above is the default, and correct for your hardware/configuration, that means 7.689Hz, +// If your PID_dT is the default, and correct for your hardware/configuration, that means 7.689Hz, // which is fine for driving a square wave into a resistive load and does not significantly impact you FET heating. // This also works fine on a Fotek SSR-10DA Solid State Relay into a 250W heater. // If your configuration is significantly different than this and you don't understand the issues involved, you probably diff --git a/Marlin/temperature.cpp b/Marlin/temperature.cpp index 713d0312f6..abbc0600c4 100644 --- a/Marlin/temperature.cpp +++ b/Marlin/temperature.cpp @@ -45,6 +45,10 @@ #define K2 (1.0-K1) #endif +#ifdef PIDTEMPBED + #define PID_dT ((OVERSAMPLENR * 12.0)/(F_CPU / 64.0 / 256.0)) +#endif + //=========================================================================== //============================= public variables ============================ //=========================================================================== From 01cc97a3c36f9cfde39cb2a7075d89aeec650383 Mon Sep 17 00:00:00 2001 From: AnHardt Date: Wed, 25 Mar 2015 12:08:23 +0100 Subject: [PATCH 06/13] Corected condition for PIDdT --- Marlin/temperature.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Marlin/temperature.cpp b/Marlin/temperature.cpp index abbc0600c4..1909280afb 100644 --- a/Marlin/temperature.cpp +++ b/Marlin/temperature.cpp @@ -45,7 +45,7 @@ #define K2 (1.0-K1) #endif -#ifdef PIDTEMPBED +#if defined(PIDTEMPBED) || defined(PIDTEMP) #define PID_dT ((OVERSAMPLENR * 12.0)/(F_CPU / 64.0 / 256.0)) #endif From a4ad9117ddb0151c32a1121bd6203a221ae00db5 Mon Sep 17 00:00:00 2001 From: wurstnase Date: Wed, 25 Mar 2015 13:46:29 +0100 Subject: [PATCH 07/13] comment #define Z_DUAL_STEPPER_DRIVERS --- Marlin/Configuration_adv.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Marlin/Configuration_adv.h b/Marlin/Configuration_adv.h index 721074e23c..9ff7644f88 100644 --- a/Marlin/Configuration_adv.h +++ b/Marlin/Configuration_adv.h @@ -98,7 +98,7 @@ // Only a few motherboards support this, like RAMPS, which have dual extruder support (the 2nd, often unused, extruder driver is used // to control the 2nd Z axis stepper motor). The pins are currently only defined for a RAMPS motherboards. // On a RAMPS (or other 5 driver) motherboard, using this feature will limit you to using 1 extruder. -#define Z_DUAL_STEPPER_DRIVERS +//#define Z_DUAL_STEPPER_DRIVERS #ifdef Z_DUAL_STEPPER_DRIVERS From 55025558dc87ecd7aed6c8fc8cd5df3dfb29d217 Mon Sep 17 00:00:00 2001 From: alexborro Date: Wed, 25 Mar 2015 11:12:30 -0300 Subject: [PATCH 08/13] Implement Dry-Run mode in G29 It just probe all the bed without appliying the matrix. Useful after a first G29 to check the topology. --- Marlin/Marlin_main.cpp | 78 +++++++++++++++++++++++++----------------- 1 file changed, 47 insertions(+), 31 deletions(-) diff --git a/Marlin/Marlin_main.cpp b/Marlin/Marlin_main.cpp index b3235f5595..6361559b0e 100644 --- a/Marlin/Marlin_main.cpp +++ b/Marlin/Marlin_main.cpp @@ -1168,6 +1168,7 @@ static void run_z_probe() { zPosition += home_retract_mm(Z_AXIS); plan_buffer_line(current_position[X_AXIS], current_position[Y_AXIS], zPosition, current_position[E_AXIS], feedrate/60, active_extruder); st_synchronize(); + endstops_hit_on_purpose(); // move back down slowly to find bed @@ -1185,6 +1186,7 @@ static void run_z_probe() { zPosition -= home_retract_mm(Z_AXIS) * 2; plan_buffer_line(current_position[X_AXIS], current_position[Y_AXIS], zPosition, current_position[E_AXIS], feedrate/60, active_extruder); st_synchronize(); + endstops_hit_on_purpose(); current_position[Z_AXIS] = st_get_position_mm(Z_AXIS); // make sure the planner knows where we are as it may be a bit different than we last said to move to @@ -1389,11 +1391,11 @@ static float probe_pt(float x, float y, float z_before, ProbeAction retract_acti if (verbose_level > 2) { SERIAL_PROTOCOLPGM(MSG_BED); SERIAL_PROTOCOLPGM(" X: "); - SERIAL_PROTOCOL(x + 0.0001); + SERIAL_PROTOCOL_F(x, 3); SERIAL_PROTOCOLPGM(" Y: "); - SERIAL_PROTOCOL(y + 0.0001); + SERIAL_PROTOCOL_F(y, 3); SERIAL_PROTOCOLPGM(" Z: "); - SERIAL_PROTOCOL(measured_z + 0.0001); + SERIAL_PROTOCOL_F(measured_z, 3); SERIAL_EOL; } return measured_z; @@ -2109,6 +2111,9 @@ inline void gcode_G28() { * * S Set the XY travel speed between probe points (in mm/min) * + * D Dry-Run mode. Just evaluate the bed Topology - It does not apply or clean the rotation Matrix + * Useful to check the topology after a first run of G29. + * * V Set the verbose level (0-4). Example: "G29 V3" * * T Generate a Bed Topology Report. Example: "G29 P5 T" for a detailed report. @@ -2150,6 +2155,7 @@ inline void gcode_G28() { } } + bool dryrun = code_seen('D') || code_seen('d'); bool enhanced_g29 = code_seen('E') || code_seen('e'); #ifdef AUTO_BED_LEVELING_GRID @@ -2159,7 +2165,10 @@ inline void gcode_G28() { #endif if (verbose_level > 0) + { SERIAL_PROTOCOLPGM("G29 Auto Bed Leveling\n"); + if (dryrun) SERIAL_ECHOLN("Running in DRY-RUN mode"); + } int auto_bed_leveling_grid_points = AUTO_BED_LEVELING_GRID_POINTS; #ifndef DELTA @@ -2216,22 +2225,27 @@ inline void gcode_G28() { st_synchronize(); - #ifdef DELTA - reset_bed_level(); - #else + if (!dryrun) + { + #ifdef DELTA + reset_bed_level(); + #else - // make sure the bed_level_rotation_matrix is identity or the planner will get it incorectly - //vector_3 corrected_position = plan_get_position_mm(); - //corrected_position.debug("position before G29"); - plan_bed_level_matrix.set_to_identity(); - vector_3 uncorrected_position = plan_get_position(); - //uncorrected_position.debug("position during G29"); - current_position[X_AXIS] = uncorrected_position.x; - current_position[Y_AXIS] = uncorrected_position.y; - current_position[Z_AXIS] = uncorrected_position.z; - plan_set_position(current_position[X_AXIS], current_position[Y_AXIS], current_position[Z_AXIS], current_position[E_AXIS]); - #endif + // make sure the bed_level_rotation_matrix is identity or the planner will get it incorectly + //vector_3 corrected_position = plan_get_position_mm(); + //corrected_position.debug("position before G29"); + plan_bed_level_matrix.set_to_identity(); + vector_3 uncorrected_position = plan_get_position(); +// uncorrected_position.debug("position during G29"); + current_position[X_AXIS] = uncorrected_position.x; + current_position[Y_AXIS] = uncorrected_position.y; + current_position[Z_AXIS] = uncorrected_position.z; + plan_set_position(current_position[X_AXIS], current_position[Y_AXIS], current_position[Z_AXIS], current_position[E_AXIS]); + + #endif + } + setup_for_endstop_move(); feedrate = homing_feedrate[Z_AXIS]; @@ -2381,12 +2395,12 @@ inline void gcode_G28() { } //do_topography_map - set_bed_level_equation_lsq(plane_equation_coefficients); + if (!dryrun) set_bed_level_equation_lsq(plane_equation_coefficients); free(plane_equation_coefficients); - #else - extrapolate_unprobed_bed_level(); + #else //Delta + if (!dryrun) extrapolate_unprobed_bed_level(); print_bed_level(); - #endif + #endif //Delta #else // !AUTO_BED_LEVELING_GRID @@ -2405,25 +2419,27 @@ inline void gcode_G28() { z_at_pt_3 = probe_pt(ABL_PROBE_PT_3_X, ABL_PROBE_PT_3_Y, current_position[Z_AXIS] + Z_RAISE_BETWEEN_PROBINGS, ProbeEngageAndRetract, verbose_level); } clean_up_after_endstop_move(); - set_bed_level_equation_3pts(z_at_pt_1, z_at_pt_2, z_at_pt_3); + if (!dryrun) set_bed_level_equation_3pts(z_at_pt_1, z_at_pt_2, z_at_pt_3); #endif // !AUTO_BED_LEVELING_GRID #ifndef DELTA - if (verbose_level > 0) - plan_bed_level_matrix.debug(" \n\nBed Level Correction Matrix:"); + if (verbose_level > 0) plan_bed_level_matrix.debug(" \n\nBed Level Correction Matrix:"); // Correct the Z height difference from z-probe position and hotend tip position. // The Z height on homing is measured by Z-Probe, but the probe is quite far from the hotend. // When the bed is uneven, this height must be corrected. - real_z = float(st_get_position(Z_AXIS)) / axis_steps_per_unit[Z_AXIS]; //get the real Z (since the auto bed leveling is already correcting the plane) - x_tmp = current_position[X_AXIS] + X_PROBE_OFFSET_FROM_EXTRUDER; - y_tmp = current_position[Y_AXIS] + Y_PROBE_OFFSET_FROM_EXTRUDER; - z_tmp = current_position[Z_AXIS]; + if (!dryrun) + { + real_z = float(st_get_position(Z_AXIS)) / axis_steps_per_unit[Z_AXIS]; //get the real Z (since the auto bed leveling is already correcting the plane) + x_tmp = current_position[X_AXIS] + X_PROBE_OFFSET_FROM_EXTRUDER; + y_tmp = current_position[Y_AXIS] + Y_PROBE_OFFSET_FROM_EXTRUDER; + z_tmp = current_position[Z_AXIS]; - apply_rotation_xyz(plan_bed_level_matrix, x_tmp, y_tmp, z_tmp); //Apply the correction sending the probe offset - current_position[Z_AXIS] = z_tmp - real_z + current_position[Z_AXIS]; //The difference is added to current position and sent to planner. - plan_set_position(current_position[X_AXIS], current_position[Y_AXIS], current_position[Z_AXIS], current_position[E_AXIS]); + apply_rotation_xyz(plan_bed_level_matrix, x_tmp, y_tmp, z_tmp); //Apply the correction sending the probe offset + current_position[Z_AXIS] = z_tmp - real_z + current_position[Z_AXIS]; //The difference is added to current position and sent to planner. + plan_set_position(current_position[X_AXIS], current_position[Y_AXIS], current_position[Z_AXIS], current_position[E_AXIS]); + } #endif #ifdef Z_PROBE_SLED From 4a78db29eb15d599f22c99d66cf79d1427061c64 Mon Sep 17 00:00:00 2001 From: Edward Patel Date: Wed, 25 Mar 2015 21:28:05 +0100 Subject: [PATCH 09/13] Added instructions for Mesh bed leveling --- Documentation/MeshBedLeveling.md | 76 ++++++++++++++++++++++++++++++++ README.md | 1 + 2 files changed, 77 insertions(+) create mode 100644 Documentation/MeshBedLeveling.md diff --git a/Documentation/MeshBedLeveling.md b/Documentation/MeshBedLeveling.md new file mode 100644 index 0000000000..318c0fa0dc --- /dev/null +++ b/Documentation/MeshBedLeveling.md @@ -0,0 +1,76 @@ +============================================== +Instructions for configuring Mesh Bed Leveling +============================================== + +Background +---------- + +This mesh based method of leveling/compensating can compensate for an non-flat bed. There are various opinions about doing this. It was primarily written to compensate a RigidBot BIG bed (40x30cm) that was somewhat bent. + +Currently there is no automatic way to probe the bed like the Auto Bed Leveling feature. This might soon be implemented though, stay tuned. + +Theory +------ + +The bed is manually probed in a grid maner. During a print the Z axis compensation will be interpolated within each square using a bi-linear method. Because the grid squares can be tilting in different directions a printing move can be split on grid square borders. During fast travel moves one can sometimes notice a de-acceleration on these borders. + +Mesh point probing can either be carried out from the display, or by issuing `G29` commands. + +The Z-endstop should be set slightly above the bed. An opto endstop is preferable but a switch with a metal arm that allow some press though should also work. + +Configuration +------------- + +In `Configuration.h` there are two options that can be enabled. + +`MESH_BED_LEVELING` will enable mesh bed leveling.
+`MANUAL_BED_LEVELING` will add the menu option for bed leveling. + +There is also some values that can be set. + +Following four define the area to cover. Default 10mm from max bed size + +`MESH_MIN_X`
+`MESH_MAX_X`
+`MESH_MIN_Y`
+`MESH_MAX_Y` + +Following two define the number of points to probe, total number will be these two multiplied. Default is 3x3 points. Don't probe more than 7x7 points (software limited) + +`MESH_NUM_X_POINTS`
+`MESH_NUM_Y_POINTS`
+ +The following will set the Z-endstop height during probing. When initiating a bed leveling probing a homing will take place and the Z-endstop will be set to this height so lowering through the endstop can take place and the bed should be within this distance. Default is 4mm + +`MESH_HOME_SEARCH_Z` + +The probed points will also be saved in the EEPROM if it has been enables. Otherwise a new probe sequence needs to be made next time the printer has been turned on. + +Probing the bed with the display +-------------------------------- + +If `MANUAL_BED_LEVELING` has been enabled then will a `Level bed` menu option be available in the `Prepare` menu. + +When selecting this option the printer will first do a homing, and then travel to the first probe point. There is will wait. By turning the encoder on the display the hotend can now be lowered until it touches the bed. Using a paper to feel the distance when it gets close. Pressing the encoder/button will store this point and then travel to the next point. Repeating this until all points have been probed. + +If the EEPROM has been enable it can be good to issue a `M500` to get these points saved. + +Issuing a `G29` will return the state of the mesh leveling. + +Probing the bed with G-codes +---------------------------- + +Probing the bed by G-codes follows the sequence much like doing it with the display. + +`G29` or `G29 S0` will return the state bed leveling. + +`G29 S1` will initiate the bed leveling, homing and traveling to the first point to probe. + +Then use your preferred Printer controller program, i.e. Printrun, to lower the hotend until it touches the bed. Using a paper to feel the distance when it gets close. + +`G29 S2` will store the point and travel to the next point until last point has been probed. + +Note +---- + +Depending how firm feel you aim for on the paper you can use the `Z offset` option in Slic3r to compensate a slight height diff. (I like the paper loose so I needed to put `-0.05` in Slic3r) \ No newline at end of file diff --git a/README.md b/README.md index 155e916f58..e674c62c65 100644 --- a/README.md +++ b/README.md @@ -10,6 +10,7 @@ * [Auto Bed Leveling](/Documentation/BedLeveling.md) * [Filament Sensor](/Documentation/FilamentSensor.md) * [Ramps Servo Power](/Documentation/RampsServoPower.md) + * [Mesh Bed Leveling](/Documentation/MeshBedLeveling.md) ##### [RepRap.org Wiki Page](http://reprap.org/wiki/Marlin) From 92a7260fd05d7af241b23dd7eedf897ac6234cd7 Mon Sep 17 00:00:00 2001 From: Edward Patel Date: Wed, 25 Mar 2015 21:34:55 +0100 Subject: [PATCH 10/13] typos --- Documentation/MeshBedLeveling.md | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/Documentation/MeshBedLeveling.md b/Documentation/MeshBedLeveling.md index 318c0fa0dc..21eabb6b09 100644 --- a/Documentation/MeshBedLeveling.md +++ b/Documentation/MeshBedLeveling.md @@ -12,11 +12,11 @@ Currently there is no automatic way to probe the bed like the Auto Bed Leveling Theory ------ -The bed is manually probed in a grid maner. During a print the Z axis compensation will be interpolated within each square using a bi-linear method. Because the grid squares can be tilting in different directions a printing move can be split on grid square borders. During fast travel moves one can sometimes notice a de-acceleration on these borders. +The bed is manually probed in a grid maner. During a print the Z axis compensation will be interpolated within each square using a bi-linear method. Because the grid squares can be tilting in different directions a printing move can be split on the borders of the grid squares. During fast travel moves one can sometimes notice a de-acceleration on these borders. Mesh point probing can either be carried out from the display, or by issuing `G29` commands. -The Z-endstop should be set slightly above the bed. An opto endstop is preferable but a switch with a metal arm that allow some press though should also work. +The Z-endstop should be set slightly above the bed. An opto endstop is preferable but a switch with a metal arm that allow some travel though should also work. Configuration ------------- @@ -26,7 +26,7 @@ In `Configuration.h` there are two options that can be enabled. `MESH_BED_LEVELING` will enable mesh bed leveling.
`MANUAL_BED_LEVELING` will add the menu option for bed leveling. -There is also some values that can be set. +There are also some values that can be set. Following four define the area to cover. Default 10mm from max bed size @@ -40,7 +40,7 @@ Following two define the number of points to probe, total number will be these t `MESH_NUM_X_POINTS`
`MESH_NUM_Y_POINTS`
-The following will set the Z-endstop height during probing. When initiating a bed leveling probing a homing will take place and the Z-endstop will be set to this height so lowering through the endstop can take place and the bed should be within this distance. Default is 4mm +The following will set the Z-endstop height during probing. When initiating a bed leveling probing, a homing will take place and the Z-endstop will be set to this height so lowering through the endstop can take place and the bed should be within this distance. Default is 4mm `MESH_HOME_SEARCH_Z` @@ -51,7 +51,7 @@ Probing the bed with the display If `MANUAL_BED_LEVELING` has been enabled then will a `Level bed` menu option be available in the `Prepare` menu. -When selecting this option the printer will first do a homing, and then travel to the first probe point. There is will wait. By turning the encoder on the display the hotend can now be lowered until it touches the bed. Using a paper to feel the distance when it gets close. Pressing the encoder/button will store this point and then travel to the next point. Repeating this until all points have been probed. +When selecting this option the printer will first do a homing, and then travel to the first probe point. There it will wait. By turning the encoder on the display the hotend can now be lowered until it touches the bed. Using a paper to feel the distance when it gets close. Pressing the encoder/button will store this point and then travel to the next point. Repeating this until all points have been probed. If the EEPROM has been enable it can be good to issue a `M500` to get these points saved. From ac81b4084feb55d8cdea584202bae0fffaeb61f2 Mon Sep 17 00:00:00 2001 From: AnHardt Date: Wed, 25 Mar 2015 21:37:15 +0100 Subject: [PATCH 11/13] Make variables and function static. --- Marlin/temperature.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Marlin/temperature.cpp b/Marlin/temperature.cpp index e236afee9a..c66959674e 100644 --- a/Marlin/temperature.cpp +++ b/Marlin/temperature.cpp @@ -1174,10 +1174,10 @@ enum TempState { #define TEMP_SENSOR_COUNT EXTRUDERS #endif -unsigned long raw_temp_value[TEMP_SENSOR_COUNT] = { 0 }; -unsigned long raw_temp_bed_value = 0; +static unsigned long raw_temp_value[TEMP_SENSOR_COUNT] = { 0 }; +static unsigned long raw_temp_bed_value = 0; -void set_current_temp_raw() { +static void set_current_temp_raw() { #ifndef HEATER_0_USES_MAX6675 current_temperature_raw[0] = raw_temp_value[0]; #endif From d43d47da1430eadbaf19a4e785868deb0c7dc1f6 Mon Sep 17 00:00:00 2001 From: Victor Torre Date: Wed, 25 Mar 2015 22:05:18 +0100 Subject: [PATCH 12/13] Clean "fromsd" array is not SDSUPPORT if not have SDSUPPORT the fromsd array is not necessary --- Marlin/Marlin_main.cpp | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/Marlin/Marlin_main.cpp b/Marlin/Marlin_main.cpp index 6361559b0e..6130ac8f50 100644 --- a/Marlin/Marlin_main.cpp +++ b/Marlin/Marlin_main.cpp @@ -395,7 +395,9 @@ static long gcode_N, gcode_LastN, Stopped_gcode_LastN = 0; static bool relative_mode = false; //Determines Absolute or Relative Coordinates static char cmdbuffer[BUFSIZE][MAX_CMD_SIZE]; +#ifdef SDSUPPORT static bool fromsd[BUFSIZE]; +#endif //!SDSUPPORT static int bufindr = 0; static int bufindw = 0; static int buflen = 0; @@ -655,10 +657,12 @@ void setup() SERIAL_ECHO(freeMemory()); SERIAL_ECHOPGM(MSG_PLANNER_BUFFER_BYTES); SERIAL_ECHOLN((int)sizeof(block_t)*BLOCK_BUFFER_SIZE); + #ifdef SDSUPPORT for(int8_t i = 0; i < BUFSIZE; i++) { fromsd[i] = false; } + #endif //!SDSUPPORT // loads data from EEPROM if available else uses defaults (and resets step acceleration rate) Config_RetrieveSettings(); @@ -764,8 +768,9 @@ void get_command() return; } cmdbuffer[bufindw][serial_count] = 0; //terminate string - + #ifdef SDSUPPORT fromsd[bufindw] = false; + #endif //!SDSUPPORT if(strchr(cmdbuffer[bufindw], 'N') != NULL) { strchr_pointer = strchr(cmdbuffer[bufindw], 'N'); From f680e509c4a3897a7563ac96e3c7e2262225af32 Mon Sep 17 00:00:00 2001 From: AnHardt Date: Wed, 25 Mar 2015 23:26:06 +0100 Subject: [PATCH 13/13] Enclosed error-messages for TEMP_SENSOR_1_AS_REDUNDANT in PSTR() --- Marlin/temperature.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Marlin/temperature.cpp b/Marlin/temperature.cpp index c66959674e..ef75ae439c 100644 --- a/Marlin/temperature.cpp +++ b/Marlin/temperature.cpp @@ -613,7 +613,7 @@ 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