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.


Topics - garysdickinson

Pages: [1] 2 3 ... 5
1
Technical support / Implementation of a Stack or LIFO in TBASIC
« on: January 06, 2020, 03:31:35 PM »
This post shows how to implement a stack or Last In First Out data structure in TBASIC.

This example builds the stack in DM32[]. 
The size and location of the stack is controlled by entries in the #Define table.
Separate custom functions to initialize, push data and pop data are written to be as small and fast as possible.

The Stack.PC6 file is attached to this post. This is test bed code that will run in the i-TRiLOGI  simulator. This code should be easily adaptable for many uses.

The next post will have post a bit of documentation on how the stack operates.

Best regards,

Gary Dickinson

2
Technical support / User written Modbus RTU example code
« on: June 11, 2019, 05:22:29 PM »
I am presenting the code that I have been using for the last 5 years as an alternative to the TBASIC ReadModbus, ReadMB2, WriteModbus and WriteMB2.

This code is supports all possible Modbus function codes.

This code is non-blocking. The PLC does not lock up waiting for a response from the slave device.

This code is an example of a user written communication protocol

This code allows you to see both the Modbus response packet and every byte received from the Modbus slave.  This allows you tremendous debug capability that is not available with the TBASIC Modbus support.

I will post the PLC code and the documentation in pieces to keep them under 200KB

Regards

Gary Dickinson

3
The forum webpages are displaying odd Unicode characters in place of ASCII spaces or ASCII tabs.  These characters are showing up: ���

Is there some secret settings I need to make to my internet browser to fix these funny characters?

Best regards,

Gary D*ckinson

4
Technical support / use of the goto @n statement
« on: December 03, 2018, 08:20:30 PM »
Gentlemen,

I am quite confused about the goto statement. I have never used one as it is considered by many to be "unsophisticated".  But I have been playing with them in an attempt to write a CF that consumes a lot of CPU time without the use of for/next, while/endwhile, delay or SetLCD statements as all of these resets the WDT mechanism.

So I set out to write a non-sense program that used nested for/next loops and a lot of string functions. I picked on the string functions because they are slow.

I wrote the following nonsense code and cannot get it to compile:

' for_next
'
' This code is an eumulation of a for/next loop using goto statements
'
'
/*
   for j = 1 to 3
      b = b + b
   next
*/


j = 1         ' loop counter initialization
@200
if j > 3      ' range check
   goto @220
else
   ' loop body
   '
   b = b + b
@210   ' continue entry point
   j = j + 1   ' counter + step value
   goto @200
endif
@220         ' loop exit
[/color]

The compiler exits with the following error message:

Error:Undefined GOTO destination: @: "-36"

and the first 3 characters of the last line of the program are highlighted in yellow:

@220         ' loop exit

Any idea what this error message means?

Any idea what I have done to offend the compiler?

Best regards,

Gary D*ckinson

5
Technical support / Watch dog timer.
« on: November 21, 2018, 06:45:08 PM »
I have a client that is concerned that his PLC based system is becoming non-responsive.  He has 25 of these systems running in at least 3 different countries. These systems have been running for 3+ years.

I am looking at the SetSystem 255 command.  This is described as an "on-CPU Watch Dog Timer".  I fully understand the concept of this mechanism.

However I am puzzled by the documentation.  The initial description, "If enabled and the CPU goes astray because of noise induced troube, the WDT will reset the CPU when it times out."  This is exactly what I would expect for a WDT.

Here is where I get into trouble.  The documentation talks about "when the programed is stucked [sic] inside a GOTO loop".  Then the documentation states that "the WDT will not kick in if your program is stucked [sic] inside a FOR..NEXT or WHILE..ENDWHILE loop."  So you are telling me that the WDT only works in a GOTO loop but not FOR..NEXT or WHILE..ENDWHILE?  This makes no sense.

Now for the big issue the documentation states, "WDT also will not activate if your program encounters undefined interrupt error..."  

I believe that there is a SetSystem command that allows me to set up an trap for undefined interrupts.  I, currently, can't find where this is documented, but I believe that I can create a CF that could reset the PLC in the event of these interrupts.

Can I use both the WDT and the undefined interrupt trap at the same time?

Can you point me to the documentation for the interrupt trap?

Best regards,

Gary D*ckinson


6
Technical support / Stepper Motor Demo Code
« on: May 02, 2018, 03:10:38 PM »
I have attached the PLC program StepperTest V2_01.PC6 to this post.

This is a test program that I wrote about 3 years ago to test a stepper motor-controlled valve.  This is a simplified version of that test code.  

If you are thinking about use the PLC for stepper control, this is an excellent starting point as all of the code can be used and extended for your purposes.

Best regards,

Gary D*ckinson

7
Technical support / Tic Tac Toe game for PLC
« on: December 08, 2017, 11:35:22 AM »
I got bored.  So I wrote PLC program to play Tic Tac Toe (Noughts and Crosses).  

The game will run on any of the current TRI PLCs.  The program does not use any physical INPUTs or OUTPUTs. You could run it with a Nano-10.  The game can be played using the on-line monitor or using a touch screen HMI.  I'll put up the code for the Weintek HMI that I am using in a future post.

The game is written in 99.9% ladder logic.  It is a good demo of the use of PLC sequencers to implement finite element state machines.

I'll put up some documentation that helps explain my use of state machine design and the PLC sequencer mechanism.

I've attached the PC6 program to this posting.

Gary D*ckinson

8
Technical support / Update to i-TRiLOGI
« on: November 07, 2017, 06:25:15 PM »
I just tried to see if a new update to the i=TrRiLOGI software was available by clicking

Help->TRiLOGI Update  (from i-TRiLOGI V 7.12 Build 04)

This opened my default web browser  with this URL: http://www.triplc.com/TRiLOGI/Help/upgrade.htm

Unfortunately this URL cannot be found and my browser returned a 404 error.

I assume that things are in flux and I will check back later.

Best Regards,

Gary D*ckinson

9
Technical support / TIMER Contact Behavior
« on: September 13, 2017, 04:41:50 PM »
I have run into a ladder logic behavior that I can't quite figure out.
I have attached a screen shot of the entire program.

The middle rung of logic is a simple oscillator that uses a TIMER and it's inverted contact in a bit of a loop.  I am an old hardware guy and I'd describe this as either a relaxation oscillator or a ring oscillator.

My expectations are that once the TIMER runs out that it's contact would go active for 1 entire scan of the ladder logic and then go inactive for the SV period of the TIMER.

This contact behavior is consistent with both the simulator and my Nano-10 test hardware.


What I observe:
  • The TIMER counts down and reloads with a period determined by it's SV.  It oscillates as expected!
  • The TIMER's contact goes active and inactive and can be "seen" on ladder rungs before the TIMER.  As expected!
  • The contact appears to only be inactive after the rung with the TIMER.
The sample code has 2 simple pulse catches that sets RELAYs if the TIMER contact is ever active.  These RELAYs can only be cleared by restarting the PLC or via the online monitoring program.

Why can't I come up with a good story as to why the RELAY contact is not visible below the line of code with the TIMER, but is visible on the next scan to ladder rungs that come before the TIMER.

I am just getting too senile to work with this stuff???

Best regards,

Gary D*ckinson

10
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

11
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

12
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

13
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

14
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

15
The simulator's handling of CHR$(n) does not match the PLC's behavior.

The simulator accepts 16-bit values for n and can create strings that appear to be an array of 16-bit values.

As an example:

A$ = CHR$(&H4548)

Creates a string that is 1 character in length and this only character has a value of &H4548 when run with the simulator.

When run on a PLC this same code creates a string that is 1 character in length and this character has a value of &H48.

I vote that the PLC's handling is correct.

I suspect that the Java library that you are using supports Unicode in some general way (localization) and that the java code that is close to CHR$() will accept 16-bit Unicode values.

I think that you should mask off and only use the least significant 8 bits of the "n" argument to CHR$(n).  This would make the simulator behavior match the PLC.

I don't care that the simulator implements strings as arrays of 16-bit integers rather than 8-bit integers as the PLC does.  This difference is not important and only shows up because of the implementation of CHR$(n) is flawed.

Gary D*ckinson

Pages: [1] 2 3 ... 5