AzeoTech

Administrators
  • Content Count

    5,686
  • Joined

  • Last visited

Posts posted by AzeoTech


  1. That's what the global variables are for.  Create a sequence marked Auto - Start that declares and initializes those variables:

    global startTime = systime()

    global endTime = systime()

    Then have the date/time controls edit those two variables.  Finally, add a button that parses the values and sends to the device as I described.


  2. OK, are you sure it is 32 bit?  Doesn't matter, but seems excessive since each value is well below the 16 bit limit.  Anyhow, you'll have to create a global variable that contains the start time and one for the end time.  Then have the user interface elements edit those variables.  You'll need a button to trigger some script that updates the schedule times in the PLC.  That script could be done in a number of ways, but probably the easiest is to use formatDateTime() [see section 4.12.11 of user's guide] to get the date/time number into a comma delimited string:

    private string x = formatDateTime("%Y,%m,%d,%H,%M,%S", starttimevariable)

    then use parse() on that string to get each value:

    private out = parse(x, -1, ",")

    which will return an array of those 6 values which you can then send to your Modbus device.


  3. Well, the trick is first determining what format your device expects the date and time.  You definitely can't just tell it January 15th 2020.  It won't understand that, and Modbus doesn't support sending that sort of information anyway.  Usually date and time is stored internally in computers as some sort of number referenced to an epoch.  For example, DAQFactory stores date/time information as seconds since Jan 1, 1970 (standard Unix time format), while Excel uses decimal days since 1900.  These are very different, as today we are at about 1.57 billion seconds since 1970,  but only about 44,000 days since 1900.  Anyhow, you'll need to find what your device expects then I can describe how to get there.


  4. I'm afraid it would take a bit of experimentation so you are on your own.  But yes, if the value is less than or equal to 32767 you can just treat it as an integer and use it as is.  If it is > 32767 then you have to do the conversion.


  5. OK, that is a new, and quite proprietary way of dealing with floating points.  I don't know why they just didn't do what everyone else does and use two registers and regular IEEE floating point format....

    You have to take the U16 value you get from the PLC and process it like they are floating point values in this weird format.  You can tell if they are floating point because the value returned will be > 32767.  

    There is not a simple Conversion you can apply.  You would have to use script.  I'd probably either use the to.bit function to get the bits and then calculate it, or use some bitwise math to extract the proper values.  The tricky part is the sign, which is not in a usual place because the breaks aren't at 8 bit intervals.  You will likely need to experiment.

     


  6. If you are opening a database but never closing it, you will leak memory.  It will be a pretty slow leak, but after a week could use up all available memory.  Windows responds to complete loss of memory in weird ways, and a bluescreen is not unheard of.  Personally I don't close my databases.  I open them at startup and just leave them open while DAQFactory is running.  DAQFactory will close it automatically when it shuts down.  File handles often have to be closed to force Windows to clear the write cache, or to allow other applications write access to the file, but databases do not have this issue.  If you are seeing that the database appears to not be updating in another program while DAQFactory is working with it, it may be that the database is transactional and you need to perform a commit on the database.  The SQL command for this varies on the database, but for, say, Firebird, the command is just "Commit".


  7. We had some issues with reliability in some cases so dropped UDP support.  The code is, however, still in there.  We just removed the button to allow you to add a new UDP connection.  So, you should be able to create a document in the older version with a UDP connection, then bring it forward to the new release and the port will still be there.  If your document is complex, we might be able to do this for you without you having to recreate your document.  Just email us the doc.  You would, however, need to be on the latest release.


  8. Yes, go to View - Properties to display the docking properties window.  Then select your component(s).  Find the property named "Align".  Set to 0 is default auto-size, 1 = left justify fixed size, 2 = center, 3 = right.  Once it is non-zero, you'll be able to resize the component, and in fact need to to make sure the component is big enough for all values as the system will no longer size it for you.


  9. First, see if you can read the bits individually from the controller.  Many controllers will offer discrete I/O both in packed form on an input / holding register, or as individual bits using coils / input status registers.

    But if you have to get it packed, just use the testbit() function.  So in your LED, if you want it to light up if bit 3 (numbered from 0, so the 4th bit) is on for "MyChannel", you would do:

    testbit(MyChannel[0], 3)

     


  10. There are actually very few times it is used as a command as it is largely left over from when DAQFactory had table driven sequences which was like 18 years ago.  It is used most often for the U12 driver as the U12 is equally old and its driver thus developed during the time before proper scripting.  The UE series devices I believe only use it for specifying the second input to use for differential analog inputs.  OPC uses it for specifying the actual OPC tag (thus the OPC part of its name) but usually you should use the OPC browser to pick it.  Other than that I can't really think of any other places a driver utilizes this field, thus the reason most people just use it for channel notes.


  11. Its actually more about the historical graphing than anything else.  I'm working on a system with a single Atom that runs 3 copies of DAQFactory simultaneously (to connect to three identical systems), but using OPC, but with about 1000+ channels each.  But most of the automation is being done in the PLC, and DAQFactory is largely just an HMI in this case.  The HMI has minimal historical trending, but does log to a CSV about 100 channels.  The Atom is more than capable for this application and really only bogs down when I fire up the PLC's development environment, which is a bit of a behemoth and has nothing to do with DAQFactory.   For that I had the customer buy an i7 laptop so that we don't have to run that PLC programming software on the atom.

    I'm working on a separate Atom powered system that is only about 15 tags, but does things at high speed (50 hz software sampled data rates) and stores and trends huge amounts of data.  For this application I feel like the Atom was a bit underpowered.  It works fine for the acquisition, but when they do the analysis and trending, it seems a bit sluggish for my taste.

    In general DAQFactory is 20 years old and was originally designed at its core to run on slow PC's 20 years ago.  Even the slowest of today's computers are way faster than ones available 20 years ago, so DAQFactory should do fine.  The issue often comes down to the OS: is the processor fast enough to adequately run the latest version of Windows?  After that, it unfortunately comes down to the details of your application and, if the application has a lot of data processing, how efficient you are in your scripting, but this really only applies on more advanced applications.


  12. You don't really need the delay() between calls as the CPU is released while waiting for a response.  You do need a delay inside any error handling, i.e.:

    while(1)
       try
          // read the devices
       catch()
          ? strLastError
          delay(0.1)
       endcatch
    endwhile

    If you don't then if there is a typo in your code, or some other error, it will get repeated without any CPU release, tying up that CPU and possibly hanging or at least greatly slowing DAQFactory.

    A few notes on your app:
    1) 115200 is quite susceptible to noise due to the duration of each pulse, so be especially diligent with your shielding and termination
    2) there is often required a 10 to 20ms delay in polls when switching between multiple devices on a multidrop system.  This is because the transciever on the first unit will "hold the line" and not allow you to move on.
    3) for the above reason, and because DAQFactory is multithreaded, you can get much higher data rates if you put each device on its own RS485 line and then have separate, concurrent running script to poll each device

    As to your original question, you can always use the time stamp of your data points to determine throughput.  Or add script to do so using the system clock.


  13. You can always just not use the built in slider and either use the separate Slider component, or another component (like up/down arrows) to scroll.  To do this, you need a variable with the top index, for example:

    global tableTop = 0
    global tableRowCount = 20

    Then, in the table, you should subset all your columns:

    myData[tableTop, tableTop + TableRowCount - 1]

    Then, use a scroll bar component or other components to adjust the tableTop variable accordingly, limiting it to 0 to however many rows you have.


  14. There is a limit defined in the Modbus spec.  I don't remember off hand what it is, but I think it is 63 bytes of data for RTU, and each register is 2 bytes.  But don't take my word for it on the exact number.  The point is that it is a Modbus limit, not DAQFactory, though DAQFactory enforces it.  Also note that some devices don't support setting of multiple registers.  This is not your case, as it is obviously working with 16 registers.  I simply mention it for others that may have issues trying to set more than one at a time.

     


  15. You can definitely do it through script.  Just pass an array for data points.  So for example:

    device.mydevice.setRegisterS32(1, 100, {1,2,3})

    which would set register 100/101 to 1, 102/103 to 2, and 104/105 to 3 (register pairs because of the S32 of course).  Note that it is "Set" not "Write", and is "Register" not "Holding" because Input Registers can't be set, so there is no reason to differentiate on the output side.

    Note that with channels, DAQFactory will automatically combine reads of the same type into a minimum number of calls if they are consecutive and the same data type.  It will not fill in blanks, though, so sometimes its best to create dummy channels.  That said, on the output side you cannot do multiple outputs with one query through channels because there is no way to set multiple channels simultaneously.


  16. It is because of the way DAQFactory optimizes the graph data on large data sets.  It does a boxcar min/max and as new data comes in the boxcar locations change causing those mins/maxs to change slightly, especially at edges like when no data is coming in.  This can make the connecting line jump around.  Normally you can't see it because its only one pixel.