Counting while V > Threshold


sdragt

Recommended Posts

This is my first LabJack project using a U3HV and DAQFactory. I am trying to measure the length and diameter of samples that are much longer than their diameter. My device has a pair of spring loaded rollers driven by a motor/encoder that puts out a signal at about 120 Hz. The distance between the rollers is measured and produces a voltage that starts around 0.02 V and ranges up to say 3 V or so. What I need to do is count the pulses from the encoder while the voltage is over its threshold and find the maximum voltage during that cycle. Using channels, I have been able to capture good voltage numbers that approach reality, but the cycle counts vary dramatically, even when running channel timing down to 0.01 s. The variability in my counts makes it look like I am far from the mark. I'm assuming that the next step is to learn how to stream both signals, but I'm not sure how to do the comparison and analyze the results. My system initializes a sequence just prior to introducing a sample. I'm thinking about moving each data set to a V channel for post processing where the signals are matched up to find the point where voltage exceeds its baseline, start counting there and stop when voltage returns to its base. Am I missing something easy, or is there a better way to approach this issue?

LabJack looked at the application and we did some testing that showed that the hardware and counter were working properly. Here is some background info from the testing process: I used the BasicCounter.ctl example and turned the roller one revolution. The system reads 84 pulses every time which is expected based on the motor/gearbox/encoder combination.

I use a variable that subtracts the initial count (when the analog signal rises above a threshold) from the final count (when it returns below the threshold) to return the total number of pulses between start and stop. The error I see is in its variability when measuring the same sample. I just ran the sample through seven times and got: 260 306 243 206 227 307 204 counts. The sample should give 160 encoder counts in theory. I then went back to the BasicCounter example and pushed the sample through with nothing else running a couple of times. I got a 169 and a 170 count result. The extra counts come from the rotation of the roller before the leading edge of the sample reaches the centerline of the roller. That I can handle in the conversion.

So, the next step was to run the full program, stop the motor and push the sample through the rollers by hand. The count came out to 174. Not too bad. If this were just a scan time error on each end, a 50 mS scan time would only miss 6 pulses and worst case, both ends miss 12. Based on the average of the seven samples above, I am gaining 90 counts somewhere with a pretty random pattern. It sounds like the hardware is working pretty well, and my problem is in the timing of data acquisition or something in my program.

Thanks in advance,

Steve

Link to comment
Share on other sites

The issue you are seeing is almost certainly due to jitter in the time axis caused by the fact that Windows is not a true real time operating system. I have two possible suggestions:

1) the absolute most reliable way to do this is to actually do it in hardware. Use a schmidt trigger to trigger the start and stop of the counts based on the voltage.

2) stream the counter. The LabJack guys can tell you how to do this.. I believe you just specify some "special" channel # to tell the LabJack you want the counter. Once you have the data in, you are going to have two big arrays, one with voltage, and one with counts. You can then simply use the filter() function to filter the counts array / channel down so it just includes the measurements within your desired range. I would use variables, and wouldn't use V channels, though it seems many people like them better than variables. It truthfully doesn't matter which you use.

Link to comment
Share on other sites

I am missing something really simple and need your help again. What is the best way to take the streamed data and populate the variables? My process cycles through several steps and I am trying to pick up the analog data array plus the counter array after they are transferred from the LabJack to their respective channels. I have a GetBacklog sequence that is a copy of the example ctl's and am wondering if a couple lines following the eGet command will move streamed data into the variable.

Just for my education, would you also explain the steps of streaming and the order they need to take place in? If you can improve the process flow, it will help me understand the way processes should be grouped. I split up the functions between the sequences that drive my process like this:

1. Setup sequence

a. Setup and reset LabJack

b. Set pin offset

c. AddRequest statements to setup counter and analog inputs

d. Clear stream channels

2. First process sequence

a. Starts the motor

b. Enters some data to variables not related to stream

3. Second process sequence

a. Clears the history of the two channels to be streamed

b. Starts the backlogUD loop

c. Starts the streaming

d. Waits for the analog signal to exceed its baseline

e. Waits for the analog signal to return to baseline

f. Stops streaming

g. Analyzes the two arrays generated from the streaming process

4. Streaming sequence

a. Set resolution

b. Set scan rate

c. Configure analog channel

d. Add counter channel to scan list

e. Set scan rate

f. eGet

g. Transfer channel array data to variables (current challenge)

5. Stop stream sequence

a. ePut to stop stream

Does that make any sense at all? I am struggling to understand the functionality of some of the commands as you can probably tell.

Link to comment
Share on other sites

Ok, streaming is now working and I am calculating real values from the channels. Please ignore my previous post as a night of reading got me through those questions. I started without using the Align function just to see if it would work, but I got large variations in my numbers. With Align I get slightly better numbers, but if I decrease the threshold too tight, I get a C1086 error point to the array filtered from the two streamed channels. If I decrease the stream scan frequency that problem goes away, but my counts still vary +/- 25% from target or more. Here is the sequence that runs after everything is set up:

// Clear the DiaR and RawCounts channel history to allow the max command

RawCounts.ClearHistory(0)

DiaR.ClearHistory(1)

// start infinite loop sequence that reads UD backlog once per second

global backlogUD = 0

beginseq(GetBacklog)

// Add a little deadband for DiaZero to handle noise

DiaZero = 0.5

// Begin streaming data

beginseq(StartStream)

// hold up the stop stream process by wating until rollers open past threshold

// and then close up again, a slow check is ok

waitfor(DiaR[0] > DiaZero, .5)

// keep checking for the rollers returning to position

waitfor(DiaR[10] <= DiaZero,.5)

delay(0.5)

// Just after rollers return to zero, stop the stream

begseq(StopStream)

endseq(GetBacklog)

// Allow time to transfer data to the arrays:

delay(.5)

Align(DiaR, RawCounts, 0.01)

CountStream = Filter(RawCounts, DiaR > DiaZero)

DiaCtTotal = max(CountStream) - min(CountStream)

DiaMax = max(DiaR)

delay(.01)

motor = 0

page.strCurrentPage = "Setup"

And here is the streaming sequence:

DiaStream.ClearHistory(0)

CountStream.ClearHistory(0)

// Start the stream:

global scanrate = 0

eGet(ID,LJ_ioSTART_STREAM, 0, @scanrate, 0)

eGet(ID,LJ_ioStart_Stream, 210, @scanrate, 0)

ErrorHandler(ID)

Where am I missing a clean array of counts when DiaR > DiaZero?

thanks,

steve

Link to comment
Share on other sites

Ah, where to start... there are a number of issues with your code here. I strongly recommend you start simple, probably with a new document, and just get the system to stream your analog input and your counter. Then you can start adding the logic.

I'm going to list the issues in no particular order. There may be others, I'm just looking at the script, not testing it:

1) Why are you calling START_STREAM twice? I'm guessing 210 is the counter "channel" for streaming? If so, you should be using CLEAR_STREAM_CHANNELS and ADD_STREAM_CHANNEL for this. I recommend looking at one of the samples from the DAQFactory-LabJack guide to see how to do streaming properly.

2) why do you clearHistory() of one channel with 0, and another with 1? The one with 1 will leave one data point in your channel causing data to be misaligned.

3) why do you even need to worry about the backlog? Unless you are doing other stuff with the LabJack or pushing the stream rate to the max, you shouldn't have to worry about the backlog

4) This line: "Align(DiaR, RawCounts, 0.01)" does nothing. DAQFactory only passes parameters by value, which means that functions can't change the parameters that are passed to it. For align(), or most any other function to actually do something useful, you have to assign the return value to something, more like: DiaR = Align(DiaR, RawCounts, 0.01). You did this correct with the filter() function.

5) Despite #4, doing Align is not required provided you fix what I said in #2. The streaming data will come back already aligned from the LabJack.

6) Not sure why you did [10] in this line: waitfor(DiaR[10] <= DiaZero,.5). That will cause it to read an extra ten data points past the DiaZero mark. Also note that you are testing this criteria only every half second, which means you could have a lot more than 10 extra data points. It doesn't really matter ince you are filtering anyway.

7) and this is just a pet peeve of mine: always put 0 before a decimal place. Its "0.5" not ".5" Without the 0, the decimal place easily gets lost.

Link to comment
Share on other sites

The code was getting rather messy so I took time over the weekend to rewrite the whole thing and have cleaned up some of the issues. The results are the same, and probably due to the problems you found. Here are answers to your questions:

1) Housekeeping / rewrite - based on the sample code for streaming multiple inputs.

2) When I clearHistory(0) on DiaR, the line: waitfor(DiaR[0] > DiaZero, 0.5) gives me an error: C1086 One of the parameters was empty: Defect_to_Measure Line 18 - Uncaught error in sequence Defect_to_Measure

Since I am starting with a window of data before and after the period where DiaR > 0.5, I just got past the problem by allowing one extra DiaR count. That does pose a problem for the align function, however. How might I get past the problem of passing an empty parameter to the waitfor evaluation?

3) Do you mean that I should leave the backlog sequence running all the time? That happened in the rewrite and it seems to work fine. Just an accident, really, but so far no problem.

4) Ha! No wonder it wasn't doing me any good. Learning is a humbling experience.

5) Ok, I will not align until after fixing 2). That code is the same in the new program, so the same problem results.

6) I tried a couple of values in the place of DiaR[X], trying to make sure the data window was wide enough to capture the event of interest. I used [0] in the rewrite and it works fine.

7) We have similar peeves - the rewrite was done with leading 0's and it looks better.

The new program seems to stream fine, but had the same issues with a wide range of counts when running a standard object. Watching the measured and calculated values from each run, I finally figured out that the analog scan was returning values at the scan frequency rate while the counter was only giving counts. When I dropped the scan frequency down close to the pulse rate, the problem with consistency was solved. What is the dynamic between scan frequency and pulse rate? My system is battery powered and the pulse rate will decrease as the battery voltage drops.

Thanks for your help and patience. I would like to resolve the issue in 2) and understand the relationship between pulse rate and scan frequency just so I don't have an issue with that later. I can probably sense battery voltage and adjust the scan frequency (?)

Link to comment
Share on other sites

OK:

2) just add a delay, say of 0.25 seconds between starting the stream and the next line. For this to work, you really should call start/stop stream as functions instead of using beginseq(). So, its "startStream()". This way it runs in the same thread. By pausing 0.25 before entering the waitfor(), it gives time for a few measurements to accumulate.

3) No, I mean you should just ignore backlog. There is no reason for you to worry about it, nor run a sequence to read it.

5) I don't think you'll need to align at all

As for your hardware question, you'll need to ask the folks at LabJack. The counter is a 1 mhz counter, so unless your pulse's are really fast, I don't see why it would matter, but as I said this is a hardware question.

Link to comment
Share on other sites

Archived

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