Jump to content
OMRON Forums

Using CaptCompISR


Recommended Posts

I am trying to use the C routine CaptCompISR to process position-compare triggers but the C code refuses to run.  My general program structure works as follows:

Run a oneshot script PLC InitPLC, including an instruction


Start script PLCs for

    reporting current values (position, velocity, ...) to the host program
    watch for emergency stop situations
    handle action requests from the host program

I prepare the trigger points for the position compare in Sys.Idata starting at 65536, with the factor 4096 multiplied in but no home offset applied.  One action request is handled in a motion script program including the following instructions:

    Gate3[0].IntCtrl = 0x200000 ;
    PReadPtr=PVarOffset+TrigPtr ;
    L1 = PReadPtr ;
    TrigEnaY = $1 ;                    // Set EquWrite = $1.
    TrigAY=(Sys.Idata[L1]/4096-TrigDir*TrigPhs+HmOffset)*4096 ;    // This is Gate3[0].Chan[1].CompA
    TrigBY=TrigAY+TrigDir*PStepAB*ScaleFct*4096;    // This is Gate3[0].Chan[1].CompB
    TriggerPlcR=True ;
    // Enable plc TriggerPlc ;
    X(MovEndX) Y(MovEndY) F(CmdFeedRt/1000) ;    //Index Through Print.
    While (InPosX == False || InPosY == False) {}
    TriggerPlcR=False ;
    // Disable plc TriggerPlc ;

The C code looks as follows:

    #include "usrcode.h"
    #define _PPScriptMode_

    #include "../Include/pp_proj.h"

    void CaptCompISR(void)
        volatile GateArray3 *MyGate3;
        int *CompDebug;
        int *Comp8Million;
        int *CompType;
        int *CompCounter;
        int *CompPosStore;
        int *CompHmOffset, *CompHmOffsetX, *CompHmOffsetY;
        int *CompStepAB;
        int *CompTrigDir;
        int *CompDataLap;
        int *CompPVarSize;
        int Temp, TempPosStore, TempPosTest, Temp8Million, TempM8M, CStepAB, CTrigDir, CpVarSize, CTrigSel;

        MyGate3 = GetGate3MemPtr(0);
        MyGate3->WpKey = 0xAAAAAAAA;        // Make IntCtrl writeable.
        MyGate3->IntCtrl = 0x20;        // Clear interrupt.
        CompDebug = (int *)pushm + 65524;    // Debug counter, serves to prove that this code is executed.
        CompPVarSize = (int *)pushm + 65525;
        CompTrigDir = (int *)pushm + 65526;
        CompStepAB = (int *)pushm + 65528;
        CompHmOffset = (int *)pushm + 65531;
        CpVarSize = *CompPVarSize;
        CTrigDir = *CompTrigDir;        // Direction of motion - +1 or -1
        CStepAB = *CompStepAB;
        CompDataLap = (int *)pushm + 65532;    // Wrap-around flag, 0 or 1.
        Comp8Million = (int *)pushm + 65533;    // end of run flag value.
        Temp8Million = *Comp8Million;
        TempM8M = - Temp8Million;
        CompType = (int *)pushm + 65534;    // 0 for rectangular flying, 1 for curved flying.
        CompCounter = (int *)pushm + 65535;    // The value for this index was preloaded,
        (*CompCounter)++;            // so we point to the second value first time we get here.
        if (*CompCounter >= CpVarSize)
            *CompCounter = 0;
            *CompDataLap = 0;
        CompPosStore = (int *)pushm + *CompCounter + 65536;
        TempPosStore = *CompPosStore;
        TempPosTest = TempPosStore / 4096 ;
        (*CompDebug)++;    // Counts calls here.

        if ((*CompType) == 0)
            if ((TempPosTest < Temp8Million) && (TempPosTest > TempM8M))
                // Set new trigger point.
                MyGate3->Chan[1].CompA = TempPosStore + *CompHmOffset ;
                MyGate3->Chan[1].CompB = TempPosStore + *CompHmOffset + CStepAB * CTrigDir;
                // Set EquWrite = 1.
                Temp = MyGate3->Chan[1].OutCtrl;
                Temp &= 0xFFFFFF7F;            // Clear bit 7 (0x80).
                MyGate3->WpKey=0xAAAAAAAA;        // Make OutCtrl writeable.
                MyGate3->Chan[1].OutCtrl = Temp | 0x40;    // Set bit 6.

        else if ((*CompType) == 1)
            // ... case not used yet ...

My usrcode.c file does also contain the dummies for other functions like GetLocal and CFromScript.  The source gets actually downloaded, I have found it with Putty on the PMAC.

If I disable the instruction to set CaptCompISR=1 in InitPlc and activate my script PLC "TriggerPlc" in the motion program, I get to see all expected triggers.  Here is how TriggerPlc works:

    Open plc TriggerPlc                        //Trigger Target Generator.
    If (TrigStateY == True)            // Test Gate3[0].Chan[1].Equ
        p793=p793+1;            // Debug counter
        TrigPtr=TrigPtr+1 ;

        If (TrigPtr == pVarSize)
            TrigPtr=0 ;
            DataLap=False ;
        PReadPtr=(PVarOffset+TrigPtr) ;
        L1 = PReadPtr ;
        TrigEnaY = $1 ;            // Set EquWrite = $1.
        TrigAY=(Sys.Idata[L1]/4096-TrigDir*TrigPhs+HmOffset)*4096 ;    // This is Gate3[0].Chan[1].CompA
        TrigBY=TrigAY+TrigDir*PStepAB*4096;    // This is Gate3[0].Chan[1].CompB

The IDE does not like the statement

    volatile GateArray3 *MyGate3;

It puts a red twiggle under the "*" of *MyGate3 and reports "syntax error, unexpected '*'".

Of my script PLCs, only TriggerPlc is a RTIPLC. Sys.WpKey is globally set to $AAAAAAAA.  I have set the build and download to include the C source code.  The build and download does not report any error.  When trying to run this code, the task list reports under "Real time interrupt" "User written 'C' Real Time Interrupt task not active".

What am I missing?

Cheers,           Jochen

Link to comment
Share on other sites

  • Replies 9
  • Created
  • Last Reply

Top Posters In This Topic

I found one omission: In the Solution Explorer, in the Properties of the file usrcode.c, the "Build Action" was still set to "Content".  I changed this to "Compile", and now the build-and-download procedure actually compiles my C code.  However, when I run my motion system, nothing has changed - "User written 'C' Real Time Interrupt Task is NOT active".  And  my counter at Sys.Idata[65524] remains at 0, so my CaptCompISR function still does not receive any position-compare trigger.

Link to comment
Share on other sites

More observations:

UserAlgo.CaptCompIntr=1 is actually happening.

usralgo.so appears in the same directory as usrcode.c and usrcode.h on the PMAC (a CK3C, by the way).


I suspect that there are more trivial or stupid omissions in the IDE or project setups to be fixed rather than, or on top of, actual programming issues.  I just can't find them ...

Link to comment
Share on other sites

17 hours ago, steve.milici said:

Are you following all the steps listed in the “Power PMAC User’s Manual” in the chapter “Writing C Functions and Programs in Power PMAC” starting on page 792?

Specifically see the section “Capture/Compare Interrupt Service Routine” starting on page 797.

Yes, I am following pages 792ff.

I have put my code for the CaptCompISR function into usrcode.c in the directory "C Language/Realtime Routines". The code follows the Compare Interrupt Routine Example on page 800, with these differences:
- I use Chan[1] rather than Chan[0], which allows me to easily switch between triggering off of the positions of my x and y axes. Accordingly, I manipulate the channel-1 bits in Gate3[0].IntCtrl, not the channel-0 bits.
- I pick up, from shared memory, the home offset and a direction parameter (+/-1) for setting the proper trigger positions.
- I count calls to the interrupt routine with a counter in shared memory. I show this in the watch window, and it never counts a call.
- I have removed additional code that I have listed in my original post.

In my script programming,
- I am setting UserAlgo.CaptCompIntr=1 and can see this in the watch window of the IDE while my program is running;
- I am preloading the first trigger position, and this one trigger does fire but is not followed by a call to CaptCompISR.

Things that are not addressed in pages 792ff:

- In Solution Explorer, the Advanced property "Build Action" of usrcode.c is set to "Compile".

I have turned the downloading of the C sources on.  On the PMAC, I do find these as well as usralgo.so and usralgo.ko under /var/ftp/usrflash/Project here:
    C Language/Realtime Routines/usralgo.so
    C Language/Realtime Routines/usrcode.c
    C Language/Realtime Routines/usrcode.h


Link to comment
Share on other sites

If you are certain that the compare triggers are occurring, then as a troubleshooting technique comment out all the code except for the “Clear interrupt” and “Call counter”. I suspect something in the logic is preventing it from working as you expect. This would at least verify the interrupt is working.

Link to comment
Share on other sites

17 hours ago, steve.milici said:

If you are certain that the compare triggers are occurring, then as a troubleshooting technique comment out all the code except for the “Clear interrupt” and “Call counter”. I suspect something in the logic is preventing it from working as you expect. This would at least verify the interrupt is working.

I tried this, and I still don't see any call to CaptCompISR.  I edited the function, issued a $$$***, did a Clean in Solution Explorer before Build and Download, issued a "save" after download (because my motion program issues a $$$ at the beginning) and ran my program. The watch window of the IDE says UserAlgo.CaptCompIntr=1 all along and the call counter Sys.Idata[65524] remains at 0.

The attached text file shows my usrcode.h, usrcode.c and the relevant script snippet. CaptCompIntr is set much earlier than the occurrence of the move shown in the snippet.  The move lasts 4 seconds.


Link to comment
Share on other sites

3 hours ago, steve.milici said:

This could be indicative of there being no compare events to trigger the ISR. As a more decisive test to verify the functionality of the Capt/Comp ISR, set up the “IntCtrl” element for a capture event. This should be relatively easy to test. If you have no other flag, use just the encoder index pulse.

I failed yet again.

I have from my homing procedure (drive into the hard end, turn around, look for index):


I move the setting of UserAlgo.CaptCompIntr=1 from my InitPlc to right before the test move in my script program:

X(MovEndX) Y(MovEndY) F(FeedRate/1000);
While (InPosX==False || InPosY==False) {}

The move nominally covers 20 mm and takes some 4 seconds.  The encoder is a rotary one on the back of a stepper motor, which produces a motion of 6 mm per revolution, so I should see 3 or 4 calls.  I see CaptCompIntr switch from 0 to 1 at the start position of my move but still/again no sign of activity in CaptCompISR - Sys.Idata[65524] remains at 0.

Things get messier, actually.  My X/Y/F move is not executed properly if I try to get CaptCompISR involved.  In the present test with the capture, this means that instead of moving in x from 133333 counts to 159900 counts (1333 counts/mm), the stage takes a detour: 133333 -> 0 -> 159900.  In the position compare test, the detour is 133333 -> 200000 -> 159900.  I have no idea where that intermediate position comes from.  If I keep the position compare a pure script affair, the moves are flawless.

Is it time to move this to ODT-Support?

Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

  • Create New...