Klipper3d / klipper

Klipper is a 3d-printer firmware
GNU General Public License v3.0
9.41k stars 5.3k forks source link

Basic menu support (beta) #404

Closed mcmatrix closed 6 years ago

mcmatrix commented 6 years ago

Hi guys,

I wanted to inform you that I'm working on a simple menu system for klipper. I already have working mockup and now I'm trying to fit it into Klippers system.

The menu structure is fully configurable via config file. Menu is working on different screens, 2x16, 4x20 and on graphics displays. It's a text based menu system. You just have to specify correct cols and rows.

It has 3 basic menu elements:

All submenus have first item as "go back". System inserts it automatically.

You can define klipper system predefined variables in args attribute. In menu item name you can use variables list defined in args as standard print format options. For navigation only 3 buttons is needed: UP, DOWN, SELECT

When menu item (only input item) is in edit mode then system shows asterisk and UP & DOWN will change value accordingly. Currently only float value type is supported. Pressing SELECT again will exit from edit mode and will execute GCODE (value is given as print format first element).

I tried to make flexible way for adding dynamic data into name and gcode. There is attribute parameter: endstop.xmax:b["OPEN", "TRIG"] In Klipper there's collection of status info from all modules. First part endstop.xmax of attribute value is value key of that collection. Second part :b["OPEN", "TRIG"] of attribute value is additional way for mapping value to list or dict. : is delimiter b is boolean typecast for value. Other casting types are: f - float, i - int, b - bool, s - str ["OPEN", "TRIG"] is literal presentation of python list. List and Dict are allowed. Python will use safe method to turn it into real dataset.

You don't have to use mapping options all the time. In most cases it's not needed and just parameter with simple value key parameter: fan.speed will do.

When preparing name or gcode then you're able to use pyhton advanced string formatting possibilities. Value is avalilable as {0} and mapped option as {1}. If there's error condition in conversion or just wrong data type then raw name or gcode string is used instead of formatted one.

Changeable input is using value and can only be float type. But in name and gcode you can use mapped one if needed.

Menu manager config

[menu]
root: main1     # mandatory
rows: 4         # mandatory
cols: 20        # mandatory

Group menu item config

[menu main1]
type: group                 # mandatory
name: Main menu             # mandatory
enter_gcode:                # optional
leave_gcode:                # optional
items: menu1, menu2, menu3  # mandatory

Menu item with action

[menu menu1]
type: command                        # mandatory
name: Fan speed: {0:d}               # mandatory
parameter: fan.speed                 # optional

[menu menu2]
type: command          # mandatory
name: Pause octoprint  # mandatory
gcode: @//pause        # optional

[menu menu3]
type: command      # mandatory
name: Kill me      # mandatory
gcode: M112        # optional

[menu menu1]
type: command                               # mandatory
name: xmax endstop: {1:4s}                  # mandatory
parameter: endstop.xmax:b["OPEN", "TRIG"]   # optional

Menu item with input

[menu enable_fan]
type: input              # mandatory
name: Enable Fan: {0:d}  # mandatory
parameter: fan.speed     # mandatory
input_min: 0             # optional
input_max: 255           # optional
input_step: 1            # mandatory
gcode: M106 {0}          # optional

Some screenshots from mockup demo image image image

NB! This is still a Work in Progress. Concept, code, and other stuff might change!

Zwaubel commented 6 years ago

@mcmatrix Just tested your branch, got to say: Awesome work, thank you very much, I really appreciate the effort you put into implementing the menu.

May I ask:

  1. Is there an easy way to dynamically hide and show menus/menu items depending on the printer state? (e.g. show menu "homing" when not printing and hide it when printing)
  2. Is there an option to invert the rotary encoder direction depending on the menu it is in?
  3. Is there an option to set time out after which the menu automatically disappears?
KevinOConnor commented 6 years ago

On Thu, Jun 28, 2018 at 12:14:29PM -0700, Janar Sööt wrote:

My dev-release-20180622 updated to the latest. Menu is now under display modules. Encoder decoding is inside buttons.py RotaryEncoder class Display is using that class.

Thanks. I've gone ahead and merged the low-level button code into the master branch. This also includes some changes: pin.strip() is done on pin lookup, I've added buttons.register_rotary_encoder() and buttons.register_button_push() helper methods, and the gcode.run_script() can now be run from button callbacks.

If you're ready for submitting your changes, that would be great.

-Kevin

mcmatrix commented 6 years ago

@KevinOConnor Thats great. I need to make slight changes in display according to new buttons methods. My button.py with changes in RotaryEncoder class can be submitted. I'll rebase it to the latest and then submit PR for buttons.

With menu I need more time for testing. Recently added 2 new menuitem types.

mcmatrix commented 6 years ago

@AxMod3DPrint Added new menuitem type sdcard It requires that virtual_sdcard is active. If not then then this item is not enabled in menu.

[menu menu99]
type: sdcard
name: SD Card print
items: sdcard01, sdcard02

[menu sdcard01]
type: command
name: Start/resume
gcode: M24

[menu sdcard02]
type: command
name: Pause
gcode: M25

All menuitems in items attribute are added before files (but you can also remove items). It shows file in menu as command type menuitem and when selecting it will execute M23 /filename

Folders are not working at the moment because virtual_sdcard is not supporting folders. But folders can be easily implemented into menu by using group menuitem.

mcmatrix commented 6 years ago

@Zwaubel

Is there an easy way to dynamically hide and show menus/menu items depending on the printer state? (e.g. show menu "homing" when not printing and hide it when printing)

There is an option. All menuitems have enable: attribute. By default it's True. You can use the same list of variables as for parameter attribute. It will convert any value to boolean. You have also option for negation.

NB! It will not hide/show menu when you are in menu. It's only checking it when you open menu from overview screen.

For example: Item is only available when printing

[menu cmd01]
type: command
enable: toolhead.is_printing
name: Home
gcode: G28

Item is only available when not printing

[menu cmd01]
type: command
enable: !toolhead.is_printing
name: Home
gcode: G28

Sorry I dont have documented all that stuff yet.

Is there an option to invert the rotary encoder direction depending on the menu it is in?

EDITED: Just general encoder direction change by reversing pins order. encoder_pins: ^!ar33,^!ar31 to encoder_pins: ^!ar31,^!ar33 Not menuitem based atm, but I think it can be implemented. You ask possibility to change encoder direction for input type menuitem?

Is there an option to set time out after which the menu automatically disappears?

Theres no timeout for menu at the moment.

Zwaubel commented 6 years ago

@mcmatrix

You ask possibility to change encoder direction for input type menuitem?

yeah, that is exactly what I'm looking for.

I just tested your new sdcardtype menu and it seems that this type does not like to have sub menus of type commandwhich use the enable:attribute. For instance if I do the following

[menu menu99]
type: sdcard
name: SD Card print
items: sdcard01, sdcard02

[menu sdcard01]
type: command
name: Start/resume
gcode: M24
enable:  !toolhead.is_printing

[menu sdcard02]
type: command
name: Pause
gcode: M25
enable:  toolhead.is_printing

klipper will crash as soon as I try to enter the menu.

Further questions regarding inputtype menus: Is there a list / file anywhere which contains all parameters that can be manipulated? Lets say I want to change the hotend temp, how would I do that?

[menu tempHotend]
type: input
name: Set Temperature: {0:.2f}
parameter: extruder.temp
input_min: 0
input_max: 250.0
input_step: 1.0
gcode: M104 S{0:.2f}

--> This does not work, most probably because the parameter I used, is nonexistent (I just guessed it).

Same (not working) example for the fan control:

[menu fanValue]
type: input
name: Fan Value {0:.3f}
parameter: fan.value
input_min: 0
input_max: 1.0
input_step: 0.05
gcode: SET_PIN PIN=fan VALUE={0:.2f}
ygtc commented 6 years ago

Hello mcmatrix, great work i can say that from now and i try to create basic menu tree on my klipper setup.Here are the config.I ll use this like 2 days sometimes need firmware restart but no issues.Maybe you want to use or another user may be decide to use. Last section is still waiting for future use :D

"RepRapDiscount 128x64 Full Graphic Smart Controller" type displays

[display] lcd_type: st7920 cs_pin: ar16 sclk_pin: ar23 sid_pin: ar17 root: main1 encoder_pins: ^!ar31,^!ar33 click_pin: ^!ar35 kill_pin: ^!ar41

Menu manager

[menu main1] type: group name: Main menu

enter_gcode:

leave_gcode:

items: menu0, menu00, menu1, menu2, menu3

[menu menu0] type: row enable: !toolhead.is_printing items: menu25,menu26,menu27

[menu menu00] type: command name: Kill gcode: M112

[menu menu1] type: group enable: !toolhead.is_printing name: Temperature items: menu11, menu12, menu13, menu14, menu15

[menu menu11] type: command name: Preheat Pla gcode: M140 S60;M104 S230

[menu menu12] type: command name: Preheat Abs gcode: M140 S110;M104 S245

[menu menu13] type: command name: CoolDown gcode: M104 S0;M140 S0

[menu menu14] type: command name: Fan On gcode: M106 S255

[menu menu15] type: command name: Fan Off gcode: M106 S0

[menu menu2] type: group enable: !toolhead.is_printing name: Movement items: menu21, menu22, menu23,menu24, menu25, menu26, menu27

[menu menu21] type: command name: Home X gcode: G28 X

[menu menu22] type: command name: Home Y gcode: G28 Y

[menu menu23] type: command name: Home Z gcode: G28 Z

[menu menu24] type: command name: Disable Steppers gcode: M84; M18

[menu menu25] type: input name: X:{0:.2f} parameter: toolhead.xpos input_min: 0 input_max: 190 input_step: 5.0 gcode: G1 X{0:.2f}

[menu menu26] type: input name: Y:{0:.2f} parameter: toolhead.ypos input_min: 0 input_max: 190 input_step: 5.0 gcode: G1 Y{0:.2f}

[menu menu27] type: input name: Z:{0:.2f} parameter: toolhead.zpos input_min: 0 input_max: 180 input_step: 1.0 gcode: G1 Z{0:.2f}

[menu menu3] type: group name: Status

enter_gcode:

leave_gcode:

items: menu31, menu32, menu33

[menu menu31] type: command name: Printing: {1:>3s} parameter: toolhead.is_printing:b['NO','YES']

[menu menu32] type: command name: Pause Print gcode: @//pause

[menu menu33] type: command name: Resume Print gcode: @//resume

[menu menu4]

type: input

name: Choose: {1:s}

parameter: 0:i('----', 'cola','pepsi','fanta','sprite')

input_min: 0

input_max: 4

input_step: 1

gcode: M117 My favorite: {1}

mcmatrix commented 6 years ago

@Zwaubel Could you attach klipper log and your printer config after it crashes. For me it's not crashing when using same menus. I'll add new gcode for menu, so that it will dump list of all parameters available.

mcmatrix commented 6 years ago

@ygtc Nice menu you have.

Zwaubel commented 6 years ago

@mcmatrix It's not crashing but simply not working the way I want it to: I want to be able to set the printers temperature using a inputtype menu but don't know what I do have to use as a parameter. Same applies to the fan control: I want to set the speed/pwm duty cycle but don't know the correct parameter to use.

=============

Just had a few crashes while using the menu:

  1. Random mid print crash while printig via the sdmenu, which I can not reproduce certainly.
  2. Printer is crashing while heating up when entering the menu
  3. Printer randomly crashed while doing nothing

Oh and the sdcard type menu does not like submenus which have a specific enableattribute set. Doing something like this:

[menu octoPrintVirtualSDCard]
type: sdcard
name: Browse Files
items: octoStartPrint, octoPausePrint

[menu octoStartPrint]
type: command
name: Start Printing
gcode: M24
enable: !toolhead.is_printing

[menu octoPausePrint]
type: command
name: Pause Printing
gcode: M25
enable: toolhead.is_printing

would lead to klipper not even starting.

I attached my config and log files for all three crashes in the zip file below. logs_and_config.zip

mcmatrix commented 6 years ago

@Zwaubel Thank you for feedback. From logs i see clearly that menu is crashing in klippy_crashed_while_idling.log and klippy_crashed_while_heating.log I'll investigate why it's doing it and will fix it.

Here klippy_while_printing_crashed.log i don't see why it's restarting, no visible exceptions. The menu itself is not printing anything. @KevinOConnor In this case could it be problem in virtual_sdcard functionality.

mcmatrix commented 6 years ago

dev-release-20180622 is updated. Fixed one bug, hopefully didn't produce more. NB! sdcard type is change to vsdcard

Added gcodes for menu control.

MENU DO=dump ; will dump all parameters (open menu, otherwise parameters are not populated)
MENU DO=exit ; exit from menu
MENU DO=up 
MENU DO=down
MENU DO=select
MENU DO=back
mcmatrix commented 6 years ago

Just now added reverse option for input. Default value it's false, accepts values 0 or 1, or just leave it out

It will reverse the input inc & dec

[menu moveX_1mm]
type: input
name: Move X: {0:.2f}
parameter: toolhead.xpos
reverse: 1
input_min: 0
input_max: 150
input_step: 1.0
gcode: G1 X{0:.2f}  
enable: !toolhead.is_printing
mcmatrix commented 6 years ago

Brave testers, please attach klippers log & config in case of error report.

Zwaubel commented 6 years ago

Just now added reverse option for input. Default value it's false, accepts values 0 or 1, or just leave it out

Nice! works perfectly!

One question remaining regarding the input type menu:

Is there a list / file anywhere which contains all parameter option that can be manipulated? I'm talking about these values: toolhead.is_printing, toolhead.zpos,... Lets say I want to change the hotend temp, how would I do that?

[menu tempHotend]
type: input
name: Set Temperature: {0:.2f}
parameter: extruder.temp
input_min: 0
input_max: 250.0
input_step: 1.0
gcode: M104 S{0:.2f}

--> This does not work, most probably because the parameter I used, is nonexistent (I just guessed it).

Same (not working) example for the fan control:

[menu fanValue]
type: input
name: Fan Value {0:.3f}
parameter: fan.value
input_min: 0
input_max: 1.0
input_step: 0.05
gcode: SET_PIN PIN=fan VALUE={0:.2f}
mcmatrix commented 6 years ago

@Zwaubel MENU DO=dump Will dump available parameters into terminal and also to log. The output will depend on what modules are enabled in config. You should open menu, otherwise parameter list is not populated

Zwaubel commented 6 years ago

MENU DO=dump Will dump available parameters into terminal and also to log. The output will depend on what modules are enabled in config. You should open menu, otherwise parameter list is not populated

Oh, my bad.. I wasn't paying enough attention to your prior posts.

Zwaubel commented 6 years ago

@mcmatrix One thing that came in my mind: Wouldn't it be a good addition to have the menu name (of the menu you are currently in) showing up in the first row of the lcd. I'm talking about something like this:

=============================
|        Temperature        |
=============================
| <-                        |
| > Preheat PLA             |
| > Set Temp. Hotend        |
| > Set Temp Bed            |
| > Cool down               |
=============================

For full graphic lcds there should be plenty of space if you lower the font size to implement something like that.

mcmatrix commented 6 years ago

@Zwaubel Currently max available row count is 4 (even for graphical lcd, it's using builtin text mode). Just updated new version where title is next to back

Zwaubel commented 6 years ago

@mcmatrix Oh okay. No chance to draw your own shapes or anything? Your solution works for me!

mcmatrix commented 6 years ago

Last update for today. I tried to add output_pin and servo values to parameters (could be buggy, sorry). There's no nice way of doing it, so i'm just peeking what output_pins and servos are available in config and then just reading their last_values. This way you are able to get feedback back to menuitem.

hg42 commented 6 years ago

@mcmatrix

New menuitem type row is available.

sorry for not answering yet... I appreciate your effort and the configuration looks good. However I don't use an LCD, yet. I only made suggestions looking forward to future uses.

One thing I noticed: Is there a possibility to configure a space between two entries on one line? It seems to be difficult to add a space before or after the string value (hmm, or can we use "..." ?).

mcmatrix commented 6 years ago

One thing I noticed: Is there a possibility to configure a space between two entries on one line? It seems to be difficult to add a space before or after the string value (hmm, or can we use "..." ?).

I think the easiest way is to support optional beginning and ending quotes (or apostrophes) for name values.

Zwaubel commented 6 years ago

@mcmatrix The menu seems to pretty stable right now, no klipper crashes while heating up or printing. 👍

How do I use the parameter: fan properly, if I want to set the value via a input type menu? Something like

[menu fanValue]
type: input
name: Fan Speed: {0:.2f}
parameter: fan.speed
input_min: 0.0
input_max: 1.0
input_step: 0.01
gcode: SET_PIN PIN=fan VALUE={0:.2f}
reverse: True
enable: !toolhead.is_printing

does not work.

Same question regarding the parameter: output_pin: This

[menu caseLightValue]
type: input
name: Case Light: {0:.2f}
parameter: caseLightPin.value
input_min: 0
input_max: 1.0
input_step: 0.05
gcode: SET_PIN PIN=caseLightPin VALUE={0:.2f}
enable: True

does not work.

mcmatrix commented 6 years ago

Some changes, hopefully without bugs. Now you can enclose name into quotes in config. name: "X:{0:.2f} "

Menu has it's own timers for blinking and timeout. Config attributes have been changed!

# new timeout option in seconds, if 0 or no parameter then there's no menu timeout
menu_timeout: 10
# root is now menu_root
menu_root: main

Parameter attribute is even more flexible now. You can use mapping options like (look 1st post) this parameter: endstop.xmax:b["OPEN", "TRIG"] or you can use it as a scaling option (it accepts ints and floats). parameter: fan.speed:i255

It means that format option 1 is now (value * scale) converted to int format option 0 is still normal value.

It can be used in cases where parameter value is in range 0....1 and value in gcode and name should be in other range like 0..255.

[menu fanValue]
type: input
name: Fan Speed {1:3d}
parameter: fan.speed:i255
input_min: 0
input_max: 1
input_step: 0.00392
gcode: M106 S{1:d}
enable: !toolhead.is_printing
mcmatrix commented 6 years ago

@Zwaubel

Same question regarding the parameter: output_pin: This

[menu caseLightValue] type: input name: Case Light: {0:.2f} parameter: caseLightPin.value input_min: 0 input_max: 1.0 input_step: 0.05 gcode: SET_PIN PIN=caseLightPin VALUE={0:.2f} enable: True does not work.

Parameter name is wrong for that pin. It's output_pin.caseLightPin Try something like this.

[menu caseLightValue]
type: input
name: Case Light: {1:3d}
parameter: output_pin.caseLightPin:i255
input_min: 0
input_max: 1.0
input_step: 0.00392
gcode: SET_PIN PIN=caseLightPin VALUE={0:.3f}
enable: True
Zwaubel commented 6 years ago

@mcmatrix

Parameter name is wrong for that pin. It's output_pin.caseLightPin Try something like this.

[menu caseLightValue]
type: input
name: Case Light: {1:3d}
parameter: output_pin.caseLightPin:i255
input_min: 0
input_max: 1.0
input_step: 0.00392
gcode: SET_PIN PIN=caseLightPin VALUE={0:.3f}
enable: True

Works like a charm, thank you very much!

mcmatrix commented 6 years ago

Hopefully no more features ;) Please test. Lets try to find as many bugs as possible! In case of menu crash please include klippers log & config.

I'll start preparing example menus, prepare preliminary description of all features and then it's more or less ready for PR.

Zwaubel commented 6 years ago

@mcmatrix

Hopefully no more features ;) Please test. Lets try to find as many bugs as possible! In case of menu crash please include klippers log & config.

I'm on it!

mvturnho commented 6 years ago

How can I help testing, What branch should I checkout?

mcmatrix commented 6 years ago

I have simplified parameter transformations. Now parameter attribute should contain only parameter name or static float | int value I added additional attribute transform Example:

# Interpolation example 
[menu fanValue]
type: input
name: Fan Speed {1:3d}
parameter: fan.speed
transform: (0,1,0,255)
input_min: 0
input_max: 1
input_step: 0.00392
gcode: M106 S{1:d}

# Scaler example
[menu caseLightValue]
type: input
name: Case Light: {1:3d}
parameter: output_pin.caseLightPin
transform: 255
input_min: 0
input_max: 1.0
input_step: 0.00392
gcode: SET_PIN PIN=caseLightPin VALUE={0:.3f}

# custom choice example
[menu menu6]
type: input
name: Choose: {1:s}
parameter: 0
transform:['----', 'cola','pepsi','fanta','sprite']
input_min: 0
input_max: 4
input_step: 1
gcode: M117 My favorite: {1}

For transform attribute you have following options. There's no more type cast letter.

(#,#) - parameter → boolean choice, output depends from tuple element type
(#,#,#,#) - parameter interpolate `(from_min, from_max, to_min, to_max)`, output type is same as  `to_max` type
"ABC" - parameter → integer choice, output type is string
[#,#,#,...] parameter → integer choice, output type depends from list element type
255 - parameter scaler, output type depends from scale factor type
{1:"open",2:"close",3:"unknown",...} parameter →  [integer | float | string] (depends from first key type) choice, output depends from element value type

Usage of these values remain same. {0} is parameter raw value {1} is transformed parameter value (not available if attribute is not used) name: Test value {0} transformed {1} All python print formatting options will work.

dev-release is updated

mcmatrix commented 6 years ago

@mvturnho Please check this comment https://github.com/KevinOConnor/klipper/issues/404#issuecomment-399739544

hg42 commented 6 years ago

I tested with my Tronxy board (Melzi type) with a Tronxy graphical LCD (ST7920).

I basically used @Zwaubel's config, with some minor changes:

Everything works well for me (though my test environment cannot print, so I couldn't test this part).

Some remarks/questions/wishes (I am not up to date with the display and menu branches, comments etc. so I appologize if I am asking something already discussed, I searched but didn't find something):

config:

[display]
lcd_type: st7920
cs_pin: tronxy:PA1
sclk_pin: tronxy:PC0
sid_pin: tronxy:PA3
encoder_pins: ^!tronxy:PD2,^!tronxy:PD3
click_pin: ^!tronxy:PA5
#kill_pin: ^!tronxy:...
menu_root: root

[menu root]
type: group
name: Main menu
#enter_gcode:
#leave_gcode:
items: xyz, kill, menu_temp, menu_move, status

[menu xyz]
type: row
enable: !toolhead.is_printing
items: move_X,move_Y,move_Z

[menu kill]
type: command
name: Kill
gcode: M112

[menu menu_temp]
type: group
enable: !toolhead.is_printing
name: Temperature
items: preheat_PLA, preheat_ABS, cool_down, fan_on, fan_off

[menu preheat_PLA]
type: command
name: Preheat Pla
gcode: M140 S60;M104 S230

[menu preheat_ABS]
type: command
name: Preheat Abs
gcode: M140 S110;M104 S245

[menu cool_down]
type: command
name: CoolDown
gcode: M104 S0;M140 S0

[menu fan_on]
type: command
name: Fan On
gcode: M106 S255

[menu fan_off]
type: command
name: Fan Off
gcode: M106 S0

[menu menu_move]
type: group
enable: !toolhead.is_printing
name: Movement
items: home_X, home_Y, home_Z,disable, move_X, move_Y, move_Z

[menu home_X]
type: command
name: Home X
gcode: G28 X

[menu home_Y]
type: command
name: Home Y
gcode: G28 Y

[menu home_Z]
type: command
name: Home Z
gcode: G28 Z

[menu disable]
type: command
name: Disable Steppers
gcode: M84; M18

[menu move_X]
type: input
name: "X:{0:.0f} "
parameter: toolhead.xpos
input_min: -159
input_max: 155
input_step: 5.0
gcode: G1 X{0:.0f}

[menu move_Y]
type: input
name: "Y:{0:.0f} "
parameter: toolhead.ypos
input_min: -155
input_max: 155
input_step: 5.0
gcode: G1 Y{0:.0f}

[menu move_Z]
type: input
name: "Z:{0:.1f} "
parameter: toolhead.zpos
input_min: 0
input_max: 300
input_step: 0.1
gcode: G1 Z{0:.1f}

[menu status]
type: group
name: Status
#enter_gcode:
#leave_gcode:
items: printing, pause, resume

[menu printing]
type: command
name: Printing: {1:>3s}
parameter: toolhead.is_printing
transform: ('NO','YES')

[menu pause]
type: command
name: Pause Print
gcode: @//pause

[menu resume]
type: command
name: Resume Print
gcode: @//resume

#[menu choose]
#type: input
#name: Choose: {1:s}
#parameter: 0:i('----', 'cola','pepsi','fanta','sprite')
#input_min: 0
#input_max: 4
#input_step: 1
#gcode: M117 My favorite: {1}
hg42 commented 6 years ago

ok, I integrated my display into a working printer. I see the menu entries update online, nice!

Entering the root menu once to display as all-in-one page once is ok for now.

I also tried some things to build an all-in-one main page (for now the root menu, which I enter once). Most things already work, but two things:

hg42 commented 6 years ago

this works:

[menu r__temp]
type: row
#enable: !toolhead.is_printing
items: e__bed, e__bed_now, e__hotend, e__hotend_now

[menu e__bed]
type: input
name: "B{0:.0f}"
parameter: heater_bed.target
input_min: 0
input_max: 135
input_step: 5
gcode: M140 S{0:.0f}

[menu e__bed_now]
type: command
name: ":{0:.0f} "
parameter: heater_bed.temperature

[menu e__hotend]
type: input
name: "T{0:.0f}"
parameter: extruder0.target
input_min: 0
input_max: 230
input_step: 5
gcode: M104 S{0:.0f}

[menu e__hotend_now]
type: command
name: ":{0:.0f} "
parameter: extruder0.temperature

It would be nice if the *_now entries could be skipped when selecting a field. Is there a type for a pure display?

I think, in addition to transform we would need something like reverse_transform to scale the current parameter value. Eventually something like: parameter --[rtransform]--> input --[transform]--> parameter2 where parameter2 could be the same as parameter.

I think, transforming at the place where the value is used or retrieved seems to be more flexible than a single transform. E.g. I could display the same value with two scales: {0:.0f(0,1,0,100)}%={0:.0f(0,1,0,255)}

In general the model could have

May be something like this could be used: parameter: heater_bed.target, heater_bed.temperature could result in the first parameter in {0} and the second in {1}. I think, this would work, if the scaling is done at the place of use. The first would always be the target of the input, the second (and even more) could be added for displaying current data. The target parameter could have a transformation attached (like it was before).

E.g. a parameter like fan.is_enabled could be displayed additionally to fan.speed or additional to heater_bed.temperature we could display something like case.temperature. just some ideas...

hg42 commented 6 years ago

I think, the title on the root menu could be ommitted (eventually as an option). There are cases where no submenu is used.

mcmatrix commented 6 years ago

@hg42

It would be nice if the *_now entries could be skipped when selecting a field.
Is there a type for a pure display?

Yep, it would be nice feature. I propose that command without gcode should be considered as static or display item for row I'm testing this change atm.

Multiple parameters will make everything too complex, i already have in testing following: Multiple transformations. Like this

[menu control_fanspeed]
type: input
enable: fan.is_enabled
name: Fan speed:{1:3d}%
parameter: fan.speed
transform: 
    (0,1,0,100)
    (0,1,0,255)
input_min: 0
input_max: 1
input_step: 0.01
gcode: M106 S{2:d}

The background value is still the same fan.speed having float range 0→1 You will define 2 transformations: {1} interpolate raw value to new range 0→100 {2} interpolate raw value to new range 0→255

In background you still change float value but with step : 1/100 = 0.01

To have percentage from value in float range 0→1, python has format option for this {0:4.0%} Fixed size percentage without decimals.

example2 of multi transforms. Btw you can have more that 2 transformation :)

[menu control_fanonoff]
type: input
enable: fan.is_enabled
name: Fan {1:3s}
parameter: fan.speed
transform:
    ('OFF','ON')
    (0,255)
input_min: 0
input_max: 1
input_step: 1
gcode: M106 S{2:d}

These changes are in my local test not released yet!

hg42 commented 6 years ago

fine, there are several ways to solve this and multiple tranformations seems to be equivalent and it is consistent, which I think is important.

"command" without gcode makes sense, too.

I always found that lcd screens need too much input operations to be useful. But now I can define a single shortcut screen that contains most of the most important operations and I really start using it. That's awesome...

Another suggestion: "command" with a python script for unusual operations.

mcmatrix commented 6 years ago

I'm thinking about getting rid of row menuitem as external separate config element. It's easier to use it like this (it remains internally). items: menu1, menu21;menu22;menu23, menu3, menu4 where items delimited by comma are separate menu items and those delimited by semicolon belong into one row. Edited: or 'pipe' character items: menu1, menu21|menu22|menu23, menu3, menu4

hg42 commented 6 years ago

usually semicolons divide more... You could use a dash to symbolize the direction.

hg42 commented 6 years ago

or simply write it without whitespace items: menu1, menu21 menu22 menu23, menu3, menu4

or write it with string as separator (special case: only whitespace): items: menu1, menu21 " " menu22 "" menu23 ": " menu24, menu3, menu4

mcmatrix commented 6 years ago

I have made many changed and added new features. My aim is to make menu as flexible as possible. So that it can even be used as working display.

I'm almost finish with these, still few thing need to complete. I hope to update to dev tomorrow, 09.07! I'll let you all know,

Maximuscr31 commented 6 years ago

So excited to add this to my printer. Thank you for the hard work

mvturnho commented 6 years ago

Hi, I tested the dev branch today and found a problem. When I start a home command from the menu's and while homing I update the printer light with the menu and rotating the encoder all goes well. The lights are only updated after homeing finishes, but that is just how ikt works.

Then when I start my bed leveling using the menu with gcode command; Z_TILT_ADJUST and then enter the menu to adjust the light the printer crashes. It seems the encoder activity crashes the printer when probe-ing

klippy.zip

I attached my log it should include miy config as well.

mcmatrix commented 6 years ago

Hi guys,

It's taking longer than excpected. I had to redesign couple of times. But now it's more or less working. It still needs work but here are 2 teaser images :) lcd_p1 lcd_p2

It's flexible and can be used as normal menu or/and statusscreen replacement.

It has built in sequencer and multipage option also inline editing of values is possible if needed.

Let you know when it's available for testing.

hg42 commented 6 years ago

sounds awesome... just take the time it needs...no hurry... I will be happy to test this, when I'm back from vacations (in about two weeks)

KevinOConnor commented 6 years ago

FYI, the more features that are added the harder reviewing will be, and that might make merging into the master branch harder. I'm all for replacement of the status display with something more flexible, but I suspect it would be preferable to do that in separate commits from basic menu support.

Cheers, -Kevin

EDIT: To be clear, I appreciate your work on this and look forward to seeing it fully merged. Thanks!

hg42 commented 6 years ago

btw. would the concept allow more than one display (eventually with different menu structure)? Just a thought (because I have another spare display laying around). Not sure how this could work and what could be the benefits. May be as a remote display or as extension for the first one with different parameters.

Klipper opens up so much possibilities never thought of before. We can use old spare hardware (or cheap new ones) for new purposes. I don't think of it being implemented right now, but this might be the best time to make the definitions open enough for such possibilities.

I guess, we would only need a named menu root (that could use the same pages or define it's own, which is easily managed by their names). So, I think the current definition would already be extensible to that.

@KevinOConnor That let's me refresh my request to allow every section to be named like [<class_name> <instance_name>]. Eventually with a shortcut [<class_name>] meaning either [<class_name> <class_name>] or some standard name like [<class_name> default] or [<class_name> main] or [<class_name> __main__] or similar.

hg42 commented 6 years ago

@KevinOConnor I guess it's a simplification and a unification, so it should improve patch management. Though it may still be possible to split this into two separate steps. First step adding support for menu modules, second adding this flexible module.

hg42 commented 6 years ago

First step adding support for menu modules

actually, I meant splitting the display code into hardware display (which could be further divided into hardware specific modules) and status display and allowing to register alternate status display(s).

However, looking at display.py it seems like half of it would be replaced by the new code. The different screen_update_xxx functions would probably be handled by different defaults for the "menu"?