Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Extend RGB LED with Printer Events #6240

Merged
merged 6 commits into from
Apr 11, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions Marlin/Conditionals_LCD.h
Original file line number Diff line number Diff line change
Expand Up @@ -385,5 +385,7 @@
#endif

#define HAS_SOFTWARE_ENDSTOPS (ENABLED(MIN_SOFTWARE_ENDSTOPS) || ENABLED(MAX_SOFTWARE_ENDSTOPS))
#define HAS_RESUME_CONTINUE (ENABLED(NEWPANEL) || ENABLED(EMERGENCY_PARSER))
#define HAS_COLOR_LEDS (ENABLED(BLINKM) || ENABLED(RGB_LED) || ENABLED(RGBW_LED))

#endif //CONDITIONALS_LCD_H
37 changes: 35 additions & 2 deletions Marlin/Configuration.h
Original file line number Diff line number Diff line change
Expand Up @@ -1514,12 +1514,45 @@
//define BlinkM/CyzRgb Support
//#define BLINKM

// Support for an RGB LED using 3 separate pins with optional PWM
/**
* RGB LED / LED Strip Control
*
* Enable support for an RGB LED connected to 5V digital pins, or
* an RGB Strip connected to MOSFETs controlled by digital pins.
*
* Adds the M150 command to set the LED (or LED strip) color.
* If pins are PWM capable (e.g., 4, 5, 6, 11) then a range of
* luminance values can be set from 0 to 255.
*
* *** CAUTION ***
* LED Strips require a MOFSET Chip between PWM lines and LEDs,
* as the Arduino cannot handle the current the LEDs will require.
* Failure to follow this precaution can destroy your Arduino!
* *** CAUTION ***
*
*/
//#define RGB_LED
#if ENABLED(RGB_LED)
//#define RGBW_LED
#if ENABLED(RGB_LED) || ENABLED(RGBW_LED)
#define RGB_LED_R_PIN 34
#define RGB_LED_G_PIN 43
#define RGB_LED_B_PIN 35
#define RGB_LED_W_PIN -1
#endif

/**
* Printer Event LEDs
*
* During printing, the LEDs will reflect the printer status:
*
* - Gradually change from blue to violet as the heated bed gets to target temp
* - Gradually change from violet to red as the hotend gets to temperature
* - Change to white to illuminate work surface
* - Change to green once print has finished
* - Turn off after the print has finished and the user has pushed a button
*/
#if ENABLED(BLINKM) || ENABLED(RGB_LED) || ENABLED(RGBW_LED)
#define PRINTER_EVENT_LEDS
#endif

/*********************************************************************\
Expand Down
2 changes: 1 addition & 1 deletion Marlin/Marlin.h
Original file line number Diff line number Diff line change
Expand Up @@ -221,7 +221,7 @@ extern bool axis_known_position[XYZ]; // axis[n].is_known
extern bool axis_homed[XYZ]; // axis[n].is_homed
extern volatile bool wait_for_heatup;

#if ENABLED(EMERGENCY_PARSER) || ENABLED(ULTIPANEL)
#if HAS_RESUME_CONTINUE
extern volatile bool wait_for_user;
#endif

Expand Down
155 changes: 111 additions & 44 deletions Marlin/Marlin_main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -443,7 +443,7 @@ static bool relative_mode = false;
volatile bool wait_for_heatup = true;

// For M0/M1, this flag may be cleared (by M108) to exit the wait-for-user loop
#if ENABLED(EMERGENCY_PARSER) || ENABLED(ULTIPANEL)
#if HAS_RESUME_CONTINUE
volatile bool wait_for_user = false;
#endif

Expand Down Expand Up @@ -945,6 +945,41 @@ void servo_init() {

#endif

#if HAS_COLOR_LEDS

void set_led_color(
const uint8_t r, const uint8_t g, const uint8_t b
#if ENABLED(RGBW_LED)
, const uint8_t w=0
#endif
) {

#if ENABLED(BLINKM)

// This variant uses i2c to send the RGB components to the device.
SendColors(r, g, b);

#else

// This variant uses 3 separate pins for the RGB components.
// If the pins can do PWM then their intensity will be set.
digitalWrite(RGB_LED_R_PIN, r ? HIGH : LOW);
digitalWrite(RGB_LED_G_PIN, g ? HIGH : LOW);
digitalWrite(RGB_LED_B_PIN, b ? HIGH : LOW);
analogWrite(RGB_LED_R_PIN, r);
analogWrite(RGB_LED_G_PIN, g);
analogWrite(RGB_LED_B_PIN, b);

#if ENABLED(RGBW_LED)
digitalWrite(RGB_LED_W_PIN, w ? HIGH : LOW);
analogWrite(RGB_LED_W_PIN, w);
#endif

#endif
}

#endif // HAS_COLOR_LEDS

void gcode_line_error(const char* err, bool doFlush = true) {
SERIAL_ERROR_START;
serialprintPGM(err);
Expand Down Expand Up @@ -1129,6 +1164,19 @@ inline void get_serial_commands() {
if (card_eof) {
SERIAL_PROTOCOLLNPGM(MSG_FILE_PRINTED);
card.printingHasFinished();
#if ENABLED(PRINTER_EVENT_LEDS)
LCD_MESSAGEPGM(MSG_INFO_COMPLETED_PRINTS);
set_led_color(0, 255, 0); // Green
#if HAS_RESUME_CONTINUE
KEEPALIVE_STATE(PAUSED_FOR_USER);
wait_for_user = true;
while (wait_for_user) idle();
KEEPALIVE_STATE(IN_HANDLER);
#else
safe_delay(1000);
#endif
set_led_color(0, 0, 0); // OFF
#endif
card.checkautostart(true);
}
else if (n == -1) {
Expand Down Expand Up @@ -4967,7 +5015,7 @@ inline void gcode_G92() {
report_current_position();
}

#if ENABLED(EMERGENCY_PARSER) || ENABLED(ULTIPANEL)
#if HAS_RESUME_CONTINUE

/**
* M0: Unconditional stop - Wait for user button press on LCD
Expand Down Expand Up @@ -5504,7 +5552,7 @@ inline void gcode_M42() {
pin_state[pin - first_pin] = digitalRead(pin);
}

#if ENABLED(EMERGENCY_PARSER) || ENABLED(ULTIPANEL)
#if HAS_RESUME_CONTINUE
wait_for_user = true;
#endif

Expand All @@ -5522,7 +5570,7 @@ inline void gcode_M42() {
}
}

#if ENABLED(EMERGENCY_PARSER) || ENABLED(ULTIPANEL)
#if HAS_RESUME_CONTINUE
if (!wait_for_user) break;
#endif

Expand Down Expand Up @@ -5692,8 +5740,8 @@ inline void gcode_M42() {
// If we have gone out too far, we can do a simple fix and scale the numbers
// back in closer to the origin.
while (HYPOT(X_current, Y_current) > DELTA_PROBEABLE_RADIUS) {
X_current /= 1.25;
Y_current /= 1.25;
X_current *= 0.8;
Y_current *= 0.8;
if (verbose_level > 3) {
SERIAL_ECHOPAIR("Pulling point towards center:", X_current);
SERIAL_ECHOLNPAIR(", ", Y_current);
Expand Down Expand Up @@ -6077,18 +6125,23 @@ inline void gcode_M109() {
#define TEMP_CONDITIONS (wants_to_cool ? thermalManager.isCoolingHotend(target_extruder) : thermalManager.isHeatingHotend(target_extruder))
#endif

float theTarget = -1.0, old_temp = 9999.0;
float target_temp = -1.0, old_temp = 9999.0;
bool wants_to_cool = false;
wait_for_heatup = true;
millis_t now, next_temp_ms = 0, next_cool_check_ms = 0;

KEEPALIVE_STATE(NOT_BUSY);

#if ENABLED(PRINTER_EVENT_LEDS)
const float start_temp = thermalManager.degHotend(target_extruder);
uint8_t old_blue = 0;
#endif

do {
// Target temperature might be changed during the loop
if (theTarget != thermalManager.degTargetHotend(target_extruder)) {
if (target_temp != thermalManager.degTargetHotend(target_extruder)) {
wants_to_cool = thermalManager.isCoolingHotend(target_extruder);
theTarget = thermalManager.degTargetHotend(target_extruder);
target_temp = thermalManager.degTargetHotend(target_extruder);

// Exit if S<lower>, continue if S<higher>, R<lower>, or R<higher>
if (no_wait_for_cooling && wants_to_cool) break;
Expand All @@ -6115,11 +6168,19 @@ inline void gcode_M109() {
idle();
refresh_cmd_timeout(); // to prevent stepper_inactive_time from running out

float temp = thermalManager.degHotend(target_extruder);
const float temp = thermalManager.degHotend(target_extruder);

#if ENABLED(PRINTER_EVENT_LEDS)
// Gradually change LED strip from violet to red as nozzle heats up
if (!wants_to_cool) {
const uint8_t blue = map(constrain(temp, start_temp, target_temp), start_temp, target_temp, 255, 0);
if (blue != old_blue) set_led_color(255, 0, (old_blue = blue));
}
#endif

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

    #if ENABLED(PRINTER_EVENT_LEDS)
      // Gradually change LED strip from violet to red as nozzle heats up
      if (wait_for_heatup && !wants_to_cool) {
        const uint8_t blue = map(constrain(temp, start_temp, target_temp), start_temp, target_temp, 255, 0);
        if (blue == old_blue) set_led_color(255, 0, 255);   //Purple to start
        if (blue != old_blue) set_led_color(255, 0, blue);  //Start transitioning to Red
      }
    #endif

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd generally reduce those two lines down to one:

set_led_color(255, 0, blue == old_blue ? 255 : blue);

…but they are incorrect. First of all, old_blue is not being set to blue when it differs. Secondly, with that correction made, blue == old_blue will evaluate true most of the time.

#if TEMP_RESIDENCY_TIME > 0

float temp_diff = fabs(theTarget - temp);
const float temp_diff = fabs(target_temp - temp);

if (!residency_start_ms) {
// Start the TEMP_RESIDENCY_TIME timer when we reach target temp for the first time.
Expand All @@ -6145,7 +6206,16 @@ inline void gcode_M109() {

} while (wait_for_heatup && TEMP_CONDITIONS);

if (wait_for_heatup) LCD_MESSAGEPGM(MSG_HEATING_COMPLETE);
if (wait_for_heatup) {
LCD_MESSAGEPGM(MSG_HEATING_COMPLETE);
#if ENABLED(PRINTER_EVENT_LEDS)
#if ENABLED(RGBW_LED)
set_led_color(0, 0, 0, 255); // Turn on the WHITE LED
#else
set_led_color(255, 255, 255); // Set LEDs All On
#endif
#endif
}

KEEPALIVE_STATE(IN_HANDLER);
}
Expand Down Expand Up @@ -6186,7 +6256,7 @@ inline void gcode_M109() {
#define TEMP_BED_CONDITIONS (wants_to_cool ? thermalManager.isCoolingBed() : thermalManager.isHeatingBed())
#endif

float theTarget = -1.0, old_temp = 9999.0;
float target_temp = -1.0, old_temp = 9999.0;
bool wants_to_cool = false;
wait_for_heatup = true;
millis_t now, next_temp_ms = 0, next_cool_check_ms = 0;
Expand All @@ -6195,11 +6265,16 @@ inline void gcode_M109() {

target_extruder = active_extruder; // for print_heaterstates

#if ENABLED(PRINTER_EVENT_LEDS)
const float start_temp = thermalManager.degBed();
uint8_t old_red = 255;
#endif

do {
// Target temperature might be changed during the loop
if (theTarget != thermalManager.degTargetBed()) {
if (target_temp != thermalManager.degTargetBed()) {
wants_to_cool = thermalManager.isCoolingBed();
theTarget = thermalManager.degTargetBed();
target_temp = thermalManager.degTargetBed();

// Exit if S<lower>, continue if S<higher>, R<lower>, or R<higher>
if (no_wait_for_cooling && wants_to_cool) break;
Expand All @@ -6226,11 +6301,20 @@ inline void gcode_M109() {
idle();
refresh_cmd_timeout(); // to prevent stepper_inactive_time from running out

float temp = thermalManager.degBed();
const float temp = thermalManager.degBed();

#if ENABLED(PRINTER_EVENT_LEDS)
// Gradually change LED strip from blue to violet as bed heats up
if (!wants_to_cool) {
const uint8_t red = map(constrain(temp, start_temp, target_temp), start_temp, target_temp, 0, 255);
if (red != old_red) set_led_color((old_red = red), 0, 255);
}
}
#endif
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

      #if ENABLED(PRINTER_EVENT_LEDS)
        // Gradually change LED strip from blue to violet as bed heats up
        if (wait_for_heatup && !wants_to_cool) {
          const uint8_t red = map(constrain(temp, start_temp, target_temp), start_temp, target_temp, 0, 255);
          if (red == old_red) set_led_color(0, 0, 255);     //Blue to start
          if (red != old_red) set_led_color(red, 0, 255);   //Start transitioning to Purple
        }
      #endif


#if TEMP_BED_RESIDENCY_TIME > 0

float temp_diff = fabs(theTarget - temp);
const float temp_diff = fabs(target_temp - temp);

if (!residency_start_ms) {
// Start the TEMP_BED_RESIDENCY_TIME timer when we reach target temp for the first time.
Expand Down Expand Up @@ -6771,47 +6855,30 @@ inline void gcode_M121() { endstops.enable_globally(false); }

#endif // PARK_HEAD_ON_PAUSE

#if ENABLED(BLINKM) || ENABLED(RGB_LED)

void set_led_color(const uint8_t r, const uint8_t g, const uint8_t b) {

#if ENABLED(BLINKM)

// This variant uses i2c to send the RGB components to the device.
SendColors(r, g, b);

#else

// This variant uses 3 separate pins for the RGB components.
// If the pins can do PWM then their intensity will be set.
digitalWrite(RGB_LED_R_PIN, r ? HIGH : LOW);
digitalWrite(RGB_LED_G_PIN, g ? HIGH : LOW);
digitalWrite(RGB_LED_B_PIN, b ? HIGH : LOW);
analogWrite(RGB_LED_R_PIN, r);
analogWrite(RGB_LED_G_PIN, g);
analogWrite(RGB_LED_B_PIN, b);

#endif
}
#if HAS_COLOR_LEDS

/**
* M150: Set Status LED Color - Use R-U-B for R-G-B
* M150: Set Status LED Color - Use R-U-B-W for R-G-B-W
*
* Always sets all 3 components. If a component is left out, set to 0.
* Always sets all 3 or 4 components. If a component is left out, set to 0.
*
* Examples:
*
* M150 R255 ; Turn LED red
* M150 R255 U127 ; Turn LED orange (PWM only)
* M150 ; Turn LED off
* M150 R U B ; Turn LED white
* M150 W ; Turn LED white using a white LED
*
*/
inline void gcode_M150() {
set_led_color(
code_seen('R') ? (code_has_value() ? code_value_byte() : 255) : 0,
code_seen('U') ? (code_has_value() ? code_value_byte() : 255) : 0,
code_seen('B') ? (code_has_value() ? code_value_byte() : 255) : 0
#if ENABLED(RGBW_LED)
, code_seen('W') ? (code_has_value() ? code_value_byte() : 255) : 0
#endif
);
}

Expand Down Expand Up @@ -8266,7 +8333,7 @@ inline void gcode_M503() {

inline void gcode_M605() {
stepper.synchronize();
extruder_duplication_enabled = code_seen('S') && code_value_int() == 2;
extruder_duplication_enabled = code_seen('S') && code_value_int() == (int)DXC_DUPLICATION_MODE;
SERIAL_ECHO_START;
SERIAL_ECHOLNPAIR(MSG_DUPLICATION_MODE, extruder_duplication_enabled ? MSG_ON : MSG_OFF);
}
Expand Down Expand Up @@ -9139,7 +9206,7 @@ void process_next_command() {
break;

case 'M': switch (codenum) {
#if ENABLED(ULTIPANEL) || ENABLED(EMERGENCY_PARSER)
#if HAS_RESUME_CONTINUE
case 0: // M0: Unconditional stop - Wait for user button press on LCD
case 1: // M1: Conditional stop - Wait for user button press on LCD
gcode_M0_M1();
Expand Down Expand Up @@ -9388,7 +9455,7 @@ void process_next_command() {
break;
#endif

#if ENABLED(BLINKM) || ENABLED(RGB_LED)
#if HAS_COLOR_LEDS

case 150: // M150: Set Status LED Color
gcode_M150();
Expand Down
Loading