AzeoTech

Administrators
  • Posts

    6,432
  • Joined

Posts posted by AzeoTech

  1. Well, normally I would say put an SSR on the low voltage side and do a PWM on it with the LabJack, but 200A is a mighty big SSR and you are AC on the low voltage side, so I can see why you'd want to do the switching on the 240V side.  And of course an SSR doesn't switch AC as well because it doesn't phase align like an SCR.  Likewise PWM isn't going to work on the LabJack because it can't phase align either.    But you knew that already.  It seems like you really are just hung up on the fact that the SCR you want takes 4-20mA not 0-10V.  I'm going to let the LabJack folks chime in on possible solutions, but you can always go with a really cheap PLC that outputs 4-20mA like a Click PLC, just for that part.  The PLC is like $100 so really not a big deal, and you can use it with the LabJack for everything else.  It is available with either a serial or Ethernet connection and talks Modbus (so DAQFactory can easily talk to it).   

  2. I do not recommend opening and closing the database.  Just open it once outside the loop or in an AutoStart sequence and leave it open.  There is no reason to close the connection.  DAQFactory will do this automatically when it quits.

    Is the name of this sequence S3?

  3. Functions are standalone and can be called by as many different sequences as you want.  They are also reentrant so you can call them recursively as long as you are careful not to blow the stack (a general pitfall for recursive function calls). 

    DAQFactory script in general is thread safe, though you do have to sometimes protect against multiple threads accessing common resources.  The most common example is a comm / ethernet port.  For this there is the lockPort() function.  It is not that you will crash or hang DAQFactory, but if you don't protect the port, you could get framing overlap in your communcations (i.e. thread 1 makes a request, then thread 2 makes a request before thread 1 gets its reply.  Thread 2 still has the processor and gets the request from thread1 instead of thread 2.)

  4. Row is used to do stacked axes. If that is what you are after, then excellent! I am glad you found it.  Use the % of full to determine the size of each axis.

  5. No.  The DDE capabilities are limited largely to posting and reading data using Poke and Request only.  DDE is a very old technology and not particularly well adapted anymore.  In fact, we are largely deprecating this feature because of this.  What exactly are you trying to do?

  6. Sure.  DAQFactory supports 6 left and 6 right axes.  Just assign each trace to whatever axis you want.  The axis tab lists the axes and allows you to adjust the scaling on each one.

  7. Just another suggestion: wrap your DB calls in a function.  So, for example at a minimum (each function is a sequence):

    function dbOpen(string dbsource)
       global dbase = db.open(dbsource)
    function dbExecute(string sql)
       db.execute(dbase, sql)
    
    function dbQueryToClass(string sql)
       private ret = db.queryToClass(dbase,sql)
       return(ret)

    Then, instead of calling db.open(), db.execute() and db.queryToClass(), call the above functions.  I gave the minimum that they'd do, but you can then add error handling and debugging code to the above to further enhance it.  

    The best solution however is to create a class:

    class CDataBase
       local handle = 0
       function Open(string dbsource)
          handle = db.open(dbsource)
       endfunction
    
       function Execute(string sql)
          db.execute(handle, sql)
       endfunction
    
       function QueryToClass(string sql)
          private ret = db.queryToClass(handle,sql)
          return(ret)
       endfunction
    endclass

    Then instantiate a single instance in startup:

    global dbase = new(CDataBase)

    and call into it like this:

    dbase.open("mydatasource")

    or

    dbase.Execute("INSERT INTO mytable (field1) values (3.423)")

    Again, this allows you to eventually add features (like error handling and debugging code) as needed and encapsulates it into a single object.

     

  8. OK, three problems:

    1) "local" is the wrong declaration.  You want "private".  "local" is for class declarations and never used inside a function.
    2) while you remembered to declare all your function parameters as strings, you forgot to declare executeSTR as a string.  So you need:

    private string executeSTR = format(...)

    This is why you get NaN().  DAQFactory is trying to convert your insert string into a number so it can store it in executeSTR.

    3) I typically do not recommend constantly opening and closing a database.  Just open it once at startup and leave it open.  Close it only if you lose connectivity (which is rare).

    Two notes:

    1) db.execute() doesn't return anything so "inserts" will never have anything
    2) I typically prefer to build up my SQL strings over several lines, if only to make it clearer.  So:
     

    private string executeSTR = "INSERT INTO app01 (serialnumber, firsthigh, firstlow, secondhigh, secondlow, thirdhigh, thirdlow) values ("
    executeSTR += ER_NO 
    executeSTR += ",'" + FIRST_HIGH + "'"
    executeSTR += ",'" +FIRST_LOW+ "'"
    executeSTR += ",'" +SECOND_HIGH+ "'"
    executeSTR += ",'" +SECOND_LOW+ "'"
    executeSTR += ",'" +THIRD_HIGH+ "'"
    executeSTR += ",'" +THIRD_LOW + "'"
    executeSTR += ")"
    

     

  9. It appears you have 8 gateways, each with a unique IP address, however, all your channels are on the same Timing/Offset.  This means that DAQFactory will read Gateway1, then move to Gateway2, then to Gateway3, etc, until it gets to Gateway8, then it will repeat.  If any of those gateways are slow or timeout, it will cause the data interval to slow way down, especially since you have a timeout of 5000 (5 seconds).  I recommend two things to fix this, especially #2:
     
    1) unless you are using a radio (which it actually appears you are), set your timing to 1000.  This is a minor issue.  For radios, then a Timeout of 5000 makes sense.  But if you are connecting directly over Ethernet to a device, if it doesn't reply within a second it probably isn't going to reply at all.
     
    2) Put all the channels for each gateway on a unique Timing / Offset pair so that DAQFactory can read them concurrently.  So, for example, all your Channels for Gateway1 should be at Timing = 1, Offset = 0.  All the channels for Gateway2 should be at Timing = 1, Offset = 0.1.  Gateway 3 should be Timing = 1, Offset = 0.2, etc.  Make sure all channels on a single gateway have the same timing / offset.
     
    If you do #2 you will see a significant improvement in the timing of your data.
  10. So are you saying that you have a 4th channel from the PLC with the timestamp of the process that you want as the X axis?  You can certainly do that.  Just put that channel name as the X Expression.  Likewise, you can plot all three variables, either on the same axis, or, given your ranges, on 3 separate axes, left or right.

  11. To display delta T on the X axis you simply need to record the time of the 0 point, and then subtract that from the data time stamps.  So if you are plotting "MyChannel" vs "Time", and you create a global variable called "StartTime" which you set in, say, a button when the process starts:

    startTime = systime()

    Then, the graph would be "myChannel" vs "GetTime(myChannel) - startTime"

    As for milliseconds, when in Date/Time mode, the graph doesn't show millisecond graduations.  To do that, and especially when you are actually doing deltaT, just change the Bottom Axis from "Date/Time" to "Lin"

    The user's guide doesn't show every because some features are considered beta.  PrintPDF() for example only support generating PDFs of certain controls, namely the graph control and text controls.  It won't, for example, print a bitmap logo.  As such, we did not document it in the user's guide so it isn't really fully functional. 

    The script in DAQFactory is loosely based on C++ and Visual Basic.  It is mostly similar to C++, but with some parts (ie. endif, endwhile, etc) of Visual Basic.  The syntax was chosen to give the flexibility and power of C, while not making the syntax so strange that beginners couldn't make sense of it.  So, for example, unlike in C where you can basically create an entire program in one line, DAQFactory limits you to one statement per line.  Likewise, DAQFactory has a number of things, namely how it deals with arrays and strings, that are not easy to do in C or Visual Basic.  For example, if "x" is an array, and you want to add 1 to every element in X, in C you would have to create a loop and increment each element.  In DAQFactory it is simply x = x + 1, or even x++.

     

  12. A tree list would be used to allow the selection of any sort of organized data.  For example if you had a bunch of parts, some are nuts, some are screws, some are bolts.  Those 3 would be the top level of the tree, then under each you might have the various types of nuts, or bolts, etc.  The DAQFactory workspace is a perfect example of a Tree List.

    Every time you add an item to the tree list you get a handle.  You can then use that handle to change the name as it appears on the tree without recreating the entire tree.

    Tree lists are typically used with nested objects (classes) which is why you really can only work with it through script.    

  13. A regular query() returns a record set that you then need to traverse to read each record.  Because DAQFactory is an interpreted language this is quite slow, so we came up with QueryToClass(). This function instead returns an object with member variable arrays for each of the fields across all records.  This is much, much faster.  In addition, two member variables, classNames, and recordCount are returned.  The details of this function are described in section 9.5 of the user's guide.  With the new QueryToClass() there really are only a few use cases where the regular Query() should be used, usually ones that involve aggregate functions.

    You can telll if open() worked by whether you get 0 for a handle (failed) or another number.

    Once it is open you can't tell except that your database commands will throw an error, which you can then catch.

     

  14. This sounds to me like a hardware issue.  Personally I would never use a ModbusRTU -> TCP converter unless I needed to connect from a tool other than DAQFactory.  DAQFactory supports ModbusRTU over Ethernet so you can use a simple Serial->Ethernet converter and avoid the issues created by having a protocol translator in the middle.  If you do use a normal Serial->Ethernet converter, I recommend the ones from SeaLevel which have a "RAW" port you can connect to.  This port eliminates the need for any intermediary software or virtual comm port drivers.

    So do you have 60 RTU devices connected to 6 TCP devices,  or 600 RTU devices connected to 60 TCP devices?  Are you seeing timeout errors?  Are you using Channels exclusively?  If you are using channels, you should set it up so that all the input channels on all the RTU devices connected to a single TCP device have the same Timing and Offset, and that ones connected to a different TCP device have a different Timing/Offset combination.  This will tell DAQFactory to query the TCP devices simultaneously.  Note that you should not use different timing parameters for RTU devices connected to the same TCP device as I would imagine that TCP device only supports one communication line at a time. 

     

  15. Actually, readuntil() would probably be the best choice.  You'll want to readuntil(0x86), then make sure you have 13 bytes, then parse it, so something like:

    private string in
    private bin
    while(1)
       in = device.mydevice.readuntil(0x86)
       bin = asca(in)
       if (numrows(bin) != 13)
          continue
       endif
       // now you can parse bin, which is an array of numbers.  Note that 0x86 will be at the end, not the beginning.
    endwhile
    

    Two notes:

    1- I actually have forgotten if readuntil() also returns the value you are reading until, so the returned length might be 12 and no 0x86 at the end.

    2- you do not need a delay() inside this loop, though you may want to add one (delay(0.1)) right after the while() until you are sure you don't have any typos.  You don't need the delay() because DAQFactory will essentially delay on its on while doing the readuntil().  If you introduce a delay that causes DAQFactory to loop slower than your device is spitting out data, it will fall behind.  

     

  16. The trial version is designed to allow you to evaluate DAQFactory.  You have obviously completed evaluation and are using it in production with your customers.  If you are using it for production or for your customers and not simply evaluating DAQFactory you need to purchase a development license for DAQFactory.  To do otherwise is taking advantage of our free trial.  

  17. Most fieldbus protocols, by their name, are designed to allow field devices to connect to each other and not so much designed for a PC to connect to it.  They usually have specialized hardware requirements and thus require a special card on the PC side.  That card is typically proprietary, and as such does not follow a standard API, making it impossible to just say "we support Foundation Fieldbus".   A very similar example is CANBus.  That said, you can, technically use a DLL provided by the Foundation fieldbus PC card manufacturer within DAQFactory in most cases.  You also may be able to go through a transport layer converter (i.e. Fieldbus to Ethernet or Serial), or even a protocol converter, or possibly an OPC server, or simply use a PLC that supports Foundation Fieldbus and then connect DAQFactory to that PLC using a more well known protocol like Modbus.  Truthfully, in 30 years of automation software I have never heard of Foundation Fieldbus so it is either relatively new, only used on the field side (i.e. not connected to a PC), or just not that widespread so I can't offer much more.  More common fieldbus protocols are things like EtherCAT (which runs on CAN) and of course CAN itself, Profibus and others.

  18. Sorry, the file wasn't attached.  But I believe you are talking about trending an output?  That it causes a graph to just draw lines between the points when the set point changes, and not showing the current state of the output? 

    If so, first usually it is best to actually use an input to read the status of the item you are controlling.  For example, if you were controlling a pump, you could have an input that reads the current use of the pump so that you know that the pump actually turned on.  This is so you get the proper feedback.

    But, understandably, this is often overkill.  To trend a setpoint like you described you need to build a history.  The easiest way to do this is to create a test D toi A channel to store the continuous history, then in the Event of one of your input channels, put:

    myGraphOutput = myOutput[0]

    so that this test channel (myGraphOutput) gets updated with the current control state of the output channel (myOutput) every iteration of your regular inputs.

  19. DAQFactory should run fine under Windows 11.  It should work in all versions of Windows except IoT Core, which isn't really a full version of Windows anyhow...  If you are using the hardware key, you may need to get the latest driver for the key from marx.com.  Go to the downloads page and download and run CBUSetup.

  20. We literally call a Windows API function for this, so any issues with it not working are related to issues with Windows.  We use this function essentially:

    https://learn.microsoft.com/en-us/cpp/c-runtime-library/reference/strftime-wcsftime-strftime-l-wcsftime-l?view=msvc-170

    Newer releases of Windows do a lot of weird double layer stuff. They even have two control panels!  So it may be related to that, that the function is using a different setting than what we would think to determine the locale.  Actually looking through it I believe that it may be the setting for Locale for non-Unicode apps.  DAQFactory is not unicode (at present). 

    In the end of course, you can use the other specifiers to format the date however you want.

  21.  Yes, those look like errors that Windows is generating because it is loosing connection with the server at the last moment.  I still believe it is a case of the message getting through, but the ack from the server is not making it back.  So the email goes out, but Windows times out waiting for the ack that the email was sent and never gets it, or gets an unexpected response and throws an error.  The problem is that you likely would get the same error if the connection was lost earlier in the process and the email wasn't sent.  So, I don't think you can just ignore the error if you have to get the email out.

    Truthfully, I would probably look to other things if you need to make sure you get the email and you don't want to get repeats.  But do remember that email delivery isn't guaranteed no matter what, so shouldn't be relied upon as the end all be all of alarming notification.  That said, a few choices for you:

    1) use a tool like DAQConnect.  This tool uses a different method for posting data with less handshaking and so might work better than old email.  It also has the ability to generate lost connection alerts.  But there is a monthly fee involved (very small for a few points)

    2) use something else similar to DAQConnect that uses a simple TCP connection, maybe just spin your own.  It is not difficult.  You could even put DAQFactory on a public IP and just listen for a very short message code to indicate an alarm (along with some encoding) and then send the email from there.  Or, use a very simple webserver.  Again, the trick is to reduce the amount of data to an absolute minimum and let the server generate the more verbose message.

    3) try a different carrier.  We maintain two cell phones on different carriers to ensure that we have reception in all areas.  It is not just coverage, but saturation as some of the more remote sites, where only one tower can be reached, get saturated with lots of users during certain events.

    4) use old fashion dial up or some other, non-cellular technique (pigeons? :) )