-
-
Notifications
You must be signed in to change notification settings - Fork 19.5k
M355 case light improvements (replaces PR #5685) #6797
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
M355 case light improvements (replaces PR #5685) #6797
Conversation
I've verified that this change is 95% functional. I still need to check that the "useable PWM" routine is working 100%. I know it connects up to the 3 PWMs I've tried so far. I also need to check the PWMs on non-2560 boards. I need a pointer to an LCD menu type that gives immediate feedback as you twirl the encoder. Right now the routine is using "MENU_MULTIPLIER_ITEM_EDIT_CALLBACK(int3" which only calls the function when the encoder button is pressed. I expect the user would like to see the LED/lights dim/brighten as they twirl the knob. |
Let me provide a 'realtime' edit macro for you… hold on… |
#6810 adds a flag to do live editing. When this flag is set to #if HAS_LCD_CONTRAST
void lcd_callback_set_contrast() { set_lcd_contrast(lcd_contrast); }
#endif // HAS_LCD_CONTRAST
. . .
#if HAS_LCD_CONTRAST
MENU_ITEM_EDIT_CALLBACK(int3, MSG_CONTRAST, &lcd_contrast, 0, 63,
lcd_callback_set_contrast, true);
#endif |
@thinkyhead - thanks. The live update works nicely. |
Marlin/Marlin_main.cpp
Outdated
@@ -176,7 +176,7 @@ | |||
* M304 - Set bed PID parameters P I and D. (Requires PIDTEMPBED) | |||
* M350 - Set microstepping mode. (Requires digital microstepping pins.) | |||
* M351 - Toggle MS1 MS2 pins directly. (Requires digital microstepping pins.) | |||
* M355 - Turn the Case Light on/off and set its brightness. (Requires CASE_LIGHT_PIN) | |||
* M355 - Sets Case Light brightness. (Requires CASE_LIGHT_PIN) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
For consistency, please phrase descriptions of G-codes as if they are prefaced with "This item will…" and not "This item…".
BAD: "Sets the frequency to 100 and opens the valve"
GOOD: "Set the frequency to 100 and open the valve"
I'm adding this guideline and others to the code and documentation style guides under construction. In general, just imitate the existing styles. Try to camouflage your code so it looks like it was always there.
Marlin/Marlin_main.cpp
Outdated
#endif | ||
uint8_t case_light_brightness; | ||
|
||
void update_case_light() { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Indent by 2 spaces.
Marlin/Marlin_main.cpp
Outdated
#else | ||
SERIAL_PROTOCOLLNPGM("Cap:TOGGLE_LIGHTS:0"); | ||
SERIAL_PROTOCOLLNPGM("Cap:CASE_LIGHT_BRIGHTNESS:0"); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@repetier Have you already been following this? I already documented Cap:TOGGLE_LIGHTS
on the RepRap wiki so maybe you already incorporated it…? Sorry there's so much mucking with these things immediately after release. I thought these features were more developed.
@Bob-the-Kuhn I'm not in agreement with dropping the separate on/off function. I think it makes good sense to keep them separate, so that the light may be toggled off and on without needing to specify a brightness every time. Imagine a case light interface in which rotating the dial sets the brightness, while clicking toggles the on/off state. When toggling that on/off state, it should retain the brightness that was last set.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No I was not following this. This change is not good as you say it is not possible to toggle light on/off. Server e.g. detects Cap:TOGGLE_LIGHTS and if not present you can not control lights in interface. Currently We use only S0/S1 to toggle light on/off which is what this capability defines. g as you can still toggle it - and I would like to see it continued to work, you should still send Cap:TOGGLE_LIGHTS:1
The fact that you can adjust brightness is an additional feature, so if that is the case add the capability. That way if server ever learns to adjust brightness it can detect it and until then it will just toggle and user has to manually adjust brightness.
Also PLEASE keep S0/1 for toggle and not switch to T0/1 - hosts use S and is just a pain if such things change knowing there are 100 forks having S still then.
Marlin/Marlin_main.cpp
Outdated
if (!useable_hardware_PWM(CASE_LIGHT_PIN)) { | ||
SERIAL_ECHO_START; | ||
SERIAL_ECHOPGM("Case lights "); | ||
(case_light_brightness >= CASE_LIGHT_THRESHOLD) ? SERIAL_ECHOLNPGM("on") : SERIAL_ECHOLNPGM("off"); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
serialprintPGM(case_light_brightness >= CASE_LIGHT_THRESHOLD ? PSTR("on") : PSTR("off"));
Marlin/Marlin_main.cpp
Outdated
SERIAL_ECHOPGM("Case lights "); | ||
(case_light_brightness >= CASE_LIGHT_THRESHOLD) ? SERIAL_ECHOLNPGM("on") : SERIAL_ECHOLNPGM("off"); | ||
} | ||
else SERIAL_PROTOCOLLNPAIR("echo:Case lights ", case_light_brightness); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Just use SERIAL_ECHO_START
. Don't preface with another echo:
.
Marlin/ultralcd.cpp
Outdated
@@ -3489,6 +3487,7 @@ void kill_screen(const char* lcd_msg) { | |||
ENCODER_DIRECTION_NORMAL(); \ | |||
if ((int32_t)encoderPosition < 0) encoderPosition = 0; \ | |||
if ((int32_t)encoderPosition > maxEditValue) encoderPosition = maxEditValue; \ | |||
bool do_it_live = liveEdit;\ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please remove this line. I thought I got it in the conflict resolution I just did, but apparently not.
Marlin/ultralcd.cpp
Outdated
else | ||
MENU_ITEM(function, MSG_LIGHTS_ON, toggle_case_light); | ||
case_light_brightness_int = case_light_brightness; | ||
MENU_ITEM_EDIT_CALLBACK(int3, MSG_CASE_LIGHTS, &case_light_brightness_int, 0, 255,case_light_level, true); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Reduce indentation by 2 spaces. Insert 1 space after 255,
.
Marlin/language_en.h
Outdated
#ifndef MSG_LIGHTS_ON | ||
#define MSG_LIGHTS_ON _UxGT("Case light on") | ||
#ifndef MSG_CASE_LIGHTS | ||
#define MSG_CASE_LIGHTS _UxGT("Case lights") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
"Case light" is the more colloquial usage (even if you have 2 or more bulbs).
I'll implement all the above, including the on/off function. |
I just looked at the RepRap wiki & it doesn't mention variable intensity. Looks like we'll need to modify it. I'm not a fan of changing published documentation. Either we change the documentation or we drop the variable intensity. I'd rather change the documentation in this case. The issues/questions I see are:
My preference is to make M355 as close to the current M42 as possible (S0-255 with the on/off (non PWM) function at 127/128). The code would have one variable for intensity and one variable for on/off. I definitely want to hear from the Repetier folks on this. I'll put together the LCD menu that implements:
|
Does adding a parameter just for the on/off function help? I'm wondering if the following is useful: Both S and T could be in the g-code at the same time. |
As long as I'm playing - how about changing the power on default from on/off to 0-255? |
@Bob-the-Kuhn Please keep S0/1 for on off. It is not the documentation that needs to be changed but also all host softwares using this already! |
How about this?
I added a toggle function. Keep it or get rid of it? |
Quite good but for case of non pwm for brightness P should simply have no function. On and off is already defined. No need to add a case where setting P also has the S function if S is omitted. |
|
@thinkyhead - right now it says Cap:CASE_LIGHT_BRIGHTNESS:1. Do you want me to change it back to TOGGLE and add a toggle function? If you do want a toggle function I'm thinking "S" with no value after it would do the toggle. |
M355 S1/0 is the toggle function, so you should put back |
Is this what you had in mind? // CASE LIGHTS (M355)
#if HAS_CASE_LIGHT
SERIAL_PROTOCOLLNPGM("Cap:TOGGLE_LIGHTS:1");
bool useable_hardware_PWM(uint8_t pin);
if(useable_hardware_PWM(CASE_LIGHT_PIN)) {
SERIAL_PROTOCOLLNPGM("Cap:CASE_LIGHT_BRIGHTNESS:1");
}
else
SERIAL_PROTOCOLLNPGM("Cap:CASE_LIGHT_BRIGHTNESS:0");
#else
SERIAL_PROTOCOLLNPGM("Cap:TOGGLE_LIGHTS:0");
SERIAL_PROTOCOLLNPGM("Cap:CASE_LIGHT_BRIGHTNESS:0");
#endif |
Something like that will work. Is that evaluated at compile-time? If the |
@@ -2487,7 +2513,7 @@ void kill_screen(const char* lcd_msg) { | |||
MENU_ITEM(submenu, MSG_FILAMENT, lcd_control_filament_menu); | |||
|
|||
#if HAS_LCD_CONTRAST | |||
MENU_ITEM_EDIT_CALLBACK(int3, MSG_CONTRAST, &lcd_contrast, LCD_CONTRAST_MIN, LCD_CONTRAST_MAX, lcd_callback_set_contrast, true); | |||
MENU_ITEM_EDIT_CALLBACK(int3, MSG_CONTRAST, (int) &lcd_contrast, LCD_CONTRAST_MIN, LCD_CONTRAST_MAX, lcd_callback_set_contrast, true); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
An address should not be cast to an int
, but an int*
.
Marlin/ultralcd.cpp
Outdated
MENU_ITEM_EDIT_CALLBACK(int3, MSG_CASE_LIGHT_BRIGHTNESS, &case_light_brightness_int, 0, 255, level_case_light, true); | ||
} | ||
MENU_ITEM(function, MSG_CASE_LIGHT_ON, on_case_light); | ||
MENU_ITEM(function, MSG_CASE_LIGHT_OFF, off_case_light); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actually, this is even better:
MENU_ITEM_EDIT_CALLBACK(bool, MSG_CASE_LIGHT, &case_light_on, update_case_light);
…then no other functions are needed for toggling.
Marlin/language_en.h
Outdated
#define MSG_CASE_LIGHT_OFF _UxGT("Light OFF") | ||
#endif | ||
#ifndef MSG_CASE_LIGHT_TOGGLE | ||
#define MSG_CASE_LIGHT_TOGGLE _UxGT("Light TOGGLE") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This string doesn't seem to be used anymore.
Marlin/language_en.h
Outdated
#endif | ||
#ifndef MSG_CASE_LIGHT_OFF | ||
#define MSG_CASE_LIGHT_OFF _UxGT("Light OFF") | ||
#endif |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
These on/off messages can go away by using the bool callback below. "On" and "Off" will be automatically shown and translated.
@@ -665,6 +671,7 @@ | |||
#define UBL_MESH_MAX_Y (Y_MAX_POS - (UBL_MESH_INSET)) | |||
#endif | |||
|
|||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Extra line fell in.
@Bob-the-Kuhn Yes that is the solution I mean. |
@thinkyhead - I've implemented all of the requested changes. The LCD menu changes were pretty straight forward. Changing the USEABLE_HARDWARE_PWM function to a series of macros may not be implemented the way you expected. 75% of the macros you see are involved in checking that other functions have not already grabbed the PWM. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Functionally, looks fine. Just some tweaks needed, and decide on a better home for the PWM macros.
Marlin/Conditionals_post.h
Outdated
#error "unknown CPU" | ||
#endif | ||
|
||
#define USEABLE_HARDWARE_PWM(p) (PWM_PINS(p) && !PWM_CHK(p)) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Let's add these kinds of macros to the fastio.h
and HAL suite and limit things in the Conditionals.h
files to things which change depending on user configuration.
Marlin/Marlin_main.cpp
Outdated
#if HAS_CASE_LIGHT | ||
SERIAL_PROTOCOLLNPGM("Cap:TOGGLE_LIGHTS:1"); | ||
bool USEABLE_HARDWARE_PWM(uint8_t pin); | ||
if(USEABLE_HARDWARE_PWM(CASE_LIGHT_PIN)) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
One space between if
and the opening parenthesis, please.
Marlin/Marlin_main.cpp
Outdated
pinMode(CASE_LIGHT_PIN, OUTPUT); // digitalWrite doesn't set the port mode | ||
uint8_t case_light_bright = (uint8_t)case_light_brightness; | ||
if (case_light_on) { | ||
if(USEABLE_HARDWARE_PWM(CASE_LIGHT_PIN)) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
if *space* (
Marlin/Marlin_main.cpp
Outdated
if (parser.seen('S')) { | ||
if (parser.has_value()) { case_light_on = parser.value_bool();} | ||
update_case_light(); | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
uint8_t args = 0;
if (parser.seen('P')) ++args, case_light_brightness = parser.value_byte();
if (parser.seen('S')) ++args, case_light_on = parser.value_bool(); // S by itself = S1
if (args) update_case_light();
Marlin/Marlin_main.cpp
Outdated
SERIAL_ECHOLN("Case light: off"); | ||
} | ||
else { | ||
if (!USEABLE_HARDWARE_PWM(CASE_LIGHT_PIN)) {SERIAL_ECHOLN("Case light: on"); } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No braces needed around SERIAL_ECHOLN
. The macro is wrapped in do{}while(0)
.
I reckon we could probably make a nice class to manage all the PWMs. I made a nice function specifically for Timer5 that works pretty well. Check it out… /**
* Set Timer 5 PWM frequency in Hz, from 3.8Hz up to ~16MHz
* with a minimum resolution of 100 steps.
*/
uint16_t set_pwm_frequency_hz(const float &hz, const float dca, const float dcb, const float dcc) {
float count = 0;
if (hz > 0 && (dca || dcb || dcc)) {
count = float(F_CPU) / hz; // 1x prescaler, TOP for 16MHz base freq.
uint16_t prescaler; // Range of 30.5Hz (65535) 64.5KHz (>31)
if (count >= 255. * 256.) { prescaler = 1024; SET_CS(5, PRESCALER_1024); }
else if (count >= 255. * 64.) { prescaler = 256; SET_CS(5, PRESCALER_256); }
else if (count >= 255. * 8.) { prescaler = 64; SET_CS(5, PRESCALER_64); }
else if (count >= 255.) { prescaler = 8; SET_CS(5, PRESCALER_8); }
else { prescaler = 1; SET_CS(5, PRESCALER_1); }
count /= float(prescaler);
pwm_top = round(count); // Get the rounded count
ICR5 = (uint16_t)pwm_top - 1; // Subtract 1 for TOP
OCR5A = pwm_top * abs(dca); // Update and scale DCs
OCR5B = pwm_top * abs(dcb);
OCR5C = pwm_top * abs(dcc);
_SET_COM(5, A, dca ? (dca < 0 ? COM_SET_CLEAR : COM_CLEAR_SET) : COM_NORMAL); // Set compare modes
_SET_COM(5, B, dcb ? (dcb < 0 ? COM_SET_CLEAR : COM_CLEAR_SET) : COM_NORMAL);
_SET_COM(5, C, dcc ? (dcc < 0 ? COM_SET_CLEAR : COM_CLEAR_SET) : COM_NORMAL);
SET_WGM(5, FAST_PWM_ICRn); // Fast PWM with ICR5 as TOP
//SERIAL_ECHOLNPGM("Timer 5 Settings:");
//SERIAL_ECHOLNPAIR(" Prescaler=", prescaler);
//SERIAL_ECHOLNPAIR(" TOP=", ICR5);
//SERIAL_ECHOLNPAIR(" OCR5A=", OCR5A);
//SERIAL_ECHOLNPAIR(" OCR5B=", OCR5B);
//SERIAL_ECHOLNPAIR(" OCR5C=", OCR5C);
}
else {
// Restore the default for Timer 5
SET_WGM(5, PWM_PC_8); // PWM 8-bit (Phase Correct)
SET_COMS(5, NORMAL, NORMAL, NORMAL); // Do nothing
SET_CS(5, PRESCALER_64); // 16MHz / 64 = 250KHz
OCR5A = OCR5B = OCR5C = 0;
}
return round(count);
} |
All requested changes have been made. |
============================== Configuration_adv.h changes ============================== add "live" LCD update ============================== P & S version ============================== final (hopefully) tested version ============================== update M115 capabilities print ============================== Menu changes portion of the requested changes ============================== changed USEABLE_HARDWARE_PWM from a function to a series of macros ============================== changes per review
This PR is a 1.1x version of PR #5685.
Initial load is just of the functional files. The Configuration_adv.h changes will be uploaded shortly.
This code has not been tested.
This code currently is modelled after the M42 command:
M355 Sxxx - xxx varies from 0-255, on/off for digital pins is 127/128
There have been discussions about using the following methods: