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 ... 4 5 [6] 7 8 ... 34
76
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

77
Technical support / Re:Trouble Reading FP Values
« on: January 27, 2019, 05:13:20 PM »
Mark,

Your Modbus register address of 5000 may be correct.  If you are aceessing FP[1] via the Wientek HMI the correct answer will be 5001.

You have a 50:50 chance of getting them correct.

It depends on how the READMODBUS deals with the register address.  I don't use the READMODBUS and WRITEMODBUS functions/statements as they are too limiting for my usage, so I can't answer this question with 100% certainty.  But, I can give you enough info so you can figure it out.

OK, lets get to the problems with your code:


C# = READMODBUS (13,2,5000)  'READ Value from Aux 2

D# = READMODBUS (13,2,5001)  'READ Value from Aux 2


Problem #1 is that ReadModbus() returns a 16-bit integer and not a floating point value. so you can't assign it to a floating point variable such as C# or D# and expect to make much sense of it

Problem #2 is that you did save the 16-bit values returned by the calls to ReadMobus() so that you could build a 32-bit value that represents the correct bit pattern of the target FP[1] value.

Problem #3 is that you need to "cast" this 32-bit integer value so that you can store it a 32-bit float.

This is closer to what you need to do get read a 32-bit float:


' Read 2 sequential registers from target PLC and
' save as integers

c = READMODBUS (13,2,5000)     ' most signficant word
d = READMODBUS (13,2,5001)     ' least signficant word

' move msw pattern read from Modbus into msw of the variable "e"
'
e = c
e = e * &h00010000

' now add in the lsw bit pattern read from Modbus
'
e = e + (d & &h0000ffff)

' assign the 32-bit signed integer, "e", bit by bit to the C#.
'
' bits2float() acts as a cast. If bits2float were not used then
' TBASIC will attempt to create a floating point representation of the
' value of "e" and this is not what you want!
'
C# = bits2float(e)
[/color]

OK. I am going to give you a way to figure out if 5000,5001 are the right register addresses:

'InitFP - CF to intialize FP[1..32] with known values
'
' The pattern was picked to be easy to "see".
'
' FP[1] -> &H01020304
' FP[2] -> &H05060708
' FP[3] -> &H090A0B0C
'  .
'  .
'  .
' FP[32] -> &H7D7E7F80
'
n = 1      ' initial byte value pattern
for i = 1 to 32
  a = n              ' msb of 32-bit pattern
  a = a * 256     ' shift left 8 bits
  a = a + n + 1
  a = a * 256     ' shift left 8 bits
  a = a + n + 2
  a = a * 256     ' shift left 8 bits
  a = a + n + 3   ' lsb of 32-bit pattern

  FP = bits2float(a)    ' convert to float and store

  n = n + 4       ' next byte value pattern
next
[/color]

Initialize the target FP[] array using the test pattern generator.  Now run your ReadModbus test code under the online simulator and look at the values that you are getting back from Modbus for the MSW and LSW and you will be able to figure out where they are coming from. You will be able to adjust the Modbus register values if needed.

In the view window of the simulator, when looking at float variables you can either view them as IEEE (which is the hexadecimal 32-bit value) or "DEC" (which is the floating point value represented as a base 10 decimal value like "-3.141597"). Pick IEEE and look at the hex values.

Best regards,

Gary D*ckinson

78
Technical support / Re:Stepper Stepping Bit ?
« on: January 13, 2019, 03:31:16 PM »
Mark,

I think what you really what to know is when is the stepper controller busy and when the stepper controller has completed a move operation.

Please note that the argument "r" in the step move command allows you to specify an internal PLC RELAY to set when the STEPMOVE has issued "count" pulses to the stepper channel specified by "ch".

STEPMOVE ch, count, r

The STEPMOVE and STEPMOVEABS statements are "non-blocking".  These statements execute quickly and the TBASIC goes on to the next part of the program before any step pulses are issued. The actual movement of the stepper might take from a few milliseconds to a few millennia depending on number of steps in the "count" argument. You don't want the PLC hung up waiting for the stepper movement to complete.

For Stepper channel #1, I define a RELAY named Ch1CmdCmp and issue a stepper command like this:

StepMove 1,Ch1Arg1,Ch1CmdCmp

The RELAY named Ch1CmdCmp will be reset to 0 by the execution of the StepMove statement. The same RELAY will be set to 1 when the stepper motion has completed.  So when the CH1CmpCmp RELAY is 1 then you can issue a new StepMove or StepMoveAbs command. When the CH1CmpCmp RELAY is 0 the CH1 stepper controller is busy moving the stepper.

There is a small issue with the StepMove and StepMoveAbs, and this is that if the count argument would result in no stepper pulses being issued (no motion) then the RELAY, "r", will be cleared but will not be set to 1.  This is how I make the behavior of the RELAY consistent:


       ' The StepMove statement will not set the Ch1CmdCmp 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 Ch1CmdCmp RELAY
       '
       StepMove 1,Ch1Arg1,Ch1CmdCmp
       if (Ch1Arg1 = 0)
              SetIO Ch1CmdCmp       ' set the command completion RELAY
       endif



       ' The StepMoveAbs statement will not set the Ch1CmdCmp 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 Ch1CmdCmp RELAY to indicate
       ' that the statement completed
       '
       s = StepCountAbs(1) - Ch1Arg1       ' s is the distance to the new position
       StepMoveAbs 1,Ch1Arg1,Ch1CmdCmp       ' issue the stepper command
       if (s = 0)
              SetIO Ch1CmdCmp       ' the Ch1CmdCmp Relay will not be set, so force it.
       endif



I have posted a full up stepper motor test system on this forum.  I have included documentation, PLC firmware as a .pc6 and firmware to support a the MT8050iE HMI that TRI offers on their website.

This code provides a full stepper test system for a single stepper.  The PLC code is very small and very fast and uses all of the stepper commands.  The code can be run without hardware with the simulator and if you have no HMI, you can run the code on real hardware using On-line monitoring.  I think that I put hints in the documentation on these things.

Look for the topic: "Stepper Motor Demo Code".
The posting date was May 02, 2018, 03:10:38 PM.
http://www.triplc.com/yabbse/index.php?board=1;action=display;threadid=2347

Best regards,

Gary D*ckinson

[Forum Editor's Note]: Have edited this post and removed the funny characters that were present in the original post.

79
Technical support / Re:Mobus Writes Blocking PLC inputs
« on: January 13, 2019, 08:53:04 AM »
Mark,

Your approach would work.  However, this requires that the CF be called on every scan.

I'd suggest something a bit different, use the dCust function and trigger it off the 0.1sec clock.  Change your CF to make a decision on each count value.

I would suggest that you NOT use one of the a..z variables as a counter as you need to preserve this value between calls to this CF.  I prefer using the #Define mechanism to "create" a variable out of the DM32[] array.  You could define MBCounter as being DM32[100].  So your code would look like this:

If MBCounter = 0
    Writemodbus ...
elif MBCounter = 1
    Writemodbus ...
endif

MBCounter = (MBCounter + 1) mod 2   'Increment and keep bounded

Best regards,

Gary D*ickinson

80
Technical support / Re:Mobus Writes Blocking PLC inputs
« on: January 12, 2019, 11:13:12 AM »
Mark,

You are not crazy.  What you are observing is exactly how the WRITEMODBUS and READMOBUS family of statements/functions operate.  These statements/functions are "blocking" operations.  By this I mean that the execution of the CF is blocked (suspended) until the Modbus communication is completed.

As an example if you have a very simple ladder logic program that calls a CF on each scan to communicate with a Modbus device and this communication takes 1 second, then this will result in your ladder logic program taking a bit more that 1 second per scan.  This, also, means that if an input changes state, the PLC program might take up to a second to respond to the input change.  If the input changes state once a second, then the PLC program will probably miss changes in the INPUT state.

OK. What can you do to to ensure that the PLC remains responsive to changing inputs?
  • Reduce the rate of Modbus requests to the slave to the absolute minimum.
  • Perform only a single Modbus operation per ladder logic scan.
  • Ensure that between Modbus operations that the ladder logic is allowed at least one scan of the ladder logic.

One of your questions has to do with speed. "How quickly can dCust functions containing something like WRITEMODBUS 13,2,1263,DM[11] be pulsed ?". The short answer is 100 to 1000ms.  The answer is depends of things that you don't have too much control over:
  • The amount of time it takes for the PLC to handle the WRITEMODUS function and generate a Modbus request data structure.
  • The time it takes for the PLC to transmit this data structure. This happens in the low level PLC firmware and is a function of the communication link.  If you are using Modbus RTU (serial link) at 9600 BAUD it will take about 1ms for every 8-bit byte in the request packet to get pushed onto the serial link.
  • The slave device has to process the Modbus request.  The slave device has to determine if the slave address matches the address of the slave device. If the address is correct then the slave device has to verify that the rest of the Modbus request is valid and then create a response data structure to be sent back to the master device.
  • The response is then transmitted back to the master. Since the data is sent out a bit at a time, there is some minimum transit time to get the data down the wire. If you are operating at 9600 BAUD it will take about 1 ms for every 8 bit byte to be pushed down the wire.
  • The master PLC has to wait until the entire response is received and then verify that the response is valid. Only then will your CF continue.
  • If the slave device does not respond to the request, the master device will wait for a long period of time before returning control to your CF.  If you follow the Modbus standard, this may result in the PLC locking up (blocking) for 3 seconds before timing out.
You can measure the amount of time a READMODBUS/WRITEMODBUS function/statement takes to execute with the Status(21) function. Status(21) returns a 32-bit value of a 10 MHz counter that is buried in the PLC hardware.  I use code like this for test:

A = Status(21)                        ' time before the statement
WriteModbus ch,id,address,data
B = ABS((Status(21) - A)/1000)   ' elapsed time in ms in B

Another question that you had was, "Should you use dCust or some other function holder ?".  The answer for 99.9% of the cases is "yes".  

If you use "Cust" without the "d" then the custom function will be called on every pass through the ladder logic.  I have invoked CFs with "Cust" but these are very special situations and the CF that gets invoked is ptimized to solve a very special problem, very quickly.

I do not use the READMODBUS/WRITEMODBUS functions/statements for Modbus communications over serial links because of the blocking behavior (and a bunch of other limitations).  I use my own Modbus communication code written in TBASIC.  I use a single CF to format and send the Modbus request.  A TIMER is started by the first CF and after the TIMER runs out a 2nd CF is called to handle the response to the Modbus request.

I can issue a maximum of 20 Modbus commands a second without causing the PLC to miss INPUT events.  This is not possible with TRI's READMODBUS/WRITEMODBUS keywords.

I have have this code in over 40 PLC based systems spread all over the world.  Some of these systems were installed 5 years back.  I have had no problems with this approach.

Best regards,

Gary D*ckinson

81
Technical support / Re:TimerPV countdown
« on: January 09, 2019, 02:03:38 PM »
Dave,

Good luck with your experiments.

The processor used on the SmartTile is fastest of all the PLCs that I have used from TRI.  I have measured scan rates for trivial ladder logic programs at about 200 Hz (0.005 second period)!

As a guide to execution speeds, ladder logic exection is extremely fast.  The execution of TBASIC (Custom Functions) takes more CPU time. So I tend to do as much work in ladder logic as possible and use CFs only as needed.

I do not know how you have connected the HMI to the PLC.  On most of my systems I have chosen to use a serial link.  I use Modbus RTU between HMI/PLC. I have found that the PLC overhead is less with this combination then when using Ethernet and the TRI hostlink protocol.

There are things that might work for you that could create a down counter with a 0.1 second resolution without the use of the PLC.  The HMI has a free running system clock with a resolution of 0.1 seconds.  This clock is accessible to the HMI's version of custom functions called macros.  It is possible to have a macro called at a rapid rate when a window is being displayed.  This would allow you to build a numeric display object would display the value of a variable local to the HMI.  This approach does not require as much bandwidth between the HMI/PLC.  This approach would present less issues with PLC scan rate as you are not using a PLC TIMER.

Best regards,

Gary D*ickinson



82
Technical support / Re:PLC hanging
« on: January 09, 2019, 09:11:26 AM »
Joel,

I am glad that you are making progress on debugging.  

Noisy mechanical contacts can be troublesome.  Your solution with setting a RELAY on an input going active and clearing it only after some event has occurred seams reasonable.

I, often, condition noisy mechanical contacts by using the noisy INPUT to control a TIMER with a SV of 1 (0.1 seconds).  I use the TIMER's contact in the rest of the ladder program.  This introduces a small bit of a delay in response to the input but filters out any false signals.

Gary D*ckinson


83
Technical support / Re:TimerPV countdown
« on: January 08, 2019, 02:25:15 PM »
Dave,

Inorder for the HMI to display a TIMER PV that is changing at a 10 Hz rate (0.1 second period) the following things must happen:
    [*] The HMI has to be able to request the TIMER PV at a 20 Hz rate (0.05 second period) to not miss a single count.  This is a the Nyquist sampling rate minimum.  The total time to send the request from the HMI to the PLC for the TIMER PV, the time for the PLC's low level firmware to respond to this request, the transit time to return the data to be to the HMI and finally the time required by the HMI to process the data and update HMI window, must be less than 0.05 seconds.
    [*] The PLC ladder logic scan rate has to equal or exceed 20 Hz for the TIMER's PV to update without missing a count.  The TIMERs are implemented in firmware on the PLC and the TIMER PV is only updated at the start of a scan of ladder logic.
    [/list]

    If your requirement is to display time to 0.1 seconds without losing counts on the HMI display, then you need to reduce the time that your PLC program takes to execute.

    The PLC scan rate is directly affected by the complexity of the PLC program.  You can test this by writing a 2 line PLC program.

    The custom function, ScanDelay, is a time waster that can be used to emulate a complex PLC program:

    ' ScanDelay - CF that wastes time to simulate a complex PLC program
    '
    ' The variable A, determines the number of ms to waste
    '
    Delay A
    [/tt]

    You can change the value of "A" using online-monitoring.  You will probably have to exit the on-line monitor to see the affect of slowing down the ladder logic scan rate.  The communication between your PC and the PLC to support on-line monitoring will probably slow the PLC to the point that the TIMER PV will appear to miss cycles.


    Gary D*ckinson

    84
    Technical support / Re:PLC hanging
    « on: January 08, 2019, 01:58:28 PM »
    Joel,

    I am glad that TRI was able to give a better answer.  I have been working with a similar problem with PLC systems in the field "hanging" after running without issue for years.

    I have been working with code to act as an interrupt trap and then REBOOT the PLC.  Simply rebooting the system may be enough to make the PLCs appear to be reliable.  Unfortunately the message that describes the run-time problem,

    "Run-Time Error in Fn #5.
    Error: DM32[] index out-of-range"

    and

    "Undef. Interrupt
    CF #0005:006E"

    are not available to PLC custom functions.  So the interrupt trap code cannot log the reason that the PLC was REBOOTed.   This makes it impossible to figure out what the real problem is and impossible to actually fix.

    Best regards,

    Gary D*ckinson

    85
    Technical support / Re:PLC hanging
    « on: January 08, 2019, 08:32:18 AM »
    Joel,

    I am pretty good at writing code that misbehaves and breaks the PLC.  

    Your issue with the runtime error about DM32 index values would be easy to fix if you were using DM32.  

    I assume that TRI is working with you to figure out the actual problem.

    You can search the forum for "F8” and you will find a bit of info on debugging of run time errors and some hints from TRI.

    Best regards,

    Gary D*ckinson

    86
    Technical support / Re:switching roller shutter motor with one push button
    « on: December 28, 2018, 01:01:39 PM »
    Rozik,

    I would implement a simple "drum sequencer" in ladder logic.

    I have attached a pdf of how you could write a sequencer for the problem that you stated.  

    You should be able to copy this example and run it under the iTRILOGi simulator.

    Best regards,

    Gary D*ckinson

    87
    Technical support / Re:Watch dog timer test Code
    « on: December 07, 2018, 04:05:04 PM »
    Please find attached PLC program that provides documentation on both the watch dog timer and the user-defined run-time error trap mechanisms.

    Gary D

    88
    Technical support / Re:Watch dog timer.
    « on: December 07, 2018, 04:01:49 PM »
    Thanks for finding the documentation on the User-Defined Run-Time Error Trap.  I couldn't find it in my panic.

    I have updated by test program for both the watch dog timer and the user-defined run-time error trap to include the TRI documentation for these mechanisms.

    I have some suggestions on how to make these two mechanisms actually useful for PLC applications:
    • Make the error messages written to the PLC "visible" to custom functions.
    • If the user-defined run-time error trap has been setup change

    the behavior of the current WDT to call the same trap handler that
    is used for the run-time errors.  If you do this, it would be great
    if the WDT timeout mechanism updated the LCD with some sort
    of error message that would indicate that the problem is WDT timeout
    [/list]

    Why?  This way the error handler can log the exception that terminated the PLC execution to either EEPROM or the filesystem. This allows debug of PLC systems that are running in the field and not in my lab.  I am looking for ways to monitor 25 systems that are running at remote sites in 3 different countries.

    To make the error messages available to the error trap provide some "special" access to the text array that your low-level firmware manages for the LCD display. I know that it is buffered on the PLC because it can be accessed via host link commands even if no LCD is physically connected to the PLC.

    Maybe one of these access methods could be provided:
    • Special case the LOAD_EEP$(n) to return the LCD buffer lines with the n has values such as -1,-2,-3,-4.  I think you have already special case LOAD_EEP$(0) to return some string about PLC firmware version.
    • Special case the $$[n] string mechanism to return the LCD buffer info for some value of n that is outside of the range 1..26.  So $$[-1] might reference the first line of text in the LCD buffer
    • Modify the run-time error trap code that writes the error message to the LCD to also copy the error message to Y$..Z$ before executing

    the user-defined run-time error trap CF.  These variables are "toast" as the CF can't do much other than reboot the PLC.
    [/list]

    Best regards,

    Gary D*ckinson

    89
    Technical support / Re:fx2424 output current
    « on: December 05, 2018, 09:03:53 PM »
    I'd vote for some sort of external buffer or relay rather than attempting to parallel two outputs.

    Paralleled MOSFET transistors share load currents much better than bipolar transistors.  There are some issues if you are switching loads at high frequency.  Because the driver IC handles 8 outputs you do have to worry if the load current for your solenoid and the other outputs will result in the driver chip over heating.  If the IC is socketed, you can replace the driver if it fries.

    I am not certain if PLC outputs turn on/off at exactly the same time.  If there is a delay from output to output then only one of the two transistors will be on for a little while and this may cause some reliability issues.

    Outputs 5-16 use discrete mosfet transistors for each Output.  These outputs could easily handle your solenoid power requirements.  Do make use of the GND terminal on the PLC output headers to try and shunt load currents back to the system ground point rather than having the load currents mix in the PCB ground plane.


    Gary D

    90
    Technical support / Re:Watch dog timer.
    « on: December 05, 2018, 03:56:19 PM »
    Thanks for reminding me about the INTRDEF 100,n,1 stuff.

    It is not documented anywhere that I have found.  

    The help info for INTRDEF from within the CF editor looks like this:

    Enable Interrupt Input channel ch.
    ch = interrupt channel number (pls refer to PLC installation guide)
    fn_num= Custom Function number to execute when interrupt pin changes according to the defined edge. This is the Interrupt Service Routine ISR.
    edge = Positive number means rising edge-triggered. 0 or negative number means falling-edge triggered.


    No mention of Undefined interrupt trap (ch# 100).

    The "help" mentions the "PLC installation guide".  However your website's product documentation section doesn't have any installation guides.

    There are user manuals on the website. I have gone through each of the user manuals there is no mention of INTRDEF with ch# 100.

    The TL6 Reference Manual does give some generic info on INTRDEF, but suggested that the Ch argument is from 1..8 (physical inputs) only.

    The TL7 addendum makes no mention of INTRDEF.

    Is there any change to TBASIC/PLC firmware that would allow a user-defined interrupt CF to determine, what interrupt caused the exception?  Or the CF number that was executing when the exception occurred?

    Gary D

    Pages: 1 ... 4 5 [6] 7 8 ... 34