QtPyVCP - Max_Velocity Override - Button Group Freebie

More
12 Dec 2019 01:42 - 14 Dec 2019 12:13 #152510 by Donb9261
Hello,

I am working on a Linux Mint 19.1 Gtk interface. I like the default Mint Dark styling better than Mate (Gnome) interface. That said, I decided to walk down the path of creating some functionality that is more mainstream in comparison to Fanuc, Mitsubishi, Siemens, and Heidenhain in regard to how a user would recognize how to use the UI based on experience with these controls.

Although RS274 GCODE is the standard, Linuxcnc tends to lean more toward a standalone paradigm making it a challenge for even the most experienced to just walk right in. That said, as I begin my journey I will share with all in hopes that I may help you on your journey or inspire you to help in mine. Either way, happy VCP'ing.

This is my latest creation. The code is crude as I am just learning the deeper parts of Python. I know Lua, some C, but for the most part have always used Ladder, Functional Programming, Sequence, etc. based on my 30+ years in the CNC machine tool engineering business. I own a small but reasonably successful CNC machine tool service, consulting, retrofitting, and integration company out of Texas.

I needed a method by which to create a series of buttons to select percentages of the max_velocity. aka... Rapid for those familiar. Borrowing from the fine example QtPyVCP numberKey tutorial I created a sloppy but fully function Rapid OVR setup with 0,25,50,75, and 100% values. It will draw from the INFO.maxVelocity() imported into the machineactions.py file. The file is located in /home/yourusername/.local/lib/python2.7/site-packages/qtpyvcp/actions folder. Make a copy and then edit. Lol. Go figure, I didn't. :-)

Here is my crude but function actions I added to the Max Velocity section under def set():

EDITED:
# -------------------------------------------------------------------------
# BEGIN MAX VEL OVERRIDE actions
# -------------------------------------------------------------------------

# Added MV actions for 25,50, and 75 perecent values

class max_velocity:
    """Max Velocity Group"""
    @staticmethod
    def set(value):
        """Max Velocity Override Set Value"""
        CMD.maxvel(float(value) / 60)

    @staticmethod
    def zero():
        # Sets MAX_VELO to 0% of max from ini file settings
        """MAX_VELO_0%"""
        c_val = (INFO.maxVelocity() / 60) # Get current MV static param from ini
        set_val = 0
        CMD.maxvel(float(set_val))

    @staticmethod
    def twentyfive():
        # Sets MAX_VELO to 25% of max from ini file settings
        """MAX_VELO_25%"""
        c_val = (INFO.maxVelocity() / 60) # Get current MV static param from ini
        set_val = c_val * .25
        CMD.maxvel(float(set_val))

    @staticmethod
    def fifty():
        # Sets MAX_VELO to 50% of max from ini file settings
        """MAX_VELO_50%"""
        c_val = (INFO.maxVelocity() / 60) # Get current MV static param from ini
        set_val = c_val * .5
        CMD.maxvel(float(set_val))

    @staticmethod
    def seventyfive():
        # Sets MAX_VELO to 75% of max from ini file settings
        """MAX_VELO_75%"""
        c_val = (INFO.maxVelocity() / 60) # Get current MV static param from ini
        set_val = c_val * .75
        CMD.maxvel(float(set_val))

    @staticmethod
    def hundred():
        # Sets MAX_VELO to 100% of max from ini file settings
        # Used because reset disbales the button when not ready. Preserve UI look and feel for the group.
        """MAX_VELO_100%"""
        c_val = (INFO.maxVelocity() / 60) # Get current MV static param from ini
        set_val = c_val * 1
        CMD.maxvel(float(set_val))

    @staticmethod
    def reset():
        """Max Velocity Override Reset Value"""
        CMD.maxvel(INFO.maxVelocity() / 60)

def _max_velocity_ok(value=100, widget=None):
    if STAT.task_state == linuxcnc.STATE_ON:
        ok = True
        msg = ""
    else:
        ok = False
        msg = "Machine must be ON to set max velocity"

    _max_velocity_ok.msg = msg

    if widget is not None:
        widget.setEnabled(ok)
        widget.setStatusTip(msg)
        widget.setToolTip(msg)

    return ok

def _max_velocity_bindOk(value=100, widget=None):

    # This will work for any widget
    STATUS.task_state.onValueChanged(lambda: _max_velocity_ok(widget=widget))

    try:
        # these will only work for QSlider or QSpinBox
        widget.setMinimum(0)
        widget.setMaximum(INFO.maxVelocity())

        try:
            widget.setSliderPosition(INFO.maxVelocity())
            STATUS.max_velocity.onValueChanged(
                lambda v: widget.setSliderPosition(v * 60))

        except AttributeError:
            widget.setValue(INFO.maxVelocity())
            STATUS.max_velocity.onValueChanged(
                lambda v: widget.setValue(v * 60))

    except AttributeError:
        pass
    except:
        LOG.exception('Error in max_velocity bindOk')

max_velocity.set.ok = max_velocity.reset.ok = _max_velocity_ok
max_velocity.set.bindOk = max_velocity.reset.bindOk = _max_velocity_bindOk

# -------------------------------------------------------------------------
# END MAX VEL OVERRIDE actions
# -------------------------------------------------------------------------

You may be wondering why I chose to have a hundred() vs. using the reset() to set the maxVelocity back to 100%. The reason is that the button defaults to disabled if you do until the machine is ready. This was goofy as the rest did not and not really needed as max_velo does not need to be a protected UI point. Regardless for simplicity I named everything pretty clear for myself and anyone who may follow. I know it is not efficient but it does work.

No rules are required for the buttons. Everything for setting the max_velo is in the actions file. The UI part is in the mainwindow.py file in your vcp folder created by you when you created your VCP.

So, follow the instructions and add the GridLayout. Then right click the layout and morph to a Group Box. Then add action buttons for each %. I did 0~100% 25% increments. My preference. Then just as instructed select them all and make them a New Button Group (May not be required). Name the button group (Should be last object in the browser after statusbar) rapidButtons. I did this just in case there was a more efficient code base for what I want. I will improve it over time for sure. Make sure ALL are checkable.

EDITED:

Name each button like so,

rapidZero
rapidTwentyFive
rapidFifty
rapidSeventyFive
rapidHundred

Then for each you can add styling individually for checked like so, ActionButton::checked{background-color:rgb(0,255,0)} and ActionButton{background-color:rgb(0,128,0)}. This will act like an indicator light for each as they are toggled.

In order to get them to act like radio buttons where only one can be on at a time, I created the following (sloppy) code for the mainwindow.py located in your VCP folder: (yours should look the same)

EDITED:
from qtpyvcp.widgets.form_widgets.main_window import VCPMainWindow

# Setup logging
from qtpyvcp.utilities import logger
LOG = logger.getLogger('qtpyvcp.' + __name__)

class MyMainWindow(VCPMainWindow):
    """Main window class for the VCP."""
    def __init__(self, *args, **kwargs):
        super(MyMainWindow, self).__init__(*args, **kwargs)
        self.rapidZero.clicked.connect(self.buttonRapidZero)
        self.rapidTwentyFive.clicked.connect(self.buttonRapidTwentyFive)
        self.rapidFifty.clicked.connect(self.buttonRapidFifty)
        self.rapidSeventyFive.clicked.connect(self.buttonRapidSeventyFive)
        self.rapidHundred.clicked.connect(self.buttonRapidHundred)

# -------------------------------------------------------------------------
# BEGIN MAX VEL OVERRIDE Button Group UI Contoller
# -------------------------------------------------------------------------
    
    def buttonRapidZero(self):
        self.rapidZero.setChecked(True)
        self.rapidTwentyFive.setChecked(False)
        self.rapidFifty.setChecked(False)
        self.rapidSeventyFive.setChecked(False)
        self.rapidHundred.setChecked(False)

    def buttonRapidTwentyFive(self):
        self.rapidZero.setChecked(False)
        self.rapidTwentyFive.setChecked(True)
        self.rapidFifty.setChecked(False)
        self.rapidSeventyFive.setChecked(False)
        self.rapidHundred.setChecked(False)

    def buttonRapidFifty(self):
        self.rapidZero.setChecked(False)
        self.rapidTwentyFive.setChecked(False)
        self.rapidFifty.setChecked(True)
        self.rapidSeventyFive.setChecked(False)
        self.rapidHundred.setChecked(False)

    def buttonRapidSeventyFive(self):
        self.rapidZero.setChecked(False)
        self.rapidTwentyFive.setChecked(False)
        self.rapidFifty.setChecked(False)
        self.rapidSeventyFive.setChecked(True)
        self.rapidHundred.setChecked(False)

    def buttonRapidHundred(self):
        self.rapidZero.setChecked(False)
        self.rapidTwentyFive.setChecked(False)
        self.rapidFifty.setChecked(False)
        self.rapidSeventyFive.setChecked(False)
        self.rapidHundred.setChecked(True)

# -------------------------------------------------------------------------
# END MAX VEL OVERRIDE Button Group UI Contoller
# -------------------------------------------------------------------------

This will toggle the selected button to on and indicating while turning any of the others off. Works great.

Save the file and VCP and then start Linuxcnc with your VCP config as normal. Thats it. Easy peasy.

Here is the button group in QT:



Here it is in Linuxcnc working:



If i missed something or you have issues please feel free to ask. I am currently working to fix the nasty QScintilla GcodeEditor. I have attached a screenshot of where I am at on styling that below:



Happy Hunting,

Don
Attachments:
Last edit: 14 Dec 2019 12:13 by Donb9261. Reason: Edited to make clearer some key points.
The following user(s) said Thank You: KCJ, Leon82

Please Log in or Create an account to join the conversation.

More
12 Dec 2019 01:51 #152511 by Leon82
That's pretty cool.

I will try it when I have some free time. I went for a fanuc manual guidei theme for my qtpyvcp.

Ultimately This would make a cool widget that can be drag and dropped in.
The following user(s) said Thank You: Donb9261

Please Log in or Create an account to join the conversation.

More
12 Dec 2019 02:12 #152513 by Donb9261
Thanks. Yes, I have seen yours. Funny, you mentioned that. Out of the thousands of machines I have worked with having Fanuc, less than 10% actually use the manualguidei screen. Usual comment, "That looks too difficult". Lol. Is what it is. I prefer that. We wrote some C classes for Fanuc years back. Worked great. Has morphed into some of the conversational screens still used.

I am still trying to figure out how to do the whole ad a widget thing. Don't know if it has to added to the .so plugin library or not. Never done a dev build in Linux. Most likely I am thinking it to hard and it is much easier than I thought.

In any case. Have a good one.

Don
The following user(s) said Thank You: Leon82

Please Log in or Create an account to join the conversation.

More
12 Dec 2019 02:23 #152514 by Leon82
The matsuuras are defaulted to it so it has grown on me lol.

Please Log in or Create an account to join the conversation.

More
12 Dec 2019 03:46 #152515 by KCJ
Don,

Very nice write up! Thank you for taking the time to share.
Also really like your changes to the GcodeEditer.

Please Log in or Create an account to join the conversation.

More
12 Dec 2019 22:42 - 12 Dec 2019 23:09 #152558 by Leon82
what did you name the buttons?

rapidZero ect?

they check correctly but are not affecting the rapid

and could the existing rapid slider affect the buttons?
Last edit: 12 Dec 2019 23:09 by Leon82.

Please Log in or Create an account to join the conversation.

More
13 Dec 2019 00:41 #152563 by Donb9261
Yes.

rapidZero
rapidTwentyFive
rapidFifty
rapidSeventyFive
rapidHundred

mainwindow.py in the connects shows you. Just under super...
The following user(s) said Thank You: Leon82

Please Log in or Create an account to join the conversation.

More
13 Dec 2019 00:42 #152564 by Donb9261
Thank you Kurt.

Were you the original victim who developed the QtPyVCP code?

Please Log in or Create an account to join the conversation.

More
13 Dec 2019 00:47 #152565 by Donb9261
I am still researching QScintilla. Man is that a complicated code base. Lexers and regex are the things of nightmares. My goal is to 1. have G's one color, M's one color, and O's another.

Not sure if it is Linux Mint 19.1 but for some reason I cannot get the current line to highlight during runs. In axis QScintilla picks up the lexer and highlights the running(current) line during runtime.

I will figure it out and do a solid step by step for that too. Seems there is very little info on how. But I am ruthless bastard. B)

Please Log in or Create an account to join the conversation.

More
13 Dec 2019 00:52 #152566 by Donb9261
Here is a cutout: Note the function defs are the same but prepend button to the button name. Tried to keep it simple. KISS!:)


self.rapidZero.clicked.connect(self.buttonRapidZero)
self.rapidTwentyFive.clicked.connect(self.buttonRapidTwentyFive)
self.rapidFifty.clicked.connect(self.buttonRapidFifty)
self.rapidSeventyFive.clicked.connect(self.buttonRapidSeventyFive)
self.rapidHundred.clicked.connect(self.buttonRapidHundred)

Please Log in or Create an account to join the conversation.

Moderators: KCJLcvette
Time to create page: 0.421 seconds
Powered by Kunena Forum