Hello Guest it is March 28, 2024, 06:12:08 AM

Author Topic: Changes In Macro Execution?  (Read 7983 times)

0 Members and 1 Guest are viewing this topic.

Changes In Macro Execution?
« on: July 14, 2015, 10:03:14 PM »
I've been away from Mach3 for several years, but now have to get back into, and write some relatively simple macros to operate my old power drawbar and toolchanger, which had been running under KFlop.  I've translated the KFlop C driver to CB, and it's sorta-kinda working, but I'm getting some really odd results.  Under various error conditions, I pop-up an error dialog using MachMsg, and I sometimes see these dialogs appear from portions of code that should never have run, and this invariably happens LONG after the macro, by all appearances, has completed execution.  

So, I am confused.  I notice in the Programmer Reference Manual, which I originally wrote many years ago, has been significantly updated.  In particular, I notice the new "RunScript" function, for which the manual seems to recommend NOT using M-macros, due to the need to "invent and handle semaphores".  WTF??

Anyway, my PDB/ATC macro is attached.  Does anyone see anything in there that could explain the bizarre behavior I'm seeing, or explain what I'm doing wrong?  It appears to me almost as though some subroutine calls are going off and running asynchronously in separate threads, so I end up with several threads running in parallel for what MUST be a linear sequence of operations.

Regards,
Ray L.
« Last Edit: July 14, 2015, 10:15:57 PM by HimyKabibble »
Regards,
Ray L.
Re: Changes In Macro Execution?
« Reply #1 on: July 14, 2015, 10:07:03 PM »
BTW - Another VERY odd thing I see:  I wrote some G-code to test this macro.  The G-code consists of nothing but a series of invocations of my macro, to invoke it's various sub-functions.  I cannot Load that g-code file into Mach3 - it hangs while loading the file, at about 30%, and never progresses any further.  The G-code program is attached.

Regards,
Ray L.
Regards,
Ray L.
Re: Changes In Macro Execution?
« Reply #2 on: July 15, 2015, 07:37:14 AM »
Hi Ray,
  One compile error. Might make a difference ? ? ?

Seems to load OK now.
 
Quite a macro .... looks like a lot of nice work !
Russ
Re: Changes In Macro Execution?
« Reply #3 on: July 15, 2015, 10:20:28 AM »
That little typo crept in just before I posted the code, but wasn't in the code as I tested it.

Regards,
Ray L.
Regards,
Ray L.
Re: Changes In Macro Execution?
« Reply #4 on: July 15, 2015, 12:00:47 PM »
This is completely F-ed up!  The code compiles without error, it seems to run correctly, except....

If I load the g-code file (which today loads correctly - Why? I don't know....), and Single-step through it, here's what happens:

The first line, M806 P0, executes correctly, and initalizes the ATC.

The second line, M806 P20, also appears to execute correctly, and lowers the ATC "lift".

The third line, M806, P21, also appears to execute correctly, and raises the ATC "lift".

Here's where it gets strange - If I just wait a bit, after 10-20 seconds, I start getting error dialogs, coming from the code that actually performs the above operations.  These dialogs report both Lift Down and Lift Up errors, and come from the LowerLift() and RasieLift() functions.  Note the timeouts in these functions are 2 seconds, yet the errors don't pop up for at least 10-20 seconds AFTER the code is executed.  Also, since I am single-stepping the G-code, should it not be impossible to single step one line until the macro for the previous line has completed execution?  That being the case, how is it possible I am stepping several lines of code, and only getting error dialogs tens of seconds later?  The more lines I execute, the more errors I get, and the longer they are delayed before popping up.

When I manually execute the Lift Down and Lift Up operations using MDI, they work perfectly every time.

This makes no sense at all to me, and is CLEARLY different behavior from what I've seen in the past.  WTF is going on here?

Here is the LowerLift code.  The RaiseLift code is essentially identical except it flips the control but the other way:

Function LowerLift (ByVal verify As Integer) As Integer

    If IsOutputActive(ATC_LIFT) = ATC_LIFT_DOWN And IsActive(ATC_LIFT_SENSE) = 0 Then
        LowerLift = ATC_ERR_NOERROR
   GoTo EXIT4
    End If

    If verify = 0 Then
        ActivateSignal(ATC_LIFT)
        Sleep(1000)
        LowerLift = ATC_ERR_NOERROR
   GoTo EXIT4
    End If

    LowerLift = ConfirmAction(ATC_LIFT, ATC_LIFT_LOWER, ATC_LIFT_SENSE, ATC_LIFT_TIMEOUT, ATC_ERR_LIFT_DOWN_FAIL)

EXIT4:
    CurrentLiftPos = 1
End Function


Function ConfirmAction (ByVal bit As Integer, _
         ByVal bitval As Integer, _
         ByVal sense As Integer, _
         ByVal timeout As Integer, _
         ByVal err As Integer) _
          As Integer
                         
     '' Must not be mid-travel at start
    If IsActive(sense) Then
   ConfirmAction = err
        GoTo Exit7
    End If

    '' Set/Clear the control bit
    If bitval = 1 Then
        ActivateSignal(bit)
    Else
        DeactivateSignal(bit)
    End If

    '' Ensure it moves - first wait for sensor high
    ElapsedTime = 0
    i = 0
    While i < 10
        If IsActive(sense) = 1 Then
            i = i + 1
        Else
            i = 0
        End If
        Sleep(1)
   ElapsedTime = ElapsedTime + 1
        If ElapsedTime >= timeout Then
       ConfirmAction = err
       GoTo EXIT7
        End If
    Wend

    '' Now wait for sensor low
    i = 0
    While i < 10
        If IsActive(sense) = 0 Then
            i = i + 1
        Else
            i = 0
        End If
        Sleep(1)
   ElapsedTime = ElapsedTime + 1
        If (ElapsedTime >= timeout) Then
       ConfirmAction = err
       GoTo EXIT7
        End If
    Wend
    ConfirmAction = ATC_ERR_NOERROR

EXIT7:
End Function

Regards,
Ray L.




Regards,
Ray L.
Re: Changes In Macro Execution?
« Reply #5 on: July 15, 2015, 12:31:21 PM »
One mystery solved:  IsActive(signal) = 0 and IsActive(signal) = 1 do not work as expected.  You must use IsActive() and Not IsActive().  I put a MachMsg at the very end of the main code, so I can now see when the code stops executing, and it now ends when I think it should.

The other mystery remains:  I can still single-step the lines in the G-code window, BEFORE the previous line(s) have completed executing!  How do I fix that??

In addition, the timeouts in my loops are taking about 10X longer to time out than they should.  The Sleep(1) seems to be acting more like a Sleep(10).....

Regards,
Ray L.
« Last Edit: July 15, 2015, 12:33:20 PM by HimyKabibble »
Regards,
Ray L.

Offline stirling

*
  • *
  •  2,188 2,188
  • UK
    • View Profile
    • www.razordance.co.uk
Re: Changes In Macro Execution?
« Reply #6 on: July 15, 2015, 01:18:53 PM »
One mystery solved:  IsActive(signal) = 0 and IsActive(signal) = 1 do not work as expected.

That's because in most (if not all) dialects of BASIC, true evaluates to -1 not 1. (if you must do an explicit compare) but the not op is preferable (in any language).

The other mystery remains:  I can still single-step the lines in the G-code window, BEFORE the previous line(s) have completed executing!  How do I fix that??

AFAIK this has always been the case with single block. Just tested it here on my trusty old 3.042.020 and that's how it is. A normal cycle runs macros "serially" though.

In addition, the timeouts in my loops are taking about 10X longer to time out than they should.  The Sleep(1) seems to be acting more like a Sleep(10).....

IIRC very low sleep values (<10) ARE inaccurate.
Re: Changes In Macro Execution?
« Reply #7 on: July 15, 2015, 01:37:29 PM »
One mystery solved:  IsActive(signal) = 0 and IsActive(signal) = 1 do not work as expected.

That's because in most (if not all) dialects of BASIC, true evaluates to -1 not 1. (if you must do an explicit compare) but the not op is preferable (in any language).

The other mystery remains:  I can still single-step the lines in the G-code window, BEFORE the previous line(s) have completed executing!  How do I fix that??

AFAIK this has always been the case with single block. Just tested it here on my trusty old 3.042.020 and that's how it is. A normal cycle runs macros "serially" though.

In addition, the timeouts in my loops are taking about 10X longer to time out than they should.  The Sleep(1) seems to be acting more like a Sleep(10).....

IIRC very low sleep values (<10) ARE inaccurate.

I guess I never single-stepped through M macros in G-code before, because I never noticed that (incredibly annoying) behavior!

It does appear Sleep(1) is, very nearly, equivalent Sleep(10).  I divided all my timeouts by 10, and they're not at least in the ballpark.

Regards,
Ray L.
Regards,
Ray L.

Offline BR549

*
  •  6,965 6,965
    • View Profile
Re: Changes In Macro Execution?
« Reply #8 on: July 15, 2015, 11:21:06 PM »
HIYA Ray, What version are you running IF V.066 then you may want to DUMP that version and back up to .062  .  

as to isactive() sometimes

true / false works sometimes NOT

is /not may or may not work

-1/1 may or may not work

0/1 may or may not work

sometime the signal inverts sometimes not

SLEEP() (;-) anything under (10) is useless and don't count on it being exact cause it may or may not be.

It just depends (;-)

(;-) TP
« Last Edit: July 15, 2015, 11:22:46 PM by BR549 »

Offline stirling

*
  • *
  •  2,188 2,188
  • UK
    • View Profile
    • www.razordance.co.uk
Re: Changes In Macro Execution?
« Reply #9 on: July 16, 2015, 04:06:44 AM »
It does appear Sleep(1) is, very nearly, equivalent Sleep(10).  I divided all my timeouts by 10, and they're not at least in the ballpark.

Sleeps longer than 10 should be reasonably accurate so there should be no need to modify or scale them. Generally just don't expect sleeps < 10 to be accurate and therefore don't use them. If your sleeps that are > 10 are wildly inaccurate then there's likely another issue somewhere.

as to isactive() sometimes

true / false works sometimes NOT

is /not may or may not work

-1/1 may or may not work

0/1 may or may not work

sometime the signal inverts sometimes not

LOL - well if you say so Terry, but I have NEVER seen isactive() fail to return true (-1) or false (0).

What I HAVE seen is functions that are documented as being boolean actually returning 0 and 1 instead of 0 and -1. Clearly there was some inconsistency in the interface implementation between the C++ "source" and the CB API. In those cases, using NOT will provide endless hours of debugging fun if you're not onto it.

Try this for your entertainment:

msgbox not 1

Perfectly logical, but a gotcha if you don't see why.

One example of a gotcha is getOEMLED. It returns 1 and 0 but how often do we see if getOEMLED(...) in code i.e. treating it as if it were a boolean function? Sure it'll work fine but then someone takes the logical next step and does a if NOT getOEMLED(...). That'll end in tears because NOT 0 implicitly casts to true BUT so does NOT 1.

isMoving() is perhaps the worst example for a few reasons. First, although it implies a boolean result it isn't (unlike most other is.... functions) so really, all the while isMoving() loops we see should really be while isMoving() = 1. Because again if you ever do a "if NOT isMoving()" it will not do what you might think. Of course isMoving()s worst "feature" is that contrary to its name it doesn't actually (exclusively) have anything to do with anything moving! Don't even get me started on isStopped().
« Last Edit: July 16, 2015, 08:08:57 AM by stirling »