Logging Virtual Channel gives blanks


Recommended Posts

I've just started with DAQFactory. I set up a few virtual channles to hold converted values; these are arrays that are displayed on a graph (they're decimals between -100 and 100).

These virtual channels do not show up as accessible in the normal logging window when selecting what to log, so I use the "manual" option to write them in manually, as v.(Whatever). When I try and log these values, only blank spaces show up between the commas. Other results--normal channels--work fine, but virtual channels just give spaces.

What's going on?



Link to comment
Share on other sites

Logging sets aren't setup to log virtual channels. You have a couple choices:

1) use an export set instead that is triggered by a sequence

2) instead of filling V channels with your converted values, fill a Test channel. You'd do this by using the Event on the normal input channel and AddValue() to stuff the converted value into the test channel. The Test channel should be device type Test, I/O type "A to D", with a Timing of 0. Then, in the event for your actual input channel, you might do something like: mytestchannel.addvalue(myinput[0] * 50 + 4)

Link to comment
Share on other sites

Thanks for the ideas. Per your suggestion I made an export set, with the expressions being






I have two questions about this:

(1) Instead of triggering with a sequence (which I don't know how to do yet) I right click on the export set and select "Begin Export Set". The small red dot on the export set's title vanishes for about a second, then reappears. I never see the "End Export Set" as available, only "Begin Export Set" is visible again, which makes it seem as though it never started. But some data is written, so what's going on here, and how can I have it run until I stop it?

(2) The first two rows have seix entries, and I only spec'd five. So it seems time is automatically added.

TheTime, Time, Thigh_L_Angle, Thigh_R_Angle, Knee_L_Angle, Knee_R_Angle


So there is a double comma, and it looks like sysTime() isn't working. Is it because it's a scalar, or what, or how can I make a vector? I'm looking for decimal seconds since the start of the sequence, and don't want to use this odd TheTime format, hence sysTime() which is in decimal seconds.

Thanks for your help,


Link to comment
Share on other sites

Okay, so my last post hasn't appeared yet, so I can't edit it. But I see what my problem is with the exports: they only write data once, and when I right-clicked and ran the export, it filled the entire channel history of 3600 values.

So I wrote this sequence instead using scalars:

global maxTime = 1
global startTime = sysTime()

while ((sysTime() - startTime) < maxTime )


(1) Shouldn't this write 100 sets of data in one second?

(2) Instead I got strange file outputs with missing values,

(3) and definitely not 100 lines (more like 30).

(4) sysTime() is a scalar, and it still doesn't appear after the TheTime column.

A snippet is below:


Link to comment
Share on other sites

-Export sets are designed to run once and stop.

-since you didn't put [0] after your V channels, running it manually dumped the entire history.

-systime() doesn't work because it doesn't have a time associated with it. The system time is in the value part of the value, not the time part. Since there is no time stamp, it can't align with the other data.

-the weird timestamp in thetime is Excel time which is decimal days since 1900. You can switch to DF time from the Details page of the export set.

-you can't trigger export sets in a tight loop like you did because they run asynchronously. So, you have to give enough time for the export set to full run before triggering it again. Because of the way Windows task switches, even though the export set probably takes < 0.01 seconds to run, Windows may not task switch to it within that time.

Are you logging streaming data? If not, I definitely recommend the Test channel method with a logging set. If you are trying to log an experiment's worth of data (batch), then an export set without [0] is probably appropriate, but to get a dT timestamp, you are going to have to create a variable with a time built in (using inserttime(), or simply myvar.time = v.mychan.time). Alternatively, just use the File. functions to create and format your own file.

Link to comment
Share on other sites

It's closer now:) Yes, this is a data for a single test, and has to be recorded at the 100 Hz, but a test only lasts about 10 seconds or so.

I have the following. In the export set, each channel has an expression v.Avariable[0,maxSamples - 1], so the export set records the last maxSamples number of data points when I press a button, like so:

global startTime = sysTime()
global maxTime = 1
global sampleRate = 100
global maxSamples = sampleRate / maxTime

//export.BipedData.Addchannel("Time", "sysTime() - startTime")  //trying something that didn't work
//Time.time = v.ThL_Ang.time   //per your suggestion, but didn't work 'cause I don't understand yet

(1) I still don't understand the time part, or in particular where "myvar.time = v.mychan.time" would go (another virtual channel that will then be logged?).


Export sets are designed to run once and stop.

Okay. What do export.myexport.START and .STOP do, then, if exports are single-use?


systime() doesn't work because it doesn't have a time associated with it. The system time is in the value part of the value, not the time part.

I'm still confused on this, and don't understand the last sentence. When I did a variable display with sysTime() in the expression box, it displayed the current time in seconds. If this is a continuously updating scalar value, how come it doesn't have time associated with it?

(4) Ultimately I'd like to set the recording interval, i.e. pres the button to start, press it again to stop, and store all the data in between these presses.

How can I detect a button press in a sequence, and store the data before exiting the sequence, instead of a hard-coded exit action from the button? It would be this:

startTime = sysTime()  //This sequence starts with a button press, so store the entrance time
stopTime = sysTime()
maxSamples = (stopTime - startTime) * sampleRate
beginExport(BipedData)  //this will now store the last maxSamples points, starting from when I pressed the button
//now exit the sequence

Thanks for your patience and for answering my questions up to this point. The docs are not terribly clear about these things...or at least I didn't find all the relevant parts.

Link to comment
Share on other sites

Yeah, the docs are already 440 some pages, and so don't go into a lot of application specific stuff. That's why the forum is so useful (and so popular).

1) for this app (wanting a dT value relative to start time), create another V channel called dT or something, then for its expression, put:

V.something.time - startTime

where v.something is one of your other logged channels. Doing .time retrieves the time component of that channel. We then subtract the startTime variable that you created to get dT.

2) well, Start actually starts an export set. Stop will stop one if it runs for a real long time, for example you had a history of a million points and you were logging to some slow flash drive. On modern PC's, export sets pretty much always run instantaneously, but many users, especially ones using embedded systems, are using much lower power PC's than what you may have on your desktop, so an export set could take a while (10 secs?)

3) ignoring history, a single channel value, v.channel value and most variables actually consist of two parts, the value and the time. When you do just:


in a variable value component you get the value, but if you do:


you get the time associated with that data point. The time stamp stays with the value through most calcs, making it easy to do a lot of things without having to track both time and value.

Systime() is a function that returns the system time, but it only returns it in the value portion. There is nothing in the time portion of the returned value. If you did x = systime(), I believe DF would automatically assign the current time to both the value and time portion of x, but these would actually be two slightly different values. Since systime() doesn't have a time portion, the export set can't use it because it can't align it to the other values (it doesn't know what row to put it in).

4) you are making it a little harder than you need to. Just record the start and stop time like you are doing and run the export set. In the export set, make it so all your rows look something like this:

v.mychannel[startTime, stopTime]

You'll need to make sure the history length in the v channels is large enough to hold your entire experiment (default is 3600, which at 100hz should be enough). In this case we are subsetting the history in v.mychannel by time instead of index. When you do [0] or [0,9] we are referring to the point number where 0 is the most recent point. When you pass a time value, which is considered any number > 1e8, DAQFactory looks at the time stamp associated with the data points and returns whatever is between the two times. Very handy!

Link to comment
Share on other sites

Thanks! Very useful info, a lot clearer than the docs.

What I have now is a start sequence:

global startTime = sysTime()

and a stop sequence:

global stopTime = sysTime()

global sampleRate = 100
global maxSamples = sampleRate * maxTime
global timeVect = v.ThL_Ang.Time[startTime, stopTime] - startTime

that are triggered by a start and stop button. Each expression in the export set is of the form

A3_KneeR_V[startTime, stopTime]

This works as you suggested, but adding the time vector doesn't.

When I put

GetTime(V.KnL_DC[startTime, stopTime]) - startTime

into the TimeVector column of the export set, the expression box is red. When it's changed to

GetTime(V.KnL_DC[0, stopTime]) - startTime

then it's green and compiles. How come?

I have other questions as well in response to your post, but the answer to this one might make those questions go away...

Link to comment
Share on other sites

Its probably showing red because you haven't run through your experiment yet so startTime and stopTime either aren't initialized to anything, don't exist yet (not declared), or are set to values that are outside the history range of the V channel. My guess is that the first expression will work when you actually run your code.

Link to comment
Share on other sites

Thanks. I still have odd and inconsistent results in the file output. Using the start and stop sequence:

global startTime = sysTime()

global stopTime = sysTime()
global timeVect = v.ThL_Ang.Time[startTime, stopTime] - startTime  //ThL_Ang is a virtual channel I'm logging

and the following expression for the last column (Time) in the export set:

timeVect[startTime, stopTime]

, the output is looks good for a while, but then the time vanishes, and then eventually so do the last data points:


In the watch window,

numRows(timeVect[startTime, stopTime])

gives 54


numRows(v.ThL_Ang[startTime, stopTime])

gives 94

so they're clearly different lengths.

Clearly I'm still confused on how to access array elements using the time argument, but it looks so straightforward... How can resulting arrays be different lengths if I have the same start and stop time?

Link to comment
Share on other sites

Good call on the timeVect subset! You are right, it doesn't need to be indexed. Removing the indexes appears--on the surface--to have resolved the issue.

Apparently, if the stop-time index is outside the time stamps' limit (as it was with the indexed timeVect), the result is something random and unpredictable.

Thanks again.

Link to comment
Share on other sites


This topic is now archived and is closed to further replies.