AzeoTech
-
Posts
6,432 -
Joined
Posts posted by AzeoTech
-
-
You will need to create a global variable or channel to hold the tare weight. A variable should work fine. In a sequence marked Auto-Start put:
global tareOffset = 0
Then create a conversion for your weight channel:
Value - tareOffset
Then apply that conversion to your weight channel.
Finally, in your button for setting the Tare, create a Quick Sequence action and put:
tareOffset = (myWeightChannel + tareOffset)
where myWeightChannel is the name of the channel you applied the conversion to.
-
No. Only if you try and save the changes to disk. If you load the prebuilt ctl doc and then modify it but don't save, then it is no issue. DAQFactory will run with the changes, but of course when you restart you will have to reapply the changes from your config since the ctl never changed.
Note of course, that you should also validate your config file to ensure against corruption since it will be read/write. But this is much easier to do than the ctl doc itself. Just make sure you don't make any assumptions about the data you are reading in. And don't use execute() or evaluate() on the data in the file directly. I've seen folks who will simply read each line of a config file they created and then do execute() on it. A hacker could just put some bad script in the config file and it would get executed within DAQFactory.
-
DAQFactory scripting, as an interpreted language, is quite slow, however, individual math functions, which are done at a low level, are quite fast. For example:
for (i = 0, i < numrows(y), i++)
y[i] += 5
endforwould be the normal way, in a language like C, to add 5 to every element in the array "y". However, in DAQFactory this would be quite slow, as you have seen. Fortunately, in DAQFactory you can do this math with a single line:
y += 5
and DAQFactory will apply it to every element in y and do so very rapidly (sub-millisecond, even for thousands of array elements).
So, the trick is to find ways to avoid the loops. This sometimes requires some creative functions and/or boolean math. For example, if I wanted to add 5 to y, but only where y was less than 10, it'd be:
y += (5 * (y < 10))
(y<10) is a Boolean expression and in DAQFactory, like C, evaluates to 1 if true, and 0 if false. y is an array, so y<10 will return an array of 1's and 0's depending on the corresponding element of y. When multiplied by 5, this results in an array of 5's and 0's which get added to the original y. Of course adding 0 does nothing, so the result is adding 5 to y wherever y < 10.
So, to make things faster you need to think about whether you can remove one or both of your loops and replace it will a simpler, single line expression.
That all said, if you have to have loops, consider two things, both of which apply to all programming languages:
1) optimize the innermost loop first as it runs the most times
2) try and remove anything from in the loop that can be precalculated
In DAQFactory, also know that every line takes time, even an if()/endif, so, for example, a simple optimization I'd do is to replace that internal if():
if (ck > Vibe_Window_Skut)
ck=ck-Vibe_Window_Skut-1 ///pri preteceni okna se zacne brat od zacatku
endifwith:
ck = iif(ck > Vibe_Window_Skut, ck-Vibe_Window_Skut-1, ck)
iif() is an inline if and returns the 2nd parameter if the first is true, and the 3rd if it is false.
I would then take that further and drop ck altogether since it is only used in one place, and put the expression there.
-
This works, but it is usually better to create a configuration file of your own that holds this information and then updates the channel table with that data on startup. Doing SaveDocument() in an automated way can be risky. If you have a power failure during the save your entire ctl file will get corrupted. More importantly, in general, for security reasons, it is recommended that your deployed .ctl documents be placed in a read-only folder so they could not be replaced with a modified version by someone who has hacked into the system. DAQFactory scripting has a lot of power and could do a lot of damage in the wrong hands.
-
I'm going to let the folks at LabJack reply to this question as it is more hardware related and they will be able to give you the best answer.
-
Yes, set the timing and offset to the same value. I am assuming you are not streaming (i.e. > 50-100hz data rate).
-
The variable value component will never display two lines. It ignores CR's and LF's. You would need to use a text component for this. The easiest way is to do this is to set the OnPaint event for the text component to "strText = myVariable".
I've attached an example (requires 17.1+)
-
We will be addressing streaming with the T series soon. In the meantime, you probably will need to script the logging into your streaming sequence. The original sample is this:
private scanRate = 10000 device.labjackM.LJM_eStreamStart("ANY", {"AIN0", "AIN1"}, scanRate, scansPerRead, 1) private dataIn private data private st = systime() global backlog while(1) dataIn = device.labjackM.LJM_eStreamRead("ANY") data = insertTime(dataIn.data.AIN0, st, 1 / scanRate) channelA.AddValue(data) data = insertTime(dataIn.data.AIN1, st, 1 / scanRate) channelB.addValue(data) st += scansPerRead / scanRate backlog = dataIn.ljmscanBacklog endwhile
You'd want to make it into something like this:
private scanRate = 10000 device.labjackM.LJM_eStreamStart("ANY", {"AIN0", "AIN1"}, scanRate, scansPerRead, 1) private dataIn private data private st = systime() global backlog global string streamFileName = "c:\myData\streamData.csv" private string curFileName = "" private handle = 0 while(1) dataIn = device.labjackM.LJM_eStreamRead("ANY") data = insertTime(dataIn.data.AIN0, st, 1 / scanRate) channelA.AddValue(data) data = insertTime(dataIn.data.AIN1, st, 1 / scanRate) channelB.addValue(data) st += scansPerRead / scanRate backlog = dataIn.ljmscanBacklog // setup logging: // check for change in file name and open file if (streamFileName != curFileName) if (handle) file.close(handle) endif handle = file.open(streamFileName, 0, 1, 1, 1) curFileName = streamFileName endif data[][0] = seqadd(st, 1/scanRate, numrows(datain.data.ain0)) data[][1] = datain.data.ain0 data[][2] = datain.data.ain1 file.writedelim(handle,data, ",", chr(10)) endwhile
The only trick to this is if you stop this sequence (like you do with stopStream), then the file will still be open. Use file.closeAll() to close all the open handles. You could, also, make the file handle and file opening global, and then just have the sequence write to the handle when it is non-zero.
-
Certainly. But AddChoice is a function, not a variable so you don't use =. It would be:
Component.myComboBox.AddChoice(strIn, strIn)
Note that the function requires two parameters, the first is what is displayed in the combo box. The second is what is set when the particular item is selected. If you want them to be the same, you just pass the same thing as I did.
-
Yes, it looks like an SPCI device on port 5025. The protocol is SPCI. You can find the commands on the net as it seems missing from the docs you provided. I'd start with sending the *IDN? command in the comm monitor and make sure you get a response. You probably will need to type:
*IDN?\013
-
There is nothing wrong with what you did with the switch, however, any place else you turn the controller on and off (i.e. other sequences) you should do so with the same channel that the switch references and not directly. That way the switch status will update appropriately.
-
Unfortunately this would require you put a Pro license on the remote computer. Please email us as we offer a discount for licenses purchased for this use case.
-
It is most likely your alignment threshold. On the details page of your logging set, select All Data Points (aligned) then set the alignment threshold to 0, or maybe 0.0001. If that doesn't work, post (or email us) your document.
-
Absolutely. Many people have done very similar applications. Just collect the two data points from the LabJack at the same data rate and create a graph that plots Force vs Velocity. Just make sure and set the bottom axis type to Lin instead of Date/Time so that it becomes an XY graph instead of a trend graph.
-
Yeah, OnLoad really was just designed for the createProperties() and AddListener() functions. You can't reliably do anything else because you can't predict when it runs. I am fairly certain it runs after sequences are loaded, but before auto-start sequences are run, but its possible that could change in future releases so I wouldn't want to rely on it.
A better, reliable, solution would be to create a message that your components receive that trigger your code, then, once your auto-start sequence is complete, you could trigger that message, and thus the desired code. 7.16 in the user's guide talks about the OnMessage event. Multiple components can receive the same message from a single SendMessage call, you just have to do an AddListener() function call (mentioned in 7.15) in your OnLoad() for each component.
The bonus part of that, is that you could, technically, change your Excel sheet, and retrigger the message and the components would update without having to reload the document.
-
OK, a few things here:
1) What is the component name? It is probably best not to rely on the name of the component, but instead create a member variable (property) of the component that you set for each component. (using CreateProperty())
2) you cannot predict the order in which DAQFactory will start things. In other words, you have no way to know that the auto-start Sequence is actually going to run before the page is loaded, if the page is also marked the initial page. So, it is entirely possible that stuff just hasn't been initialized yet because OnLoad is getting called before your sequence runs. This is why I always only have a single sequence marked auto-start and then start other sequences from there. In your case, OnLoad is done when the document loads, so you really can't control when it executes, and it almost certainly is executing before the sequence runs. I'm not exactly sure what you are trying to achieve (use case) so I can't offer an alternative solution.
-
Yes. Resolution index 12 is the highest resolution available for the U6. The higher the resolution, the slower the device becomes. As seen on their website here:
The U6 at resolution index 12 has a sample time of 159 ms PER CHANNEL. So you have to multiply 159ms * the number of channels and that is the minimum Timing. Truthfully you need slightly (5ms?) more than that for comms. If you need faster you either need to use a lower resolution index, or get a second LabJack so DAQFactory can sample both simultaneously.
-
It might be. I'd reboot just to be sure and make sure you aren't running any other software that might access the LabJack. I'd also try using the actual ID of the LabJack as the D#.
I'd also try a different USB port, preferably a hub without other stuff on it.
Do the LabJack tools also seem sluggish?
-
You are right. Your application is not particularly complex, and I see only one minor detail that probably wouldn't cause slow acquisition. The issue is in your conversions. Two of them reference channels but without [0] so will end up using the full history in the calculation.
After fixing that, I'd start by making sure you are running the latest firmware / drivers from LabJack. Also make sure you don't have any other applications, like LJLogger, etc. running that also access the LabJack. Then I'd try setting all the channel timing's to 0, and then set just one channel to 2, then try smaller values.
-
There is no reason to use OpenEx() if you aren't using a password or specifying the driver. Just use Db.open("Advantech"). Next, make sure you have the same data source name (Advantech) and that that data source can actually get to the database. Usually the data source configuration has an option to test the connection. You'll also need to make sure you create it in the proper section. User DSN's for example are only visible to one user. Finally, 5.87 is really quite old, probably almost 15 years at this point, and as such may not work with some of the more recent ODBC drivers. I know that for MySQL you typically have to use the 3.51 ODBC driver. You might try a different driver.
That all said, the most common error is to accidently create the ODBC data source in the 64 bit version of the ODBC configuration tool.
-
I'm assuming DAQFactory was operating normally up until you quit the application? If so, then the issue is likely with your application. Something you are doing, probably in one of the sequences, isn't allowing the thread to quit. Normally DAQFactory will force quit these threads after 5 seconds, but it is possible that a driver you are using has started its own thread that DAQFactory has no control over and that thread is lingering. What drivers are you calling from DAQFactory? Have you tried manually stopping all sequences, or perhaps, going to safe mode, before quitting?
-
Hmm, which version of DAQFactory are you using? In newer releases you can use date/time specifiers right in the file name and thus make it log every day. So, you'd do:
Results_%y_%m_%d.csv
and then just leave it alone. DAQFactory should then log it with the date stamp, changing it each night at midnight.
-
Depends on the printer. Most normal printers with a Windows driver are going to probably wait for a whole page before printing, however, if you can find a serial printer and thus not have to use a windows print driver, then yes, you should be able to send a line and line feed direct to the printer, one line at a time. I know there are specialized printers for this, such as product printers, but don't have a source, off-hand for a normal paper printer though I am sure they are available.
-
OK, well, if you just want to give your channels alternate names, use the aliasFor() function. So, if you have a channel called "MyChannel" and a variable called "MyVariable" that you want to use to reference MyChannel, just call this once:
MyVariable.AliasFor("MyChannel")
Now, whenever you access MyVariable, DAQFactory will actually go get the data from MyChannel instead of from the variable. There is no copying of data so you don't have to worry about your memory. Note that member functions do not work through this, i.e. MyChannel.ClearHistory() will clear the history of MyChannel, but MyVariable.ClearHistory() won't do anything.
AliasFor() was originally designed to allow structured data in classes to be mapped to the rather flat channel structure, especially for OPC which has no functions for reading data from script. But it works for other stuff too!
But as to your specific question, if you are filling the variable with AddValue, then, yes, there is a history amount. So, for example:
global x
x.HistoryLength = 3
x.addValue(1) // x now = 1
x.addValue(2) // x now = {2,1}
x.addValue(3) // x now = {3,2,1}
x.addValue(4) // x now = {4,3,2}Note that history only applies when using AddValue(). It does not apply when using InsertAt() or Append() until you do another addValue, so continuing on with my example:
x.append(5) // x now = {4,3,2,5}, history length has no effect
x.addValue(6) // x now = {6,4,3}, history length was applied
Sampling data
in Graphing
Posted
No, I mean a variable. See 5.10 in the user's guide. Its just a place to store a value, kind of like a channel, but simpler.
As for the sequence, create a new one (5.2 in the user's guide). Call it, say, "StartUp", and then make sure it is marked Auto-Start (5.22 in the user's guide).