12-10-2012 09:45 AM
I have tried researching this and can't seem to find something that exactly matches what I am trying to do...
In a nutshell, this is what I am trying to do: I have a (non-ni) relay control board with which I communicate via tcp over ethernet. The manufacturer provides a .net dll for use in various programming languages, which I am successfully using in labview. The relay board has 32 relays, divided into 4 "banks" of 8 relays, each addressed with a command like (this is just pseudocode) relay_on(bank, relay) and relay_off(bank,relay). No problems there. For all 32 relays I had to create front panel indicators giving the relay state (on or off) and controls that either set or reset the relay in "manual" mode or apply pwm with user-set on and off times in "auto" mode. I basically setup the vi based on a fsm i devised. There is a button that switches between manual and auto. Still no problems there.
Sorry for the long-windedness but I'm trying to build up to the issue I'm having, and unfortunately I am not in a position to be able to post a vi.
Here is the issue: the method I am using to automatically turn the relays on or off based on on/off times is this: if the relay is set to "on" in auto mode, an interation in a dual for loop (8 inside of 4) that parses 2d arrays of on times and off times compares an initial ms tick value to the current ms tick value and sees if the on or off time (based on current relay state) is exceeded, switches the state, and, on a high-to-low transition, increments the appropriate element in a 2d count array.
I'm not sure if I'm painting a good picture but the bottom line is this: I have some serious timing problems. When only 1 relay timer is turned on, the timing is fine. But when I have the timers turned on for all 32 channels, everything goes haywire. Some relays follow the on/off times "relatively" closely to with 1 second (not that great) and others that have a period of, say, an hour, switch in something like 5 seconds.
Again, I'm sorry I can't post code, but I think this is a (somewhat) simple matter of determinism and independent timed loops. IS there a better way to "poll" all 32 relay channels, check for elapsed on or off time, and switch states when this time exceeds a user-defined timer value? I'm using seemingly countless 2d arrays to handle all the different per-relay indicators and controls (4 rows for bank, 8 columns for relay #) that are difficult enough to parse, but then sequentially checking whether the user turned the timer on or off, checking the on or off time elapsed, writing a new state, reading the state back to verify the relay actually switched, updating a counter AND updating the appropriate front panel indicators AND writing the counter array to a log file to boot... sufficed to say my block diagram is a birds nest. I avoided sub-vi's because frankly I figured zillions of sub-vi's would simply bog down the computer memory and processor even more. Also, as far as I can tell I can only send one write or one read at a time, since the board only has one ip address/tcp port. I tried loading multiple instances of the dll but they run into each other and throw exceptions because the port is busy.
Let me restate/rephrase the question: what's a good way to handle all these operations, minimize loop time, and improve timer accuracy? I've read about the "producer/consumer" methodology, but not only am I not very clear on how that works since I've never used those queue/notifier/semaphore, etc. vi's, adding all those loops would seem only to turn a big bird's nest into a gigantic bird's nest.
Help!
12-11-2012 03:26 PM - edited 12-11-2012 03:27 PM
Hi dcl123,
Are you using timed loops in Windows enviroment?
Regards,
Carmen C.
Application Engineer
National Instruments
12-12-2012 01:50 PM - edited 12-12-2012 01:57 PM
Carmen,
Sorry for not getting back with you sooner. I thought i would get notified if someone replied...
No I am not using timed loops at all. When I am in the "auto" state (case for enum = "auto"), I run a single loop that iterates through all 32 positions. If the on or off (depending on the relay's current state) time hasn't been exceeded nothing should happen and it moves on to the next for loop iteration.
I've been able to find very few discussions about similar situations, but I'm sure the problem is related to needing to do so many writes and reads over ethernet. With all 32 relays being turned on and off, i would expect the overall loop to be slow, say 3-5 seconds, but i don't see why that would affect the actual timing calculation. I was also wondering if casting may be an issue. I'm the value of the tick count can get really big and I was thinking if some kind of wrap-around or overflow of the tick count was happening that would explain why on/off times that measure in hours would be thrown off, but I digress...
12-12-2012 02:27 PM
A rollover can occur with the tick count. It will happen at intervals of 2^32-1 milliseconds after the computer was last rebooted and the same number of milliseconds after the previous rollover. This interval is about 49 days. The accuarcy is not particularly good as it is derived form the processor clock. I think 100 ppm is about as good as it will get. The time of day clock can be used, but then you can run into Daylight Savings Time issues.
I suggest you try separating the timing from the tcp communications. Do the timing in one loop and the communications in a parallel loop. The timing can then occur with ~millisecond resolution. The timing of the communications will depend on the OS (because the actual ethernet driver and tcp/ip stack is managed by the OS), the amount of data being sent, and how fast the relay board responds. Pass messages bewteen the two loop via queues or notifiers. Look at the many examples of Producer/Consumer architecture.
Lynn
12-13-2012 02:55 PM
johnsold,
I've actually tried reading up on producer/consumer, but I can only ever find highly simplified examples. I still don't have a good grasp on how the queue system works. I understand the theory, but I can't quite see how to implement it in my vi. my vi is just so complicated when I look at it that I just can't see how to drop the queue stuff in. How would I handle the queue system with 7 [4x8] arrays of front panel controls and indicators as well as my on/off timer tick counts? All I can seem to find is examples that show one control and two loops. I can't extrapolate in my mind how I would apply that to many arrays of controls, indicators, and variables. right now i have one big while loop that reads all the front panel controls and passes them to shift registers. The while loop contains a for loop that iterates through the 32 relays, along with relay n's associated front panel controls, indicators and current on or off timer value.