Home AMX User Forum NetLinx Studio

WAIT in DEFINE_PROGRAM section

Does a WAIT in the define_program section get executed once until wait time expires, or do the WAIT's stack up and ultimately hose the processor. More specifically, is the following code snippet example a problem?

DEFINE_PROGRAM

WAIT 5 // .5 seconds
{
UpdateTouchPanelFeedback()
}

P.S. I added something like this "in a hurry" on Friday. The processor needed to be rebooted over the weekend. I'm guessing this is the cause. I have rewritten using TIMELINE and am planning on updating the system tomorrow.

Comments

  • a_riot42a_riot42 Posts: 1,624
    pushtoplay wrote: »
    Does a WAIT in the define_program section get executed once until wait time expires, or do the WAIT's stack up and ultimately hose the processor. More specifically, is the following code snippet example a problem?

    DEFINE_PROGRAM

    WAIT 5 // .5 seconds
    {
    UpdateTouchPanelFeedback()
    }

    P.S. I added something like this "in a hurry" on Friday. The processor needed to be rebooted over the weekend. I'm guessing this is the cause. I have rewritten using TIMELINE and am planning on updating the system tomorrow.

    No the waits don't stack up. Otherwise you couldn't use them in define_program as you have mentioned. Your wait will get executed every half second, but that is still far too often to update a touch panel, and this is what is hosing your master. I don't know what UpdateTouchPanelFeedback does, but if it sends text to the touch panel or does anything other than turn on/off channels, you are seriously compromising the reliability and responsiveness of the system. Is there some reason you need to update the panel every half second? Is it controlling a nuclear launch site or a particle accelerator?
  • viningvining Posts: 4,368
    a_riot42 wrote:
    but if it sends text to the touch panel or does anything other than turn on/off channels, you are seriously compromising the reliability and responsiveness of the system.
    I may be over looking something but pretty much everything except sending text would be ok since the master keeps track of channels and levels and only sends these updates when it needs to regardless of how oftens this function runs.

    If you are sending text then you should change how you send or how you track what you send. You can either send as you receive data and parse it or create a variable, variable array or structure to store your sent strings and then compare those strings to the received data to verify the text on the TP's indeed needs to be updated. Something like this:
    DEFINE_FUNCTION CHAR fnVAV_MyWeatherFB()
         {  
         if (sRSSsent.lastupdate != sRSS.lastupdate)                             
    	  {               
    	  SEND_COMMAND dvTPWeatherArray,"'!T',nFeedback[VT_lastupdate],sRSS.lastupdate"
    	  sRSSsent.lastupdate = sRSS.lastupdate
    	  }
         if (sRSSsent.title != sRSS.title)                             
    	  {               
    	  SEND_COMMAND dvTPWeatherArray,"'!T',nFeedback[VT_title],sRSS.title"
    	  //SEND_COMMAND dvTPWeatherArray,"'!T',nFeedback[VT_title],'Salisbury, Connecticut Weather'"
    	  sRSSsent.title = sRSS.title
    	  }
         if (sRSSsent.rcvdzip != sRSS.rcvdzip)                             
    	  {               
    	  SEND_COMMAND dvTPWeatherArray,"'!T',nFeedback[VT_rcvdzip],sRSS.rcvdzip"
    	  sRSSsent.rcvdzip = sRSS.rcvdzip
    	  }
    

    If your just sending strings straight from the DATA_EVENT after parsing data you should still store the strings being sent somewhere so you can updates TPs when they come online or when another TP flips to that page, that is unless you're sending to the entire TP array like the example above. Now the example above is old code which hasn't yet been re-written to send updates only to TPs on this particular device page which is the direction we all should be moving towards.
  • a_riot42a_riot42 Posts: 1,624
    vining wrote: »
    a_riot42 wrote:
    I may be over looking something but pretty much everything except sending text would be ok since the master keeps track of channels and levels and only sends these updates when it needs to regardless of how oftens this function runs.

    You may not be sending any data to a TP for on/off channels and levels that haven't changed, but the processor has to check each one of those variables 200 times a second to see if they have. I tend to see this in code a lot and I think its responsible for a laggy system once they start to get big.
    define_program
    for (i = 1; i <= cnNumTPs; i++)
    {
      updateTP(i)
    }
    

    99.99% of the time this code will run and nothing will change, so why bother, especially when it can usually be put in a channel event with no overhead? As sloppy as this code is, it would still be better than the above:
    channel_event[vdvDevices, iBtns]
    {
      on:
      {
        updateTPs()
      }
      off:
      {
         updateTPs()
      }
    }
    

    Paul
  • viningvining Posts: 4,368
    a-riot42 wrote:
    You may not be sending any data to a TP for on/off channels and levels that haven't changed, but the processor has to check each one of those variables 200 times a second to see if they have.
    very true! The ieal method of sending feedback is to have it event driven in either a channel_event as in your example or button_event, date_event, etc. Then in these events also store your VT and other values so you can update new TPs that come online or flip to a particular page.

    Unforetunately most code presently being used isn't written this way, especially the AMX modules and a lot of coders aren't into that level of feedback and processor management yet so for them they need simple ways to modify their existing code so that their output light isn't solid red all the time.

    Also a lot of text being sent to the TPs like like surround modes or audio inputs can be done easier with less effort but sending levels and have TP button made as multi-state bargraphs with each state holding its own text. Then sending levels (fixed or constant VT) is manage by the master.
  • JeffJeff Posts: 374
    vining wrote: »
    a-riot42 wrote:

    very true! The ieal method of sending feedback is to have it event driven in either a channel_event as in your example or button_event, date_event, etc. Then in these events also store your VT and other values so you can update new TPs that come online or flip to a particular page.

    Unforetunately most code presently being used isn't written this way, especially the AMX modules and a lot of coders aren't into that level of feedback and processor management yet so for them they need simple ways to modify their existing code so that their output light isn't solid red all the time.

    Also a lot of text being sent to the TPs like like surround modes or audio inputs can be done easier with less effort but sending levels and have TP button made as multi-state bargraphs with each state holding its own text. Then sending levels (fixed or constant VT) is manage by the master.

    I don't know that I'd agree entirely. I think there are a lot of places, especially with wireless panels that may or may not be online all the time, that doing feedback in the [dvTP,1]=nProjectorPower method works fine, and might even be preferable. Also, I prefer tracking thing like Proj status in variables, instead of just sending the state directly to the panel, so you can more easily follow things in debug.

    I like having a system designed such that I don't have to manually update panels when they come back online, and short of combining panels to a virtual device, I think the best way to do it is through assigning button channels to variables.

    I'd agree that sending text to panels over and over is poor, and I only do that in events, but I do my TP feedback in a timeline that runs every half second or so, and in several decently large systems I've never once experienced a slowdown that commenting out my TP timeline fixed.

    I like my timeline for feedback instead of a wait in define program, but its certainly a valid way to code.

    J
  • Guys, great comments! Too bad nobody seems to have an opinion on this :-). I was mostly just wondering about how the WAIT is handled (got the answer, thanks), but the other stuff you guys bring up is important in understanding system performance. As a sidenote, I am only updating channels, no text is being retransmitted so it seems like my assumption on limited system performance impact is probably correct. Thanks again, Keith
  • viningvining Posts: 4,368
    Jeff wrote:
    especially with wireless panels that may or may not be online all the time, that doing feedback in the [dvTP,1]=nProjectorPower method works fine, and might even be preferable.
    I still have plenty of code running that does that but even with wireless panels you can still do feedback based on events you just also have to consider the online and offline events and w/ the 5200i now awake and standby. On my newer module if a panel falls offline I stop feedback since the offline event will set my TP_X_ActiveArry index for that TP for that device to 0 and when it comes back online my online event clears all pop ups and displays the main page. I'm not sure how to treat the awake and stanby options since they've only been available since the NS beta release. Now when a panel flips to a specific page my TP_X_ActiveArry is set to 1 and I run a update display function to bring the feedback up to date and from that point on feedback is event driven. So you can do all feedback strictly trigger by events and never need a timeline or put feed back in define_program or triggered by a function in await in define program.

    A wait in the program simply adds the statement or stetements that follows to the system timeline which repeats at 100ms to see if it time to execute the code. The problem with putting waits in the system timeline (wait queue) is that every 100ms it has to check every item in the queue to see if it's time is up and if not subtract 100ms from its time to execute. So depending on how much stuff through out the entire code is running waits at any given time the system could have a substantial list to run through and subtract time from every 100ms.
  • Probably not a good example, but I put a WAIT in the mainline to make a button flash off and on every half second. I use it for a mute button on the master volume. The mute button flashes when it is on. Probably not the "best" way, but it worked.
  • JeffJeff Posts: 374
    I used to do that too.
    define_variable
    non_volatile integer nFlash
    non_volatile integer nMuted
    
    define_program
    wait 5 nFlash=!nFlash
    [dvTP,1]=nFlash and nMuted
    

    That way you just set nMuted to on, and the button blinks every half second.

    The only reason I stopped doing it was that it made stepping through code frustrating beyond all belief. Lately I've been having non blinking mute buttons, but I admit I'd rather have it blink again.

    J
  • DHawthorneDHawthorne Posts: 4,584
    The master is tracking channels whether you run feedback on them or not. Comparing a variable to an internal stack is probably the least CPU intensive thing you can do; I'm quite sure normal idle processes use more resources. I wouldn't worry about it - as stated, it's SEND_COMMANDs to update text that bog things down, and if your feedback includes them, then you have a problem. However, I must also add that if your feedback is flawed (for example, the same channel continuously going on and off), all bets are off ... that can indeed bring the system crashing down (which I know from personal experience).
  • Jeff wrote: »
    I used to do that too.
    define_variable
    non_volatile integer nFlash
    non_volatile integer nMuted
    
    define_program
    wait 5 nFlash=!nFlash
    [dvTP,1]=nFlash and nMuted
    

    That way you just set nMuted to on, and the button blinks every half second.

    The only reason I stopped doing it was that it made stepping through code frustrating beyond all belief. Lately I've been having non blinking mute buttons, but I admit I'd rather have it blink again.

    J
    Wouldn't it be better to simply create a small Timeline for this task? Sure, it's a few more lines of code, but at least you can kill it when you're finished and recall it when you want it again - as opposed to assuming it will forever be checking this? It just doesn't strike me as good programming habit to have the processor handling code it oughtn't need worry about.
  • Spire_JeffSpire_Jeff Posts: 1,917
    Jeff wrote: »
    I used to do that too.
    define_variable
    non_volatile integer nFlash
    non_volatile integer nMuted
    
    define_program
    wait 5 nFlash=!nFlash
    [dvTP,1]=nFlash and nMuted
    

    That way you just set nMuted to on, and the button blinks every half second.

    The only reason I stopped doing it was that it made stepping through code frustrating beyond all belief. Lately I've been having non blinking mute buttons, but I admit I'd rather have it blink again.

    J

    Why would you even need to make the processor handle this? Unless you are dealing with keypads, you can just set the button feedback to Blink. It will only blink when the channel is on. This way, all you have to do is: [dvTP,MuteButton] = nMuteState; .

    This solves all of the processor overhead and extra coding problems :)

    Jeff
  • a_riot42a_riot42 Posts: 1,624
    Spire_Jeff wrote: »
    Why would you even need to make the processor handle this? Unless you are dealing with keypads, you can just set the button feedback to Blink. It will only blink when the channel is on. This way, all you have to do is: [dvTP,MuteButton] = nMuteState; .

    This solves all of the processor overhead and extra coding problems :)

    Jeff

    Why even have that in mainline when you could do this?
    channel_event[vdvRcvr, cnMute]
    {
      on:
      {
        on[dvTP, cnMute]
      }
      off:
      {
        off[dvTP, cnMute]
      }
    }
    
Sign In or Register to comment.