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 - garysdickinson

Pages: 1 ... 9 10 [11] 12 13 ... 34
151
Joel,

In my client's application, the use of the stepmoveabs statements are at a very small rate.  In my case it is possible for the PLC to run for days or weeks without needing to move the stepper motors, so I have not run into the problem.

But, I did run into something, similar,  back in August 2016 with the high speed counters.  The problem with the highspeed counter mechanism was that it was supposed to invoke a CF when a count value was reached. But, periodically, the CF was not invoked. This caused all sorts of havoc with the behavior of the system that my client sold and delivered to his customers. I worked this problem offline with Leon at TRI.

Leon traced the problem to how the PLC firmware handled interrupts.  My understanding was that the low level firmware responded to an interrupt caused by the PLC hardware and in response to this event queued a request to call the CF.  The bottom line problem was that the queue mechanism would periodically, loose (ignore, discard, ...) the queued request and the CF never was invoked.

It is possible that the stepper notification (RELAY set) mechanism may be implemented in the low-level PLC firmware in a very similar way. If this is true, then the same issues with the low-level PLC firmware may be causing the problem that you are observing.

I do have a suggestion that may help both detect your problem and make your PLC way more reliable.  This is the sort of work-around that I am still doing for the HighSpeed counter:

  • Use a "dead man timer" to detect the absence of a response (RELAY set from completion of the motion comand).
  • When you issue the StepMoveAbs statement, set RELAY that is connected to the dead man TIMER.  The Set Value of the TIMER should be greater than the worst case time required for the stepper to move to the new position.
  • If the RELAY associated with the StepMoveAbs is received, clear the RELAY controlling the dead man timer.
  • If the dead man TIMER goes off, then you know that the StepMoveAbs command has failed to set the RELAY specified by the command and you can now clear the RELAY that controls the dead man TIMER.

Another approach is to set up a mechanism that periodically calls a CF while your StepMovAbs command is active.  The CF that is called periodically will use the StepCountAbs(1) function to read the current absolute position for the stepper system.  If the stepper has moved to the position that you have commanded and the RELAY has not been set, you can then set the RELAY in your CF and then the rest of your PLC code will operate as you have designed.  Problem is not solved, but you have a work around.

Best regards,

Gary D*ckinson

152
Technical support / Re:Timebomb
« on: June 18, 2017, 12:59:15 PM »
I have found no TBASIC keywords that can directly alter the stored program.  You can alter SV of TIMERs and COUNTERs.  

If your PLC has non-volatile EEP storage you can wipe this out.  I use EEP to store all sorts of configuration data so that my customer can run the same PL6/7 program on several systems.  Only the EEP image changes between systems.

Why do I mention this?  I look for a unique signature in EEP to determine if the EEP based configuration data is valid. If valid, the code runs.  If not valid the code builds a generic configuration data set in EEP.

For your usages, when the usage counter expires,  zero out the EEPROM and reset the PLC.  The CF that is called on the first scan can simply put the PLC in an endless loop if the EEP has been cleared. This will brick the PLC for 99.9% of your customers.



Best regards,

Gary D*ickinson

153
Technical support / Parsing issue with bitwise not "~" operator
« on: June 16, 2017, 02:45:51 PM »
The bitwise not operator, "~", is not handled very well by i-TRiLOGI.

In an arithmetic expression the bitwise not operator is only must be the first thing in the expression to be correctly parsed.  If "~" is not the first thing in the expression, then "~" and the expression that follows must by grouped with parenthesis (I'm guessing that the expression parser is recursive and this why the use of parenthesis makes the unary operator appear to be the first operator since the open parenthesis).

OK. This works:
Code: [Select]
B = ~A & &hff      ' bitwise not compiles
This fails:
Code: [Select]
B =  &hFF & ~A      ' Error:Unknown Keyword: "~"
This will compile:
Code: [Select]
B =  &hFF & (~A)      ' OK

"Bitwise not" is a unary operator and should work on the numeric expression that follows the ~. But the design of TBASIC either got the hierarchy of operators (operator precedence) wrong or was never designed to handle unwary operators correctly. Unary operators should be right below the parentheses in hierarchy and not lumped in with other binary operators (&,|,^).

The negate operator "-" has the same parsing behavior issue as "~".  The negate operator is, also, a unary operator and only works on the numeric argument that follows.  It's operator precedence should be up with the "~".

In both cases, I don't think that you can fix TBASIC, now.  It is way too late.  But you could document the behavior and suggest that the programmer force the evaluation order by using parenthesis around most usages of the unary operators "-" and "~".

The documentation on Bitwise logical operators:
iii) Bitwise Logical Operators: logical operations is perform bit-for-bit between two 16-bit integer data.

There are a major problems with the documentation:
1. All operations are 32 bit not 16 bit for current FMD, Fx, Nano-10 style PLCs.
2. The ~ operator is a unary (not binary) operator and does not "perform bit-for-bit between two 16-bit integer data [values]".  The ~ operator acts on the numeric expression that follows and the result of the operation will be 32 bit.
3. The negate, "-",  operator is a unary (not binary) operator and does not "perform bit-for-bit between two 16-bit integer data [values]".  The - operator acts on the numeric expression that follows the operator.
4. TBASIC's expression parser cannot handle 2 consecutive operators.  if the second operator is - or ~ you must enclose this operator and the expression to the operator's right in parenthesis inorder to get TBASIC to properly evaluate the expression.
5. Mixing up the terms, bitwise, logical and comparison operators.  I think of logical and comparison operators resulting in a value of 0 and not 0.  Bit wise operators result in a 32-bit value with each individual bit being some function of the value(s) and the operator involved.

Best regards,

Gary D*ckinson

154
Technical support / Inconsistent parsing of ":" as delimiter 7.12
« on: June 15, 2017, 11:42:25 AM »
I noticed that the parsing of ":" as a delimiter is very inconsistent.

This is the documented example of the use of ":" as a delimiter:
Code: [Select]
IF A >B:C=D*5:ELSE:C=D/5:ENDIF
The sample leads one to believe that the delimiter is exactly ":" with no additional whitespace requirements.  However, in some cases the parser requires " :" or " : " to be recognized as a delimiter.

This is my test sample that came up with my observed results.  The first line of code uses exactly ":" as a delimiter.  Each successive line I added white space until the parser was happy.  The last line will compile and please note that  ":" is not always recognized as a delimiter:
Code: [Select]
a#=0.0:call StrFmt:PRINT #8 A$;"\09ProductGpmGoal"      ' Error:Unknown Keyword: "all"
a#=0.0 :call StrFmt:PRINT #8 A$;"\09ProductGpmGoal"      ' Error:Unknown Keyword: "all"
a#=0.0: call StrFmt:PRINT #8 A$;"\09ProductGpmGoal"      ' Error:Undefined Custom Function Label:: "StrFmt:PRINT"
a#=0.0: call StrFmt :PRINT #8 A$;"\09ProductGpmGoal"   ' Error:Unknown Keyword: "RINT"
a#=0.0: call StrFmt :PRINT #8 A$;"\09ProductGpmGoal"   ' Error:Unknown Keyword: "RINT"
a#=0.0: call StrFmt: PRINT #8 A$;"\09ProductGpmGoal"   ' Error:Undefined Custom Function Label:: "StrFmt:"
a#=0.0: call StrFmt : PRINT #8 A$;"\09ProductGpmGoal"   ' Compiles
I know that this is not the biggest problem on the face of the earth, but it is just plain messy and very inconsistent.

Best regards,

Gary D*ckinson

155
Technical support / Re:IF THEN
« on: June 14, 2017, 04:17:18 PM »
Lorne,

You should think of the IF statement as IF..ENDIF.  The use of "THEN" is optional and you should just forget about it.

Your program is missing an ENDIF and could not possibly compile.

This is probably what you had in mind:
Code: [Select]
CLRIO CBP 'First Clear CBP

IF DM[535] > 0
   FOR N = 0 TO 7
      IF TESTBIT (DM[541], N)
         IF TESTBIT(DM[537],N) =0
               SETIO CBP
         ENDIF
      ENDIF
   NEXT
ENDIF

I would suggest for "readability" that you indent your code so that the IF lines up with the ENDIF, FOR lines up with NEXT and the statements between then are indented.  This is not required by TBASIC, but it helps to make it easier to see what is going on.

You could simplify your code a bit by using the logical "AND" to test for a "1" in DM[541] and a "0" in DM[537]:

Code: [Select]
CLRIO CBP 'First Clear CBP

IF DM[535] > 0
   FOR N = 0 TO 7
      IF (TESTBIT (DM[541], N) = 1) AND (TESTBIT(DM[537],N) = 0)
           SETIO CBP
      ENDIF
   NEXT
ENDIF

You could probably simplify your code even more by eliminating the FOR/NEXT loop.  You look at all of the bit patterns in parallel by using the bit-wise and operator, "&".  The "~" is the bit-wise NOT operator. I know that this won't make much sense, yet.  But, someday it might:

Code: [Select]
CLRIO CBP 'First Clear CBP (assume that the tests will fail)

IF DM[535] > 0
   ' Test for a "1" in each bit position in DM[541] against a "0" in
   ' the corresponding bit position in DM[537].
   '
   ' TBASIC does most of its operations with 32-bit math and it will
   '  sign-extend the contents of the 16-bit DM[] registers to 32-bit variables
   '  and perform the math as if the variables are 32-bits wide.
   '  
   '  But you are only interested in the least significant 8-bits of the DM[]
   '  registers. The fix is to perform a bit-wise and operation and preserve
   '  the least significant 8-bits and force to 0 all of the rest of the bits that
   '  either you don't care about or never existed (sign-extension).
   '
   IF ((DM[541] & (~DM[537])) & &hff)
       SETIO CBP
   ENDIF
ENDIF

Best regards

Gary D*ckinson

156
I am having problem debugging a trivial program in 7.12.  I am breaking the simulator with the following code:
Code: [Select]
' FmtFloat - test CF that passes a copy of the the floating value, A#, and the argument, 1, to
'   the StripPlus function with the home that it will return a string in A$

%[1] = StripPlus(A#, 1)

When I try to test this code in the simulator I get the following run-time error message after StripPlus() executes and returns:


"Run-Time Error in Fn #1
 Error:illegal memory access!
 Program has been Halted"


This is the CF, StripPlus:
Code: [Select]
' StripPlus on entry %[1] is the float to convert, %[2] is the number of decimal digits
'
A$ = str$(%[1], -%[2])

' Now discarad the leading "+" that gets attached to positive values

if strcmp(mid$(A$,1,1), "+") = 0
   A$ = mid$(A$,2,len(A$)-1)
endif

Strip Plus actually does what I want, but I can't figure out what I have done to annoy the simulator.

I can write the code without the use of the "new" parameterized function calls, but I keep thinking there must be a use for this feature.

Do you have any ideas on how I broke the simulator?

Best regards,

Gary D*ckinson

157
Technical support / Re:Self Starting Timer
« on: June 08, 2017, 01:13:04 PM »
Please be aware that the time to the first output will be 1799 seconds and the time between each subsequent output will be 1800 seconds.

This has to do with the behavior of the COUNTER when used as an up counter.  If you need the first output and all subsequent outputs to be 1800 seconds apart then you must force the Present Value of the COUNTER to 0.

This initialization can be done with a custom function that contains the following code:

CtrPV[Count30Min]=0

You need a bit of ladder logic before the rung with the COUNTER that calls your custom function on the first scan of the ladder logic file.  The "1st.Scan" contact will get the jobs done.

Best regards,

Gary D*ckinson

158
Technical support / Re:TL7.12 Build 3
« on: May 31, 2017, 08:39:12 AM »
Thanks for the quick response.  I know that these are small issues on a cosmic scale. But I appreciate your Your willingness to continue improving your products.

Best regards,

Gary D*ickinson

159
Technical support / Re:TL7.12 Build 3 Save_EEP# documentation issue
« on: May 30, 2017, 03:51:30 PM »
I do have an issue with the documentation that pops up in the CF editor when you select the keyword, "Save_EEP#".  The attached screen shows the problem.

The title is "SAVE_EEP#(n)".  The problem is that SAVE_EEP# is a statement and not a function so the use of the "(n)" is nonsensical and the SAVE_EEP# accepts 2 variables, and value and a 32-bit index into the EEP data.

SAVE_EEP# is correctly documented in the TL7 reference addendum.  

However, if you attempt to get to this addendum from i-TRiLOGI 7.12 by Help->TL7 Reference Addendum you will get a 404 error with the following message, "Error 404 - Not Found
The document you are looking for may have been removed or re-named. Please contact the web site owner for further assistance."

i-TRiLOGI 7.12 is using the URL, http://www.triplc.com/TL7ReferenceAddendum.pdf, to access the addendum.  I'm betting that you wanted to point it at the .pdf that is in c:/TRiLOGI/TL7.

Best Regards,

Gary D*ckinson

160
Technical support / Re:reversing bits
« on: May 26, 2017, 08:47:51 AM »
You can eliminate the "else" clause in the "if" statement as all of the bits in B have been set to 0 outside the for loop:

B = 0

FOR I = 0 to 15
   IF TESTBIT(A, 15-I)
      SETBIT B, I
   ENDIF
NEXT


Gary D

161
Technical support / SetStop and Fx1616-BA Issue
« on: April 18, 2017, 02:04:08 PM »
The Fx1616-BA has 4 MOSFETs that drive OUTPUTS 5,6,7 and 8.  These can be used to drive 2 stepper motors using external driver boards.  This is fact and well documented.

In order to use Stepper Channel #2 to drive OUPUTS 7 and 8, i-TRiLOGI the ch argument must be 32 to access the stepper channel for the following TBASIC statements:
  • StepMove 32, count, r
  • StepMoveAbs 32, count, r
The following TBASIC functions and statements will accept either "32" and "2" as the "ch" argument and execute on real hardware as expected:
  • StepCountAbs(32)
  • StepCountAbs(2)
  • StepCount(32)
  • StepCount(2)
  • StepSpeed 32, pps, acc
  • StepSpeed 2, pps, acc
The "odd man out" is the StepStop statement.  The i-TRiLOGI complier will accept both "StepStop 2" and "StepStop 32". When running on Fx1616BA hardware,  "StepStop 32" does not abort the current motion command . "StepStop 2" does abort the current motion command.

The online help does suggests that legal values of "ch" are 1..8.  This is not true of any PLC that you have manufactured, yet.  There is no mention of the additional bits that are added into the channel number that determine if the channel is used as a direct stepper controller with 1 and 2 prefixes.  The 32 value is mentioned in the Fx1616BA User's manual for use with the StepMove statements.

Just add it to the list of stuff that is neither obvious nor consistent.

Best regards,

Gary D*ckinson

162
Technical support / StepMove and StepMoveAbs Documentation
« on: April 13, 2017, 05:03:04 PM »
There is a key bit of information that is not spelled out in the TRI documentation of the "StepMove ch, count, r" and the "StepMoveAbs ch, count, r" statements.

The issue has to do with the handling of the "r" argument to these statements. The "r" argument specifies which RELAY is to be cleared by the execution of the statement and then set, later, when the motion of the stepper motor has completed.  If the value of the "count" argument will result in the stepper not moving, then the RELAY WILL NOT be SET.

The problem with the StepMove and StepMoveAbs statements is that certain values for the "count" argument will result in the RELAY "r" not being set and this will result in PLC programs hanging up waiting for this RELAY "r" to be set.

The value that breaks StepMove is when "count" = 0.  The documentation states, "count is a 32-bit integer number which allows you to program the stepper motor to move from -231 to +/-231 .(i.e. about ± 2 x 109) steps".  Notice that the documentation includes the value of "0" in the range of legal values.  Trust me, 0 is not handled the same as the other 2 x 109 possibilities.

The value that breaks StepMoveAbs is when "count" equals the current absolute position.  The documentation for this statement does not mention this fact.

This is the sort of work-around that I use to ensure that all legal values for "count" work the same:


   ' The StepMove statement will not set the BrnCmdCmp RELAY if the
   ' the statement will result in no physical motion of the stepper motor
   '
   ' The fix is to execute the StepMove statement and then
   ' set the BrnCmdCmp RELAY
   '
   StepMove BrineStpprChnl,BrnArg1,BrnCmdCmp
   if (BrnArg1 = 0)
      SetIO BrnCmdCmp            ' set the command completion RELAY
   endif



   ' The StepMoveAbs statement will not set the BrnCmdCmp RELAY if the
   ' statement will result in no stepper motion
   '
   ' The fix is to test if the current absolute position is the same
   ' and the position specified in the argument to StepMoveAbs and after
   ' the StepMoveAbs statement is executed, set the BrnCmdCmp RELAY to indicate
   ' that the statement completed
   '
   if StepCountAbs(BrineStpprChnl) <> BrnArg1
      ' Move stepper to new position
      '
      StepMoveAbs BrineStpprChnl,BrnArg1,BrnCmdCmp
   else
      ' Stepper will not move, so execute the StepMoveAbs statement
      ' to update the stepper motion counters and then set the
      ' command completion RELAY to indicate that the statement has
      ' completed
      '
      StepMoveAbs BrineStpprChnl,BrnArg1,BrnCmdCmp
      SetIO BrnCmdCmp
   endif

[/color]


I know that the StepMove family of statements have been around for a long time.  I'm just new to using them.

Best regards,

Gary D*ckinson

163
Technical support / Re:Reseting Multiple Relays
« on: March 06, 2017, 01:20:19 PM »
Lorne your understanding of the for..next loop is essentially correct.

TRI's for..next documentation is not correct. Their text is in green. I've struck out the things that are flat out wrong and have added text in red for some of the stuff that they omited:


    FOR variable = x TO y [STEP z]
         . . . .
    NEXT

where variable may be any integer variable only
including A to Z, DM[] and DM32 and is used as a counter. x, y and z are numeric expressions either a constant value such as 1 or a variable such as J. Other numeric expressions are NOT allowed. STEP z is an optional part of the statement. x is the initial value of the counter, y is the final value of the counter. Program lines following the FOR statement are executed until the NEXT statement is encountered. Then the counter is incremented by the amount specified by STEP. If STEP is not specified, the increment is assumed to be 1. A check is performed to see if the value of the counter is greater than the final value y if STEP is positive (or smaller than the y if STEP is negative). If it is not greater, the program branches back to the statement after the FOR statement, and the process is repeated. If it is greater, execution continues with the statement following the NEXT statement. This is called a FOR-NEXT loop. A run-time error will result if STEP is evaluated to be 0.

For PLCs that support floating point, the x, y and z values can be floating point constants or simple floating point variables such as A#..Z# and FP[1..1000].

If the x,y or z values are located in DM[], DM32[] or FP[] the compiler will allow limited arithmetic expressions that involve constants and variables.  The following sort of expressions will run under simulation:
DM[0+1] and DM[n+1].

Please note that the values of the control, start, end and start arguments are evaluated and stored when the "for" part of the for..next statement is executed. Additionally the control variable's address is stored.  The end result of this is that if you specify a for..next loop using variables, changing these variables within the body of the for..next loop will have no effect on the operation of the loop.


The following PLC code will work:


' integer variable, constant start and end values
'
print #3 "for i = 1 to 10: ";
for i = 1 to 10
   print #3 i;" ";
next
print #3 ""

' integer variable DM[1], constant start and end values
'
print #3 "for dm[1] = 1 to 10: ";
for dm[1] = 1 to 10
   print #3 dm[1];" ";
next
print #3 ""

' integer variable, constant start, variable end
'
k = 15
print #3 "for i = 10 to k: ";
for i = 10 to k
   print #3 i;" ";
next
print #3 ""

' integer variable, variables start and end values
'
j = 10
k = 15
print #3 "for i = j to k: ";
for i = j to k
   print #3 i;" ";
next
print #3 ""

' integer start, end and step values
'
print #3 "for i = 10 to 1 step -1: ";
for i = 10 to 1 step -1
   print #3 i;" ";
next
print #3 ""

' integer start and end, variable step value
'
j = -2
print #3 "for i = 10 to 0 step j: ";
for i = 10 to 0 step j
   print #3 i;" ";
next
print #3 ""

' float variable, constant start and end values
'
print #3 "for i# = 1.0 to 10.0: ";
for i# = 1.0 to 10.0
   print #3 i#;" ";
next
print #3 ""

' float variable, variable start and end values
'
j# = 10.0
k# = 15.0
print #3 "for i# = j# to k#: ";
for i# = j# to k#
   print #3 i#;" ";
next
print #3 ""
[/font]

When run under the simulator the code will write this to a window:

for i = 1 to 10: 1 2 3 4 5 6 7 8 9 10
for dm[1] = 1 to 10: 1 2 3 4 5 6 7 8 9 10
for i = 10 to k: 10 11 12 13 14 15
for i = j to k: 10 11 12 13 14 15
for i = 10 to 1 step -1: 10 9 8 7 6 5 4 3 2 1
for i = 10 to 0 step j: 10 8 6 4 2 0
for i# = 1.0 to 10.0: 1.0 2.0 3.0 4.0 5.0 6.0 7.0 8.0 9.0 10.0
for i# = j# to k#: 10.0 11.0 12.0 13.0 14.0 15.0

Lorne there are a lot of things that you can do with the for..next structure.  

Once you get this mastered, that TBASIC also supports another powerful looping structure: while..endwhile.  The other very useful control structure is if..elif..elif..else..endif.

No end of stuff to learn.

Gary D

164
Technical support / Re:Reseting Multiple Relays
« on: March 04, 2017, 09:53:55 PM »
Lorne,

Your code will not clear relays 273..310.  As written it will only clear relays 273..289 because it only clears the 16 relays at RELAY[18] multiple times.

As written your code will not compile due the unmatched "ENDIF" statement.  

Perhaps you intended to write something like this:


' clear relays #273 to 321
for i = 18 to 20
    Relay = 0
next
[/size]

However, my code clears relays through 321 and not 310 as you seemed to want to do.

I would suggest that you name your RELAYS in the I/O table and use the names.  In this case I have named relays 1..3 as "Run", "Stop" and "Restart".
#Label Name
1Run
2Stop
2Restart

If you want to clear the relays in a custom function, just use ClrIO:

ClrIO Run
ClrIO Stop
ClrIO Restart
[/size]


I prefer that approach for the following reasons:
1. The code is easier to understand as the RELAYs have descriptive names.
2. If you insert or delete a RELAY in the I/O table and this results in the relay having a different number, your code will work as written. This is not the case with RELAY[n] as it always accesses the same relay numbers.
3. The use of the RELAY[n] notation affects 16 RELAYS.  The use of RELAY[n] requires you and the next guy that tries to fix your code to "know" what relays are affected by the use of RELAY[n].
4. The use of RELAY[n] notation requires you to be very careful and deliberate on how you name your RELAYs. If you delete something from the I/O Table and this results in your RELAYS moving up/down in the table, then your relays may not align on on the required 16 bit boundary.

I do use the RELAY[n] in my code BUT, it is very limited and I document it usage very carefully so that I (or the next guy) will be able to understand my intent.  

Gary D



165
Technical support / Re:Creating a FIFO
« on: February 22, 2017, 09:59:12 AM »
 Lorne,

Great to hear that you have been able to figure things out.  Debugging PLC programs is nearly impossible.

Let me know if there is anything else that I can help you with.  

Gary D

Pages: 1 ... 9 10 [11] 12 13 ... 34