08-13-2007 12:03 PM
08-13-2007 02:14 PM
Kevin,
Glad you're still along for the ride, and we're comprehending each other so far.
Thanks for *numsamps.vi. I tried it. It runs without timing out (guess timeouts are obviously impossible), but clicking or holding Strobe Now does not change TotalSamp 0 or TotalSamp 1, they remain at zero. I am interested to see how to ask the counter how many samples it has. Have I missed something that would be telling the counters they are SUPPOSED to buffer samples? I did try explicitly setting the number of samples in the buffer, with the "number of samples to take" input (which is mislabeled in this case), but no different.
On a hunch that it would be humorous, I modified this to create *numsampsParallel.vi by putting the samples taken queries in their own while loop, running in parallel with the existing loop. This also runs but, contrary to my hunch, it also keeps reporting zero samples. I figured this change would make it start reporting samples, probably one on each counter per Strobe Now. I don't know what to make of this. I did, however, run NestedSequences.vi again to verify that counts do appear, and they do indeed, so it's not a hardware change from days ago.
I know I need more counters. The NI salesman looked for a counter that sees rising and falling edges both, but said he found none. So I think this requires multiple counters. Also, of course, I need about 17 or 18 bits, so I wind up needing 4 counters per instrument, as far as I know. Which is no problem, as long as I can make buffering work.
>The basic idea would be to use change detection to buffer your instruments' signal states each time any of them had a transition. Then whenever you get a "read opportunity", you'd read whatever # of samples are presently available --- Wow. Does this imply that there's a stack in play, and I'm actually using the stack depth as my measured variable? Wow. If not a stack, what's the mechanism for holding multiple unread samples, and checking the count of those samples? Can it hold 10^4 or 10^5 or so of them? Do I follow correctly?
>...you'd need to explicitly program at least 5 of the tasks to use interrupt-based data acq... --- What does "explicitly program" mean? Writing it with nodes rather than VI's? Writing a .dll outside of LV and calling it? Would this be hardware interrupts or software interrupts? Seems like a product that doesn't try to set aside a whole DMA channel for what is actually a non-time-critical movement of two bytes would be a cleaner choice, no? I mean, even an RS232 port would probably have the bandwidth.
I'm going to go see if I can try some things on the larger hardware system. Thanks!
08-13-2007 02:44 PM
08-13-2007 05:07 PM
08-14-2007 09:54 AM
08-14-2007 01:25 PM
Kevin,
Exciting new results on the PXI system after a fresh start. Now things work fine, and I can't mess them up to save my life. I'm gonna go dump some tomato juice into the vents, as historically that has been a strong challenge, but in the meantime...
Attached here are two new VIs. ReadCountersOnce fires a timed pulse and then gets the latest values out of both counters. It sequences all these operations, which is what won't work on the development hardware. This is an important vi because I want to be able to employ it throughout the project. It takes the task references as inputs, so I can call it many times but only create the task once.
DistributionOfReadCountersOnce.vi calls ReadCountersOnce as a subvi, and does so in a loop that also displays the deltas and the difference between the deltas. Furthermore, it tallies how many times the difference is 0, or 1 or 2 or >2, or -1 or -2 or <-2, and displays what this distribution is. The purpose of this vi is just to test ReadCountersOnce with many repetitions. And when I left the lab, it was still doing so, at maybe 100 Hz, without any timeouts yet in the current configuration.
Actually, I did have the PXI system time out once, early on in this step when I didn't think I had changed anything but might have anyway, but I haven't reproduced that timeout, so am a little cautious.
Conclusions: 1) I have had various little things wrong here and there, 2) There is something significant but mysterious wrong with the development system hardware or install, 3) The first combination of little things being right and being tried on the PXI system has only just, and tentatively, occurred today, and, 4) Focusing on the development system shouldn't have been a bad choice but I got very unlucky.
Kevin, thanks for all this work! If you don't mind my asking, how'd I get lucky to have your help here? I see you've posted over a thousand replies but only started 4 threads. Are you just a kind of Lone Ranger, doing good deeds? I'm appreciative and also curious. Do I, uh, owe you anything? Should I take you out to lunch? What continent do you live on? How can I thank you for all this (assuming I'm not going to post an "Oh, no..." followup in an hour)?
08-14-2007 04:19 PM
Oh, no...
On the PXI system it ran almost 1e6 iterations without stopping and I stopped it. Then I discovered that about 15% of the time, it dies on the first iteration when starting, with a timeout, at random as far as I noticed.
I thought to add a pulse on the digital line before the loop starts in the calling, test program Distribution....vi. I sequenced the task configuration and start vi's for the counters to finish before the task configuration of the digital line starts, so the counters are ready and waiting when this initial extra pulse occurs. Now I find in 50 starts there were no timeouts. So I'm letting it run overnight.
But there's a problem. I added the pulse because I worried there might be some off-by-one error in how many samples are buffered, but the more I think about it, the less reasonable the idea seems. Besides, doing what I did should make the result I am getting obsolete by one iteration. So, an idea that was really pretty stupid turned out to eliminate the symptom, creating one more mystery and one more doubt.
Tomorrow I may create another test program that keeps calling the existing test program, to see how confident I can be that it will start. But at this point I'm checking Receiving several times a day to see if the other counters are here. I know, I know, UPS only comes once a day.
08-15-2007 01:41 PM
08-15-2007 03:41 PM
Hi, Chris
I'm still trying to wrap my head around what is happening and why you need the extra steps. However, I do have a couple comments on the LV code you attached.
1. Are the 1 ms waits between DAQmx nodes really necessary? I've never had to put waits between DAQ functions before.
2. What I do when a wait is necessary is to encapsulate it in a little subVI with error I/O terminals as shown in the attached VIs. This maintains the data flow and preserves error information.
3. The sequence structure in the inner loop is completely unnecessary. There is data dependency through the wires coming out of the subVI and the comparison functions, so you don't need the sequence to define which operations occur first. In general, you shouldn't have to use sequences (there are very rare occasions). They tend to make the diagram busier than necessary and overly complicate the code.
4. It always makes me nervous to see any sort of I/O where the error terminals aren't wired. You might not have a good plan for handling those errors at the beginning, but it is good practice to always wire the error in and error out terminals. This defines the data flow through the program and prevents downstream VIs from attempting to run if an error occurred previously. If you have operations that need to operate in parallel, then you can run the errors parallel and downstream use the Merge Errors to consolidate them.
5. There is a Boolean to 0:1 function that eliminates the need for the Select function and the 0 and 1 constants. This is a very minor thing, but it does replace 3 nodes with 1.
I'm sorry I've not been more helpful on the HW end, but it seems like Kevin was completely on top of things and he actually has counter/timer HW to try things out with...I didn't have any readily available. Thanks for the timing diagrams and wiring info. I'm sorting through all of it now.
08-16-2007 08:13 AM
Crystal, thanks, nice to hear from you!
>Are the 1 ms waits between DAQmx nodes really necessary? --- I don't know under what conditions different waits are necessary. Since there are sometimes funny dependencies between steps that I expected not to have them, and since at some level we should have to wait after asserting a line in one device until its desired effect has happened in another device to which it's physically wired, I think the conservative approach is to try things with the waits and then if the things work try reducing or eliminating the waits. In some of the vi's I've posted, though (I think TwoLoops was one such), the typical number of iterations I could get before a timeout would depend on the wait duration, so maybe with 5 ms it would run a few thousand times between timeouts whereas with 2 ms it would only run a hundred or so. In fact, I wonder if *longer* waits would accomplish anything new?
>In general, you shouldn't have to use sequences.... --- This gets at a programming style issue that I think NI actually teaches incorrectly. Let me rant about why: The terminals that are clearly called "Error" often get used to determine sequences, in NI's examples and in the first two courses (which I took), even though the Flat Sequence and Stacked Sequence are fundamental constructs provided just for this purpose. Certainly, this is a programming trick which confuses and obscures the distinction between the otherwise unrelated and clear goals of controlling execution order and catching exceptions. To quote _The Elements of Programming Style_ (Kernighan & Plaugher), "Write clearly - don't be too clever.", "Say what you mean, simply and directly.", and "Use the fundamental control flow constructs." Worse still, the timing vi's, which perhaps more than any others tend to get used in order-sensitive situations, lack Error terminals, so they actually require using sequences, or else other tricky means like nesting into a subVI, or wiring the numeric inputs and outputs (with numerical operations that essentially neutralize the significance of the wirings) as I used earlier. So I hear you, and know your advice is in the mainstream of LabVIEW programming, but still think using the Sequence constructs wise and consistent with good programming principles.
>The sequence structure in the inner loop is completely unnecessary. There is data dependency through the wires coming out of the subVI and the comparison functions, so you don't need the sequence to define which operations occur first. ---- Yes, I do need it! Though I agree with you I shouldn't need it! On 8/8/07 I posted InSeparateSequence.vi, which introduced this sequencing, with this explanation: "Here's an odd, unexpected observation: I have to sequence the reads of the counters to occur before I use the results I read, or else many of the cycles of this combine a new count from one counter with the one-back count from the other counter, and Diff takes on values like the number of counts in a loop. I though the dataflow principle would dictate that current values would get used, but apparently not so. Sequencing the calculations to happen after the reads fixes this. Any idea why?" Since posting this I have not thought of or read anything new on the question. It seems like an important clue, but I haven't figured out how.
>It always makes me nervous to see any sort of I/O where the error terminals aren't wired. --- And rightly so. I'm being lazy with many of these. Some do have errors wired through, and some even use Merge, but many don't. Sorry! I've been lazy partly because I've had to create so many vi's as part of this problem and partly because when I did use error terminals the messages were never interesting (the only error I've seen has been the timeout, which creates its own warning box on the desktop whether I use error terminals or not). But you are right, I am taking a chance when doing so and could have missed The Answer because of it! Kernighan would be ashamed of me, especially since I quoted him. I resolve to use them on future vi's I post.
>There is a Boolean to 0:1 function... --- Well, so there is. Thanks! Point out any others I've missed if you notice them.
>...Kevin was completely on top of things... --- Yes, I've been amazed with how he has helped. With what he brought to this discussion, I'd think I could be doing buffered event counting using nothing but a couple of diodes and LPT1. If it weren't for his postings, I'd think I was just learning disabled.