HAL - Connections To UI Elements

More
09 Jan 2020 15:21 - 10 Jan 2020 14:10 #154447 by Donb9261
I am trying to wrapped my head around to wrap my head around how I can get the hal pin value into a button check event.

I have net flood => qtpyvcp.flood-on.in in postgui attached to a HalLabel. Works great. %d gives me a 0 or 1. No problem.

What I want is to build a diagnostics screen that will set a button to checked based on the hal pin value.

net flood => qtpyvcp.some-button.in ???

If so, great is that a passed parameter I can access with a connect?

Since there is no HalLineEdit there is no changed event. QLabels do not have this.

Maybe I am overlooking something here? Would some-button.in be tied to the enable? Can I do some-button.checked?

Any help?

Don
Last edit: 10 Jan 2020 14:10 by Donb9261.

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

More
09 Jan 2020 16:04 #154453 by aleksamc
Will you be sattisfied with pyVCP led signals that indicate your conditions of button?
Or you can use in g-code some o-code with if-statement to serve your needs...

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

More
10 Jan 2020 00:28 #154511 by BigJohnT
Yes you can setChecked(True) a button in Python. I think the syntax is correct.

You can set the enable with a rule.

JT

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

More
10 Jan 2020 14:09 #154550 by Donb9261
John,

You may have misunderstood my question. What I needed was a way to convert a HalButton to be used as an indicator light reflecting the status of Hal Pins. The way in which the HalButton Widget is written ischecked is simply verified and the widget tries to create a new out pin for the button. So, if say I wanted to see whether the flood out bit is true visually vice True or False in a HalLabel Widget I would have to use a HalLED widget which does not comply with my UI design aesthetics.

So, to make this possible I have made some modifications to the HalButton Widget that allow the button to be used as either an output setter or as an indicator. Works good. I am still ensuring there are no side effects though. Shouldn't be as I have created if statements to allow for original code to work if the option is not set to be an indicator.

It is a tad complicated to wrap around but once you read the code it makes sense.

To begin with, you have to set the postgui.hal to net the appropriate signal like so. (Flood used as an example)

net flood => qtpyvcp.flood-on-btn.checked

Here if the flood pin is on it will set the checked value of the HalButton Widget to True else it will be False.

Next you to modify the HalButton Widget as follows: (Entire code is below to hopefully dissolve confusion)

"""
HAL Button
----------

Button for setting `bit` HAL pin values.

.. table:: Generated HAL Pins

    ========================= ===== =========
    HAL Pin Name              Type  Direction
    ========================= ===== =========
    qtpyvcp.button.enable     bit   in
    qtpyvcp.button.out        bit   out
    ========================= ===== =========
"""

"""
Added btnAsIndicator Setup for HalButton to act as an indicator vs button

You will need to set a stylesheet property for how the indicator will appear when checked for
each HalButton Instance used. 

Example:

HalButton:checked{
background-color: rgb(0,190,0);
font: 12pt "Ubuntu";
border-color: rgb(83, 83, 83);
border-radius: 7px;
color: white;
}

HalButton{
background-color: rgb(17, 0, 30);
font: 12pt "Ubuntu";
border-color: rgb(83, 83, 83);
border-radius: 7px;
color: white;
}
"""

from qtpy.QtCore import Property, QTimer
from qtpy.QtWidgets import QPushButton

from qtpyvcp import hal
from qtpyvcp.widgets import HALWidget


class HalButton(QPushButton, HALWidget):
    """HAL Button"""
    def __init__(self, parent=None):
        super(HalButton, self).__init__(parent)

        self.setText("HAL Button")

        self._enable_pin = None
        self._pressed_pin = None
        self._checked_pin = None

        self._pulse = False
        self._pulse_duration = 100
        self.pulse_timer = None
        
        """ Additonal Variable Added """
        # Used to initalize the value of the btnAsIndicator BOOL
        self._indicator = False

        self.pressed.connect(self.onPress)
        self.released.connect(self.onRelease)
        self.toggled.connect(self.onCheckedStateChanged)

    def onPress(self):
        if self._pressed_pin is not None:
            self._pressed_pin.value = True
        if self._pulse:
            self.pulse_timer.start(self._pulse_duration)

    def onRelease(self):
        if self._pressed_pin is not None:
            self._pressed_pin.value = False

    def onCheckedStateChanged(self, checked):
        if self._checked_pin is not None:
            self._checked_pin.value = checked

    @Property(bool)
    def pulseOnPress(self):
        """If active, when the button is pressed the ``out`` pin will be `True`
        for :class:`.pulseDuration` ms, otherwise the ``out`` pin will
        be `True` for the duration of the button press.
        """
        return self._pulse

    @pulseOnPress.setter
    def pulseOnPress(self, pulse):
        self._pulse = pulse

    """ Add Property btnAsIndicator """
    # Will be present as a HalButton Property
    @Property(bool)
    def btnAsIndicator(self):
        return self._indicator

    """ Setter for new Property """
    # Set btnAsIndicator variable to True or False based on property selection
    @btnAsIndicator.setter
    def btnAsIndicator(self, indicator):
        self._indicator = indicator

    @Property(int)
    def pulseDuration(self):
        """Pulse duration in ms used when :class:`.pulseOnPress` is active."""
        return self._pulse_duration

    @pulseDuration.setter
    def pulseDuration(self, duration):
        self._pulse_duration = duration

    def initialize(self):
        comp = hal.COMPONENTS['qtpyvcp']
        obj_name = str(self.objectName()).replace('_', '-')

        """ NO CHANGE """
        # add button.enable HAL pin
        self._enable_pin = comp.addPin(obj_name + ".enable", "bit", "in")
        self._enable_pin.value = self.isEnabled()
        self._enable_pin.valueChanged.connect(self.setEnabled)

        # add button.out HAL pin
        """ Decide Button Type Out or Indicator """
        # Must bypass setting if no output is required as with an Indicator
        if not self._indicator:
            self._pressed_pin = comp.addPin(obj_name + ".out", "bit", "out")

        """ MAGIC """
        # Here we decide how to handle the Out or Indicator Question???
        # add checkbox.checked HAL pin
        ### If the btnAsIndicator Property is NOT checked then it's an Output
        if not self._indicator:
            self._checked_pin = comp.addPin(obj_name + ".checked", "bit", "out")
            self._checked_pin.value = self.isChecked()
        else:
            # Connect the setChecked method to the HalButton and change from out to in.
            # notice the change to addPin(obj_name + ".checked", "bit", "in")
            # vs addPin(obj_name + ".checked", "bit", "out")
            self._checked_pin = comp.addPin(obj_name + ".checked", "bit", "in")
            self._checked_pin.value = self.isChecked()
            # Set the button to checked
            self._checked_pin.valueChanged.connect(self.setChecked)

        if self._pulse:
            self.pulse_timer = QTimer()
            self.pulse_timer.setSingleShot(True)
            self.pulse_timer.timeout.connect(self.onRelease)

Close and ReOpen QtDesigner through command line>> editvcp your_vcp as normal.

You will see the new property available in the HalButton Property section once the HalButton is inserted into your vcp. Checking the btnAsIndicator will allow for the button to work as an indicator without creating a new Hal Pin.

Set your checked or unchecked styling for the button on an individual basis. Not in the qss file.

Name the HalButton the same as the postgui.hal file noted above.

Save the vcp and postgui.hal file.

Launch your LCNC VCP and check to ensure the indicator works as planned. It should. If not, double check your code and/or button name.

If you launch and LCNC crashes with a hal pin error such as code 4 (pin already exists or something like that) you have not coded correctly as per my instructions and you need to start over verifying each step. Typically, the hal pin in the postgui.hal was set to .out vs .checked. That is important regardless of whether it is a button or indicator. If using it as a normal HalButton you choose .out, .enabled, or .checked. But the result will be different. If as an indicator, .checked is really the best and only option since it will not do anything but light up if the output is on.

Hope that simplifies the solution enough for all. Pics below...









Attachments:

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

More
10 Jan 2020 20:18 #154573 by KCJ
Don, you could get the same result by using a plain jane HalLabel and the hal-lable.enabled pin. Enter the text you want to display in the Designer text property and don't connect anything to the hal-label.in pin. Then use the QSS to change the background color depending on whether it is enabled or not.
HalLabel:enabled{
background-color: rgb(0,190,0);
font: 12pt "Ubuntu";
border-color: rgb(83, 83, 83);
border-radius: 7px;
color: white;
}

HalLabel{
background-color: rgb(17, 0, 30);
font: 12pt "Ubuntu";
border-color: rgb(83, 83, 83);
border-radius: 7px;
color: white;
}


If you use HalLabels in other places in your UI you could distinguish them by adding a bool dynamic property in designer named "indicator" and setting it to true for the indicator labels. This will apply the indicator styling to only the widgets that have the dynamic property set.
HalLabel:enabled[indicator="true"]{
background-color: rgb(0,190,0);
font: 12pt "Ubuntu";
border-color: rgb(83, 83, 83);
border-radius: 7px;
color: white;
}

HalLabel[indicator="true"]{
background-color: rgb(17, 0, 30);
font: 12pt "Ubuntu";
border-color: rgb(83, 83, 83);
border-radius: 7px;
color: white;
}

BTW: what Qt theme are you using? Youre UIs look really nice and clean...

Are you planing to share your VCP? What you have done so far is extremely impressive.

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

More
10 Jan 2020 21:38 #154585 by Donb9261
Kurt San,

Thanks for the compliment. I am not using a theme per-say. The UI is composed of individual frames styled to appear as individual panels. I will work out a theme file later on. There is supposed to be a shadow effect for each panel but there is an issue where you use stacked panels stacked in a stacked panel messing up the hierarchy with setGraphicEffect. I will work that out soon. Most likely will have to forego the stacked on stacked concept to prevent the setGraphicEffect from throwing an exception as it has no idea which frame to use. Although, I kinda like a flat theme so I may just blow that concept and do it for my next VCP. I have this running on Mint 19.2 using the theme settings shown in the pic attacked.

What I do for a living is develop custom automation solutions for industrial settings where CNC equipment is involved as well as service existing CNC equipment. Although the concept of Qt and using Python is very new to me, the concept of UI development and logic based operations is not. I always work front to back as the UI in the end decides whether a particular apparatus will be utilized to the potential you intend. KISS. Right. But make it easy on the eyes.

I had thought to use the label as you said but felt converting a label to a visual element was bit confusing. My logic made sense at the time. Lol. Regardless either method achieves the desired result and I will consider you idea.

I will be sharing the VCP soon once I have the code DRY'd a bit and know I all the bugs worked out or set up to have exceptions where needed and created the theme via qss. Python tends to force verbose code in some cases but in the end I find it much easier to read than Lua, C, and C++. :-) It will be shared fully operational as a standard LCNC version for 3,4,5 axis UI with tool and part probing via macros only. Conversational machines are cool but produce waste as the machine is idle waiting for you something to do. Drives me insane. :)

So you know my end game, this VCP is a boiler plate for a larger concept that incorporates standard CNC technologies as well as custom GCODES for specialized canned cycles, advanced 3d probing, for kinematics for 3+2 machines and 4+1 machines, high capacity magazines, and a host of others. It will incorporate a OPC-UA client and have modules for ERP(SQL) integration for automating reporting for paperless manufacturing using Lean Manufacturing. I have done this with Fanuc and Siemens with great success and hope to build an solution for those who do not have a spare million to buy a machine with all my options attached breaking the barrier to entry that consumes the lower markets. I suppose it is a humanitarian thing. :)

Again Thanks for the compliment.


Regards,
Don San


Attachments:
The following user(s) said Thank You: KCJ

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

More
10 Jan 2020 21:44 #154586 by Donb9261
Kurt San,

And I wanted to better understand you code. :) I am curious like a cat that way. Lol.

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

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