Hello Guest it is April 26, 2024, 12:04:20 AM

Show Posts

This section allows you to view all posts made by this member. Note that you can only see posts made in areas you currently have access to.


Messages - smurph

591
For that, you will most definitely have to use the screen API.

string: value, number: rc = scr.GetProperty(string: ctrlName, string: propertyName)

number: rc = scr.SetProperty(string: ctrlName, string: propertyName, string: value)

The control name is the name you have given the screen element in the Name property.  It is case sensitive. 
The property name is the name of the property as spelled in the property grid.  Value, for example. Or Top, Left, Width, Height, etc...

The value of the property is always a string.  Use tonumber() to convert a string to a number in LUA.  Conversely, use tostring() to convert a number to a string.  Some properties are lists, which have values associated with the string description in the list.  In this case, you will get the value instead of the string description.

If you open up the screen editor and look at the properties of a regular button, you will see a property called "Bg Color".  This is the property you will want to set with scr.SetProperty().  The property is editable in the screen editor with a color picker control.  But it is actually stored as a string.  A call to scr.GetProperty("myButton", "Bg Color") will reveal the stored value.  If the returned sting is blank/empty, then the default color based on the current Windows theme will be used.  Otherwise, it will return a value in HTML RGB format like "#RRGGBB"  #FF0000 is pure red, #00FF00 is pure green, #0000FF is pure blue.  Any color can be represented with this syntax. 

An easy way to get the value for the color you want is to open the screen editor, set a button's "Bg Color" to the color you want, and then use scr.GetProperty("myButton", "Bg Color") to get the value.  Record it, and then maybe change the color and get more values.  Otherwise, there are probably lots of color picker tools out there that are capable of doing this too. 

Once you have your color values, then you can set the button color based on the current jog increment in the PLC script.
Code: [Select]
if (incr == .001) then
    rc = scr.SetProperty("myButton", "Bg Color", "#FF0000") -- set button color to red if incr == .001
elseif (incr == .01) then
    rc = scr.SetProperty("myButton", "Bg Color", "#00FF00") -- set button color to green if incr == .01
elseif (incr == .1) then
    rc = scr.SetProperty("myButton", "Bg Color", "#0000FF") -- set button color to blue if incr == .1
end

Steve

592
Allan is 100% correct on this.  And he also tested empirically.  Good job!  

A G31 move will either skip, or not.  Meaning probe strike, or not.  If the probe strikes a surface, the G code variables are filled with the strike position.  If the probe does NOT touch a surface, the G code variables will contain the end point of the move.  Normally, this is the ONLY way to know if the probe has touched a surface in G code is by comparing the G code variable positions to the end point of the move.  If different, the probe struck a surface.  

Since Mach is not running on a real time OS, it can't possibly capture the strike position accurately.  So this job is delegated to the motion controller, which is a real-time device.  So if the values in those G code variables are not correct, then I would suspect an issue with the motion controller or its' plugin.  

If there is a hang waiting on a set still, then the motion control plugin is not working correctly.  Again, since Mach is not running on a real-time OS, and Mach doesn't know the outcome of the G31 move, it will ask the motion controller/plugin to tell it when the move is complete.  It could have reached the endpoint of the move or stopped somewhere in between.  Mach just doesn't know.  So Mach will wait indefinitely for a response back from the motion controller. If no response is given, hang.  

Fanuc only specifies the variables #5061-#5066, which should be the position with all current offsets applied.  Mach also gives you #5071-#5076, which should be the machine position.  All of these positions are in native machine units.  Meaning if you setup the machine for inch, then inches is what you will see in those variables, even if you are probing in G21.  

On an inch machine:
G90 G21
G00 X0
G31 X10 F1000 (probe does not strike)

At the end of the move #5071 == .393701 (inch value for 10mm)

Steve

593
Thanks for the input Steve,

Just curious, why is anything under 16 GB bad for windows 10? 

When it comes to regenerating my toolpath, I've gotten in this cycle start habit of Regen --> Cycle Start.  Just to be safe.

Because a stock Windows 10 installation on a new machine (Dell, etc...) idles at 12GB.  They put all of that bloatware on there.  Plus all of the MS telemetry stuff.  If you are persistent enough to remove all of the crap, then 8GB might be ok.  All it takes is a quick look to the task manager to see how well the machine will perform.  Virt mem vs. Physical mem.  If your virt mem is higher, expect the machine to be sluggish.   My machine is idling at 21GB as we speak!  Now, it is a development machine.  But let's face it, that is the amount of memory my machine REQUIRES to operate like I want it to.  All that is running is Visual Studio, email, web browser, file manager, Skype, and Mach.  The big ones are Skype and the web browser.  Next is the Visual Studio.

Steve

594
Mach4 General Discussion / Re: IMTS 2018
« on: May 24, 2018, 04:57:13 PM »
I don't know what our plans are for IMTS this year.  When I find out, I'll let everyone know. 

I like going and meeting the people I converse with on this board.  I missed it last time around because it fell on my 10th wedding anniversary.  :(

Steve

595
It is not a 32 vs. 64 bit thing.  It is a processor/memory thing.  Mach 4 does things differently than Mach 3 did on the file loads.  The capabilities of the interpreter are far more advanced and requires a LOT more switch code.  Thus it does take more processor power to generate the tool path.  The newer builds will be an improvement in this regard, as I optimized it as much as I could.  

With the latest build, on my desktop machine, I can process 1000 lines of G code per second or 1 G code line per millisecond.  Now, my Atom board WILL NOT do this.  :)

The files are memory mapped.  This enables files that are far larger than the 32 bit address space.  However, if your machine is swapping memory to disk, well...  it is GOING TO BE SLOW.  I agree that 8GB of RAM is not sufficient for a Windows 10 machine.  Anything less than 16GB is uncivilized.  

If you change an offset, you MUST regenerate the tool path.  We don't auto regenerate because you may need to change several offsets and would then have to wait on each offset to regenerate the tool path.  

Steve

596
The stock jogging will follow G20/G21.  Also, the increments are defined in the General setup tab.  Define them in the order and content that you want. 

The common cycle start is on 95% of the commercial controls.  There is usually a switch on the panel to direct the cycle start to run the MDI.  All the YASNACs, Fanucs, and Fidias that I have run have been like that.  In this case, the "switch" is the current tab.  But I don't use the screen for these functions at all, because of some of the same concerns.  I use a panel to run my whole machine just like I did when the control was a YASNAC.  No mouse clicky stuff.  It is a touch screen and I do use that to load files, etc..  But that is the extent of it.  Basically, the screen is there for display purposes and I run the machine with the panel.  MPG, FRO, SRO, jog buttons, cycle start/stop feed hold.  Like God meant for CNC machines to be run.  :)

Steve

597
What kind of pendant?  And what kind of motion controller are you running? 

Steve

598
I use a rotary knob on my panel to set the jog increments.  And use Mach API function mcJogSetInc().  To find the current jog increment, use mcJogGetInc().  It is by axis, so to make all of the coordinated axes have the same jog increment, you have to do it for all of them.  The GUI does this for you in its' default configuration.  But if you want something different, then you have to do the legwork that the GUI does. 

So, how would one track this?  In the PLC script.  LEDs can be driven by signals.  One could grab some output signals that are not mapped to hardware outputs and use them for the purpose of driving LEDs.  In the PLC script, use mcJogGetInc() to determine which increment is in use and drive the appropriate output signal.  Say you have 3 LEDs to represent 3 different increments of .001, .01, and .1.  At this point, you may want to put this function in the screen load script and call it from the PLC script. 

Code: [Select]
-- this is in the screen load script.
currentInc = 0 -- global var to track the current increment. 

function SetIncrementLeds()
    local inst = mc.GetInstance()
    -- track using OSIG_OUTPUT61, OSIG_OUTPUT62, and OSIG_OUTPUT63 (for .001, .001, and .1, respectively)
    local hSig61 -- signal handle
    local hSig62 -- signal handle
    local hSig63 -- signal handle
    local inc, rc = mc.mcJogGetInc(inst, mc.X_AXIS)
    if (currentInc ~= inc) then -- the increment has changed, so light up the appropriate LED
        currentInc = inc;
        hSig61, rc = mc.mcSignalGetHandle(inst, mc.OSIG_OUTPUT61)
        if (rc ~= mc.MERROR_NOERROR) then
            -- Error condition.
            mc.mcCntlSetLastError(inst, "Failed to get signal handle in SetIncrementLeds()!"
            return;
        end
        hSig62, rc = mc.mcSignalGetHandle(inst, mc.OSIG_OUTPUT62)
        if (rc ~= mc.MERROR_NOERROR) then
            -- Error condition.
            mc.mcCntlSetLastError(inst, "Failed to get signal handle in SetIncrementLeds()!"
            return;
        end
        hSig63, rc = mc.mcSignalGetHandle(inst, mc.OSIG_OUTPUT63)
        if (rc ~= mc.MERROR_NOERROR) then
            -- Error condition.
            mc.mcCntlSetLastError(inst, "Failed to get signal handle in SetIncrementLeds()!"
            return;
        end
        -- No errors at this point, set all output signals to off.
        mc.mcSignalSetState(hSig61, 0) -- check the return code for production code!  This is an example. 
        mc.mcSignalSetState(hSig62, 0)
        mc.mcSignalSetState(hSig63, 0)
        if (inc == .001) then
            mc.mcSignalSetState(hSig61, 1) -- .001 is current, turn on its' output signal. 
        elseif (inc == .01) then
            mc.mcSignalSetState(hSig62, 1) -- .01 is current, turn on its' output signal. 
        elseif (inc == .1) then
            mc.mcSignalSetState(hSig63, 1) -- .1 is current, turn on its' output signal. 
        end
    end
end

function SetIncrement(incr)
    for axis=0,5,1 do
        mc.mcJogSetInc(inst, axis, incr) -- probably want to check the rc as well... 
    end
end

Put a line in the PLC script to update the LEDs
Code: [Select]
SetIncrementLeds() -- call the function that is in the screen load script

Then map output signals 61 to 63 to some LEDs.

Then put something like the following in some button up event scripts

Code: [Select]
SetIncrement(.001) -- Call the SetIncrement() function in the screen load script.  .01 and .1 in other buttons.

That is all done without scr.Get/SetProperty().  AND it has the added benefit of working along side a panel knob.  But also do realize that you also have the PMC to do all of this stuff in ladder logic as well.  Both of these should be considered preferable to using the screen API stuff.   

Steve

599
Yes, you use the screen API.  It is not documented other than you will get the function signatures in the ZeroBrane editor.  The two staples are:

string: value, number: rc = scr.GetProperty(string: ctrlName, string: propertyName)

number: rc = scr.SetProperty(string: ctrlName, string: propertyName, string: value)

The control name is the name you have given the screen element in the Name property.  It is case sensitive.  
The property name is the name of the property as spelled in the property grid.  Value, for example. Or Top, Left, Width, Height, etc...

The value of the property is always a string.  Use tonumber() to convert a string to a number in LUA.  Conversely, use tostring() to convert a number to a string.  Some properties are lists, which have values associated with the string description in the list.  In this case, you will get the value instead of the string description.

Keep in mid that it is ALWAYS better to use the underlying data that backs the screen element instead of the screen element itself, if possible.  For instance, if there is a slider on the screen named "myFROslider" that sets the feed rate override, use mc.mcCntlGetFRO() instead of scr.GetProperty('myFROslider', 'Value").  This is part of the reason that this stuff is not documented.  Because people will use it and not use the main Mach API proper.  I JUST ran into this when support gave me a supposed "BUG" the other day.  It wasn't a bug.  The slider is imprecise because it is pixel based.  If the slider has a range of 0 to 250, but the slider is displayed in less than 250 pixels, well...  there are going to be gaps in the range when using the slider.  Meaning you can start sliding it up from zero and get counts like 1, 2, 3, 5, 6, 7, 9.  So it wasn't a bug at all!!!!  It is why the FRO slider in fresh on my mind.  Yeah, I went down that rabbit hole. 

The other reason is I just don't like writing documentation.  LOL

99% of the time, these scr.* functions are not needed.  If you find yourself needing them all of the time, take a step back and think about how it could be done some other way.  Most of the time, the ONLY time you may absolutely need them is for a screen specific function.  Like the figuring out what tab is current to make the Start Cycle button process MDI commands instead of running a file.  

Steve

600
Mach4 General Discussion / Re: Simple one line MDI required
« on: May 20, 2018, 02:32:01 PM »
What is wrong with Mach4's "Run From Here"?  It works fine for me.  Let me explain what it does.

1.  The first thing it does is do a dry run to and including the line before the selected restart line.  Why?  To get the interpreter state correct.  So if cutter comp was in effect, it would start at the correct offset.  Or any offset, for that matter. 
2.  The dry run is for the interpreter state only, not necessarily the machine state.  If you turned the spindle off, you had better have turned it back on.  Why?  Because you turned it off.  You are master and commander of the machine tool.  And there might not be a line in the G code to tell the control to restart the spindle.  Otherwise, you will drag the cutter through the part and you WILL break something.  At this point, you really can't blame it on the machine control.  :)
3.  Execution will start at the beginning point of the desired line.  If the machine is not already at those coordinates, it will do a feed move to get there.  This includes Z.  This may seem contradictory to the statement above.  But is it?  The last line of the dry run set the starting point of the line.  If the machine is not there, you basically have told the machine to get there. 

Mach doesn't "automatically" restart spindles and such because it has no way of knowing the reason for the run from here.  It could be used to restart a program.  Or it could be used to start a program at a certain place.  You, the operator, know this and it is your responsibility to make sure the machine is in a state to accomplish this.

It is all about understanding what goes on in automatic vs. manual mode.  There is nothing magical about Run From Here.  It will do the same things every time.

Steve