AzeoTech

Administrators
  • Posts

    6,436
  • Joined

Posts posted by AzeoTech

  1. Express is an option from the Windows Start menu, under DAQFactory.  It is not an option within DAQFactory itself.  You have to start using the shortcut in the Start menu.

    No, you cannot create a standalone .exe.  DAQFactory must be installed to run any application.  This has the huge benefit that you can switch to development mode (with proper licensing) on any machine and debug any problems you may have.  I should add that most programs that have standalone .exe files are actually not standalone, but instead require a large runtime library, so really gains you nothing, and loses the ability to make edits on that machine.  LabView is like this.  Even .NET  and MFC are like this.

    To prevent a 3rd party from editing your document, simply set a document editing password by going to File - Document Settings.  

     

  2. That is really up to you.  If you have Pro you there is a 3 position switch in the symbol library, or I should say, three different images you can use to create a three position switch.  But you can do it with your own images, or just use 3 buttons.  It just depends on what you want it to look like.

  3. The thing is, the Modbus driver setting for whether you are using 40,000 notation or 0 indexed is global across all Modbus devices of a particular protocol (i.e. all ModbusTCP devices or all ModbusRTU devices).  So, if you read a value > 50,000 you will lock the entire driver into 0 indexed mode.  That means you have to make sure and use 0 indexed mode on all your Modbus devices.  In your case, it looks like you have a single device that you got working in 40,001 mode, so 28673 was stripped to 8672.  Then you enabled 0 indexed mode, and so 28673 was left at 28673, which apparently on your device is invalid.

    So, in general I personally just pretty much always use 0 indexed mode and if I have to work with a device whose manual uses 40,001 notation, I just do the math in my head and translate it to 0 indexed.  Just strip the 10,000's place and subtract one.  So 40,001 becomes 0.  30,503 becomes 502.  28673 isn't in the 40,001 notation space, so would tell me that the manual is already 0 indexed, but often device manufacturers are clueless about this whole thing.  The 40,001 space only includes 1 to 19,999 and 30,001 to 49,999.

    BTW: the 40,001 notation is purely a documentation thing.  In the actual protocol, 40,001 is actually sent as 0.  The device itself never sees 40,001.

     

     

  4. You'd have to use a variable or a Test D/A channel to hold the HOA state.  Let's say you did a variable.  Initialize it in a sequence marked Auto-Start:

    global HOA = 2   // 0 = off, 1 = on, 2 = auto.  Default is auto

    Then in your Channel Event, let's say you had:

    if (tankLevel[0] > 10)
       DO = 1
    endif
    if (tanklevel[0] < 9)
       DO = 0
    endif

    Replace that with:

    if (hoa == 2)
       if (tankLevel[0] > 10)
          DO = 1
       endif
       if (tanklevel[0] < 9)
          DO = 0
       endif
    else
       DO = HOA
    endif

     

  5. If you just have one, the easiest way is to simply use a Channel Event.  So, if you have a channel called "level" with your level reading, and a digital output channel called "pump" that controls the pump, and you want the pump to turn on at 3, and off at 4 (I'm assuming the pump is filling the tank), you would put this in the Event for the level channel:

    if (level[0] < 3)
       pump = 1
    endif
    if (level[0] > 4)
       pump = 0
    endif

    Make sure it goes in the event for "level" and NOT pump.  The event is a tab in the channel view for the channel.  Expand CHANNELS: in the workspace, then click on the level channel.

     

  6. There are a couple ways:

    1) you can use a registry variable.  The limitation here is that numbers are limited to integers.  Strings are no issue.  

    2) you can use a Test D/A channel with Persist = 1 (or more).  This is limited to numbers, but supports decimals.3) you can use the file. functions to write variables to a file, and retrieve them.  Use file.open() to open the file, then file.read() or file.write() and file.close().  Personally I find it easiest to use a class too.  Then I can put all my settings in one place and not have to worry about file formatting or versioning.  Something like this:
     

    class CSettings
       local string emailAddresses = ""
    
       function save()
          try
             private handle = file.open("c:\data\mySettings.json", 0, 1, 0, 1)
             file.write(handle, gSettings.toJson())
             file.close(handle)
          catch()
             ? strLastError
          endcatch
       endfunction
    
       function load()
          try
             private handle = file.open("c:\data\mySettings.json", 1, 0, 0, 1)
             private string in = file.read(handle)
             gsettings = fromJson(in)
             file.close(handle)
          catch()
             ? strLastError
          endcatch
       endfunction
    endclass
    global gSettings
    gSettings.load()

     

  7. What do you mean by manually?  With the PrtSc key?

    So I gave it a try and initially it failed because I am running a 4k screen.  It probably would have completed but I got tired of waiting.  So, I added screen coordinates to my capture so that I only got the part I wanted.  Then it went really fast and gave me what I wanted.  You should try that.  For example:

    page.Capture("TURB_KW_GRAPH-0,0,500,500","C:\DAQFactory\UNIT_KW_REPORTING.jpeg")

    You can get the exact coordinates of the graph component by selecting it, and viewing the position parameters in the docking Properties window (View-Properties).

    Note also that in 17.1 and earlier you have to view the graph at least once on the screen before capturing it.

  8. First, I would look to changing your alarm settings so they don't constantly refire.  This is called hysteresis and is why there is a separate Reset expression.  For example, if you want the alarm to trigger when temperature > 100, you would set the Reset condition to temperature < 90 say, so that noise in the temperature reading doesn't cause it to constantly fire and reset.

    To keep it from firing a separate email until acknowledgement you would have to create a flag (a variable) that gets set when the email is sent, and reset in the Acknowledge event.  The email would only send when this flag is clear.

  9. Truthfully I wouldn't worry so much about the CPU.  Don't feel like you have to purchase a monster.  Any reasonable chip will be fine.  As I said, I usually only see slow refresh rates on industrial panels because they typically use CPU's that are low power and 10 years old.  And the slow refresh is pretty easy to work around.

    There are no known issues with CPU or GPU brand.  I think the only real hardware issues we have had is with folks using low cost USB->Serial converters.  

  10. Glad it is working for you.  I run a 4k monitor on my workstation and DAQFactory doesn't really have issue with it.  Really it will come down to how many screen components you have and how quickly you want the screen to refresh.  Fortunately, you'll see in the DAQFactory status bar there is "Page Draw" time displayed.  This will give you a good idea how much time DAQFactory is spending refreshing the screen, and therefore how quickly you can get it to regenerate.  Some components, like complex graphs, can take a fair bit of time, but it really depends.  I typically only see slow screen draws on significantly underpowered machines typically found is industrial panel PC's.  Then the trick is just to design the pages to make them less complex, which, truthfully, is often for the better anyway as it is easier for the operator to see the important information without the clutter.

    Now, as to GPU, that doesn't really matter as long as it can actually drive the desired resolution.  As a 2D app, DAQFactory does not utilize any GPU features and does all its rendering on-CPU.  This may change as we improve the screen controls soon, but for now, it really is more important what your CPU speed is, especially since all the rendering is done in a single thread and so at least that part can't take advantage of multiple cores.  That said, the rest of DAQFactory absolutely can take advantage of multiple cores, its just the screen rendering that is stuck working with just one core at a time.

  11. I'm sorry but we never received the email, so I am glad you followed up here.  The issue with the LED component is that you are using a single = sign.  This is "assignment" and used to assign a value to variable/channel.  For comparison, you need two equal signs: 

    CR1[0] == 1  

    (FYI: This matches up with most other programming languages in that assignment and comparison are two different operators.  The double = matches up with many of the more common ones, such as Javascript and C.)

    You also want [0] so it only compares the most recent value.  CR1[] is the same as just CR1, which gives the entire history of CR1.

    As to the LJ side, there are a number of possibilities, including lack of pull-up/down resistor, wrong input, wrong LabJack, and improper input configuration.  I'm going to assume that the resistor is not the issue since you say it works in the LabJack software.  I doubt you have the wrong input.  You should be in FIO6 and 7.  You are using D# 0 which means first found, and I suggest instead specifying the exact LabJack ID.  This ensures that you are connecting to the LabJack you think you are if you ever plug in multiple LabJacks.  Which leaves input configuration.  For this I recommend contacting LabJack.  DAQFactory largely wraps LabJack's UD driver.  It does a few things automatically, such as ensure the input type is correct based on the I/O type, but it does little else so as to give you access to all the flexibility the LabJack has to offer.  It is possible, though I am not sure what, that the LabJack software is sending a configuration command that DAQFactory is not.  Again, LabJack would likely have the answer.

    BTW: you can start by testing the input with a jumper.  Disconnect your circuit, then wire a jumper into your input.  Attach it to ground and the channel in DAQFactory should read 0.  Attach it to Vref and it should show 1.  If it does, then you have eliminated the "wrong input" and "wrong LabJack" options.

     

  12. Not directly.  But you can write a script that looks to see if the data is updating.  Just don't compare the data's time stamp with your system time as the clocks may drift.  The data will have the time of the remote.  Instead you need to write something to see if the time stamp has changed over some period of time.  Something like:

    private lastTime = 0
    while(1)
       if (getTime(remote.mydata[0]) == lastTime)
          connectionFail = 1
       else
          connectionFail = 0
          lastTime = getTime(remote.myData[0])
       endif
       delay(15)
    endwhile

     

  13. Probably the best way is to create a sequence function for each possible alarm status, i.e. fire, reset, and ack.  So, for example, AlarmFire.  You'd need to create a global string variable declared in a startup sequence, for example:

    global string alarmStatus

    Alternatively, you could create a String Test channel with the same name.

    Then, create a sequence called alarmFired:

    function alarmFired(string desc)
       alarmStatus.addValue("FIRED: " + desc)

    Do the same for alarmReset, and alarmAck if desired.

    Next, in each alarm, go to the Fire Event and put:

    alarmFired(strDescription)

    In the ResetEvent put:

    alarmReset(strDescription)

    and likewise for the Ack event if desired.

    Finally, you can use a table component to display the alarmStatus variable.  You probably want to have the first column be time.  That expression would be:

    formatdateTime("%c", getTime(alarmStatus))

    while the second column would just be:

    alarmStatus

    Finally, you'll need to set the Description field for each alarm based on what you how you want it described in that table. 

    It might seem a little cumbersome at first, but it will give you A LOT of flexibility.  For example, you could, down the road, add email alerts, or handle a stack light or horn without minimal changes.

    That said, I might actually pass a few other items to the alarmFired/Reset/Ack functions, so:

    function alarmFired(string desc, priority, string help)

    Then the Fired event would be:

    alarmFired(strDescription, Priority, strHelp)

    You don't have to use priority or help, but at least it is being passed in so if you need it down the road it is already there.

     

     

  14. This is because everyone seems to want something different.  So instead of a lot of high level built in controls, we give access to allow you to create exactly what you want.  The next step, hopefully coming soon, is the ability to create your own sort of modules, so stay tuned on that.

    But as to alarm info,  it depends on whether you want to display the status of all alarms at once (usually for smaller alarm counts), or a running list of active alarms as they occur.  These are, at least, the two most common.  You may want something different.

  15. Yes, it automatically shades between values.  To make it do discrete colors just double up.  So, if you want it blue all the way to 95, then red from 95 up, set the blue threshold to 94.99 and the red one at 95.  If you wanted 3 colors, say, blue to 50, yellow to 95, and red above, you'd do blue 49.99, yellow 50, yellow 94.99 and red 95.  It is still technically shading from 50 to 94.99, but since both colors are the same, it results in just that color.  It is also technically shading from 94.99 to 95, but the range is so small you don't see it.  You can of course add more 9's to the end.