Feedback problem I haven't seen before ...
DHawthorne
Junior Member
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 ...
Comments
-
Just curious - what firmware revs are you running?
I've been noticing weird things with ^TXT lately as well. -
Is this a case of having channels above 255? If so you have to send the set the number of channels in code at the online of the device. (even if it's a real device)
I've been burned by this coountless times.
e -
ericmedley wrote: »If so you have to send the set the number of channels in code at the online of the device. (even if it's a real device)
As in SET_VIRTUAL_CHANNEL_COUNT? -
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. -
Have you stepped through the code with debug to make sure that it is actually getting to the send_command? I don't see anything obvious sticking out in the code posted.
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 -
This particular module has it's own port on the panels. Feedback channels are 1-64. The panel arrays are one-dimensional. And, as I stated, I can see the command going to the panel in Device Notifications. It just isn't acting on it.
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. -
DHawthorne wrote: »I can see the command going to the panel in Device Notifications.
I know. I've still seen it misbehave even though diganostics showed it worked. -
As in SET_VIRTUAL_CHANNEL_COUNT?
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 ... -
DHawthorne wrote: »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. -
ericmedley wrote: »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 ... -
No joy ... but I have to take back a previous statement, adamant as I was about it ... the command is NOT going out from the master. The first panel in the FOR loop gets it, anything past that does not. Been staring at things too long, and apparently, I was focusing on the port number, not the device number.
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 spinning my wheels now ... the message queue idea doesn't really pan out, since if I remove the bActive test and send to the entire dang array instead of a single indexed panel each pass of the loop, I can watch the dozens of messages go out just fine. It's got to be sending them faster to the entire array than what a FOR loop can generate. But I also might be bypassing some internal buffering by doing that. And the entire array thing just won't work if I have to send different data out depending on the panel stat (like in this case, what zone it is controlling).
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. -
Have you gone into debug and followed the execution to find out if the program is seeing/interpreting things as you did when you coded? I have found a few bugs this way (mainly the number of dimensions being used
) In the least, stepping through with debug should slow down the outgoing messages to the point that if it all works in debug, you have some evidence pointing to the message queue getting perplexed.
Jeff -
Sounds like there is a problem in either your if statement or with the array.
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:DEFINE_FUNCTION fnUpdateDisplay() { STACK_VAR CHAR nPanelCount STACK_VAR CHAR nCount STACK_VAR CHAR nSubCount FOR(nPanelCount = 1 ; nPanelCount <= nNumPanels; nPanelCount ++) { send_string 0, "'-->Loop count 1: evaluating bActive[',ITOA(nPanelCount),'] && (dvPanels[nPanelCount].NUMBER < 32000))'" IF(bActive[nPanelCount] && (dvPanels[nPanelCount].NUMBER < 32000)) { send_string 0, "'bActive[',ITOA(nPanelCount),'] = ', ITOA(bActive[nPanelCount]),' dvPanels[nPanelCount].NUMBER = ',ITOA(dvPanels[nPanelCount].NUMBER),' evaluated as true'" // 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) ; } else { send_string 0, "'bActive[',ITOA(nPanelCount),'] = ',ITOA(bActive[nPanelCount]),' dvPanels[nPanelCount].NUMBER = ',ITOA(dvPanels[nPanelCount].NUMBER), ' evaluated as false'" } } } }
Code not tested so you might have to fix some string expressions. -
DHawthorne wrote: »That worked, but I don't want to make a habit of it, that can be a lot of feedback statements all at once.
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 -
Profile it.
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.) -
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 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 -
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. -
Well, there's nothing like a fresh look. But at least I'm somewhat consoled none of you guys picked it up either
... was a very brain dead mistake.
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.DEFINE_FUNCTION fnUpdateDisplay( ) { LOCAL_VAR CHAR nPanelCount LOCAL_VAR CHAR nCount LOCAL_VAR CHAR nSubCount IF(bActive[nPanelCount] && (dvPanels[nPanelCount].NUMBER < 32000)) { // Light input button FOR(nPanelCount = 1 ; nPanelCount <= nNumPanels; nPanelCount ++) FOR(nCount = 1; nCount <= nSwitchSize[2]; nCount ++) [dvPanels[nPanelCount], nButtons[nCount]] = (nCurrentInput == nCount) ; // Input Gains FOR(nCount = 1; nCount <= nSwitchSize[2]; nCount ++) { IF(nLastGain[nCount] <> nGains[nCount]) { FOR(nPanelCount = 1 ; nPanelCount <= nNumPanels; nPanelCount ++) SEND_COMMAND dvPanels[nPanelCount], "'^TXT-', ITOA(nCount),',0,', FTOA(nGains[nCount]), ' dB'" ; nLastGain[nCount] = nGains[nCount] ; } } } }
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. -
It's like a "Where's Waldo" puzzle! I see it now!
Glad you caught it Dave.
-John -
Are you sure that was the problem? I am not seeing what you mean.
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 -
Are you sure that was the problem? I am not seeing what you mean.
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.
Categories
- All Categories
- 2.5K AMX General Discussion
- 922 AMX Technical Discussion
- 514 AMX Hardware
- 502 AMX Control Products
- 3 AMX Video Distribution Products
- 9 AMX Networked AV (SVSI) Products
- AMX Workspace & Collaboration Products
- 3.4K AMX Software
- 151 AMX Resource Management Suite Software
- 386 AMX Design Tools
- 2.4K NetLinx Studio
- 135 Duet/Cafe Duet
- 248 NetLinx Modules & Duet Modules
- 57 AMX RPM Forum
- 228 MODPEDIA - The Public Repository of Modules for Everyone
- 943 AMX Specialty Forums
- 2.6K AMXForums Archive
- 2.6K AMXForums Archive Threads
- 1.5K AMX Hardware
- 432 AMX Applications and Solutions
- 249 Residential Forum
- 182 Tips and Tricks
- 146 AMX Website/Forums