Feedback problem I haven't seen before ...
DHawthorne
Posts: 4,584
I have been using device arrays for panel feedback for a long time, and have not had any real issues with it. My typical procedure is to iterate through the array with a FOR loop, and send the feedback as appropriate. But, it seems to not be working anymore, and I can't for the life of me figure out why. Here's a snippet from the code that is plaguing me:
The routine is called in a timeline that fires every half second. There is more to it, but I clipped it for brevity's sake; just what is above is enough to screw up.
The deal is, if only one panel is active (as set in the bActive array), it works fine. But if more than one flag is set in that array, the feedback on the ^TXT command never happens. The button on/off feedback is fine. What is making me crazy is that with device notifications turned on, I can clearly see the command going out to the panel, but the panel isn't reflecting it. I don't know if I have a case of brain fog here,or if there is something very fishy going on, but this has the potential of wrecking a lot of my projects if it is some new change due to a firmware or NS update. I use routines like this in pretty much every project that has more than one panel.
I keep getting the idea that I'm sending too many ^TXT commands too quickly because of the FOR loop ... but, like I said, I'm tracking it with device notifications, and I can see clearly that not much is going out at all, and the exact command I expect is also going out. It just does nothing, like it's being eaten before it gets to the panel. So now I'm following the hunch that it's something fairly obvious and I am just missing it by virtue of being too close to it for too long, and hopefully one of you folks will see something I'm missing ...
DEFINE_FUNCTION fnUpdateDisplay() { STACK_VAR CHAR nPanelCount STACK_VAR CHAR nCount STACK_VAR CHAR nSubCount FOR(nPanelCount = 1 ; nPanelCount <= nNumPanels; nPanelCount ++) { IF(bActive[nPanelCount] && (dvPanels[nPanelCount].NUMBER < 32000)) { // Input Gains FOR(nCount = 1; nCount <= nSwitchSize[2]; nCount ++) { IF(nLastGain[nCount] <> nGains[nCount]) { SEND_COMMAND dvPanels[nPanelCount], "'^TXT-', ITOA(nCount),',0,', FTOA(nGains[nCount]), ' dB'" ; nLastGain[nCount] = nGains[nCount] ; } [dvPanels[nPanelCount], nButtons[nCount]] = (nCurrentInput == nCount) ; } } } }
The routine is called in a timeline that fires every half second. There is more to it, but I clipped it for brevity's sake; just what is above is enough to screw up.
The deal is, if only one panel is active (as set in the bActive array), it works fine. But if more than one flag is set in that array, the feedback on the ^TXT command never happens. The button on/off feedback is fine. What is making me crazy is that with device notifications turned on, I can clearly see the command going out to the panel, but the panel isn't reflecting it. I don't know if I have a case of brain fog here,or if there is something very fishy going on, but this has the potential of wrecking a lot of my projects if it is some new change due to a firmware or NS update. I use routines like this in pretty much every project that has more than one panel.
I keep getting the idea that I'm sending too many ^TXT commands too quickly because of the FOR loop ... but, like I said, I'm tracking it with device notifications, and I can see clearly that not much is going out at all, and the exact command I expect is also going out. It just does nothing, like it's being eaten before it gets to the panel. So now I'm following the hunch that it's something fairly obvious and I am just missing it by virtue of being too close to it for too long, and hopefully one of you folks will see something I'm missing ...
0
Comments
I've been noticing weird things with ^TXT lately as well.
I've been burned by this coountless times.
e
As in SET_VIRTUAL_CHANNEL_COUNT?
yes, I've had to do this on AxLink devices before. Also, touch panels where I get above 255 channels. I have yet to find a rhyme or reason to it. I just know that sometimes when feedback isn't working I send the command to the device and all is well.
Are all of the variable arrays one dimensional? I have had problems where I was testing a 2 dimensional array with just the first dimension being used in the comparison (ie if(bActive[x]) instead of if(bActive[nCurrentWhatever][x]) ).
Jeff
The master is an NI-4100, firmware 3.50.430
Panels are mixed; I have some 5200's, at firmware 2.66.21, some R4's at 3.01.05, and some 500's at 2.3.22.
The code snippet above is acting up on the 500's for sure; I haven't tested on the others (job isn't complete, they don't all exist yet), but for this module, the R4's are not active. However, I had the exact same problem in a different module in another project going to R4's. In that case, I did a quick-and-dirty trick of getting rid of the FOR loop and sending to the entire array instead of indexing it. That worked, but I don't want to make a habit of it, that can be a lot of feedback statements all at once.
I know. I've still seen it misbehave even though diganostics showed it worked.
It works if I am only sending to one panel. Same exact code, with more than one active, it doesn't. I would think a virtual channel issue wouldn't work ever ...
I don't think it's a virtual channel issue. I think it must have something to do with how the master sets up its internal allocation of RAM to deal with channel feedback. The command doesn't care if you put it on a virtual device or not. Like I said, I've actually had to do it on an Axlink device to get channel 254 to work. 1-253 worked fine without it but not 254. Once I put in the set_virutal... it worked. take it out it stops.
I'm not saying it makes sense. I'm just reporting what worked.
I'll give it a shot, though all my channels are under 100 right now, let alone 255. Maybe because it's port 22 ...
So I guess I'm flooding the message queue too quickly. I'm certain this has worked just fine for me in the past. I have a wrenching gut feeling when I consider all the old projects which might now be broken because of this ...
I'm just going to have to revisit this when I'm fresh ... starting to goof things up simply by virtue of staring at it too long.
Jeff
It's a pain to do it but I've always been able to solve similar problems by adding in my own debug code that spits out diagnostic messages at each step of the way.
To get you started:
Code not tested so you might have to fix some string expressions.
If it worked, I would suggest making a habit of it. Nested for loops are very inefficient, and hog the processor, and there's usually a more efficient way anyway. If you have 20 panels and a 64 IO switch, those loops will run 1280 times, potentially sending that many commands. I would imagine that would bog down the command queue. If you are running this twice a second, that seems like an awful lot of processing to simply update volume text fields. Perhaps that is why with one panel it works, but beyond that it just can't do it.
Paul
The amount of instructions taken for the loop and incrementing an iterator is fairly small. Conditions for checking to continue the loop are also small and may be more "efficient" than sending to a dev array. Maybe not as "efficient" machine-wise as writing 1200 statements, and I haven't profiled sending to a dev array so I don't know of "efficiency" there, but writing a loop is certainly more "efficient" than trying to maintain those 1200 lines when one will do and is usually the same or only slightly more difficult than sending to a dev array.
The decision of whether to iterate through devices or send to an array of them depends on application, though.
("efficiency" is mentioned a lot on these boards, but I rarely see concrete numbers backing it up. We're not running at 1 MIPS.)
The problem isn't with the for loop processing, its with sending thousands of ^TXT commands to a touch panel every second. It doesn't really matter how efficient the code is if you are doing that, as you will encounter problems and can even lockup a touch panel if you aren't careful.
Paul
Exactly, and since this has a lot of R4's in the mix, I'm trying to keep commands to the controllers to a minimum.
I'm sending the ^TXT commands based on whether the text value to be sent has changed, then storing it to another variable which I later compare against to detect future changes. But I'm doing it inside the loop! So, naturally, second pass of the panel loop, it thinks it hasn't changed, because my compare value now matches; ergo only the first panel in the loop actually gets it. Duh. Easiest solution was to move the panel loop to inside the input loop, and now she works as expected.
A few more loops in there than I like, but I'll take another look at it later and clean that up if I can.
I just hate it when you look, and look, and look, but still miss something obvious.
Glad you caught it Dave.
-John
EDIT: I see what you mean. But now you have 2 nested for loops! That will tie up your processor on job with many touch panels. You could bum that down to one for loop.
Paul
I do it all the time, and there doesn't seem to be much of a hit. Since the actual operations in the loops are fairly simple, it blows through them very quickly. That is also why inside the loop there are comparisons made before anything goes out to the panel. Comparisons are fairly cheap, processor wise, where sending commands to a panel brings in the message queue and device responses. I'm more interested in minimizing that than minimizing memory operations.
Another reason is flexibility - the size of those loops can vary with the size of the installation, very easily.