From 3b315b3da0464efd39e1f5a379eaeba601c4871f Mon Sep 17 00:00:00 2001 From: Tim Koster Date: Fri, 6 Sep 2013 22:25:39 +0300 Subject: [PATCH 01/15] Added BlinkM support over i2c --- Marlin/BlinkM.cpp | 23 +++++++++++++++++++++++ Marlin/BlinkM.h | 14 ++++++++++++++ Marlin/Configuration.h | 3 +++ Marlin/Marlin_main.cpp | 17 +++++++++++++++++ 4 files changed, 57 insertions(+) create mode 100644 Marlin/BlinkM.cpp create mode 100644 Marlin/BlinkM.h diff --git a/Marlin/BlinkM.cpp b/Marlin/BlinkM.cpp new file mode 100644 index 0000000000..15a2527bbf --- /dev/null +++ b/Marlin/BlinkM.cpp @@ -0,0 +1,23 @@ +/* + BlinkM.cpp - Library for controlling a BlinkM over i2c + Created by Tim Koster, August 21 2013. +*/ +#if (ARDUINO >= 100) + # include "Arduino.h" +#else + # include "WProgram.h" +#endif +#include "BlinkM.h" + +void SendColors(byte red, byte grn, byte blu) +{ + Wire.begin(); + Wire.beginTransmission(0x09); + Wire.write('o'); //to disable ongoing script, only needs to be used once + Wire.write('n'); + Wire.write(red); + Wire.write(grn); + Wire.write(blu); + Wire.endTransmission(); +} + diff --git a/Marlin/BlinkM.h b/Marlin/BlinkM.h new file mode 100644 index 0000000000..5136828782 --- /dev/null +++ b/Marlin/BlinkM.h @@ -0,0 +1,14 @@ +/* + BlinkM.h + Library header file for BlinkM library + */ +#if (ARDUINO >= 100) + # include "Arduino.h" +#else + # include "WProgram.h" +#endif + +#include "Wire.h" + +void SendColors(byte red, byte grn, byte blu); + diff --git a/Marlin/Configuration.h b/Marlin/Configuration.h index 9ff27f5b00..67760abe3b 100644 --- a/Marlin/Configuration.h +++ b/Marlin/Configuration.h @@ -533,6 +533,9 @@ const bool Z_MAX_ENDSTOP_INVERTING = true; // set to true to invert the logic of # endif #endif +// define BlinkM Support +#define BlinkM + // Increase the FAN pwm frequency. Removes the PWM noise but increases heating in the FET/Arduino //#define FAST_PWM_FAN diff --git a/Marlin/Marlin_main.cpp b/Marlin/Marlin_main.cpp index 4609ce818e..26fbd41232 100644 --- a/Marlin/Marlin_main.cpp +++ b/Marlin/Marlin_main.cpp @@ -40,6 +40,9 @@ #include "language.h" #include "pins_arduino.h" +#include "BlinkM.h" +#include "Wire.h" + #if NUM_SERVOS > 0 #include "Servo.h" #endif @@ -109,6 +112,7 @@ // M128 - EtoP Open (BariCUDA EtoP = electricity to air pressure transducer by jmil) // M129 - EtoP Closed (BariCUDA EtoP = electricity to air pressure transducer by jmil) // M140 - Set bed target temp +// M150 - Set BlinkM Colour Output R: Red<0-255> U(!): Green<0-255> B: Blue<0-255> over i2c, G for green does not work. // M190 - Sxxx Wait for bed current temp to reach target temp. Waits only when heating // Rxxx Wait for bed current temp to reach target temp. Waits when heating and cooling // M200 - Set filament diameter @@ -1613,6 +1617,19 @@ void process_commands() #endif break; //TODO: update for all axis, use for loop + case 150: // M150 + { + byte red; + byte grn; + byte blu; + + if(code_seen('R')) red = code_value(); + if(code_seen('U')) grn = code_value(); + if(code_seen('B')) blu = code_value(); + + SendColors(red,grn,blu); + } + break; case 201: // M201 for(int8_t i=0; i < NUM_AXIS; i++) { From 7016cc951186d876e7812cbeb945f5d27b125fb7 Mon Sep 17 00:00:00 2001 From: Tim Koster Date: Tue, 10 Sep 2013 12:18:29 +0300 Subject: [PATCH 02/15] Added BlinkM support over i2c --- Marlin/BlinkM.cpp | 23 +++++++++++++++++++++++ Marlin/BlinkM.h | 14 ++++++++++++++ Marlin/Configuration.h | 3 +++ Marlin/Marlin_main.cpp | 17 +++++++++++++++++ 4 files changed, 57 insertions(+) create mode 100644 Marlin/BlinkM.cpp create mode 100644 Marlin/BlinkM.h diff --git a/Marlin/BlinkM.cpp b/Marlin/BlinkM.cpp new file mode 100644 index 0000000000..15a2527bbf --- /dev/null +++ b/Marlin/BlinkM.cpp @@ -0,0 +1,23 @@ +/* + BlinkM.cpp - Library for controlling a BlinkM over i2c + Created by Tim Koster, August 21 2013. +*/ +#if (ARDUINO >= 100) + # include "Arduino.h" +#else + # include "WProgram.h" +#endif +#include "BlinkM.h" + +void SendColors(byte red, byte grn, byte blu) +{ + Wire.begin(); + Wire.beginTransmission(0x09); + Wire.write('o'); //to disable ongoing script, only needs to be used once + Wire.write('n'); + Wire.write(red); + Wire.write(grn); + Wire.write(blu); + Wire.endTransmission(); +} + diff --git a/Marlin/BlinkM.h b/Marlin/BlinkM.h new file mode 100644 index 0000000000..5136828782 --- /dev/null +++ b/Marlin/BlinkM.h @@ -0,0 +1,14 @@ +/* + BlinkM.h + Library header file for BlinkM library + */ +#if (ARDUINO >= 100) + # include "Arduino.h" +#else + # include "WProgram.h" +#endif + +#include "Wire.h" + +void SendColors(byte red, byte grn, byte blu); + diff --git a/Marlin/Configuration.h b/Marlin/Configuration.h index 9ff27f5b00..195331252f 100644 --- a/Marlin/Configuration.h +++ b/Marlin/Configuration.h @@ -557,6 +557,9 @@ const bool Z_MAX_ENDSTOP_INVERTING = true; // set to true to invert the logic of // Support for the BariCUDA Paste Extruder. //#define BARICUDA +//define BlinkM/CyzRgb Support +//#define BlinkM + /*********************************************************************\ * R/C SERVO support * Sponsored by TrinityLabs, Reworked by codexmas diff --git a/Marlin/Marlin_main.cpp b/Marlin/Marlin_main.cpp index 4609ce818e..26fbd41232 100644 --- a/Marlin/Marlin_main.cpp +++ b/Marlin/Marlin_main.cpp @@ -40,6 +40,9 @@ #include "language.h" #include "pins_arduino.h" +#include "BlinkM.h" +#include "Wire.h" + #if NUM_SERVOS > 0 #include "Servo.h" #endif @@ -109,6 +112,7 @@ // M128 - EtoP Open (BariCUDA EtoP = electricity to air pressure transducer by jmil) // M129 - EtoP Closed (BariCUDA EtoP = electricity to air pressure transducer by jmil) // M140 - Set bed target temp +// M150 - Set BlinkM Colour Output R: Red<0-255> U(!): Green<0-255> B: Blue<0-255> over i2c, G for green does not work. // M190 - Sxxx Wait for bed current temp to reach target temp. Waits only when heating // Rxxx Wait for bed current temp to reach target temp. Waits when heating and cooling // M200 - Set filament diameter @@ -1613,6 +1617,19 @@ void process_commands() #endif break; //TODO: update for all axis, use for loop + case 150: // M150 + { + byte red; + byte grn; + byte blu; + + if(code_seen('R')) red = code_value(); + if(code_seen('U')) grn = code_value(); + if(code_seen('B')) blu = code_value(); + + SendColors(red,grn,blu); + } + break; case 201: // M201 for(int8_t i=0; i < NUM_AXIS; i++) { From 88dfeefca3c47158e634998c2ed96a21a6b04f50 Mon Sep 17 00:00:00 2001 From: Tim Koster Date: Tue, 10 Sep 2013 12:32:21 +0300 Subject: [PATCH 03/15] Define BlinkM default disabled --- Marlin/Configuration.h | 3 --- 1 file changed, 3 deletions(-) diff --git a/Marlin/Configuration.h b/Marlin/Configuration.h index 33b96f5b33..195331252f 100644 --- a/Marlin/Configuration.h +++ b/Marlin/Configuration.h @@ -533,9 +533,6 @@ const bool Z_MAX_ENDSTOP_INVERTING = true; // set to true to invert the logic of # endif #endif -// define BlinkM Support -#define BlinkM - // Increase the FAN pwm frequency. Removes the PWM noise but increases heating in the FET/Arduino //#define FAST_PWM_FAN From 7ee275b620fa055bb2b7516cf302ac3e531438ac Mon Sep 17 00:00:00 2001 From: Richard Miles Date: Tue, 17 Sep 2013 19:02:00 +0100 Subject: [PATCH 04/15] Added Y_DUAL_STEPPER_DRIVERS Enables two stepper drivers to be used for the Y axis (useful for Shapeoko style machines) Each Y driver can be stepped either the same way or in opposite directions, accounting for different hardware setups (leadscrew vs. belt driven) --- Marlin/Configuration_adv.h | 73 +++++++- Marlin/Marlin.h | 30 ++- Marlin/stepper.cpp | 368 ++++++++++++++++++++++++------------- 3 files changed, 326 insertions(+), 145 deletions(-) diff --git a/Marlin/Configuration_adv.h b/Marlin/Configuration_adv.h index 5f1c77a056..648a9beafc 100644 --- a/Marlin/Configuration_adv.h +++ b/Marlin/Configuration_adv.h @@ -18,12 +18,6 @@ //#define WATCH_TEMP_PERIOD 40000 //40 seconds //#define WATCH_TEMP_INCREASE 10 //Heat up at least 10 degree in 20 seconds -// Wait for Cooldown -// This defines if the M109 call should not block if it is cooling down. -// example: From a current temp of 220, you set M109 S200. -// if CooldownNoWait is defined M109 will not wait for the cooldown to finish -#define CooldownNoWait true - #ifdef PIDTEMP // this adds an experimental additional term to the heatingpower, proportional to the extrusion speed. // if Kc is choosen well, the additional required power due to increased melting should be compensated. @@ -152,6 +146,68 @@ #define EXTRUDERS 1 #endif +// Same again but for Y Axis. +#define Y_DUAL_STEPPER_DRIVERS + +// 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 + +#ifdef Z_DUAL_STEPPER_DRIVERS && 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 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 + +// As the x-carriages are independent we can now account for any relative Z offset +#define EXTRUDER1_Z_OFFSET 0.0 // z offset relative to extruder 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 @@ -174,6 +230,11 @@ #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 + // minimum time in microseconds that a movement needs to take if the buffer is emptied. #define DEFAULT_MINSEGMENTTIME 20000 diff --git a/Marlin/Marlin.h b/Marlin/Marlin.h index c9759eb219..3066017966 100644 --- a/Marlin/Marlin.h +++ b/Marlin/Marlin.h @@ -51,22 +51,22 @@ #define MYSERIAL MSerial #endif -#define SERIAL_PROTOCOL(x) MYSERIAL.print(x); -#define SERIAL_PROTOCOL_F(x,y) MYSERIAL.print(x,y); -#define SERIAL_PROTOCOLPGM(x) serialprintPGM(PSTR(x)); -#define SERIAL_PROTOCOLLN(x) {MYSERIAL.print(x);MYSERIAL.write('\n');} -#define SERIAL_PROTOCOLLNPGM(x) {serialprintPGM(PSTR(x));MYSERIAL.write('\n');} +#define SERIAL_PROTOCOL(x) (MYSERIAL.print(x)) +#define SERIAL_PROTOCOL_F(x,y) (MYSERIAL.print(x,y)) +#define SERIAL_PROTOCOLPGM(x) (serialprintPGM(PSTR(x))) +#define SERIAL_PROTOCOLLN(x) (MYSERIAL.print(x),MYSERIAL.write('\n')) +#define SERIAL_PROTOCOLLNPGM(x) (serialprintPGM(PSTR(x)),MYSERIAL.write('\n')) const char errormagic[] PROGMEM ="Error:"; const char echomagic[] PROGMEM ="echo:"; -#define SERIAL_ERROR_START serialprintPGM(errormagic); +#define SERIAL_ERROR_START (serialprintPGM(errormagic)) #define SERIAL_ERROR(x) SERIAL_PROTOCOL(x) #define SERIAL_ERRORPGM(x) SERIAL_PROTOCOLPGM(x) #define SERIAL_ERRORLN(x) SERIAL_PROTOCOLLN(x) #define SERIAL_ERRORLNPGM(x) SERIAL_PROTOCOLLNPGM(x) -#define SERIAL_ECHO_START serialprintPGM(echomagic); +#define SERIAL_ECHO_START (serialprintPGM(echomagic)) #define SERIAL_ECHO(x) SERIAL_PROTOCOL(x) #define SERIAL_ECHOPGM(x) SERIAL_PROTOCOLPGM(x) #define SERIAL_ECHOLN(x) SERIAL_PROTOCOLLN(x) @@ -96,7 +96,11 @@ void process_commands(); void manage_inactivity(); -#if defined(X_ENABLE_PIN) && X_ENABLE_PIN > -1 +#if defined(DUAL_X_CARRIAGE) && defined(X_ENABLE_PIN) && X_ENABLE_PIN > -1 \ + && defined(X2_ENABLE_PIN) && X2_ENABLE_PIN > -1 + #define enable_x() do { WRITE(X_ENABLE_PIN, X_ENABLE_ON); WRITE(X2_ENABLE_PIN, X_ENABLE_ON); } while (0) + #define disable_x() do { WRITE(X_ENABLE_PIN,!X_ENABLE_ON); WRITE(X2_ENABLE_PIN,!X_ENABLE_ON); } while (0) +#elif defined(X_ENABLE_PIN) && X_ENABLE_PIN > -1 #define enable_x() WRITE(X_ENABLE_PIN, X_ENABLE_ON) #define disable_x() WRITE(X_ENABLE_PIN,!X_ENABLE_ON) #else @@ -105,8 +109,13 @@ void manage_inactivity(); #endif #if defined(Y_ENABLE_PIN) && Y_ENABLE_PIN > -1 - #define enable_y() WRITE(Y_ENABLE_PIN, Y_ENABLE_ON) - #define disable_y() WRITE(Y_ENABLE_PIN,!Y_ENABLE_ON) + #ifdef Y_DUAL_STEPPER_DRIVERS + #define enable_y() { WRITE(Y_ENABLE_PIN, Y_ENABLE_ON); WRITE(Y2_ENABLE_PIN, Y_ENABLE_ON); } + #define disable_y() { WRITE(Y_ENABLE_PIN,!Y_ENABLE_ON); WRITE(Y2_ENABLE_PIN, !Y_ENABLE_ON); } + #else + #define enable_y() WRITE(Y_ENABLE_PIN, Y_ENABLE_ON) + #define disable_y() WRITE(Y_ENABLE_PIN,!Y_ENABLE_ON) + #endif #else #define enable_y() ; #define disable_y() ; @@ -159,6 +168,7 @@ void ClearToSend(); void get_coordinates(); #ifdef DELTA void calculate_delta(float cartesian[3]); +extern float delta[3]; #endif void prepare_move(); void kill(); diff --git a/Marlin/stepper.cpp b/Marlin/stepper.cpp index a7991501e9..217030217a 100644 --- a/Marlin/stepper.cpp +++ b/Marlin/stepper.cpp @@ -48,8 +48,8 @@ block_t *current_block; // A pointer to the block currently being traced // Variables used by The Stepper Driver Interrupt static unsigned char out_bits; // The next stepping-bits to be output static long counter_x, // Counter variables for the bresenham line tracer - counter_y, - counter_z, + counter_y, + counter_z, counter_e; volatile static unsigned long step_events_completed; // The number of step events executed in the current block #ifdef ADVANCE @@ -224,27 +224,27 @@ void enable_endstops(bool check) // | BLOCK 1 | BLOCK 2 | d // // time -----> -// -// The trapezoid is the shape the speed curve over time. It starts at block->initial_rate, accelerates -// first block->accelerate_until step_events_completed, then keeps going at constant speed until +// +// The trapezoid is the shape the speed curve over time. It starts at block->initial_rate, accelerates +// first block->accelerate_until step_events_completed, then keeps going at constant speed until // step_events_completed reaches block->decelerate_after after which it decelerates until the trapezoid generator is reset. // The slope of acceleration is calculated with the leib ramp alghorithm. void st_wake_up() { // TCNT1 = 0; - ENABLE_STEPPER_DRIVER_INTERRUPT(); + ENABLE_STEPPER_DRIVER_INTERRUPT(); } void step_wait(){ for(int8_t i=0; i < 6; i++){ } } - + FORCE_INLINE unsigned short calc_timer(unsigned short step_rate) { unsigned short timer; if(step_rate > MAX_STEP_FREQUENCY) step_rate = MAX_STEP_FREQUENCY; - + if(step_rate > 20000) { // If steprate > 20kHz >> step 4 times step_rate = (step_rate >> 2)&0x3fff; step_loops = 4; @@ -255,11 +255,11 @@ FORCE_INLINE unsigned short calc_timer(unsigned short step_rate) { } else { step_loops = 1; - } - + } + if(step_rate < (F_CPU/500000)) step_rate = (F_CPU/500000); step_rate -= (F_CPU/500000); // Correct for minimal speed - if(step_rate >= (8*256)){ // higher step rate + if(step_rate >= (8*256)){ // higher step rate unsigned short table_address = (unsigned short)&speed_lookuptable_fast[(unsigned char)(step_rate>>8)][0]; unsigned char tmp_step_rate = (step_rate & 0x00ff); unsigned short gain = (unsigned short)pgm_read_word_near(table_address+2); @@ -276,7 +276,7 @@ FORCE_INLINE unsigned short calc_timer(unsigned short step_rate) { return timer; } -// Initializes the trapezoid generator from the current block. Called whenever a new +// Initializes the trapezoid generator from the current block. Called whenever a new // block begins. FORCE_INLINE void trapezoid_generator_reset() { #ifdef ADVANCE @@ -284,7 +284,7 @@ FORCE_INLINE void trapezoid_generator_reset() { final_advance = current_block->final_advance; // Do E steps + advance steps e_steps[current_block->active_extruder] += ((advance >>8) - old_advance); - old_advance = advance >>8; + old_advance = advance >>8; #endif deceleration_time = 0; // step_rate to timer interval @@ -294,7 +294,7 @@ FORCE_INLINE void trapezoid_generator_reset() { acc_step_rate = current_block->initial_rate; acceleration_time = calc_timer(acc_step_rate); OCR1A = acceleration_time; - + // SERIAL_ECHO_START; // SERIAL_ECHOPGM("advance :"); // SERIAL_ECHO(current_block->advance/256.0); @@ -304,13 +304,13 @@ FORCE_INLINE void trapezoid_generator_reset() { // SERIAL_ECHO(current_block->initial_advance/256.0); // SERIAL_ECHOPGM("final advance :"); // SERIAL_ECHOLN(current_block->final_advance/256.0); - + } -// "The Stepper Driver Interrupt" - This timer interrupt is the workhorse. -// It pops blocks from the block_buffer and executes them by pulsing the stepper pins appropriately. +// "The Stepper Driver Interrupt" - This timer interrupt is the workhorse. +// It pops blocks from the block_buffer and executes them by pulsing the stepper pins appropriately. ISR(TIMER1_COMPA_vect) -{ +{ // If there is no current block, attempt to pop one from the buffer if (current_block == NULL) { // Anything in the buffer? @@ -322,24 +322,24 @@ ISR(TIMER1_COMPA_vect) counter_y = counter_x; counter_z = counter_x; counter_e = counter_x; - step_events_completed = 0; - - #ifdef Z_LATE_ENABLE + step_events_completed = 0; + + #ifdef Z_LATE_ENABLE if(current_block->steps_z > 0) { enable_z(); OCR1A = 2000; //1ms wait return; } #endif - + // #ifdef ADVANCE // e_steps[current_block->active_extruder] = 0; // #endif - } + } else { OCR1A=2000; // 1kHz. - } - } + } + } if (current_block != NULL) { // Set directions TO DO This should be done once during init of trapezoid. Endstops -> interrupt @@ -348,22 +348,58 @@ ISR(TIMER1_COMPA_vect) // Set the direction bits (X_AXIS=A_AXIS and Y_AXIS=B_AXIS for COREXY) if((out_bits & (1<active_extruder != 0) + WRITE(X2_DIR_PIN, INVERT_X_DIR); + else + WRITE(X_DIR_PIN, INVERT_X_DIR); + } + #else + WRITE(X_DIR_PIN, INVERT_X_DIR); + #endif count_direction[X_AXIS]=-1; } else{ - WRITE(X_DIR_PIN, !INVERT_X_DIR); + #ifdef DUAL_X_CARRIAGE + if (extruder_duplication_enabled){ + WRITE(X_DIR_PIN, !INVERT_X_DIR); + WRITE(X2_DIR_PIN, !INVERT_X_DIR); + } + else{ + if (current_block->active_extruder != 0) + WRITE(X2_DIR_PIN, !INVERT_X_DIR); + else + WRITE(X_DIR_PIN, !INVERT_X_DIR); + } + #else + WRITE(X_DIR_PIN, !INVERT_X_DIR); + #endif count_direction[X_AXIS]=1; } if((out_bits & (1< -1 - bool x_min_endstop=(READ(X_MIN_PIN) != X_ENDSTOPS_INVERTING); - if(x_min_endstop && old_x_min_endstop && (current_block->steps_x > 0)) { - endstops_trigsteps[X_AXIS] = count_position[X_AXIS]; - endstop_x_hit=true; - step_events_completed = current_block->step_event_count; - } - old_x_min_endstop = x_min_endstop; - #endif + #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 > -1 + bool x_min_endstop=(READ(X_MIN_PIN) != X_MIN_ENDSTOP_INVERTING); + if(x_min_endstop && old_x_min_endstop && (current_block->steps_x > 0)) { + endstops_trigsteps[X_AXIS] = count_position[X_AXIS]; + endstop_x_hit=true; + step_events_completed = current_block->step_event_count; + } + old_x_min_endstop = x_min_endstop; + #endif + } } } else { // +direction - CHECK_ENDSTOPS + CHECK_ENDSTOPS { - #if defined(X_MAX_PIN) && X_MAX_PIN > -1 - bool x_max_endstop=(READ(X_MAX_PIN) != X_ENDSTOPS_INVERTING); - if(x_max_endstop && old_x_max_endstop && (current_block->steps_x > 0)){ - endstops_trigsteps[X_AXIS] = count_position[X_AXIS]; - endstop_x_hit=true; - step_events_completed = current_block->step_event_count; - } - old_x_max_endstop = x_max_endstop; - #endif + #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_MAX_PIN) && X_MAX_PIN > -1 + bool x_max_endstop=(READ(X_MAX_PIN) != X_MAX_ENDSTOP_INVERTING); + if(x_max_endstop && old_x_max_endstop && (current_block->steps_x > 0)){ + endstops_trigsteps[X_AXIS] = count_position[X_AXIS]; + endstop_x_hit=true; + step_events_completed = current_block->step_event_count; + } + old_x_max_endstop = x_max_endstop; + #endif + } } } @@ -406,7 +456,7 @@ ISR(TIMER1_COMPA_vect) CHECK_ENDSTOPS { #if defined(Y_MIN_PIN) && Y_MIN_PIN > -1 - bool y_min_endstop=(READ(Y_MIN_PIN) != Y_ENDSTOPS_INVERTING); + bool y_min_endstop=(READ(Y_MIN_PIN) != Y_MIN_ENDSTOP_INVERTING); if(y_min_endstop && old_y_min_endstop && (current_block->steps_y > 0)) { endstops_trigsteps[Y_AXIS] = count_position[Y_AXIS]; endstop_y_hit=true; @@ -420,7 +470,7 @@ ISR(TIMER1_COMPA_vect) CHECK_ENDSTOPS { #if defined(Y_MAX_PIN) && Y_MAX_PIN > -1 - bool y_max_endstop=(READ(Y_MAX_PIN) != Y_ENDSTOPS_INVERTING); + bool y_max_endstop=(READ(Y_MAX_PIN) != Y_MAX_ENDSTOP_INVERTING); if(y_max_endstop && old_y_max_endstop && (current_block->steps_y > 0)){ endstops_trigsteps[Y_AXIS] = count_position[Y_AXIS]; endstop_y_hit=true; @@ -434,15 +484,15 @@ ISR(TIMER1_COMPA_vect) if ((out_bits & (1< -1 - bool z_min_endstop=(READ(Z_MIN_PIN) != Z_ENDSTOPS_INVERTING); + bool z_min_endstop=(READ(Z_MIN_PIN) != Z_MIN_ENDSTOP_INVERTING); if(z_min_endstop && old_z_min_endstop && (current_block->steps_z > 0)) { endstops_trigsteps[Z_AXIS] = count_position[Z_AXIS]; endstop_z_hit=true; @@ -455,7 +505,7 @@ ISR(TIMER1_COMPA_vect) else { // +direction WRITE(Z_DIR_PIN,!INVERT_Z_DIR); - #ifdef Z_DUAL_STEPPER_DRIVERS + #ifdef Z_DUAL_STEPPER_DRIVERS WRITE(Z2_DIR_PIN,!INVERT_Z_DIR); #endif @@ -463,7 +513,7 @@ ISR(TIMER1_COMPA_vect) CHECK_ENDSTOPS { #if defined(Z_MAX_PIN) && Z_MAX_PIN > -1 - bool z_max_endstop=(READ(Z_MAX_PIN) != Z_ENDSTOPS_INVERTING); + bool z_max_endstop=(READ(Z_MAX_PIN) != Z_MAX_ENDSTOP_INVERTING); if(z_max_endstop && old_z_max_endstop && (current_block->steps_z > 0)) { endstops_trigsteps[Z_AXIS] = count_position[Z_AXIS]; endstop_z_hit=true; @@ -484,10 +534,10 @@ ISR(TIMER1_COMPA_vect) count_direction[E_AXIS]=1; } #endif //!ADVANCE - - - for(int8_t i=0; i < step_loops; i++) { // Take multiple steps per interrupt (For high speed moves) + + + for(int8_t i=0; i < step_loops; i++) { // Take multiple steps per interrupt (For high speed moves) #ifndef AT90USB MSerial.checkRx(); // Check for serial chars. #endif @@ -502,38 +552,73 @@ ISR(TIMER1_COMPA_vect) else { e_steps[current_block->active_extruder]++; } - } + } #endif //ADVANCE counter_x += current_block->steps_x; if (counter_x > 0) { + #ifdef DUAL_X_CARRIAGE + if (extruder_duplication_enabled){ + WRITE(X_STEP_PIN, !INVERT_X_STEP_PIN); + WRITE(X2_STEP_PIN, !INVERT_X_STEP_PIN); + } + else { + if (current_block->active_extruder != 0) + WRITE(X2_STEP_PIN, !INVERT_X_STEP_PIN); + else + WRITE(X_STEP_PIN, !INVERT_X_STEP_PIN); + } + #else WRITE(X_STEP_PIN, !INVERT_X_STEP_PIN); + #endif counter_x -= current_block->step_event_count; count_position[X_AXIS]+=count_direction[X_AXIS]; + #ifdef DUAL_X_CARRIAGE + if (extruder_duplication_enabled){ + WRITE(X_STEP_PIN, INVERT_X_STEP_PIN); + WRITE(X2_STEP_PIN, INVERT_X_STEP_PIN); + } + else { + if (current_block->active_extruder != 0) + WRITE(X2_STEP_PIN, INVERT_X_STEP_PIN); + else + WRITE(X_STEP_PIN, INVERT_X_STEP_PIN); + } + #else WRITE(X_STEP_PIN, INVERT_X_STEP_PIN); + #endif } - + counter_y += current_block->steps_y; if (counter_y > 0) { WRITE(Y_STEP_PIN, !INVERT_Y_STEP_PIN); - counter_y -= current_block->step_event_count; - count_position[Y_AXIS]+=count_direction[Y_AXIS]; + + #ifdef Y_DUAL_STEPPER_DRIVERS + WRITE(Y2_STEP_PIN, !INVERT_Y_STEP_PIN); + #endif + + counter_y -= current_block->step_event_count; + count_position[Y_AXIS]+=count_direction[Y_AXIS]; WRITE(Y_STEP_PIN, INVERT_Y_STEP_PIN); + + #ifdef Y_DUAL_STEPPER_DRIVERS + WRITE(Y2_STEP_PIN, INVERT_Y_STEP_PIN); + #endif } - + counter_z += current_block->steps_z; if (counter_z > 0) { WRITE(Z_STEP_PIN, !INVERT_Z_STEP_PIN); - #ifdef Z_DUAL_STEPPER_DRIVERS + #ifdef Z_DUAL_STEPPER_DRIVERS WRITE(Z2_STEP_PIN, !INVERT_Z_STEP_PIN); #endif - + counter_z -= current_block->step_event_count; count_position[Z_AXIS]+=count_direction[Z_AXIS]; WRITE(Z_STEP_PIN, INVERT_Z_STEP_PIN); - #ifdef Z_DUAL_STEPPER_DRIVERS + #ifdef Z_DUAL_STEPPER_DRIVERS WRITE(Z2_STEP_PIN, INVERT_Z_STEP_PIN); #endif } @@ -547,17 +632,17 @@ ISR(TIMER1_COMPA_vect) WRITE_E_STEP(INVERT_E_STEP_PIN); } #endif //!ADVANCE - step_events_completed += 1; + step_events_completed += 1; if(step_events_completed >= current_block->step_event_count) break; } // Calculare new timer value unsigned short timer; unsigned short step_rate; if (step_events_completed <= (unsigned long int)current_block->accelerate_until) { - + MultiU24X24toH16(acc_step_rate, acceleration_time, current_block->acceleration_rate); acc_step_rate += current_block->initial_rate; - + // upper limit if(acc_step_rate > current_block->nominal_rate) acc_step_rate = current_block->nominal_rate; @@ -573,13 +658,13 @@ ISR(TIMER1_COMPA_vect) //if(advance > current_block->advance) advance = current_block->advance; // Do E steps + advance steps e_steps[current_block->active_extruder] += ((advance >>8) - old_advance); - old_advance = advance >>8; - + old_advance = advance >>8; + #endif - } - else if (step_events_completed > (unsigned long int)current_block->decelerate_after) { + } + else if (step_events_completed > (unsigned long int)current_block->decelerate_after) { MultiU24X24toH16(step_rate, deceleration_time, current_block->acceleration_rate); - + if(step_rate > acc_step_rate) { // Check step_rate stays positive step_rate = current_block->final_rate; } @@ -602,7 +687,7 @@ ISR(TIMER1_COMPA_vect) if(advance < final_advance) advance = final_advance; // Do E steps + advance steps e_steps[current_block->active_extruder] += ((advance >>8) - old_advance); - old_advance = advance >>8; + old_advance = advance >>8; #endif //ADVANCE } else { @@ -611,12 +696,12 @@ ISR(TIMER1_COMPA_vect) step_loops = step_loops_nominal; } - // If current block is finished, reset pointer + // If current block is finished, reset pointer if (step_events_completed >= current_block->step_event_count) { current_block = NULL; plan_discard_current_block(); - } - } + } + } } #ifdef ADVANCE @@ -635,7 +720,7 @@ ISR(TIMER1_COMPA_vect) WRITE(E0_DIR_PIN, INVERT_E0_DIR); e_steps[0]++; WRITE(E0_STEP_PIN, !INVERT_E_STEP_PIN); - } + } else if (e_steps[0] > 0) { WRITE(E0_DIR_PIN, !INVERT_E0_DIR); e_steps[0]--; @@ -649,7 +734,7 @@ ISR(TIMER1_COMPA_vect) WRITE(E1_DIR_PIN, INVERT_E1_DIR); e_steps[1]++; WRITE(E1_STEP_PIN, !INVERT_E_STEP_PIN); - } + } else if (e_steps[1] > 0) { WRITE(E1_DIR_PIN, !INVERT_E1_DIR); e_steps[1]--; @@ -664,7 +749,7 @@ ISR(TIMER1_COMPA_vect) WRITE(E2_DIR_PIN, INVERT_E2_DIR); e_steps[2]++; WRITE(E2_STEP_PIN, !INVERT_E_STEP_PIN); - } + } else if (e_steps[2] > 0) { WRITE(E2_DIR_PIN, !INVERT_E2_DIR); e_steps[2]--; @@ -680,22 +765,29 @@ void st_init() { digipot_init(); //Initialize Digipot Motor Current microstep_init(); //Initialize Microstepping Pins - + //Initialize Dir Pins #if defined(X_DIR_PIN) && X_DIR_PIN > -1 SET_OUTPUT(X_DIR_PIN); #endif - #if defined(Y_DIR_PIN) && Y_DIR_PIN > -1 - SET_OUTPUT(Y_DIR_PIN); + #if defined(X2_DIR_PIN) && X2_DIR_PIN > -1 + SET_OUTPUT(X2_DIR_PIN); #endif - #if defined(Z_DIR_PIN) && Z_DIR_PIN > -1 + #if defined(Y_DIR_PIN) && Y_DIR_PIN > -1 + SET_OUTPUT(Y_DIR_PIN); + + #if defined(Y_DUAL_STEPPER_DRIVERS) && defined(Y2_DIR_PIN) && (Y2_DIR_PIN > -1) + SET_OUTPUT(Y2_DIR_PIN); + #endif + #endif + #if defined(Z_DIR_PIN) && Z_DIR_PIN > -1 SET_OUTPUT(Z_DIR_PIN); #if defined(Z_DUAL_STEPPER_DRIVERS) && defined(Z2_DIR_PIN) && (Z2_DIR_PIN > -1) SET_OUTPUT(Z2_DIR_PIN); #endif #endif - #if defined(E0_DIR_PIN) && E0_DIR_PIN > -1 + #if defined(E0_DIR_PIN) && E0_DIR_PIN > -1 SET_OUTPUT(E0_DIR_PIN); #endif #if defined(E1_DIR_PIN) && (E1_DIR_PIN > -1) @@ -711,14 +803,23 @@ void st_init() SET_OUTPUT(X_ENABLE_PIN); if(!X_ENABLE_ON) WRITE(X_ENABLE_PIN,HIGH); #endif + #if defined(X2_ENABLE_PIN) && X2_ENABLE_PIN > -1 + SET_OUTPUT(X2_ENABLE_PIN); + if(!X_ENABLE_ON) WRITE(X2_ENABLE_PIN,HIGH); + #endif #if defined(Y_ENABLE_PIN) && Y_ENABLE_PIN > -1 SET_OUTPUT(Y_ENABLE_PIN); if(!Y_ENABLE_ON) WRITE(Y_ENABLE_PIN,HIGH); + + #if defined(Y_DUAL_STEPPER_DRIVERS) && defined(Y2_ENABLE_PIN) && (Y2_ENABLE_PIN > -1) + SET_OUTPUT(Y2_ENABLE_PIN); + if(!Y_ENABLE_ON) WRITE(Y2_ENABLE_PIN,HIGH); + #endif #endif #if defined(Z_ENABLE_PIN) && Z_ENABLE_PIN > -1 SET_OUTPUT(Z_ENABLE_PIN); if(!Z_ENABLE_ON) WRITE(Z_ENABLE_PIN,HIGH); - + #if defined(Z_DUAL_STEPPER_DRIVERS) && defined(Z2_ENABLE_PIN) && (Z2_ENABLE_PIN > -1) SET_OUTPUT(Z2_ENABLE_PIN); if(!Z_ENABLE_ON) WRITE(Z2_ENABLE_PIN,HIGH); @@ -738,62 +839,71 @@ void st_init() #endif //endstops and pullups - + #if defined(X_MIN_PIN) && X_MIN_PIN > -1 - SET_INPUT(X_MIN_PIN); + SET_INPUT(X_MIN_PIN); #ifdef ENDSTOPPULLUP_XMIN WRITE(X_MIN_PIN,HIGH); #endif #endif - + #if defined(Y_MIN_PIN) && Y_MIN_PIN > -1 - SET_INPUT(Y_MIN_PIN); + SET_INPUT(Y_MIN_PIN); #ifdef ENDSTOPPULLUP_YMIN WRITE(Y_MIN_PIN,HIGH); #endif #endif - + #if defined(Z_MIN_PIN) && Z_MIN_PIN > -1 - SET_INPUT(Z_MIN_PIN); + SET_INPUT(Z_MIN_PIN); #ifdef ENDSTOPPULLUP_ZMIN WRITE(Z_MIN_PIN,HIGH); #endif #endif - + #if defined(X_MAX_PIN) && X_MAX_PIN > -1 - SET_INPUT(X_MAX_PIN); + SET_INPUT(X_MAX_PIN); #ifdef ENDSTOPPULLUP_XMAX WRITE(X_MAX_PIN,HIGH); #endif #endif - + #if defined(Y_MAX_PIN) && Y_MAX_PIN > -1 - SET_INPUT(Y_MAX_PIN); + SET_INPUT(Y_MAX_PIN); #ifdef ENDSTOPPULLUP_YMAX WRITE(Y_MAX_PIN,HIGH); #endif #endif - + #if defined(Z_MAX_PIN) && Z_MAX_PIN > -1 - SET_INPUT(Z_MAX_PIN); + SET_INPUT(Z_MAX_PIN); #ifdef ENDSTOPPULLUP_ZMAX WRITE(Z_MAX_PIN,HIGH); #endif #endif - + //Initialize Step Pins - #if defined(X_STEP_PIN) && (X_STEP_PIN > -1) + #if defined(X_STEP_PIN) && (X_STEP_PIN > -1) SET_OUTPUT(X_STEP_PIN); WRITE(X_STEP_PIN,INVERT_X_STEP_PIN); disable_x(); - #endif - #if defined(Y_STEP_PIN) && (Y_STEP_PIN > -1) + #endif + #if defined(X2_STEP_PIN) && (X2_STEP_PIN > -1) + SET_OUTPUT(X2_STEP_PIN); + WRITE(X2_STEP_PIN,INVERT_X_STEP_PIN); + disable_x(); + #endif + #if defined(Y_STEP_PIN) && (Y_STEP_PIN > -1) SET_OUTPUT(Y_STEP_PIN); WRITE(Y_STEP_PIN,INVERT_Y_STEP_PIN); + #if defined(Y_DUAL_STEPPER_DRIVERS) && defined(Y2_STEP_PIN) && (Y2_STEP_PIN > -1) + SET_OUTPUT(Y2_STEP_PIN); + WRITE(Y2_STEP_PIN,INVERT_Y_STEP_PIN); + #endif disable_y(); - #endif - #if defined(Z_STEP_PIN) && (Z_STEP_PIN > -1) + #endif + #if defined(Z_STEP_PIN) && (Z_STEP_PIN > -1) SET_OUTPUT(Z_STEP_PIN); WRITE(Z_STEP_PIN,INVERT_Z_STEP_PIN); #if defined(Z_DUAL_STEPPER_DRIVERS) && defined(Z2_STEP_PIN) && (Z2_STEP_PIN > -1) @@ -801,33 +911,33 @@ void st_init() WRITE(Z2_STEP_PIN,INVERT_Z_STEP_PIN); #endif disable_z(); - #endif - #if defined(E0_STEP_PIN) && (E0_STEP_PIN > -1) + #endif + #if defined(E0_STEP_PIN) && (E0_STEP_PIN > -1) SET_OUTPUT(E0_STEP_PIN); WRITE(E0_STEP_PIN,INVERT_E_STEP_PIN); disable_e0(); - #endif - #if defined(E1_STEP_PIN) && (E1_STEP_PIN > -1) + #endif + #if defined(E1_STEP_PIN) && (E1_STEP_PIN > -1) SET_OUTPUT(E1_STEP_PIN); WRITE(E1_STEP_PIN,INVERT_E_STEP_PIN); disable_e1(); - #endif - #if defined(E2_STEP_PIN) && (E2_STEP_PIN > -1) + #endif + #if defined(E2_STEP_PIN) && (E2_STEP_PIN > -1) SET_OUTPUT(E2_STEP_PIN); WRITE(E2_STEP_PIN,INVERT_E_STEP_PIN); disable_e2(); - #endif + #endif // waveform generation = 0100 = CTC TCCR1B &= ~(1< -1 const uint8_t digipot_motor_current[] = DIGIPOT_MOTOR_CURRENT; - - SPI.begin(); - pinMode(DIGIPOTSS_PIN, OUTPUT); - for(int i=0;i<=4;i++) + + SPI.begin(); + pinMode(DIGIPOTSS_PIN, OUTPUT); + for(int i=0;i<=4;i++) //digitalPotWrite(digipot_ch[i], digipot_motor_current[i]); digipot_current(i,digipot_motor_current[i]); #endif From f4a59e4ce5987fafb1a4e849bc7fbcbb8d3bc920 Mon Sep 17 00:00:00 2001 From: Richard Miles Date: Tue, 17 Sep 2013 19:05:49 +0100 Subject: [PATCH 05/15] Revert "Added Y_DUAL_STEPPER_DRIVERS" This reverts commit 7ee275b620fa055bb2b7516cf302ac3e531438ac. --- Marlin/Configuration_adv.h | 73 +------- Marlin/Marlin.h | 30 +-- Marlin/stepper.cpp | 366 +++++++++++++------------------------ 3 files changed, 144 insertions(+), 325 deletions(-) diff --git a/Marlin/Configuration_adv.h b/Marlin/Configuration_adv.h index 648a9beafc..5f1c77a056 100644 --- a/Marlin/Configuration_adv.h +++ b/Marlin/Configuration_adv.h @@ -18,6 +18,12 @@ //#define WATCH_TEMP_PERIOD 40000 //40 seconds //#define WATCH_TEMP_INCREASE 10 //Heat up at least 10 degree in 20 seconds +// Wait for Cooldown +// This defines if the M109 call should not block if it is cooling down. +// example: From a current temp of 220, you set M109 S200. +// if CooldownNoWait is defined M109 will not wait for the cooldown to finish +#define CooldownNoWait true + #ifdef PIDTEMP // this adds an experimental additional term to the heatingpower, proportional to the extrusion speed. // if Kc is choosen well, the additional required power due to increased melting should be compensated. @@ -146,68 +152,6 @@ #define EXTRUDERS 1 #endif -// Same again but for Y Axis. -#define Y_DUAL_STEPPER_DRIVERS - -// 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 - -#ifdef Z_DUAL_STEPPER_DRIVERS && 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 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 - -// As the x-carriages are independent we can now account for any relative Z offset -#define EXTRUDER1_Z_OFFSET 0.0 // z offset relative to extruder 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 @@ -230,11 +174,6 @@ #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 - // minimum time in microseconds that a movement needs to take if the buffer is emptied. #define DEFAULT_MINSEGMENTTIME 20000 diff --git a/Marlin/Marlin.h b/Marlin/Marlin.h index 3066017966..c9759eb219 100644 --- a/Marlin/Marlin.h +++ b/Marlin/Marlin.h @@ -51,22 +51,22 @@ #define MYSERIAL MSerial #endif -#define SERIAL_PROTOCOL(x) (MYSERIAL.print(x)) -#define SERIAL_PROTOCOL_F(x,y) (MYSERIAL.print(x,y)) -#define SERIAL_PROTOCOLPGM(x) (serialprintPGM(PSTR(x))) -#define SERIAL_PROTOCOLLN(x) (MYSERIAL.print(x),MYSERIAL.write('\n')) -#define SERIAL_PROTOCOLLNPGM(x) (serialprintPGM(PSTR(x)),MYSERIAL.write('\n')) +#define SERIAL_PROTOCOL(x) MYSERIAL.print(x); +#define SERIAL_PROTOCOL_F(x,y) MYSERIAL.print(x,y); +#define SERIAL_PROTOCOLPGM(x) serialprintPGM(PSTR(x)); +#define SERIAL_PROTOCOLLN(x) {MYSERIAL.print(x);MYSERIAL.write('\n');} +#define SERIAL_PROTOCOLLNPGM(x) {serialprintPGM(PSTR(x));MYSERIAL.write('\n');} const char errormagic[] PROGMEM ="Error:"; const char echomagic[] PROGMEM ="echo:"; -#define SERIAL_ERROR_START (serialprintPGM(errormagic)) +#define SERIAL_ERROR_START serialprintPGM(errormagic); #define SERIAL_ERROR(x) SERIAL_PROTOCOL(x) #define SERIAL_ERRORPGM(x) SERIAL_PROTOCOLPGM(x) #define SERIAL_ERRORLN(x) SERIAL_PROTOCOLLN(x) #define SERIAL_ERRORLNPGM(x) SERIAL_PROTOCOLLNPGM(x) -#define SERIAL_ECHO_START (serialprintPGM(echomagic)) +#define SERIAL_ECHO_START serialprintPGM(echomagic); #define SERIAL_ECHO(x) SERIAL_PROTOCOL(x) #define SERIAL_ECHOPGM(x) SERIAL_PROTOCOLPGM(x) #define SERIAL_ECHOLN(x) SERIAL_PROTOCOLLN(x) @@ -96,11 +96,7 @@ void process_commands(); void manage_inactivity(); -#if defined(DUAL_X_CARRIAGE) && defined(X_ENABLE_PIN) && X_ENABLE_PIN > -1 \ - && defined(X2_ENABLE_PIN) && X2_ENABLE_PIN > -1 - #define enable_x() do { WRITE(X_ENABLE_PIN, X_ENABLE_ON); WRITE(X2_ENABLE_PIN, X_ENABLE_ON); } while (0) - #define disable_x() do { WRITE(X_ENABLE_PIN,!X_ENABLE_ON); WRITE(X2_ENABLE_PIN,!X_ENABLE_ON); } while (0) -#elif defined(X_ENABLE_PIN) && X_ENABLE_PIN > -1 +#if defined(X_ENABLE_PIN) && X_ENABLE_PIN > -1 #define enable_x() WRITE(X_ENABLE_PIN, X_ENABLE_ON) #define disable_x() WRITE(X_ENABLE_PIN,!X_ENABLE_ON) #else @@ -109,13 +105,8 @@ void manage_inactivity(); #endif #if defined(Y_ENABLE_PIN) && Y_ENABLE_PIN > -1 - #ifdef Y_DUAL_STEPPER_DRIVERS - #define enable_y() { WRITE(Y_ENABLE_PIN, Y_ENABLE_ON); WRITE(Y2_ENABLE_PIN, Y_ENABLE_ON); } - #define disable_y() { WRITE(Y_ENABLE_PIN,!Y_ENABLE_ON); WRITE(Y2_ENABLE_PIN, !Y_ENABLE_ON); } - #else - #define enable_y() WRITE(Y_ENABLE_PIN, Y_ENABLE_ON) - #define disable_y() WRITE(Y_ENABLE_PIN,!Y_ENABLE_ON) - #endif + #define enable_y() WRITE(Y_ENABLE_PIN, Y_ENABLE_ON) + #define disable_y() WRITE(Y_ENABLE_PIN,!Y_ENABLE_ON) #else #define enable_y() ; #define disable_y() ; @@ -168,7 +159,6 @@ void ClearToSend(); void get_coordinates(); #ifdef DELTA void calculate_delta(float cartesian[3]); -extern float delta[3]; #endif void prepare_move(); void kill(); diff --git a/Marlin/stepper.cpp b/Marlin/stepper.cpp index 217030217a..a7991501e9 100644 --- a/Marlin/stepper.cpp +++ b/Marlin/stepper.cpp @@ -48,8 +48,8 @@ block_t *current_block; // A pointer to the block currently being traced // Variables used by The Stepper Driver Interrupt static unsigned char out_bits; // The next stepping-bits to be output static long counter_x, // Counter variables for the bresenham line tracer - counter_y, - counter_z, + counter_y, + counter_z, counter_e; volatile static unsigned long step_events_completed; // The number of step events executed in the current block #ifdef ADVANCE @@ -224,27 +224,27 @@ void enable_endstops(bool check) // | BLOCK 1 | BLOCK 2 | d // // time -----> -// -// The trapezoid is the shape the speed curve over time. It starts at block->initial_rate, accelerates -// first block->accelerate_until step_events_completed, then keeps going at constant speed until +// +// The trapezoid is the shape the speed curve over time. It starts at block->initial_rate, accelerates +// first block->accelerate_until step_events_completed, then keeps going at constant speed until // step_events_completed reaches block->decelerate_after after which it decelerates until the trapezoid generator is reset. // The slope of acceleration is calculated with the leib ramp alghorithm. void st_wake_up() { // TCNT1 = 0; - ENABLE_STEPPER_DRIVER_INTERRUPT(); + ENABLE_STEPPER_DRIVER_INTERRUPT(); } void step_wait(){ for(int8_t i=0; i < 6; i++){ } } - + FORCE_INLINE unsigned short calc_timer(unsigned short step_rate) { unsigned short timer; if(step_rate > MAX_STEP_FREQUENCY) step_rate = MAX_STEP_FREQUENCY; - + if(step_rate > 20000) { // If steprate > 20kHz >> step 4 times step_rate = (step_rate >> 2)&0x3fff; step_loops = 4; @@ -255,11 +255,11 @@ FORCE_INLINE unsigned short calc_timer(unsigned short step_rate) { } else { step_loops = 1; - } - + } + if(step_rate < (F_CPU/500000)) step_rate = (F_CPU/500000); step_rate -= (F_CPU/500000); // Correct for minimal speed - if(step_rate >= (8*256)){ // higher step rate + if(step_rate >= (8*256)){ // higher step rate unsigned short table_address = (unsigned short)&speed_lookuptable_fast[(unsigned char)(step_rate>>8)][0]; unsigned char tmp_step_rate = (step_rate & 0x00ff); unsigned short gain = (unsigned short)pgm_read_word_near(table_address+2); @@ -276,7 +276,7 @@ FORCE_INLINE unsigned short calc_timer(unsigned short step_rate) { return timer; } -// Initializes the trapezoid generator from the current block. Called whenever a new +// Initializes the trapezoid generator from the current block. Called whenever a new // block begins. FORCE_INLINE void trapezoid_generator_reset() { #ifdef ADVANCE @@ -284,7 +284,7 @@ FORCE_INLINE void trapezoid_generator_reset() { final_advance = current_block->final_advance; // Do E steps + advance steps e_steps[current_block->active_extruder] += ((advance >>8) - old_advance); - old_advance = advance >>8; + old_advance = advance >>8; #endif deceleration_time = 0; // step_rate to timer interval @@ -294,7 +294,7 @@ FORCE_INLINE void trapezoid_generator_reset() { acc_step_rate = current_block->initial_rate; acceleration_time = calc_timer(acc_step_rate); OCR1A = acceleration_time; - + // SERIAL_ECHO_START; // SERIAL_ECHOPGM("advance :"); // SERIAL_ECHO(current_block->advance/256.0); @@ -304,13 +304,13 @@ FORCE_INLINE void trapezoid_generator_reset() { // SERIAL_ECHO(current_block->initial_advance/256.0); // SERIAL_ECHOPGM("final advance :"); // SERIAL_ECHOLN(current_block->final_advance/256.0); - + } -// "The Stepper Driver Interrupt" - This timer interrupt is the workhorse. -// It pops blocks from the block_buffer and executes them by pulsing the stepper pins appropriately. +// "The Stepper Driver Interrupt" - This timer interrupt is the workhorse. +// It pops blocks from the block_buffer and executes them by pulsing the stepper pins appropriately. ISR(TIMER1_COMPA_vect) -{ +{ // If there is no current block, attempt to pop one from the buffer if (current_block == NULL) { // Anything in the buffer? @@ -322,24 +322,24 @@ ISR(TIMER1_COMPA_vect) counter_y = counter_x; counter_z = counter_x; counter_e = counter_x; - step_events_completed = 0; - - #ifdef Z_LATE_ENABLE + step_events_completed = 0; + + #ifdef Z_LATE_ENABLE if(current_block->steps_z > 0) { enable_z(); OCR1A = 2000; //1ms wait return; } #endif - + // #ifdef ADVANCE // e_steps[current_block->active_extruder] = 0; // #endif - } + } else { OCR1A=2000; // 1kHz. - } - } + } + } if (current_block != NULL) { // Set directions TO DO This should be done once during init of trapezoid. Endstops -> interrupt @@ -348,58 +348,22 @@ ISR(TIMER1_COMPA_vect) // Set the direction bits (X_AXIS=A_AXIS and Y_AXIS=B_AXIS for COREXY) if((out_bits & (1<active_extruder != 0) - WRITE(X2_DIR_PIN, INVERT_X_DIR); - else - WRITE(X_DIR_PIN, INVERT_X_DIR); - } - #else - WRITE(X_DIR_PIN, INVERT_X_DIR); - #endif + WRITE(X_DIR_PIN, INVERT_X_DIR); count_direction[X_AXIS]=-1; } else{ - #ifdef DUAL_X_CARRIAGE - if (extruder_duplication_enabled){ - WRITE(X_DIR_PIN, !INVERT_X_DIR); - WRITE(X2_DIR_PIN, !INVERT_X_DIR); - } - else{ - if (current_block->active_extruder != 0) - WRITE(X2_DIR_PIN, !INVERT_X_DIR); - else - WRITE(X_DIR_PIN, !INVERT_X_DIR); - } - #else - WRITE(X_DIR_PIN, !INVERT_X_DIR); - #endif + WRITE(X_DIR_PIN, !INVERT_X_DIR); count_direction[X_AXIS]=1; } if((out_bits & (1<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 > -1 - bool x_min_endstop=(READ(X_MIN_PIN) != X_MIN_ENDSTOP_INVERTING); - if(x_min_endstop && old_x_min_endstop && (current_block->steps_x > 0)) { - endstops_trigsteps[X_AXIS] = count_position[X_AXIS]; - endstop_x_hit=true; - step_events_completed = current_block->step_event_count; - } - old_x_min_endstop = x_min_endstop; - #endif - } + #if defined(X_MIN_PIN) && X_MIN_PIN > -1 + bool x_min_endstop=(READ(X_MIN_PIN) != X_ENDSTOPS_INVERTING); + if(x_min_endstop && old_x_min_endstop && (current_block->steps_x > 0)) { + endstops_trigsteps[X_AXIS] = count_position[X_AXIS]; + endstop_x_hit=true; + step_events_completed = current_block->step_event_count; + } + old_x_min_endstop = x_min_endstop; + #endif } } else { // +direction - CHECK_ENDSTOPS + CHECK_ENDSTOPS { - #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_MAX_PIN) && X_MAX_PIN > -1 - bool x_max_endstop=(READ(X_MAX_PIN) != X_MAX_ENDSTOP_INVERTING); - if(x_max_endstop && old_x_max_endstop && (current_block->steps_x > 0)){ - endstops_trigsteps[X_AXIS] = count_position[X_AXIS]; - endstop_x_hit=true; - step_events_completed = current_block->step_event_count; - } - old_x_max_endstop = x_max_endstop; - #endif - } + #if defined(X_MAX_PIN) && X_MAX_PIN > -1 + bool x_max_endstop=(READ(X_MAX_PIN) != X_ENDSTOPS_INVERTING); + if(x_max_endstop && old_x_max_endstop && (current_block->steps_x > 0)){ + endstops_trigsteps[X_AXIS] = count_position[X_AXIS]; + endstop_x_hit=true; + step_events_completed = current_block->step_event_count; + } + old_x_max_endstop = x_max_endstop; + #endif } } @@ -456,7 +406,7 @@ ISR(TIMER1_COMPA_vect) CHECK_ENDSTOPS { #if defined(Y_MIN_PIN) && Y_MIN_PIN > -1 - bool y_min_endstop=(READ(Y_MIN_PIN) != Y_MIN_ENDSTOP_INVERTING); + bool y_min_endstop=(READ(Y_MIN_PIN) != Y_ENDSTOPS_INVERTING); if(y_min_endstop && old_y_min_endstop && (current_block->steps_y > 0)) { endstops_trigsteps[Y_AXIS] = count_position[Y_AXIS]; endstop_y_hit=true; @@ -470,7 +420,7 @@ ISR(TIMER1_COMPA_vect) CHECK_ENDSTOPS { #if defined(Y_MAX_PIN) && Y_MAX_PIN > -1 - bool y_max_endstop=(READ(Y_MAX_PIN) != Y_MAX_ENDSTOP_INVERTING); + bool y_max_endstop=(READ(Y_MAX_PIN) != Y_ENDSTOPS_INVERTING); if(y_max_endstop && old_y_max_endstop && (current_block->steps_y > 0)){ endstops_trigsteps[Y_AXIS] = count_position[Y_AXIS]; endstop_y_hit=true; @@ -484,15 +434,15 @@ ISR(TIMER1_COMPA_vect) if ((out_bits & (1< -1 - bool z_min_endstop=(READ(Z_MIN_PIN) != Z_MIN_ENDSTOP_INVERTING); + bool z_min_endstop=(READ(Z_MIN_PIN) != Z_ENDSTOPS_INVERTING); if(z_min_endstop && old_z_min_endstop && (current_block->steps_z > 0)) { endstops_trigsteps[Z_AXIS] = count_position[Z_AXIS]; endstop_z_hit=true; @@ -505,7 +455,7 @@ ISR(TIMER1_COMPA_vect) else { // +direction WRITE(Z_DIR_PIN,!INVERT_Z_DIR); - #ifdef Z_DUAL_STEPPER_DRIVERS + #ifdef Z_DUAL_STEPPER_DRIVERS WRITE(Z2_DIR_PIN,!INVERT_Z_DIR); #endif @@ -513,7 +463,7 @@ ISR(TIMER1_COMPA_vect) CHECK_ENDSTOPS { #if defined(Z_MAX_PIN) && Z_MAX_PIN > -1 - bool z_max_endstop=(READ(Z_MAX_PIN) != Z_MAX_ENDSTOP_INVERTING); + bool z_max_endstop=(READ(Z_MAX_PIN) != Z_ENDSTOPS_INVERTING); if(z_max_endstop && old_z_max_endstop && (current_block->steps_z > 0)) { endstops_trigsteps[Z_AXIS] = count_position[Z_AXIS]; endstop_z_hit=true; @@ -534,10 +484,10 @@ ISR(TIMER1_COMPA_vect) count_direction[E_AXIS]=1; } #endif //!ADVANCE + - - - for(int8_t i=0; i < step_loops; i++) { // Take multiple steps per interrupt (For high speed moves) + + for(int8_t i=0; i < step_loops; i++) { // Take multiple steps per interrupt (For high speed moves) #ifndef AT90USB MSerial.checkRx(); // Check for serial chars. #endif @@ -552,73 +502,38 @@ ISR(TIMER1_COMPA_vect) else { e_steps[current_block->active_extruder]++; } - } + } #endif //ADVANCE counter_x += current_block->steps_x; if (counter_x > 0) { - #ifdef DUAL_X_CARRIAGE - if (extruder_duplication_enabled){ - WRITE(X_STEP_PIN, !INVERT_X_STEP_PIN); - WRITE(X2_STEP_PIN, !INVERT_X_STEP_PIN); - } - else { - if (current_block->active_extruder != 0) - WRITE(X2_STEP_PIN, !INVERT_X_STEP_PIN); - else - WRITE(X_STEP_PIN, !INVERT_X_STEP_PIN); - } - #else WRITE(X_STEP_PIN, !INVERT_X_STEP_PIN); - #endif counter_x -= current_block->step_event_count; count_position[X_AXIS]+=count_direction[X_AXIS]; - #ifdef DUAL_X_CARRIAGE - if (extruder_duplication_enabled){ - WRITE(X_STEP_PIN, INVERT_X_STEP_PIN); - WRITE(X2_STEP_PIN, INVERT_X_STEP_PIN); - } - else { - if (current_block->active_extruder != 0) - WRITE(X2_STEP_PIN, INVERT_X_STEP_PIN); - else - WRITE(X_STEP_PIN, INVERT_X_STEP_PIN); - } - #else WRITE(X_STEP_PIN, INVERT_X_STEP_PIN); - #endif } - + counter_y += current_block->steps_y; if (counter_y > 0) { WRITE(Y_STEP_PIN, !INVERT_Y_STEP_PIN); - - #ifdef Y_DUAL_STEPPER_DRIVERS - WRITE(Y2_STEP_PIN, !INVERT_Y_STEP_PIN); - #endif - - counter_y -= current_block->step_event_count; - count_position[Y_AXIS]+=count_direction[Y_AXIS]; + counter_y -= current_block->step_event_count; + count_position[Y_AXIS]+=count_direction[Y_AXIS]; WRITE(Y_STEP_PIN, INVERT_Y_STEP_PIN); - - #ifdef Y_DUAL_STEPPER_DRIVERS - WRITE(Y2_STEP_PIN, INVERT_Y_STEP_PIN); - #endif } - + counter_z += current_block->steps_z; if (counter_z > 0) { WRITE(Z_STEP_PIN, !INVERT_Z_STEP_PIN); - #ifdef Z_DUAL_STEPPER_DRIVERS + #ifdef Z_DUAL_STEPPER_DRIVERS WRITE(Z2_STEP_PIN, !INVERT_Z_STEP_PIN); #endif - + counter_z -= current_block->step_event_count; count_position[Z_AXIS]+=count_direction[Z_AXIS]; WRITE(Z_STEP_PIN, INVERT_Z_STEP_PIN); - #ifdef Z_DUAL_STEPPER_DRIVERS + #ifdef Z_DUAL_STEPPER_DRIVERS WRITE(Z2_STEP_PIN, INVERT_Z_STEP_PIN); #endif } @@ -632,17 +547,17 @@ ISR(TIMER1_COMPA_vect) WRITE_E_STEP(INVERT_E_STEP_PIN); } #endif //!ADVANCE - step_events_completed += 1; + step_events_completed += 1; if(step_events_completed >= current_block->step_event_count) break; } // Calculare new timer value unsigned short timer; unsigned short step_rate; if (step_events_completed <= (unsigned long int)current_block->accelerate_until) { - + MultiU24X24toH16(acc_step_rate, acceleration_time, current_block->acceleration_rate); acc_step_rate += current_block->initial_rate; - + // upper limit if(acc_step_rate > current_block->nominal_rate) acc_step_rate = current_block->nominal_rate; @@ -658,13 +573,13 @@ ISR(TIMER1_COMPA_vect) //if(advance > current_block->advance) advance = current_block->advance; // Do E steps + advance steps e_steps[current_block->active_extruder] += ((advance >>8) - old_advance); - old_advance = advance >>8; - + old_advance = advance >>8; + #endif - } - else if (step_events_completed > (unsigned long int)current_block->decelerate_after) { + } + else if (step_events_completed > (unsigned long int)current_block->decelerate_after) { MultiU24X24toH16(step_rate, deceleration_time, current_block->acceleration_rate); - + if(step_rate > acc_step_rate) { // Check step_rate stays positive step_rate = current_block->final_rate; } @@ -687,7 +602,7 @@ ISR(TIMER1_COMPA_vect) if(advance < final_advance) advance = final_advance; // Do E steps + advance steps e_steps[current_block->active_extruder] += ((advance >>8) - old_advance); - old_advance = advance >>8; + old_advance = advance >>8; #endif //ADVANCE } else { @@ -696,12 +611,12 @@ ISR(TIMER1_COMPA_vect) step_loops = step_loops_nominal; } - // If current block is finished, reset pointer + // If current block is finished, reset pointer if (step_events_completed >= current_block->step_event_count) { current_block = NULL; plan_discard_current_block(); - } - } + } + } } #ifdef ADVANCE @@ -720,7 +635,7 @@ ISR(TIMER1_COMPA_vect) WRITE(E0_DIR_PIN, INVERT_E0_DIR); e_steps[0]++; WRITE(E0_STEP_PIN, !INVERT_E_STEP_PIN); - } + } else if (e_steps[0] > 0) { WRITE(E0_DIR_PIN, !INVERT_E0_DIR); e_steps[0]--; @@ -734,7 +649,7 @@ ISR(TIMER1_COMPA_vect) WRITE(E1_DIR_PIN, INVERT_E1_DIR); e_steps[1]++; WRITE(E1_STEP_PIN, !INVERT_E_STEP_PIN); - } + } else if (e_steps[1] > 0) { WRITE(E1_DIR_PIN, !INVERT_E1_DIR); e_steps[1]--; @@ -749,7 +664,7 @@ ISR(TIMER1_COMPA_vect) WRITE(E2_DIR_PIN, INVERT_E2_DIR); e_steps[2]++; WRITE(E2_STEP_PIN, !INVERT_E_STEP_PIN); - } + } else if (e_steps[2] > 0) { WRITE(E2_DIR_PIN, !INVERT_E2_DIR); e_steps[2]--; @@ -765,29 +680,22 @@ void st_init() { digipot_init(); //Initialize Digipot Motor Current microstep_init(); //Initialize Microstepping Pins - + //Initialize Dir Pins #if defined(X_DIR_PIN) && X_DIR_PIN > -1 SET_OUTPUT(X_DIR_PIN); #endif - #if defined(X2_DIR_PIN) && X2_DIR_PIN > -1 - SET_OUTPUT(X2_DIR_PIN); - #endif - #if defined(Y_DIR_PIN) && Y_DIR_PIN > -1 + #if defined(Y_DIR_PIN) && Y_DIR_PIN > -1 SET_OUTPUT(Y_DIR_PIN); - - #if defined(Y_DUAL_STEPPER_DRIVERS) && defined(Y2_DIR_PIN) && (Y2_DIR_PIN > -1) - SET_OUTPUT(Y2_DIR_PIN); - #endif #endif - #if defined(Z_DIR_PIN) && Z_DIR_PIN > -1 + #if defined(Z_DIR_PIN) && Z_DIR_PIN > -1 SET_OUTPUT(Z_DIR_PIN); #if defined(Z_DUAL_STEPPER_DRIVERS) && defined(Z2_DIR_PIN) && (Z2_DIR_PIN > -1) SET_OUTPUT(Z2_DIR_PIN); #endif #endif - #if defined(E0_DIR_PIN) && E0_DIR_PIN > -1 + #if defined(E0_DIR_PIN) && E0_DIR_PIN > -1 SET_OUTPUT(E0_DIR_PIN); #endif #if defined(E1_DIR_PIN) && (E1_DIR_PIN > -1) @@ -803,23 +711,14 @@ void st_init() SET_OUTPUT(X_ENABLE_PIN); if(!X_ENABLE_ON) WRITE(X_ENABLE_PIN,HIGH); #endif - #if defined(X2_ENABLE_PIN) && X2_ENABLE_PIN > -1 - SET_OUTPUT(X2_ENABLE_PIN); - if(!X_ENABLE_ON) WRITE(X2_ENABLE_PIN,HIGH); - #endif #if defined(Y_ENABLE_PIN) && Y_ENABLE_PIN > -1 SET_OUTPUT(Y_ENABLE_PIN); if(!Y_ENABLE_ON) WRITE(Y_ENABLE_PIN,HIGH); - - #if defined(Y_DUAL_STEPPER_DRIVERS) && defined(Y2_ENABLE_PIN) && (Y2_ENABLE_PIN > -1) - SET_OUTPUT(Y2_ENABLE_PIN); - if(!Y_ENABLE_ON) WRITE(Y2_ENABLE_PIN,HIGH); - #endif #endif #if defined(Z_ENABLE_PIN) && Z_ENABLE_PIN > -1 SET_OUTPUT(Z_ENABLE_PIN); if(!Z_ENABLE_ON) WRITE(Z_ENABLE_PIN,HIGH); - + #if defined(Z_DUAL_STEPPER_DRIVERS) && defined(Z2_ENABLE_PIN) && (Z2_ENABLE_PIN > -1) SET_OUTPUT(Z2_ENABLE_PIN); if(!Z_ENABLE_ON) WRITE(Z2_ENABLE_PIN,HIGH); @@ -839,71 +738,62 @@ void st_init() #endif //endstops and pullups - + #if defined(X_MIN_PIN) && X_MIN_PIN > -1 - SET_INPUT(X_MIN_PIN); + SET_INPUT(X_MIN_PIN); #ifdef ENDSTOPPULLUP_XMIN WRITE(X_MIN_PIN,HIGH); #endif #endif - + #if defined(Y_MIN_PIN) && Y_MIN_PIN > -1 - SET_INPUT(Y_MIN_PIN); + SET_INPUT(Y_MIN_PIN); #ifdef ENDSTOPPULLUP_YMIN WRITE(Y_MIN_PIN,HIGH); #endif #endif - + #if defined(Z_MIN_PIN) && Z_MIN_PIN > -1 - SET_INPUT(Z_MIN_PIN); + SET_INPUT(Z_MIN_PIN); #ifdef ENDSTOPPULLUP_ZMIN WRITE(Z_MIN_PIN,HIGH); #endif #endif - + #if defined(X_MAX_PIN) && X_MAX_PIN > -1 - SET_INPUT(X_MAX_PIN); + SET_INPUT(X_MAX_PIN); #ifdef ENDSTOPPULLUP_XMAX WRITE(X_MAX_PIN,HIGH); #endif #endif - + #if defined(Y_MAX_PIN) && Y_MAX_PIN > -1 - SET_INPUT(Y_MAX_PIN); + SET_INPUT(Y_MAX_PIN); #ifdef ENDSTOPPULLUP_YMAX WRITE(Y_MAX_PIN,HIGH); #endif #endif - + #if defined(Z_MAX_PIN) && Z_MAX_PIN > -1 - SET_INPUT(Z_MAX_PIN); + SET_INPUT(Z_MAX_PIN); #ifdef ENDSTOPPULLUP_ZMAX WRITE(Z_MAX_PIN,HIGH); #endif #endif - + //Initialize Step Pins - #if defined(X_STEP_PIN) && (X_STEP_PIN > -1) + #if defined(X_STEP_PIN) && (X_STEP_PIN > -1) SET_OUTPUT(X_STEP_PIN); WRITE(X_STEP_PIN,INVERT_X_STEP_PIN); disable_x(); - #endif - #if defined(X2_STEP_PIN) && (X2_STEP_PIN > -1) - SET_OUTPUT(X2_STEP_PIN); - WRITE(X2_STEP_PIN,INVERT_X_STEP_PIN); - disable_x(); - #endif - #if defined(Y_STEP_PIN) && (Y_STEP_PIN > -1) + #endif + #if defined(Y_STEP_PIN) && (Y_STEP_PIN > -1) SET_OUTPUT(Y_STEP_PIN); WRITE(Y_STEP_PIN,INVERT_Y_STEP_PIN); - #if defined(Y_DUAL_STEPPER_DRIVERS) && defined(Y2_STEP_PIN) && (Y2_STEP_PIN > -1) - SET_OUTPUT(Y2_STEP_PIN); - WRITE(Y2_STEP_PIN,INVERT_Y_STEP_PIN); - #endif disable_y(); - #endif - #if defined(Z_STEP_PIN) && (Z_STEP_PIN > -1) + #endif + #if defined(Z_STEP_PIN) && (Z_STEP_PIN > -1) SET_OUTPUT(Z_STEP_PIN); WRITE(Z_STEP_PIN,INVERT_Z_STEP_PIN); #if defined(Z_DUAL_STEPPER_DRIVERS) && defined(Z2_STEP_PIN) && (Z2_STEP_PIN > -1) @@ -911,33 +801,33 @@ void st_init() WRITE(Z2_STEP_PIN,INVERT_Z_STEP_PIN); #endif disable_z(); - #endif - #if defined(E0_STEP_PIN) && (E0_STEP_PIN > -1) + #endif + #if defined(E0_STEP_PIN) && (E0_STEP_PIN > -1) SET_OUTPUT(E0_STEP_PIN); WRITE(E0_STEP_PIN,INVERT_E_STEP_PIN); disable_e0(); - #endif - #if defined(E1_STEP_PIN) && (E1_STEP_PIN > -1) + #endif + #if defined(E1_STEP_PIN) && (E1_STEP_PIN > -1) SET_OUTPUT(E1_STEP_PIN); WRITE(E1_STEP_PIN,INVERT_E_STEP_PIN); disable_e1(); - #endif - #if defined(E2_STEP_PIN) && (E2_STEP_PIN > -1) + #endif + #if defined(E2_STEP_PIN) && (E2_STEP_PIN > -1) SET_OUTPUT(E2_STEP_PIN); WRITE(E2_STEP_PIN,INVERT_E_STEP_PIN); disable_e2(); - #endif + #endif // waveform generation = 0100 = CTC TCCR1B &= ~(1< -1 const uint8_t digipot_motor_current[] = DIGIPOT_MOTOR_CURRENT; - - SPI.begin(); - pinMode(DIGIPOTSS_PIN, OUTPUT); - for(int i=0;i<=4;i++) + + SPI.begin(); + pinMode(DIGIPOTSS_PIN, OUTPUT); + for(int i=0;i<=4;i++) //digitalPotWrite(digipot_ch[i], digipot_motor_current[i]); digipot_current(i,digipot_motor_current[i]); #endif From ed1ab42186fd8631456e4d7c6b572bf0a2d124f7 Mon Sep 17 00:00:00 2001 From: Richard Miles Date: Tue, 17 Sep 2013 19:19:20 +0100 Subject: [PATCH 06/15] Added Y_DUAL_STEPPER_DRIVERS Enables two stepper drivers to be used for the Y axis (useful for Shapeoko style machines) Each Y driver can be stepped in either the same way or in opposite directions, accounting for different hardware setups (leadscrew vs. belt driven) --- Marlin/Configuration_adv.h | 15 +++++++++++++++ Marlin/Marlin.h | 9 +++++++-- Marlin/stepper.cpp | 32 ++++++++++++++++++++++++++++++++ 3 files changed, 54 insertions(+), 2 deletions(-) diff --git a/Marlin/Configuration_adv.h b/Marlin/Configuration_adv.h index 5f1c77a056..bd411a403b 100644 --- a/Marlin/Configuration_adv.h +++ b/Marlin/Configuration_adv.h @@ -152,6 +152,21 @@ #define EXTRUDERS 1 #endif +// Same again but for Y Axis. +#define Y_DUAL_STEPPER_DRIVERS + +// 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 + +#ifdef Z_DUAL_STEPPER_DRIVERS && Y_DUAL_STEPPER_DRIVERS + #error "You cannot have dual drivers for both Y and Z" +#endif + //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 diff --git a/Marlin/Marlin.h b/Marlin/Marlin.h index c9759eb219..c4460e79f0 100644 --- a/Marlin/Marlin.h +++ b/Marlin/Marlin.h @@ -105,8 +105,13 @@ void manage_inactivity(); #endif #if defined(Y_ENABLE_PIN) && Y_ENABLE_PIN > -1 - #define enable_y() WRITE(Y_ENABLE_PIN, Y_ENABLE_ON) - #define disable_y() WRITE(Y_ENABLE_PIN,!Y_ENABLE_ON) + #ifdef Y_DUAL_STEPPER_DRIVERS + #define enable_y() { WRITE(Y_ENABLE_PIN, Y_ENABLE_ON); WRITE(Y2_ENABLE_PIN, Y_ENABLE_ON); } + #define disable_y() { WRITE(Y_ENABLE_PIN,!Y_ENABLE_ON); WRITE(Y2_ENABLE_PIN, !Y_ENABLE_ON); } + #else + #define enable_y() WRITE(Y_ENABLE_PIN, Y_ENABLE_ON) + #define disable_y() WRITE(Y_ENABLE_PIN,!Y_ENABLE_ON) + #endif #else #define enable_y() ; #define disable_y() ; diff --git a/Marlin/stepper.cpp b/Marlin/stepper.cpp index a7991501e9..10c41b9a62 100644 --- a/Marlin/stepper.cpp +++ b/Marlin/stepper.cpp @@ -357,10 +357,20 @@ ISR(TIMER1_COMPA_vect) } if((out_bits & (1<steps_y; if (counter_y > 0) { WRITE(Y_STEP_PIN, !INVERT_Y_STEP_PIN); + + #ifdef Y_DUAL_STEPPER_DRIVERS + WRITE(Y2_STEP_PIN, !INVERT_Y_STEP_PIN); + #endif + counter_y -= current_block->step_event_count; count_position[Y_AXIS]+=count_direction[Y_AXIS]; WRITE(Y_STEP_PIN, INVERT_Y_STEP_PIN); + + #ifdef Y_DUAL_STEPPER_DRIVERS + WRITE(Y2_STEP_PIN, INVERT_Y_STEP_PIN); + #endif } counter_z += current_block->steps_z; @@ -687,6 +706,10 @@ void st_init() #endif #if defined(Y_DIR_PIN) && Y_DIR_PIN > -1 SET_OUTPUT(Y_DIR_PIN); + + #if defined(Y_DUAL_STEPPER_DRIVERS) && defined(Y2_DIR_PIN) && (Y2_DIR_PIN > -1) + SET_OUTPUT(Y2_DIR_PIN); + #endif #endif #if defined(Z_DIR_PIN) && Z_DIR_PIN > -1 SET_OUTPUT(Z_DIR_PIN); @@ -714,6 +737,11 @@ void st_init() #if defined(Y_ENABLE_PIN) && Y_ENABLE_PIN > -1 SET_OUTPUT(Y_ENABLE_PIN); if(!Y_ENABLE_ON) WRITE(Y_ENABLE_PIN,HIGH); + + #if defined(Y_DUAL_STEPPER_DRIVERS) && defined(Y2_ENABLE_PIN) && (Y2_ENABLE_PIN > -1) + SET_OUTPUT(Y2_ENABLE_PIN); + if(!Y_ENABLE_ON) WRITE(Y2_ENABLE_PIN,HIGH); + #endif #endif #if defined(Z_ENABLE_PIN) && Z_ENABLE_PIN > -1 SET_OUTPUT(Z_ENABLE_PIN); @@ -791,6 +819,10 @@ void st_init() #if defined(Y_STEP_PIN) && (Y_STEP_PIN > -1) SET_OUTPUT(Y_STEP_PIN); WRITE(Y_STEP_PIN,INVERT_Y_STEP_PIN); + #if defined(Y_DUAL_STEPPER_DRIVERS) && defined(Y2_STEP_PIN) && (Y2_STEP_PIN > -1) + SET_OUTPUT(Y2_STEP_PIN); + WRITE(Y2_STEP_PIN,INVERT_Y_STEP_PIN); + #endif disable_y(); #endif #if defined(Z_STEP_PIN) && (Z_STEP_PIN > -1) From 77df2ab0e7e6253d2e1d975c76a9876ec46bd96b Mon Sep 17 00:00:00 2001 From: Richard Miles Date: Tue, 17 Sep 2013 21:49:44 +0100 Subject: [PATCH 07/15] Make Y_DUAL_STEPPER_DRIVERS disabled by default --- 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 bd411a403b..4747842479 100644 --- a/Marlin/Configuration_adv.h +++ b/Marlin/Configuration_adv.h @@ -153,7 +153,7 @@ #endif // Same again but for Y Axis. -#define Y_DUAL_STEPPER_DRIVERS +//#define Y_DUAL_STEPPER_DRIVERS // Define if the two Y drives need to rotate in opposite directions #define INVERT_Y2_VS_Y_DIR true From 61db046b3285c56dea66e658d9b8530debaf63a1 Mon Sep 17 00:00:00 2001 From: Tim Koster Date: Fri, 20 Sep 2013 10:57:42 +0300 Subject: [PATCH 08/15] Added #ifdef BLINKM around new code. Also refined BlinkM.h. --- Marlin/BlinkM.cpp | 1 + Marlin/BlinkM.h | 4 ++++ Marlin/Configuration.h | 2 +- Marlin/Marlin_main.cpp | 2 ++ 4 files changed, 8 insertions(+), 1 deletion(-) diff --git a/Marlin/BlinkM.cpp b/Marlin/BlinkM.cpp index 15a2527bbf..7b8a7867c2 100644 --- a/Marlin/BlinkM.cpp +++ b/Marlin/BlinkM.cpp @@ -7,6 +7,7 @@ #else # include "WProgram.h" #endif + #include "BlinkM.h" void SendColors(byte red, byte grn, byte blu) diff --git a/Marlin/BlinkM.h b/Marlin/BlinkM.h index 5136828782..fbb9399c23 100644 --- a/Marlin/BlinkM.h +++ b/Marlin/BlinkM.h @@ -8,7 +8,11 @@ # include "WProgram.h" #endif +#ifndef BLINKM +#define BLINKM + #include "Wire.h" void SendColors(byte red, byte grn, byte blu); +#endif diff --git a/Marlin/Configuration.h b/Marlin/Configuration.h index 195331252f..d3168b5450 100644 --- a/Marlin/Configuration.h +++ b/Marlin/Configuration.h @@ -558,7 +558,7 @@ const bool Z_MAX_ENDSTOP_INVERTING = true; // set to true to invert the logic of //#define BARICUDA //define BlinkM/CyzRgb Support -//#define BlinkM +//#define BLINKM /*********************************************************************\ * R/C SERVO support diff --git a/Marlin/Marlin_main.cpp b/Marlin/Marlin_main.cpp index 26fbd41232..7ecf6032c8 100644 --- a/Marlin/Marlin_main.cpp +++ b/Marlin/Marlin_main.cpp @@ -1617,6 +1617,7 @@ void process_commands() #endif break; //TODO: update for all axis, use for loop + #ifdef BLINKM case 150: // M150 { byte red; @@ -1630,6 +1631,7 @@ void process_commands() SendColors(red,grn,blu); } break; + #endif //BLINKM case 201: // M201 for(int8_t i=0; i < NUM_AXIS; i++) { From 97b0da0c2e33270ea56e7c801ce5c15b0c4d0a2f Mon Sep 17 00:00:00 2001 From: Tim Koster Date: Sun, 22 Sep 2013 10:43:27 +0300 Subject: [PATCH 09/15] Removed #ifndef BLINKM --- Marlin/BlinkM.h | 4 ---- 1 file changed, 4 deletions(-) diff --git a/Marlin/BlinkM.h b/Marlin/BlinkM.h index fbb9399c23..5136828782 100644 --- a/Marlin/BlinkM.h +++ b/Marlin/BlinkM.h @@ -8,11 +8,7 @@ # include "WProgram.h" #endif -#ifndef BLINKM -#define BLINKM - #include "Wire.h" void SendColors(byte red, byte grn, byte blu); -#endif From dd3086d3f22337fd144672b85344d40777073ade Mon Sep 17 00:00:00 2001 From: Alex Borro Date: Sat, 12 Oct 2013 10:41:23 -0300 Subject: [PATCH 10/15] Show Temperature ADC values If "SHOW_TEMP_ADC_VALUES" is defined in Configuration_adv.h, the M105 command will present, after tradicional temperatures, the ADC value read from temp sensors. This is great for adjusting thermistor tables with thermocouple. From Pronterface you can see the ADC value and compare with a thermocouple reading.. then you just need to create your own thermistor table. Since this merge doesnt change the original information, it doesnt mess with PC software parsing (tested under Pronterface and Repetier-Host). --- Marlin/Configuration_adv.h | 4 ++++ Marlin/Marlin_main.cpp | 17 +++++++++++++++++ Marlin/temperature.h | 14 ++++++++++++++ 3 files changed, 35 insertions(+) diff --git a/Marlin/Configuration_adv.h b/Marlin/Configuration_adv.h index 23ca5efec8..220458d918 100644 --- a/Marlin/Configuration_adv.h +++ b/Marlin/Configuration_adv.h @@ -40,6 +40,10 @@ #define AUTOTEMP_OLDWEIGHT 0.98 #endif +//Show Temperature ADC value +//The M105 command return, besides traditional information, the ADC value read from temperature sensors. +//#define SHOW_TEMP_ADC_VALUES + // 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 diff --git a/Marlin/Marlin_main.cpp b/Marlin/Marlin_main.cpp index 932af13552..dc7edd0a5c 100644 --- a/Marlin/Marlin_main.cpp +++ b/Marlin/Marlin_main.cpp @@ -1570,6 +1570,23 @@ void process_commands() SERIAL_PROTOCOLPGM(" B@:"); SERIAL_PROTOCOL(getHeaterPower(-1)); + #ifdef SHOW_TEMP_ADC_VALUES + #if defined(TEMP_BED_PIN) && TEMP_BED_PIN > -1 + SERIAL_PROTOCOLPGM(" ADC B:"); + SERIAL_PROTOCOL_F(degBed(),1); + SERIAL_PROTOCOLPGM("C->"); + SERIAL_PROTOCOL_F(rawBedTemp()/OVERSAMPLENR,0); + #endif + for (int8_t cur_extruder = 0; cur_extruder < EXTRUDERS; ++cur_extruder) { + SERIAL_PROTOCOLPGM(" T"); + SERIAL_PROTOCOL(cur_extruder); + SERIAL_PROTOCOLPGM(":"); + SERIAL_PROTOCOL_F(degHotend(cur_extruder),1); + SERIAL_PROTOCOLPGM("C->"); + SERIAL_PROTOCOL_F(rawHotendTemp(cur_extruder)/OVERSAMPLENR,0); + } + #endif + SERIAL_PROTOCOLLN(""); return; break; diff --git a/Marlin/temperature.h b/Marlin/temperature.h index a5974241c4..1bf47e02ed 100644 --- a/Marlin/temperature.h +++ b/Marlin/temperature.h @@ -35,6 +35,10 @@ void manage_heater(); //it is critical that this is called periodically. // do not use these routines and variables outside of temperature.cpp extern int target_temperature[EXTRUDERS]; extern float current_temperature[EXTRUDERS]; +#ifdef SHOW_TEMP_ADC_VALUES + extern int current_temperature_raw[EXTRUDERS]; + extern int current_temperature_bed_raw; +#endif extern int target_temperature_bed; extern float current_temperature_bed; #ifdef TEMP_SENSOR_1_AS_REDUNDANT @@ -66,6 +70,16 @@ FORCE_INLINE float degHotend(uint8_t extruder) { return current_temperature[extruder]; }; +#ifdef SHOW_TEMP_ADC_VALUES + FORCE_INLINE float rawHotendTemp(uint8_t extruder) { + return current_temperature_raw[extruder]; + }; + + FORCE_INLINE float rawBedTemp() { + return current_temperature_bed_raw; + }; +#endif + FORCE_INLINE float degBed() { return current_temperature_bed; }; From 6f85a8c7aa95474c653e326a3727e252d280d057 Mon Sep 17 00:00:00 2001 From: Alex Borro Date: Sat, 12 Oct 2013 17:28:11 -0300 Subject: [PATCH 11/15] Bed auto Leveling change: Raise Z before homing - Added "Z_RAISE_BEFORE_HOMING" for raising Z the defined distance before homing. This is useful to avoid Z-Probe collision when hotend is near bed. - Fixed the issue of Z not going bellow Z_PROBE_OFFSET when "min_software_endstops" is true. Now the Z_PROBE_OFFSET is not set in Z_MIN_POS, it is added after homing. --- Marlin/Configuration.h | 10 ++++------ Marlin/Marlin_main.cpp | 24 ++++++++++++++++++------ 2 files changed, 22 insertions(+), 12 deletions(-) diff --git a/Marlin/Configuration.h b/Marlin/Configuration.h index 502ebd4389..459640fbc3 100644 --- a/Marlin/Configuration.h +++ b/Marlin/Configuration.h @@ -309,7 +309,10 @@ const bool Z_MAX_ENDSTOP_INVERTING = true; // set to true to invert the logic of #define X_PROBE_OFFSET_FROM_EXTRUDER -25 #define Y_PROBE_OFFSET_FROM_EXTRUDER -29 #define Z_PROBE_OFFSET_FROM_EXTRUDER -12.35 - + + #define Z_RAISE_BEFORE_HOMING 4 // (in mm) Raise Z before homing (G28) for Probe Clearance. + // Be sure you have this distance over your Z_MAX_POS in case + #define XY_TRAVEL_SPEED 8000 // X and Y axis travel speed between probes, in mm/min #define Z_RAISE_BEFORE_PROBING 15 //How much the extruder will be raised before traveling to the first probing point. @@ -330,12 +333,7 @@ const bool Z_MAX_ENDSTOP_INVERTING = true; // set to true to invert the logic of #define Y_MAX_POS 205 #define Y_MIN_POS 0 #define Z_MAX_POS 200 - -#ifndef ENABLE_AUTO_BED_LEVELING #define Z_MIN_POS 0 -#else -#define Z_MIN_POS (-1*Z_PROBE_OFFSET_FROM_EXTRUDER) //With Auto Bed Leveling, the Z_MIN MUST have the same distance as Z_PROBE -#endif #define X_MAX_LENGTH (X_MAX_POS - X_MIN_POS) #define Y_MAX_LENGTH (Y_MAX_POS - Y_MIN_POS) diff --git a/Marlin/Marlin_main.cpp b/Marlin/Marlin_main.cpp index dc7edd0a5c..2a3534221e 100644 --- a/Marlin/Marlin_main.cpp +++ b/Marlin/Marlin_main.cpp @@ -920,19 +920,28 @@ static void homeaxis(int axis) { axis_home_dir = x_home_dir(active_extruder); #endif + current_position[axis] = 0; + plan_set_position(current_position[X_AXIS], current_position[Y_AXIS], current_position[Z_AXIS], current_position[E_AXIS]); + // Engage Servo endstop if enabled #ifdef SERVO_ENDSTOPS -#if defined (ENABLE_AUTO_BED_LEVELING) && (PROBE_SERVO_DEACTIVATION_DELAY > 0) - if (axis==Z_AXIS) engage_z_probe(); - else -#endif + #if defined (ENABLE_AUTO_BED_LEVELING) && (PROBE_SERVO_DEACTIVATION_DELAY > 0) + if (axis==Z_AXIS) { + #if defined (Z_RAISE_BEFORE_HOMING) && (Z_RAISE_BEFORE_HOMING > 0) + destination[axis] = Z_RAISE_BEFORE_HOMING * axis_home_dir * (-1); // Set destination away from bed + feedrate = max_feedrate[axis]; + plan_buffer_line(destination[X_AXIS], destination[Y_AXIS], destination[Z_AXIS], destination[E_AXIS], feedrate, active_extruder); + st_synchronize(); + #endif + engage_z_probe(); + } + else + #endif if (servo_endstops[axis] > -1) { servos[servo_endstops[axis]].write(servo_endstop_angles[axis * 2]); } #endif - current_position[axis] = 0; - plan_set_position(current_position[X_AXIS], current_position[Y_AXIS], current_position[Z_AXIS], current_position[E_AXIS]); 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); @@ -1198,6 +1207,9 @@ void process_commands() current_position[Z_AXIS]=code_value()+add_homeing[2]; } } + #ifdef ENABLE_AUTO_BED_LEVELING + current_position[Z_AXIS] -= Z_PROBE_OFFSET_FROM_EXTRUDER; //Add Z_Probe offset (the distance is negative) + #endif plan_set_position(current_position[X_AXIS], current_position[Y_AXIS], current_position[Z_AXIS], current_position[E_AXIS]); #endif // else DELTA From 87e28c059980bcf85633cc1f5ccfdf0b3a6d088d Mon Sep 17 00:00:00 2001 From: Erik van der Zalm Date: Sun, 20 Oct 2013 09:55:15 +0200 Subject: [PATCH 12/15] Added ifdefs to blinkm --- Marlin/BlinkM.cpp | 4 ++++ Marlin/Marlin_main.cpp | 2 ++ 2 files changed, 6 insertions(+) diff --git a/Marlin/BlinkM.cpp b/Marlin/BlinkM.cpp index 7b8a7867c2..52a45859ff 100644 --- a/Marlin/BlinkM.cpp +++ b/Marlin/BlinkM.cpp @@ -2,6 +2,8 @@ BlinkM.cpp - Library for controlling a BlinkM over i2c Created by Tim Koster, August 21 2013. */ +#ifdef BLINKM + #if (ARDUINO >= 100) # include "Arduino.h" #else @@ -22,3 +24,5 @@ void SendColors(byte red, byte grn, byte blu) Wire.endTransmission(); } +#endif //BLINKM + diff --git a/Marlin/Marlin_main.cpp b/Marlin/Marlin_main.cpp index d62c2f6b90..d0262d30e0 100644 --- a/Marlin/Marlin_main.cpp +++ b/Marlin/Marlin_main.cpp @@ -44,8 +44,10 @@ #include "language.h" #include "pins_arduino.h" +#ifdef BLINKM #include "BlinkM.h" #include "Wire.h" +#endif #if NUM_SERVOS > 0 #include "Servo.h" From bf27e79e7498b48c945807091aa4be98da749453 Mon Sep 17 00:00:00 2001 From: Erik van der Zalm Date: Sun, 20 Oct 2013 10:06:02 +0200 Subject: [PATCH 13/15] Small BlinkM fix --- Marlin/BlinkM.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/Marlin/BlinkM.cpp b/Marlin/BlinkM.cpp index 52a45859ff..de604ecd35 100644 --- a/Marlin/BlinkM.cpp +++ b/Marlin/BlinkM.cpp @@ -2,6 +2,7 @@ BlinkM.cpp - Library for controlling a BlinkM over i2c Created by Tim Koster, August 21 2013. */ +#include "Marlin.h" #ifdef BLINKM #if (ARDUINO >= 100) From 667d278f54aad426316775807e558c9dcc187c90 Mon Sep 17 00:00:00 2001 From: Erik van der Zalm Date: Sun, 20 Oct 2013 10:16:46 +0200 Subject: [PATCH 14/15] Revert "Fix for Viki display" This reverts commit 314fd13c39e1a5420adfbc9127339da80a1039aa. --- Marlin/ultralcd.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/Marlin/ultralcd.cpp b/Marlin/ultralcd.cpp index 12a9e23bc3..895c3ed4e9 100644 --- a/Marlin/ultralcd.cpp +++ b/Marlin/ultralcd.cpp @@ -104,6 +104,7 @@ static void menu_action_setting_edit_callback_long5(const char* pstr, unsigned l if (encoderPosition > 0x8000) encoderPosition = 0; \ if (encoderPosition / ENCODER_STEPS_PER_MENU_ITEM < currentMenuViewOffset) currentMenuViewOffset = encoderPosition / ENCODER_STEPS_PER_MENU_ITEM;\ uint8_t _lineNr = currentMenuViewOffset, _menuItemNr; \ + bool wasClicked = LCD_CLICKED;\ for(uint8_t _drawLineNr = 0; _drawLineNr < LCD_HEIGHT; _drawLineNr++, _lineNr++) { \ _menuItemNr = 0; #define MENU_ITEM(type, label, args...) do { \ @@ -142,7 +143,6 @@ uint8_t currentMenuViewOffset; /* scroll offset in the current menu uint32_t blocking_enc; uint8_t lastEncoderBits; uint32_t encoderPosition; -bool wasClicked; #if (SDCARDDETECT > 0) bool lcd_oldcardstatus; #endif @@ -1042,7 +1042,6 @@ void lcd_update() if (lcd_next_update_millis < millis()) { - wasClicked = LCD_CLICKED; #ifdef ULTIPANEL #ifdef REPRAPWORLD_KEYPAD if (REPRAPWORLD_KEYPAD_MOVE_Z_UP) { From 8a08cca0f2c16d6863bacefa41966cee17ee5b26 Mon Sep 17 00:00:00 2001 From: Erik van der Zalm Date: Sun, 20 Oct 2013 12:12:35 +0200 Subject: [PATCH 15/15] Added temperature status less. Hopefully fixed viky button handling without braking other boards --- Marlin/Configuration.h | 5 + Marlin/Marlin_main.cpp | 38 +- Marlin/pins.h | 7 + .../ultralcd_implementation_hitachi_HD44780.h | 1511 +++++++++-------- 4 files changed, 810 insertions(+), 751 deletions(-) diff --git a/Marlin/Configuration.h b/Marlin/Configuration.h index 974709ff44..8496a8b24b 100644 --- a/Marlin/Configuration.h +++ b/Marlin/Configuration.h @@ -540,6 +540,11 @@ const bool Z_MAX_ENDSTOP_INVERTING = true; // set to true to invert the logic of // Increase the FAN pwm frequency. Removes the PWM noise but increases heating in the FET/Arduino //#define FAST_PWM_FAN +// Temperature status leds that display the hotend and bet temperature. +// If alle hotends and bed temperature and temperature setpoint are < 54C then the BLUE led is on. +// Otherwise the RED led is on. There is 1C hysteresis. +//#define TEMP_STAT_LEDS + // Use software PWM to drive the fan, as for the heaters. This uses a very low frequency // which is not ass annoying as with the hardware PWM. On the other hand, if this frequency // is too low, you should also increment SOFT_PWM_SCALE. diff --git a/Marlin/Marlin_main.cpp b/Marlin/Marlin_main.cpp index d0262d30e0..e431ad6c12 100644 --- a/Marlin/Marlin_main.cpp +++ b/Marlin/Marlin_main.cpp @@ -2938,6 +2938,39 @@ void controllerFan() } #endif +#ifdef TEMP_STAT_LEDS +static bool blue_led = false; +static bool red_led = false; +static uint32_t stat_update = 0; + +void handle_status_leds(void) { + float max_temp = 0.0; + if(millis() > stat_update) { + stat_update += 500; // Update every 0.5s + for (int8_t cur_extruder = 0; cur_extruder < EXTRUDERS; ++cur_extruder) { + max_temp = max(max_temp, degHotend(cur_extruder)); + max_temp = max(max_temp, degTargetHotend(cur_extruder)); + } + #if defined(TEMP_BED_PIN) && TEMP_BED_PIN > -1 + max_temp = max(max_temp, degTargetBed()); + max_temp = max(max_temp, degBed()); + #endif + if((max_temp > 55.0) && (red_led == false)) { + digitalWrite(STAT_LED_RED, 1); + digitalWrite(STAT_LED_BLUE, 0); + red_led = true; + blue_led = false; + } + if((max_temp < 54.0) && (blue_led == false)) { + digitalWrite(STAT_LED_RED, 0); + digitalWrite(STAT_LED_BLUE, 1); + red_led = false; + blue_led = true; + } + } +} +#endif + void manage_inactivity() { if( (millis() - previous_millis_cmd) > max_inactive_time ) @@ -2991,7 +3024,10 @@ void manage_inactivity() memcpy(destination,current_position,sizeof(destination)); prepare_move(); } - #endif + #endif + #ifdef TEMP_STAT_LEDS + handle_status_leds(); + #endif check_axes_activity(); } diff --git a/Marlin/pins.h b/Marlin/pins.h index 1ae3cb486b..12dd931346 100644 --- a/Marlin/pins.h +++ b/Marlin/pins.h @@ -544,6 +544,13 @@ #endif #endif + #ifdef TEMP_STAT_LEDS + #if MOTHERBOARD == 67 + #define STAT_LED_RED 6 + #define STAT_LED_BLUE 11 + #endif + #endif + #ifdef ULTRA_LCD #ifdef NEWPANEL diff --git a/Marlin/ultralcd_implementation_hitachi_HD44780.h b/Marlin/ultralcd_implementation_hitachi_HD44780.h index ac397f6753..36462d8872 100644 --- a/Marlin/ultralcd_implementation_hitachi_HD44780.h +++ b/Marlin/ultralcd_implementation_hitachi_HD44780.h @@ -1,750 +1,761 @@ -#ifndef ULTRA_LCD_IMPLEMENTATION_HITACHI_HD44780_H -#define ULTRA_LCD_IMPLEMENTATION_HITACHI_HD44780_H - -/** -* Implementation of the LCD display routines for a hitachi HD44780 display. These are common LCD character displays. -* When selecting the rusian language, a slightly different LCD implementation is used to handle UTF8 characters. -**/ - -#ifndef REPRAPWORLD_KEYPAD -extern volatile uint8_t buttons; //the last checked buttons in a bit array. -#else -extern volatile uint16_t buttons; //an extended version of the last checked buttons in a bit array. -#endif - -//////////////////////////////////// -// Setup button and encode mappings for each panel (into 'buttons' variable -// -// This is just to map common functions (across different panels) onto the same -// macro name. The mapping is independent of whether the button is directly connected or -// via a shift/i2c register. - -#ifdef ULTIPANEL -// All Ultipanels might have an encoder - so this is always be mapped onto first two bits -#define BLEN_B 1 -#define BLEN_A 0 - -#define EN_B (1< -1 - // encoder click is directly connected - #define BLEN_C 2 - #define EN_C (1< -1 - // the pause/stop/restart button is connected to BTN_ENC when used - #define B_ST (EN_C) // Map the pause/stop/resume button into its normalized functional name - #define LCD_CLICKED (buttons&(B_MI|B_RI|B_ST)) // pause/stop button also acts as click until we implement proper pause/stop. - #else - #define LCD_CLICKED (buttons&(B_MI|B_RI)) - #endif - - // I2C buttons take too long to read inside an interrupt context and so we read them during lcd_update - #define LCD_HAS_SLOW_BUTTONS - -#elif defined(LCD_I2C_PANELOLU2) - // encoder click can be read through I2C if not directly connected - #if BTN_ENC <= 0 - #define B_I2C_BTN_OFFSET 3 // (the first three bit positions reserved for EN_A, EN_B, EN_C) - - #define B_MI (PANELOLU2_ENCODER_C< - #include - #include - #define LCD_CLASS LiquidCrystal_I2C - LCD_CLASS lcd(LCD_I2C_ADDRESS,LCD_I2C_PIN_EN,LCD_I2C_PIN_RW,LCD_I2C_PIN_RS,LCD_I2C_PIN_D4,LCD_I2C_PIN_D5,LCD_I2C_PIN_D6,LCD_I2C_PIN_D7); - -#elif defined(LCD_I2C_TYPE_MCP23017) - //for the LED indicators (which maybe mapped to different things in lcd_implementation_update_indicators()) - #define LED_A 0x04 //100 - #define LED_B 0x02 //010 - #define LED_C 0x01 //001 - - #define LCD_HAS_STATUS_INDICATORS - - #include - #include - #define LCD_CLASS LiquidTWI2 - LCD_CLASS lcd(LCD_I2C_ADDRESS); - -#elif defined(LCD_I2C_TYPE_MCP23008) - #include - #include - #define LCD_CLASS LiquidTWI2 - LCD_CLASS lcd(LCD_I2C_ADDRESS); - -#elif defined(LCD_I2C_TYPE_PCA8574) - #include - #define LCD_CLASS LiquidCrystal_I2C - LCD_CLASS lcd(LCD_I2C_ADDRESS, LCD_WIDTH, LCD_HEIGHT); - -#else - // Standard directly connected LCD implementations - #if LANGUAGE_CHOICE == 6 - #include "LiquidCrystalRus.h" - #define LCD_CLASS LiquidCrystalRus - #else - #include - #define LCD_CLASS LiquidCrystal - #endif - LCD_CLASS lcd(LCD_PINS_RS, LCD_PINS_ENABLE, LCD_PINS_D4, LCD_PINS_D5,LCD_PINS_D6,LCD_PINS_D7); //RS,Enable,D4,D5,D6,D7 -#endif - -/* Custom characters defined in the first 8 characters of the LCD */ -#define LCD_STR_BEDTEMP "\x00" -#define LCD_STR_DEGREE "\x01" -#define LCD_STR_THERMOMETER "\x02" -#define LCD_STR_UPLEVEL "\x03" -#define LCD_STR_REFRESH "\x04" -#define LCD_STR_FOLDER "\x05" -#define LCD_STR_FEEDRATE "\x06" -#define LCD_STR_CLOCK "\x07" -#define LCD_STR_ARROW_RIGHT "\x7E" /* from the default character set */ - -static void lcd_implementation_init() -{ - byte bedTemp[8] = - { - B00000, - B11111, - B10101, - B10001, - B10101, - B11111, - B00000, - B00000 - }; //thanks Sonny Mounicou - byte degree[8] = - { - B01100, - B10010, - B10010, - B01100, - B00000, - B00000, - B00000, - B00000 - }; - byte thermometer[8] = - { - B00100, - B01010, - B01010, - B01010, - B01010, - B10001, - B10001, - B01110 - }; - byte uplevel[8]={ - B00100, - B01110, - B11111, - B00100, - B11100, - B00000, - B00000, - B00000 - }; //thanks joris - byte refresh[8]={ - B00000, - B00110, - B11001, - B11000, - B00011, - B10011, - B01100, - B00000, - }; //thanks joris - byte folder [8]={ - B00000, - B11100, - B11111, - B10001, - B10001, - B11111, - B00000, - B00000 - }; //thanks joris - byte feedrate [8]={ - B11100, - B10000, - B11000, - B10111, - B00101, - B00110, - B00101, - B00000 - }; //thanks Sonny Mounicou - byte clock [8]={ - B00000, - B01110, - B10011, - B10101, - B10001, - B01110, - B00000, - B00000 - }; //thanks Sonny Mounicou - -#if defined(LCDI2C_TYPE_PCF8575) - lcd.begin(LCD_WIDTH, LCD_HEIGHT); - #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); - lcd.begin(LCD_WIDTH, LCD_HEIGHT); - lcd.setBacklight(0); //set all the LEDs off to begin with - -#elif defined(LCD_I2C_TYPE_MCP23008) - lcd.setMCPType(LTI_TYPE_MCP23008); - lcd.begin(LCD_WIDTH, LCD_HEIGHT); - -#elif defined(LCD_I2C_TYPE_PCA8574) - lcd.init(); - lcd.backlight(); - -#else - lcd.begin(LCD_WIDTH, LCD_HEIGHT); -#endif - - lcd.createChar(LCD_STR_BEDTEMP[0], bedTemp); - lcd.createChar(LCD_STR_DEGREE[0], degree); - lcd.createChar(LCD_STR_THERMOMETER[0], thermometer); - lcd.createChar(LCD_STR_UPLEVEL[0], uplevel); - lcd.createChar(LCD_STR_REFRESH[0], refresh); - lcd.createChar(LCD_STR_FOLDER[0], folder); - lcd.createChar(LCD_STR_FEEDRATE[0], feedrate); - lcd.createChar(LCD_STR_CLOCK[0], clock); - lcd.clear(); -} -static void lcd_implementation_clear() -{ - lcd.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) -{ - char c; - while((c = pgm_read_byte(str++)) != '\0') - { - lcd.write(c); - } -} -/* -Possible status screens: -16x2 |0123456789012345| - |000/000 B000/000| - |Status line.....| - -16x4 |0123456789012345| - |000/000 B000/000| - |SD100% Z000.0| - |F100% T--:--| - |Status line.....| - -20x2 |01234567890123456789| - |T000/000D B000/000D | - |Status line.........| - -20x4 |01234567890123456789| - |T000/000D B000/000D | - |X+000.0 Y+000.0 Z+000.0| - |F100% SD100% T--:--| - |Status line.........| - -20x4 |01234567890123456789| - |T000/000D B000/000D | - |T000/000D Z000.0| - |F100% SD100% T--:--| - |Status line.........| -*/ -static void lcd_implementation_status_screen() -{ - int tHotend=int(degHotend(0) + 0.5); - int tTarget=int(degTargetHotend(0) + 0.5); - -#if LCD_WIDTH < 20 - lcd.setCursor(0, 0); - lcd.print(itostr3(tHotend)); - lcd.print('/'); - lcd.print(itostr3left(tTarget)); - -# if EXTRUDERS > 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 EXTRUDERS > 1 - tHotend = int(degHotend(1) + 0.5); - tTarget = int(degTargetHotend(1) + 0.5); - lcd.print(LCD_STR_THERMOMETER[0]); -# else//Heated bed - tHotend=int(degBed() + 0.5); - tTarget=int(degTargetBed() + 0.5); - lcd.print(LCD_STR_BEDTEMP[0]); -# endif - lcd.print(itostr3(tHotend)); - lcd.print('/'); - lcd.print(itostr3left(tTarget)); -# endif//EXTRUDERS > 1 || TEMP_SENSOR_BED != 0 - -#else//LCD_WIDTH > 19 - lcd.setCursor(0, 0); - lcd.print(LCD_STR_THERMOMETER[0]); - lcd.print(itostr3(tHotend)); - lcd.print('/'); - lcd.print(itostr3left(tTarget)); - lcd_printPGM(PSTR(LCD_STR_DEGREE " ")); - if (tTarget < 10) - lcd.print(' '); - -# if EXTRUDERS > 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 EXTRUDERS > 1 - tHotend = int(degHotend(1) + 0.5); - tTarget = int(degTargetHotend(1) + 0.5); - lcd.print(LCD_STR_THERMOMETER[0]); -# else//Heated bed - tHotend=int(degBed() + 0.5); - tTarget=int(degTargetBed() + 0.5); - lcd.print(LCD_STR_BEDTEMP[0]); -# endif - lcd.print(itostr3(tHotend)); - lcd.print('/'); - lcd.print(itostr3left(tTarget)); - lcd_printPGM(PSTR(LCD_STR_DEGREE " ")); - if (tTarget < 10) - lcd.print(' '); -# endif//EXTRUDERS > 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 EXTRUDERS > 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); - lcd.print('X'); - lcd.print(ftostr3(current_position[X_AXIS])); - lcd_printPGM(PSTR(" Y")); - lcd.print(ftostr3(current_position[Y_AXIS])); -# endif//EXTRUDERS > 1 || TEMP_SENSOR_BED != 0 -# endif//LCD_WIDTH > 19 - lcd.setCursor(LCD_WIDTH - 8, 1); - lcd.print('Z'); - lcd.print(ftostr32(current_position[Z_AXIS])); -#endif//LCD_HEIGHT > 2 - -#if LCD_HEIGHT > 3 - lcd.setCursor(0, 2); - lcd.print(LCD_STR_FEEDRATE[0]); - lcd.print(itostr3(feedmultiply)); - lcd.print('%'); -# if LCD_WIDTH > 19 -# ifdef SDSUPPORT - lcd.setCursor(7, 2); - lcd_printPGM(PSTR("SD")); - if (IS_SD_PRINTING) - lcd.print(itostr3(card.percentDone())); - else - lcd_printPGM(PSTR("---")); - lcd.print('%'); -# endif//SDSUPPORT -# endif//LCD_WIDTH > 19 - lcd.setCursor(LCD_WIDTH - 6, 2); - lcd.print(LCD_STR_CLOCK[0]); - if(starttime != 0) - { - uint16_t time = millis()/60000 - starttime/60000; - lcd.print(itostr2(time/60)); - lcd.print(':'); - lcd.print(itostr2(time%60)); - }else{ - lcd_printPGM(PSTR("--:--")); - } -#endif - - //Status message line on the last line - lcd.setCursor(0, LCD_HEIGHT - 1); - lcd.print(lcd_status_message); -} -static void lcd_implementation_drawmenu_generic(uint8_t row, const char* pstr, char pre_char, char post_char) -{ - char c; - //Use all characters in narrow LCDs - #if LCD_WIDTH < 20 - uint8_t n = LCD_WIDTH - 1 - 1; - #else - uint8_t n = LCD_WIDTH - 1 - 2; - #endif - lcd.setCursor(0, row); - lcd.print(pre_char); - while( ((c = pgm_read_byte(pstr)) != '\0') && (n>0) ) - { - lcd.print(c); - pstr++; - n--; - } - while(n--) - lcd.print(' '); - lcd.print(post_char); - lcd.print(' '); -} -static void lcd_implementation_drawmenu_setting_edit_generic(uint8_t row, const char* pstr, char pre_char, char* data) -{ - char c; - //Use all characters in narrow LCDs - #if LCD_WIDTH < 20 - uint8_t n = LCD_WIDTH - 1 - 1 - strlen(data); - #else - uint8_t n = LCD_WIDTH - 1 - 2 - strlen(data); - #endif - lcd.setCursor(0, row); - lcd.print(pre_char); - while( ((c = pgm_read_byte(pstr)) != '\0') && (n>0) ) - { - lcd.print(c); - pstr++; - n--; - } - lcd.print(':'); - while(n--) - lcd.print(' '); - lcd.print(data); -} -static void lcd_implementation_drawmenu_setting_edit_generic_P(uint8_t row, const char* pstr, char pre_char, const char* data) -{ - char c; - //Use all characters in narrow LCDs - #if LCD_WIDTH < 20 - uint8_t n = LCD_WIDTH - 1 - 1 - strlen_P(data); - #else - uint8_t n = LCD_WIDTH - 1 - 2 - strlen_P(data); - #endif - lcd.setCursor(0, row); - lcd.print(pre_char); - while( ((c = pgm_read_byte(pstr)) != '\0') && (n>0) ) - { - lcd.print(c); - pstr++; - n--; - } - lcd.print(':'); - while(n--) - lcd.print(' '); - lcd_printPGM(data); -} -#define lcd_implementation_drawmenu_setting_edit_int3_selected(row, pstr, pstr2, data, minValue, maxValue) lcd_implementation_drawmenu_setting_edit_generic(row, pstr, '>', itostr3(*(data))) -#define lcd_implementation_drawmenu_setting_edit_int3(row, pstr, pstr2, data, minValue, maxValue) lcd_implementation_drawmenu_setting_edit_generic(row, pstr, ' ', itostr3(*(data))) -#define lcd_implementation_drawmenu_setting_edit_float3_selected(row, pstr, pstr2, data, minValue, maxValue) lcd_implementation_drawmenu_setting_edit_generic(row, pstr, '>', ftostr3(*(data))) -#define lcd_implementation_drawmenu_setting_edit_float3(row, pstr, pstr2, data, minValue, maxValue) lcd_implementation_drawmenu_setting_edit_generic(row, pstr, ' ', ftostr3(*(data))) -#define lcd_implementation_drawmenu_setting_edit_float32_selected(row, pstr, pstr2, data, minValue, maxValue) lcd_implementation_drawmenu_setting_edit_generic(row, pstr, '>', ftostr32(*(data))) -#define lcd_implementation_drawmenu_setting_edit_float32(row, pstr, pstr2, data, minValue, maxValue) lcd_implementation_drawmenu_setting_edit_generic(row, pstr, ' ', ftostr32(*(data))) -#define lcd_implementation_drawmenu_setting_edit_float5_selected(row, pstr, pstr2, data, minValue, maxValue) lcd_implementation_drawmenu_setting_edit_generic(row, pstr, '>', ftostr5(*(data))) -#define lcd_implementation_drawmenu_setting_edit_float5(row, pstr, pstr2, data, minValue, maxValue) lcd_implementation_drawmenu_setting_edit_generic(row, pstr, ' ', ftostr5(*(data))) -#define lcd_implementation_drawmenu_setting_edit_float52_selected(row, pstr, pstr2, data, minValue, maxValue) lcd_implementation_drawmenu_setting_edit_generic(row, pstr, '>', ftostr52(*(data))) -#define lcd_implementation_drawmenu_setting_edit_float52(row, pstr, pstr2, data, minValue, maxValue) lcd_implementation_drawmenu_setting_edit_generic(row, pstr, ' ', ftostr52(*(data))) -#define lcd_implementation_drawmenu_setting_edit_float51_selected(row, pstr, pstr2, data, minValue, maxValue) lcd_implementation_drawmenu_setting_edit_generic(row, pstr, '>', ftostr51(*(data))) -#define lcd_implementation_drawmenu_setting_edit_float51(row, pstr, pstr2, data, minValue, maxValue) lcd_implementation_drawmenu_setting_edit_generic(row, pstr, ' ', ftostr51(*(data))) -#define lcd_implementation_drawmenu_setting_edit_long5_selected(row, pstr, pstr2, data, minValue, maxValue) lcd_implementation_drawmenu_setting_edit_generic(row, pstr, '>', ftostr5(*(data))) -#define lcd_implementation_drawmenu_setting_edit_long5(row, pstr, pstr2, data, minValue, maxValue) lcd_implementation_drawmenu_setting_edit_generic(row, pstr, ' ', ftostr5(*(data))) -#define lcd_implementation_drawmenu_setting_edit_bool_selected(row, pstr, pstr2, data) lcd_implementation_drawmenu_setting_edit_generic_P(row, pstr, '>', (*(data))?PSTR(MSG_ON):PSTR(MSG_OFF)) -#define lcd_implementation_drawmenu_setting_edit_bool(row, pstr, pstr2, data) lcd_implementation_drawmenu_setting_edit_generic_P(row, pstr, ' ', (*(data))?PSTR(MSG_ON):PSTR(MSG_OFF)) - -//Add version for callback functions -#define lcd_implementation_drawmenu_setting_edit_callback_int3_selected(row, pstr, pstr2, data, minValue, maxValue, callback) lcd_implementation_drawmenu_setting_edit_generic(row, pstr, '>', itostr3(*(data))) -#define lcd_implementation_drawmenu_setting_edit_callback_int3(row, pstr, pstr2, data, minValue, maxValue, callback) lcd_implementation_drawmenu_setting_edit_generic(row, pstr, ' ', itostr3(*(data))) -#define lcd_implementation_drawmenu_setting_edit_callback_float3_selected(row, pstr, pstr2, data, minValue, maxValue, callback) lcd_implementation_drawmenu_setting_edit_generic(row, pstr, '>', ftostr3(*(data))) -#define lcd_implementation_drawmenu_setting_edit_callback_float3(row, pstr, pstr2, data, minValue, maxValue, callback) lcd_implementation_drawmenu_setting_edit_generic(row, pstr, ' ', ftostr3(*(data))) -#define lcd_implementation_drawmenu_setting_edit_callback_float32_selected(row, pstr, pstr2, data, minValue, maxValue, callback) lcd_implementation_drawmenu_setting_edit_generic(row, pstr, '>', ftostr32(*(data))) -#define lcd_implementation_drawmenu_setting_edit_callback_float32(row, pstr, pstr2, data, minValue, maxValue, callback) lcd_implementation_drawmenu_setting_edit_generic(row, pstr, ' ', ftostr32(*(data))) -#define lcd_implementation_drawmenu_setting_edit_callback_float5_selected(row, pstr, pstr2, data, minValue, maxValue, callback) lcd_implementation_drawmenu_setting_edit_generic(row, pstr, '>', ftostr5(*(data))) -#define lcd_implementation_drawmenu_setting_edit_callback_float5(row, pstr, pstr2, data, minValue, maxValue, callback) lcd_implementation_drawmenu_setting_edit_generic(row, pstr, ' ', ftostr5(*(data))) -#define lcd_implementation_drawmenu_setting_edit_callback_float52_selected(row, pstr, pstr2, data, minValue, maxValue, callback) lcd_implementation_drawmenu_setting_edit_generic(row, pstr, '>', ftostr52(*(data))) -#define lcd_implementation_drawmenu_setting_edit_callback_float52(row, pstr, pstr2, data, minValue, maxValue, callback) lcd_implementation_drawmenu_setting_edit_generic(row, pstr, ' ', ftostr52(*(data))) -#define lcd_implementation_drawmenu_setting_edit_callback_float51_selected(row, pstr, pstr2, data, minValue, maxValue, callback) lcd_implementation_drawmenu_setting_edit_generic(row, pstr, '>', ftostr51(*(data))) -#define lcd_implementation_drawmenu_setting_edit_callback_float51(row, pstr, pstr2, data, minValue, maxValue, callback) lcd_implementation_drawmenu_setting_edit_generic(row, pstr, ' ', ftostr51(*(data))) -#define lcd_implementation_drawmenu_setting_edit_callback_long5_selected(row, pstr, pstr2, data, minValue, maxValue, callback) lcd_implementation_drawmenu_setting_edit_generic(row, pstr, '>', ftostr5(*(data))) -#define lcd_implementation_drawmenu_setting_edit_callback_long5(row, pstr, pstr2, data, minValue, maxValue, callback) lcd_implementation_drawmenu_setting_edit_generic(row, pstr, ' ', ftostr5(*(data))) -#define lcd_implementation_drawmenu_setting_edit_callback_bool_selected(row, pstr, pstr2, data, callback) lcd_implementation_drawmenu_setting_edit_generic_P(row, pstr, '>', (*(data))?PSTR(MSG_ON):PSTR(MSG_OFF)) -#define lcd_implementation_drawmenu_setting_edit_callback_bool(row, pstr, pstr2, data, callback) lcd_implementation_drawmenu_setting_edit_generic_P(row, pstr, ' ', (*(data))?PSTR(MSG_ON):PSTR(MSG_OFF)) - - -void lcd_implementation_drawedit(const char* pstr, char* value) -{ - lcd.setCursor(1, 1); - lcd_printPGM(pstr); - lcd.print(':'); - #if LCD_WIDTH < 20 - lcd.setCursor(LCD_WIDTH - strlen(value), 1); - #else - lcd.setCursor(LCD_WIDTH -1 - strlen(value), 1); - #endif - lcd.print(value); -} -static void lcd_implementation_drawmenu_sdfile_selected(uint8_t row, const char* pstr, const char* filename, char* longFilename) -{ - char c; - uint8_t n = LCD_WIDTH - 1; - lcd.setCursor(0, row); - lcd.print('>'); - if (longFilename[0] != '\0') - { - filename = longFilename; - longFilename[LCD_WIDTH-1] = '\0'; - } - while( ((c = *filename) != '\0') && (n>0) ) - { - lcd.print(c); - filename++; - n--; - } - while(n--) - lcd.print(' '); -} -static void lcd_implementation_drawmenu_sdfile(uint8_t row, const char* pstr, const char* filename, char* longFilename) -{ - char c; - uint8_t n = LCD_WIDTH - 1; - lcd.setCursor(0, row); - lcd.print(' '); - if (longFilename[0] != '\0') - { - filename = longFilename; - longFilename[LCD_WIDTH-1] = '\0'; - } - while( ((c = *filename) != '\0') && (n>0) ) - { - lcd.print(c); - filename++; - n--; - } - while(n--) - lcd.print(' '); -} -static void lcd_implementation_drawmenu_sddirectory_selected(uint8_t row, const char* pstr, const char* filename, char* longFilename) -{ - char c; - uint8_t n = LCD_WIDTH - 2; - lcd.setCursor(0, row); - lcd.print('>'); - lcd.print(LCD_STR_FOLDER[0]); - if (longFilename[0] != '\0') - { - filename = longFilename; - longFilename[LCD_WIDTH-2] = '\0'; - } - while( ((c = *filename) != '\0') && (n>0) ) - { - lcd.print(c); - filename++; - n--; - } - while(n--) - lcd.print(' '); -} -static void lcd_implementation_drawmenu_sddirectory(uint8_t row, const char* pstr, const char* filename, char* longFilename) -{ - char c; - uint8_t n = LCD_WIDTH - 2; - lcd.setCursor(0, row); - lcd.print(' '); - lcd.print(LCD_STR_FOLDER[0]); - if (longFilename[0] != '\0') - { - filename = longFilename; - longFilename[LCD_WIDTH-2] = '\0'; - } - while( ((c = *filename) != '\0') && (n>0) ) - { - lcd.print(c); - filename++; - n--; - } - while(n--) - lcd.print(' '); -} -#define lcd_implementation_drawmenu_back_selected(row, pstr, data) lcd_implementation_drawmenu_generic(row, pstr, LCD_STR_UPLEVEL[0], LCD_STR_UPLEVEL[0]) -#define lcd_implementation_drawmenu_back(row, pstr, data) lcd_implementation_drawmenu_generic(row, pstr, ' ', LCD_STR_UPLEVEL[0]) -#define lcd_implementation_drawmenu_submenu_selected(row, pstr, data) lcd_implementation_drawmenu_generic(row, pstr, '>', LCD_STR_ARROW_RIGHT[0]) -#define lcd_implementation_drawmenu_submenu(row, pstr, data) lcd_implementation_drawmenu_generic(row, pstr, ' ', LCD_STR_ARROW_RIGHT[0]) -#define lcd_implementation_drawmenu_gcode_selected(row, pstr, gcode) lcd_implementation_drawmenu_generic(row, pstr, '>', ' ') -#define lcd_implementation_drawmenu_gcode(row, pstr, gcode) lcd_implementation_drawmenu_generic(row, pstr, ' ', ' ') -#define lcd_implementation_drawmenu_function_selected(row, pstr, data) lcd_implementation_drawmenu_generic(row, pstr, '>', ' ') -#define lcd_implementation_drawmenu_function(row, pstr, data) lcd_implementation_drawmenu_generic(row, pstr, ' ', ' ') - -static void lcd_implementation_quick_feedback() -{ -#ifdef LCD_USE_I2C_BUZZER - lcd.buzz(60,1000/6); -#elif defined(BEEPER) && BEEPER > -1 - SET_OUTPUT(BEEPER); - for(int8_t i=0;i<10;i++) - { - WRITE(BEEPER,HIGH); - delayMicroseconds(100); - WRITE(BEEPER,LOW); - delayMicroseconds(100); - } -#endif -} - -#ifdef LCD_HAS_STATUS_INDICATORS -static void lcd_implementation_update_indicators() -{ - #if defined(LCD_I2C_PANELOLU2) || defined(LCD_I2C_VIKI) - //set the LEDS - referred to as backlights by the LiquidTWI2 library - static uint8_t ledsprev = 0; - uint8_t leds = 0; - if (target_temperature_bed > 0) leds |= LED_A; - if (target_temperature[0] > 0) leds |= LED_B; - if (fanSpeed) leds |= LED_C; - #if EXTRUDERS > 1 - if (target_temperature[1] > 0) leds |= LED_C; - #endif - if (leds != ledsprev) { - lcd.setBacklight(leds); - ledsprev = leds; - } - #endif -} -#endif - -#ifdef LCD_HAS_SLOW_BUTTONS -static uint8_t lcd_implementation_read_slow_buttons() -{ - #ifdef LCD_I2C_TYPE_MCP23017 - // Reading these buttons this is likely to be too slow to call inside interrupt context - // so they are called during normal lcd_update - return lcd.readButtons() << B_I2C_BTN_OFFSET; - #endif -} -#endif - -#endif//ULTRA_LCD_IMPLEMENTATION_HITACHI_HD44780_H +#ifndef ULTRA_LCD_IMPLEMENTATION_HITACHI_HD44780_H +#define ULTRA_LCD_IMPLEMENTATION_HITACHI_HD44780_H + +/** +* Implementation of the LCD display routines for a hitachi HD44780 display. These are common LCD character displays. +* When selecting the rusian language, a slightly different LCD implementation is used to handle UTF8 characters. +**/ + +#ifndef REPRAPWORLD_KEYPAD +extern volatile uint8_t buttons; //the last checked buttons in a bit array. +#else +extern volatile uint16_t buttons; //an extended version of the last checked buttons in a bit array. +#endif + +//////////////////////////////////// +// Setup button and encode mappings for each panel (into 'buttons' variable +// +// This is just to map common functions (across different panels) onto the same +// macro name. The mapping is independent of whether the button is directly connected or +// via a shift/i2c register. + +#ifdef ULTIPANEL +// All Ultipanels might have an encoder - so this is always be mapped onto first two bits +#define BLEN_B 1 +#define BLEN_A 0 + +#define EN_B (1< -1 + // encoder click is directly connected + #define BLEN_C 2 + #define EN_C (1< -1 + // the pause/stop/restart button is connected to BTN_ENC when used + #define B_ST (EN_C) // Map the pause/stop/resume button into its normalized functional name + #define LCD_CLICKED (buttons&(B_MI|B_RI|B_ST)) // pause/stop button also acts as click until we implement proper pause/stop. + #else + #define LCD_CLICKED (buttons&(B_MI|B_RI)) + #endif + + // I2C buttons take too long to read inside an interrupt context and so we read them during lcd_update + #define LCD_HAS_SLOW_BUTTONS + +#elif defined(LCD_I2C_PANELOLU2) + // encoder click can be read through I2C if not directly connected + #if BTN_ENC <= 0 + #define B_I2C_BTN_OFFSET 3 // (the first three bit positions reserved for EN_A, EN_B, EN_C) + + #define B_MI (PANELOLU2_ENCODER_C< + #include + #include + #define LCD_CLASS LiquidCrystal_I2C + LCD_CLASS lcd(LCD_I2C_ADDRESS,LCD_I2C_PIN_EN,LCD_I2C_PIN_RW,LCD_I2C_PIN_RS,LCD_I2C_PIN_D4,LCD_I2C_PIN_D5,LCD_I2C_PIN_D6,LCD_I2C_PIN_D7); + +#elif defined(LCD_I2C_TYPE_MCP23017) + //for the LED indicators (which maybe mapped to different things in lcd_implementation_update_indicators()) + #define LED_A 0x04 //100 + #define LED_B 0x02 //010 + #define LED_C 0x01 //001 + + #define LCD_HAS_STATUS_INDICATORS + + #include + #include + #define LCD_CLASS LiquidTWI2 + LCD_CLASS lcd(LCD_I2C_ADDRESS); + +#elif defined(LCD_I2C_TYPE_MCP23008) + #include + #include + #define LCD_CLASS LiquidTWI2 + LCD_CLASS lcd(LCD_I2C_ADDRESS); + +#elif defined(LCD_I2C_TYPE_PCA8574) + #include + #define LCD_CLASS LiquidCrystal_I2C + LCD_CLASS lcd(LCD_I2C_ADDRESS, LCD_WIDTH, LCD_HEIGHT); + +#else + // Standard directly connected LCD implementations + #if LANGUAGE_CHOICE == 6 + #include "LiquidCrystalRus.h" + #define LCD_CLASS LiquidCrystalRus + #else + #include + #define LCD_CLASS LiquidCrystal + #endif + LCD_CLASS lcd(LCD_PINS_RS, LCD_PINS_ENABLE, LCD_PINS_D4, LCD_PINS_D5,LCD_PINS_D6,LCD_PINS_D7); //RS,Enable,D4,D5,D6,D7 +#endif + +/* Custom characters defined in the first 8 characters of the LCD */ +#define LCD_STR_BEDTEMP "\x00" +#define LCD_STR_DEGREE "\x01" +#define LCD_STR_THERMOMETER "\x02" +#define LCD_STR_UPLEVEL "\x03" +#define LCD_STR_REFRESH "\x04" +#define LCD_STR_FOLDER "\x05" +#define LCD_STR_FEEDRATE "\x06" +#define LCD_STR_CLOCK "\x07" +#define LCD_STR_ARROW_RIGHT "\x7E" /* from the default character set */ + +static void lcd_implementation_init() +{ + byte bedTemp[8] = + { + B00000, + B11111, + B10101, + B10001, + B10101, + B11111, + B00000, + B00000 + }; //thanks Sonny Mounicou + byte degree[8] = + { + B01100, + B10010, + B10010, + B01100, + B00000, + B00000, + B00000, + B00000 + }; + byte thermometer[8] = + { + B00100, + B01010, + B01010, + B01010, + B01010, + B10001, + B10001, + B01110 + }; + byte uplevel[8]={ + B00100, + B01110, + B11111, + B00100, + B11100, + B00000, + B00000, + B00000 + }; //thanks joris + byte refresh[8]={ + B00000, + B00110, + B11001, + B11000, + B00011, + B10011, + B01100, + B00000, + }; //thanks joris + byte folder [8]={ + B00000, + B11100, + B11111, + B10001, + B10001, + B11111, + B00000, + B00000 + }; //thanks joris + byte feedrate [8]={ + B11100, + B10000, + B11000, + B10111, + B00101, + B00110, + B00101, + B00000 + }; //thanks Sonny Mounicou + byte clock [8]={ + B00000, + B01110, + B10011, + B10101, + B10001, + B01110, + B00000, + B00000 + }; //thanks Sonny Mounicou + +#if defined(LCDI2C_TYPE_PCF8575) + lcd.begin(LCD_WIDTH, LCD_HEIGHT); + #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); + lcd.begin(LCD_WIDTH, LCD_HEIGHT); + lcd.setBacklight(0); //set all the LEDs off to begin with + +#elif defined(LCD_I2C_TYPE_MCP23008) + lcd.setMCPType(LTI_TYPE_MCP23008); + lcd.begin(LCD_WIDTH, LCD_HEIGHT); + +#elif defined(LCD_I2C_TYPE_PCA8574) + lcd.init(); + lcd.backlight(); + +#else + lcd.begin(LCD_WIDTH, LCD_HEIGHT); +#endif + + lcd.createChar(LCD_STR_BEDTEMP[0], bedTemp); + lcd.createChar(LCD_STR_DEGREE[0], degree); + lcd.createChar(LCD_STR_THERMOMETER[0], thermometer); + lcd.createChar(LCD_STR_UPLEVEL[0], uplevel); + lcd.createChar(LCD_STR_REFRESH[0], refresh); + lcd.createChar(LCD_STR_FOLDER[0], folder); + lcd.createChar(LCD_STR_FEEDRATE[0], feedrate); + lcd.createChar(LCD_STR_CLOCK[0], clock); + lcd.clear(); +} +static void lcd_implementation_clear() +{ + lcd.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) +{ + char c; + while((c = pgm_read_byte(str++)) != '\0') + { + lcd.write(c); + } +} +/* +Possible status screens: +16x2 |0123456789012345| + |000/000 B000/000| + |Status line.....| + +16x4 |0123456789012345| + |000/000 B000/000| + |SD100% Z000.0| + |F100% T--:--| + |Status line.....| + +20x2 |01234567890123456789| + |T000/000D B000/000D | + |Status line.........| + +20x4 |01234567890123456789| + |T000/000D B000/000D | + |X+000.0 Y+000.0 Z+000.0| + |F100% SD100% T--:--| + |Status line.........| + +20x4 |01234567890123456789| + |T000/000D B000/000D | + |T000/000D Z000.0| + |F100% SD100% T--:--| + |Status line.........| +*/ +static void lcd_implementation_status_screen() +{ + int tHotend=int(degHotend(0) + 0.5); + int tTarget=int(degTargetHotend(0) + 0.5); + +#if LCD_WIDTH < 20 + lcd.setCursor(0, 0); + lcd.print(itostr3(tHotend)); + lcd.print('/'); + lcd.print(itostr3left(tTarget)); + +# if EXTRUDERS > 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 EXTRUDERS > 1 + tHotend = int(degHotend(1) + 0.5); + tTarget = int(degTargetHotend(1) + 0.5); + lcd.print(LCD_STR_THERMOMETER[0]); +# else//Heated bed + tHotend=int(degBed() + 0.5); + tTarget=int(degTargetBed() + 0.5); + lcd.print(LCD_STR_BEDTEMP[0]); +# endif + lcd.print(itostr3(tHotend)); + lcd.print('/'); + lcd.print(itostr3left(tTarget)); +# endif//EXTRUDERS > 1 || TEMP_SENSOR_BED != 0 + +#else//LCD_WIDTH > 19 + lcd.setCursor(0, 0); + lcd.print(LCD_STR_THERMOMETER[0]); + lcd.print(itostr3(tHotend)); + lcd.print('/'); + lcd.print(itostr3left(tTarget)); + lcd_printPGM(PSTR(LCD_STR_DEGREE " ")); + if (tTarget < 10) + lcd.print(' '); + +# if EXTRUDERS > 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 EXTRUDERS > 1 + tHotend = int(degHotend(1) + 0.5); + tTarget = int(degTargetHotend(1) + 0.5); + lcd.print(LCD_STR_THERMOMETER[0]); +# else//Heated bed + tHotend=int(degBed() + 0.5); + tTarget=int(degTargetBed() + 0.5); + lcd.print(LCD_STR_BEDTEMP[0]); +# endif + lcd.print(itostr3(tHotend)); + lcd.print('/'); + lcd.print(itostr3left(tTarget)); + lcd_printPGM(PSTR(LCD_STR_DEGREE " ")); + if (tTarget < 10) + lcd.print(' '); +# endif//EXTRUDERS > 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 EXTRUDERS > 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); + lcd.print('X'); + lcd.print(ftostr3(current_position[X_AXIS])); + lcd_printPGM(PSTR(" Y")); + lcd.print(ftostr3(current_position[Y_AXIS])); +# endif//EXTRUDERS > 1 || TEMP_SENSOR_BED != 0 +# endif//LCD_WIDTH > 19 + lcd.setCursor(LCD_WIDTH - 8, 1); + lcd.print('Z'); + lcd.print(ftostr32(current_position[Z_AXIS])); +#endif//LCD_HEIGHT > 2 + +#if LCD_HEIGHT > 3 + lcd.setCursor(0, 2); + lcd.print(LCD_STR_FEEDRATE[0]); + lcd.print(itostr3(feedmultiply)); + lcd.print('%'); +# if LCD_WIDTH > 19 +# ifdef SDSUPPORT + lcd.setCursor(7, 2); + lcd_printPGM(PSTR("SD")); + if (IS_SD_PRINTING) + lcd.print(itostr3(card.percentDone())); + else + lcd_printPGM(PSTR("---")); + lcd.print('%'); +# endif//SDSUPPORT +# endif//LCD_WIDTH > 19 + lcd.setCursor(LCD_WIDTH - 6, 2); + lcd.print(LCD_STR_CLOCK[0]); + if(starttime != 0) + { + uint16_t time = millis()/60000 - starttime/60000; + lcd.print(itostr2(time/60)); + lcd.print(':'); + lcd.print(itostr2(time%60)); + }else{ + lcd_printPGM(PSTR("--:--")); + } +#endif + + //Status message line on the last line + lcd.setCursor(0, LCD_HEIGHT - 1); + lcd.print(lcd_status_message); +} +static void lcd_implementation_drawmenu_generic(uint8_t row, const char* pstr, char pre_char, char post_char) +{ + char c; + //Use all characters in narrow LCDs + #if LCD_WIDTH < 20 + uint8_t n = LCD_WIDTH - 1 - 1; + #else + uint8_t n = LCD_WIDTH - 1 - 2; + #endif + lcd.setCursor(0, row); + lcd.print(pre_char); + while( ((c = pgm_read_byte(pstr)) != '\0') && (n>0) ) + { + lcd.print(c); + pstr++; + n--; + } + while(n--) + lcd.print(' '); + lcd.print(post_char); + lcd.print(' '); +} +static void lcd_implementation_drawmenu_setting_edit_generic(uint8_t row, const char* pstr, char pre_char, char* data) +{ + char c; + //Use all characters in narrow LCDs + #if LCD_WIDTH < 20 + uint8_t n = LCD_WIDTH - 1 - 1 - strlen(data); + #else + uint8_t n = LCD_WIDTH - 1 - 2 - strlen(data); + #endif + lcd.setCursor(0, row); + lcd.print(pre_char); + while( ((c = pgm_read_byte(pstr)) != '\0') && (n>0) ) + { + lcd.print(c); + pstr++; + n--; + } + lcd.print(':'); + while(n--) + lcd.print(' '); + lcd.print(data); +} +static void lcd_implementation_drawmenu_setting_edit_generic_P(uint8_t row, const char* pstr, char pre_char, const char* data) +{ + char c; + //Use all characters in narrow LCDs + #if LCD_WIDTH < 20 + uint8_t n = LCD_WIDTH - 1 - 1 - strlen_P(data); + #else + uint8_t n = LCD_WIDTH - 1 - 2 - strlen_P(data); + #endif + lcd.setCursor(0, row); + lcd.print(pre_char); + while( ((c = pgm_read_byte(pstr)) != '\0') && (n>0) ) + { + lcd.print(c); + pstr++; + n--; + } + lcd.print(':'); + while(n--) + lcd.print(' '); + lcd_printPGM(data); +} +#define lcd_implementation_drawmenu_setting_edit_int3_selected(row, pstr, pstr2, data, minValue, maxValue) lcd_implementation_drawmenu_setting_edit_generic(row, pstr, '>', itostr3(*(data))) +#define lcd_implementation_drawmenu_setting_edit_int3(row, pstr, pstr2, data, minValue, maxValue) lcd_implementation_drawmenu_setting_edit_generic(row, pstr, ' ', itostr3(*(data))) +#define lcd_implementation_drawmenu_setting_edit_float3_selected(row, pstr, pstr2, data, minValue, maxValue) lcd_implementation_drawmenu_setting_edit_generic(row, pstr, '>', ftostr3(*(data))) +#define lcd_implementation_drawmenu_setting_edit_float3(row, pstr, pstr2, data, minValue, maxValue) lcd_implementation_drawmenu_setting_edit_generic(row, pstr, ' ', ftostr3(*(data))) +#define lcd_implementation_drawmenu_setting_edit_float32_selected(row, pstr, pstr2, data, minValue, maxValue) lcd_implementation_drawmenu_setting_edit_generic(row, pstr, '>', ftostr32(*(data))) +#define lcd_implementation_drawmenu_setting_edit_float32(row, pstr, pstr2, data, minValue, maxValue) lcd_implementation_drawmenu_setting_edit_generic(row, pstr, ' ', ftostr32(*(data))) +#define lcd_implementation_drawmenu_setting_edit_float5_selected(row, pstr, pstr2, data, minValue, maxValue) lcd_implementation_drawmenu_setting_edit_generic(row, pstr, '>', ftostr5(*(data))) +#define lcd_implementation_drawmenu_setting_edit_float5(row, pstr, pstr2, data, minValue, maxValue) lcd_implementation_drawmenu_setting_edit_generic(row, pstr, ' ', ftostr5(*(data))) +#define lcd_implementation_drawmenu_setting_edit_float52_selected(row, pstr, pstr2, data, minValue, maxValue) lcd_implementation_drawmenu_setting_edit_generic(row, pstr, '>', ftostr52(*(data))) +#define lcd_implementation_drawmenu_setting_edit_float52(row, pstr, pstr2, data, minValue, maxValue) lcd_implementation_drawmenu_setting_edit_generic(row, pstr, ' ', ftostr52(*(data))) +#define lcd_implementation_drawmenu_setting_edit_float51_selected(row, pstr, pstr2, data, minValue, maxValue) lcd_implementation_drawmenu_setting_edit_generic(row, pstr, '>', ftostr51(*(data))) +#define lcd_implementation_drawmenu_setting_edit_float51(row, pstr, pstr2, data, minValue, maxValue) lcd_implementation_drawmenu_setting_edit_generic(row, pstr, ' ', ftostr51(*(data))) +#define lcd_implementation_drawmenu_setting_edit_long5_selected(row, pstr, pstr2, data, minValue, maxValue) lcd_implementation_drawmenu_setting_edit_generic(row, pstr, '>', ftostr5(*(data))) +#define lcd_implementation_drawmenu_setting_edit_long5(row, pstr, pstr2, data, minValue, maxValue) lcd_implementation_drawmenu_setting_edit_generic(row, pstr, ' ', ftostr5(*(data))) +#define lcd_implementation_drawmenu_setting_edit_bool_selected(row, pstr, pstr2, data) lcd_implementation_drawmenu_setting_edit_generic_P(row, pstr, '>', (*(data))?PSTR(MSG_ON):PSTR(MSG_OFF)) +#define lcd_implementation_drawmenu_setting_edit_bool(row, pstr, pstr2, data) lcd_implementation_drawmenu_setting_edit_generic_P(row, pstr, ' ', (*(data))?PSTR(MSG_ON):PSTR(MSG_OFF)) + +//Add version for callback functions +#define lcd_implementation_drawmenu_setting_edit_callback_int3_selected(row, pstr, pstr2, data, minValue, maxValue, callback) lcd_implementation_drawmenu_setting_edit_generic(row, pstr, '>', itostr3(*(data))) +#define lcd_implementation_drawmenu_setting_edit_callback_int3(row, pstr, pstr2, data, minValue, maxValue, callback) lcd_implementation_drawmenu_setting_edit_generic(row, pstr, ' ', itostr3(*(data))) +#define lcd_implementation_drawmenu_setting_edit_callback_float3_selected(row, pstr, pstr2, data, minValue, maxValue, callback) lcd_implementation_drawmenu_setting_edit_generic(row, pstr, '>', ftostr3(*(data))) +#define lcd_implementation_drawmenu_setting_edit_callback_float3(row, pstr, pstr2, data, minValue, maxValue, callback) lcd_implementation_drawmenu_setting_edit_generic(row, pstr, ' ', ftostr3(*(data))) +#define lcd_implementation_drawmenu_setting_edit_callback_float32_selected(row, pstr, pstr2, data, minValue, maxValue, callback) lcd_implementation_drawmenu_setting_edit_generic(row, pstr, '>', ftostr32(*(data))) +#define lcd_implementation_drawmenu_setting_edit_callback_float32(row, pstr, pstr2, data, minValue, maxValue, callback) lcd_implementation_drawmenu_setting_edit_generic(row, pstr, ' ', ftostr32(*(data))) +#define lcd_implementation_drawmenu_setting_edit_callback_float5_selected(row, pstr, pstr2, data, minValue, maxValue, callback) lcd_implementation_drawmenu_setting_edit_generic(row, pstr, '>', ftostr5(*(data))) +#define lcd_implementation_drawmenu_setting_edit_callback_float5(row, pstr, pstr2, data, minValue, maxValue, callback) lcd_implementation_drawmenu_setting_edit_generic(row, pstr, ' ', ftostr5(*(data))) +#define lcd_implementation_drawmenu_setting_edit_callback_float52_selected(row, pstr, pstr2, data, minValue, maxValue, callback) lcd_implementation_drawmenu_setting_edit_generic(row, pstr, '>', ftostr52(*(data))) +#define lcd_implementation_drawmenu_setting_edit_callback_float52(row, pstr, pstr2, data, minValue, maxValue, callback) lcd_implementation_drawmenu_setting_edit_generic(row, pstr, ' ', ftostr52(*(data))) +#define lcd_implementation_drawmenu_setting_edit_callback_float51_selected(row, pstr, pstr2, data, minValue, maxValue, callback) lcd_implementation_drawmenu_setting_edit_generic(row, pstr, '>', ftostr51(*(data))) +#define lcd_implementation_drawmenu_setting_edit_callback_float51(row, pstr, pstr2, data, minValue, maxValue, callback) lcd_implementation_drawmenu_setting_edit_generic(row, pstr, ' ', ftostr51(*(data))) +#define lcd_implementation_drawmenu_setting_edit_callback_long5_selected(row, pstr, pstr2, data, minValue, maxValue, callback) lcd_implementation_drawmenu_setting_edit_generic(row, pstr, '>', ftostr5(*(data))) +#define lcd_implementation_drawmenu_setting_edit_callback_long5(row, pstr, pstr2, data, minValue, maxValue, callback) lcd_implementation_drawmenu_setting_edit_generic(row, pstr, ' ', ftostr5(*(data))) +#define lcd_implementation_drawmenu_setting_edit_callback_bool_selected(row, pstr, pstr2, data, callback) lcd_implementation_drawmenu_setting_edit_generic_P(row, pstr, '>', (*(data))?PSTR(MSG_ON):PSTR(MSG_OFF)) +#define lcd_implementation_drawmenu_setting_edit_callback_bool(row, pstr, pstr2, data, callback) lcd_implementation_drawmenu_setting_edit_generic_P(row, pstr, ' ', (*(data))?PSTR(MSG_ON):PSTR(MSG_OFF)) + + +void lcd_implementation_drawedit(const char* pstr, char* value) +{ + lcd.setCursor(1, 1); + lcd_printPGM(pstr); + lcd.print(':'); + #if LCD_WIDTH < 20 + lcd.setCursor(LCD_WIDTH - strlen(value), 1); + #else + lcd.setCursor(LCD_WIDTH -1 - strlen(value), 1); + #endif + lcd.print(value); +} +static void lcd_implementation_drawmenu_sdfile_selected(uint8_t row, const char* pstr, const char* filename, char* longFilename) +{ + char c; + uint8_t n = LCD_WIDTH - 1; + lcd.setCursor(0, row); + lcd.print('>'); + if (longFilename[0] != '\0') + { + filename = longFilename; + longFilename[LCD_WIDTH-1] = '\0'; + } + while( ((c = *filename) != '\0') && (n>0) ) + { + lcd.print(c); + filename++; + n--; + } + while(n--) + lcd.print(' '); +} +static void lcd_implementation_drawmenu_sdfile(uint8_t row, const char* pstr, const char* filename, char* longFilename) +{ + char c; + uint8_t n = LCD_WIDTH - 1; + lcd.setCursor(0, row); + lcd.print(' '); + if (longFilename[0] != '\0') + { + filename = longFilename; + longFilename[LCD_WIDTH-1] = '\0'; + } + while( ((c = *filename) != '\0') && (n>0) ) + { + lcd.print(c); + filename++; + n--; + } + while(n--) + lcd.print(' '); +} +static void lcd_implementation_drawmenu_sddirectory_selected(uint8_t row, const char* pstr, const char* filename, char* longFilename) +{ + char c; + uint8_t n = LCD_WIDTH - 2; + lcd.setCursor(0, row); + lcd.print('>'); + lcd.print(LCD_STR_FOLDER[0]); + if (longFilename[0] != '\0') + { + filename = longFilename; + longFilename[LCD_WIDTH-2] = '\0'; + } + while( ((c = *filename) != '\0') && (n>0) ) + { + lcd.print(c); + filename++; + n--; + } + while(n--) + lcd.print(' '); +} +static void lcd_implementation_drawmenu_sddirectory(uint8_t row, const char* pstr, const char* filename, char* longFilename) +{ + char c; + uint8_t n = LCD_WIDTH - 2; + lcd.setCursor(0, row); + lcd.print(' '); + lcd.print(LCD_STR_FOLDER[0]); + if (longFilename[0] != '\0') + { + filename = longFilename; + longFilename[LCD_WIDTH-2] = '\0'; + } + while( ((c = *filename) != '\0') && (n>0) ) + { + lcd.print(c); + filename++; + n--; + } + while(n--) + lcd.print(' '); +} +#define lcd_implementation_drawmenu_back_selected(row, pstr, data) lcd_implementation_drawmenu_generic(row, pstr, LCD_STR_UPLEVEL[0], LCD_STR_UPLEVEL[0]) +#define lcd_implementation_drawmenu_back(row, pstr, data) lcd_implementation_drawmenu_generic(row, pstr, ' ', LCD_STR_UPLEVEL[0]) +#define lcd_implementation_drawmenu_submenu_selected(row, pstr, data) lcd_implementation_drawmenu_generic(row, pstr, '>', LCD_STR_ARROW_RIGHT[0]) +#define lcd_implementation_drawmenu_submenu(row, pstr, data) lcd_implementation_drawmenu_generic(row, pstr, ' ', LCD_STR_ARROW_RIGHT[0]) +#define lcd_implementation_drawmenu_gcode_selected(row, pstr, gcode) lcd_implementation_drawmenu_generic(row, pstr, '>', ' ') +#define lcd_implementation_drawmenu_gcode(row, pstr, gcode) lcd_implementation_drawmenu_generic(row, pstr, ' ', ' ') +#define lcd_implementation_drawmenu_function_selected(row, pstr, data) lcd_implementation_drawmenu_generic(row, pstr, '>', ' ') +#define lcd_implementation_drawmenu_function(row, pstr, data) lcd_implementation_drawmenu_generic(row, pstr, ' ', ' ') + +static void lcd_implementation_quick_feedback() +{ +#ifdef LCD_USE_I2C_BUZZER + lcd.buzz(60,1000/6); +#elif defined(BEEPER) && BEEPER > -1 + SET_OUTPUT(BEEPER); + for(int8_t i=0;i<10;i++) + { + WRITE(BEEPER,HIGH); + delayMicroseconds(100); + WRITE(BEEPER,LOW); + delayMicroseconds(100); + } +#endif +} + +#ifdef LCD_HAS_STATUS_INDICATORS +static void lcd_implementation_update_indicators() +{ + #if defined(LCD_I2C_PANELOLU2) || defined(LCD_I2C_VIKI) + //set the LEDS - referred to as backlights by the LiquidTWI2 library + static uint8_t ledsprev = 0; + uint8_t leds = 0; + if (target_temperature_bed > 0) leds |= LED_A; + if (target_temperature[0] > 0) leds |= LED_B; + if (fanSpeed) leds |= LED_C; + #if EXTRUDERS > 1 + if (target_temperature[1] > 0) leds |= LED_C; + #endif + if (leds != ledsprev) { + lcd.setBacklight(leds); + ledsprev = leds; + } + #endif +} +#endif + +#ifdef LCD_HAS_SLOW_BUTTONS +extern uint32_t blocking_enc; + +static uint8_t lcd_implementation_read_slow_buttons() +{ + #ifdef LCD_I2C_TYPE_MCP23017 + uint8_t slow_buttons; + // Reading these buttons this is likely to be too slow to call inside interrupt context + // so they are called during normal lcd_update + slow_buttons = lcd.readButtons() << B_I2C_BTN_OFFSET; + #if defined(LCD_I2C_VIKI) + if(slow_buttons & (B_MI|B_RI)) { //LCD clicked + if(blocking_enc > millis()) { + slow_buttons &= ~(B_MI|B_RI); // Disable LCD clicked buttons if screen is updated + } + } + #endif + return slow_buttons; + #endif +} +#endif + +#endif//ULTRA_LCD_IMPLEMENTATION_HITACHI_HD44780_H