Home AMX User Forum NetLinx Studio

Axxcess programming: looping commands

Hello. I need help, and don't have time to really figure it out. I have a couple of ideas on how this can be done, but I am hoping someone may have a better idea or can tell me if my thoughts are on the correct path.

Here is what I am trying to do: Periodically send out a series of serial commands maybe every 30 seconds. I have to poll a dimmer rack to see if some lights are at a level above 0 so that it can trigger the HVAC system. Basically I was hoping that I could have a single group to poll, but the rack won't allow me to do that. I have to poll about 5-8 dimmers and just get a general census of the status.. Depending on what the status of some of those dimmers are, I have to send out a string saying whether the dimmers in one room are on to trigger that hvac unit, or if dimmers in another room are on to trigger that hvac unit.

I was thinking of putting the section just right on the main program. Where it is just a:

Send string...
if statment
(true) send string..

Or I can just put a call in the main line and in the call have all that.

I am just worried about it going to fast and stalling up, and I don't know how to just to execute the commands every 30 or so seconds.

Thanks for your help!

Ryan

Comments

  • In Axcess you would use a named wait for this purpose (it does not offer timelines).
    WAIT 300 'CHECK EVERY 30.0 SECONDS'
    {
      SEND_STRING DIMMER,"'STATUS CHECK'" (* FILL IN YOUR REAL DATA *)
    }
    
    IF (LENGTH_STRING(DIMMER_DATA))
    {
      (* PROCESS THE FEEDBACK AS IT COMES IN AND TRIGGER HVAC ACCORDINGLY *)
    }
    
    Should be simple enough.
  • ryanwwryanww Posts: 196
    Thanks.. that was what I was thinking would work. I just wasn't sure that if each time it came around it would just start from scratch and if it wasn't complete, it would just start over.

    Thanks again!

    Ryan
  • ryanww wrote:
    I just wasn't sure that if each time it came around it would just start from scratch and if it wasn't complete, it would just start over.
    Axcess Mainline (the section that starts with DEFINE_PROGRAM) will contineously loop.

    When one of the itmes (PUSH/RELEASE/boolean statement/etc.) becomes active, it processes wahatever requires processing, then continues on.

    After checking the entire code, it will check for expired WAITs and other housekeeping and process those. Unless your code it too unwieldly, the WAIT 300 should process pretty accurately every 30.0 seconds.

    This is a *very* basic description, but should explain the process for you until you get into anything extremely complex (and please upgrade to Netlinx if you do).
  • ryanwwryanww Posts: 196
    Haha.. yea I just anted to make sure. I am not doing anything too intensive. I am just controlling 2 projectors (barco slm r6 performers), an etc unison dimmer, talon ac system, symetrix processing, and about 24 relays for power control. There is nothing too complex, this will probably be the most complex. Majority of the main coding is going to be going from mostly pushes, to mostly if statements in buffers. I am sure that in a few years down the road we will consider moving to netlinx, but that will be another whole batch of stuff for me to learn. I just picked up a axcess system and learned everything myself just my messing around and downloading documents and manuals from the amx site. I know I can't do the cleanest code, but at least it is working, and it really hasn't let me down (yet).. You know how that goes. I am mostly concerned about overloading the processors and letting some of the relays turn off. After all, that is what has to work no matter what.

    Thanks again for the help!

    Ryan
  • TurnipTruckTurnipTruck Posts: 1,485
    In Axcess you would use a named wait for this purpose (it does not offer timelines).
    WAIT 300 'CHECK EVERY 30.0 SECONDS'
    {
      SEND_STRING DIMMER,"'STATUS CHECK'" (* FILL IN YOUR REAL DATA *)
    }
    
    IF (LENGTH_STRING(DIMMER_DATA))
    {
      (* PROCESS THE FEEDBACK AS IT COMES IN AND TRIGGER HVAC ACCORDINGLY *)
    }
    
    Should be simple enough.

    Wouldn't that start a new wait every pass though mainline?

    You can make pseudo-timelines in Axcess:
    DEFINE_START
    nLOOP=0
    
    DEFINE_PROGRAM
        nLOOP=(nLOOP+1)
        IF(nLOOP=1000) nLOOP=0
        IF(nLOOP=0)
            {
            DO SOMETHING HERE
            }
        IF(nLOOP=500)
            {
            DO SOMETHING ELSE HERE
            }
    
    

    The timing will be related to how long your program is. So you will have to tweak the loop length and the values at which your events occur. You can also have many more events that occur at other loop values.

    This method works quite well for regularly polling devices in a specific order. It also works for sending strings at some interval while holding down a button, such as a command to up the volume of some device.
  • Wouldn't that start a new wait every pass though mainline?
    Named waits are not started every time; they are assigned a fixed location in memory the moment the code is compiled. Once a named wait has been started, it is not affected until the wait expires (and the code within the wait is executed, after which the wait could become active again) or affected by CANCEL_WAIT, RESTART_WAIT, etc. commands.
    Dynamic (non-named) waits could potentially start every time mainline runs - but I have never seen that happen.
  • dchristodchristo Posts: 177
    Just to be clear, all WAIT's work the same, regardless of if they are named or not. The advantage of naming a WAIT is that it allows you to cancel the wait. A WAIT in Mainline, weather named or not, once triggered will not restart until the Wait has expired.

    --D
  • DHawthorneDHawthorne Posts: 4,584
    It could be my memory is failing me from Axcent training, it was so long ago ... but I have had it in my head for a long time that unnamed waits will stack, and named ones will not. So if you call an unnamed wait while another is running, the second will engage when the first is done. If they are named, the second is ignored (if it's the same name, that is). I would be interested if I have had it wrong all this time; I don't have an Axcent handy I could try it out on.
  • dchristodchristo Posts: 177
    No, all Wait's work the same. Naming a Wait only gives the advantage of being able to cancel.

    --D
  • DHawthorneDHawthorne Posts: 4,584
    This has been bugging me, so I looked it up. They are not quite the same, though my admittedly old impression was not quite accurate either. From tech note 208:
    Axcess keeps track of each instance of waits in mainline, and does not repeat that instance until that wait instance has expired/executed. The list of waits is built as mainline is executed, so that encountered waits will not be re-initiated during the following mainline passes, until such time as the wait instances have expired.

    In the example you note, the wait is under a WHILE. Therefore, the wait is encountered multiple times in mainline within a single pass, and as such is seen as multiple discrete waits. If a while loop loops 5 times, then five wait instances are each tracked and each instance will not re-initialize the next pass through mainline, but they are effectively then treated as 5 differerent waits rather than one.
    Note the last line - unnamed waits are treated as seperate enities, where if you name them, they are recognized as sharing the wait with all like-named waits. It's not simply a matter of being able to cancel them, there are cases where they can behave differently because of this. So unless you are deliberately trying to exploit this, waits should always be named to avoid unexpected behavior. It may well be this does not carry over to NetLinx, and I haven't found any reference to that; this applies to Axcent programming.
  • TurnipTruckTurnipTruck Posts: 1,485
    I've been there and been through this. Establishing waits in any sort of loop (including Axcess mainline) is not a wise idea.

    In Axcess, it is much better to do the pseudo-timeline I exampled a few posts back if you want repetitious events.
  • ryanwwryanww Posts: 196
    Ok.. so which is best? Now I have started a whole debate. Geez.

    I have never used the pseudo method. I would like to try it though. It look fairly solid. Now how do I know how fast it will increment the nLOOP? I am going to use waits in the code with it because I basically have 3 sections of dimmers that it is going to check. So it will start with the first section, poll that dimmer, and if it returns anything higher then 2500 as the value then it will send a string out to the hvac. If else, it will poll the next dimmer channel to see if that is higher then 2500. And then it will do a third. Then probably a couple second wait I will start the process over with another batch of channels. It will be polling the same device though so I cant send it all out at once.

    Now my other question is about how to read the incoming data string. The string output is basically like this: Send String DR,"'[BALLROOM.Downlights.nINT]'" so it will return '[BALLROOM.Downlights.nINT=0]'
    The nINT value is the value of the actual intensity. It returns a 16 bit number (0-65535) 0-100%. When doing an if command to look at the string, what would be best to use to look for the value to see if it is above like 2500 or if it was converted to an tad smaller number (0-255)? And I am also not sure how to format it to look for a value greater then 2500. I knew, but am totally blanking on it..

    Thanks for all the help! Sorry to bring out all the old-school stuff.. but hey, it still works really well and is way solid!

    Ryan
  • DHawthorneDHawthorne Posts: 4,584
    ryanww wrote:
    Ok.. so which is best? Now I have started a whole debate. Geez.

    Some of the best stuff comes out of these little side debates, it's an excellent advantage of this type of venue. I've learned quite a lot from all the various impromptu discussions that spring up on these forums.
  • TurnipTruckTurnipTruck Posts: 1,485
    ryanww wrote:
    I would like to try it though. It look fairly solid. Now how do I know how fast it will increment the nLOOP?

    It depends on how long your Axcess program is. I would not use this method if the timing bewteen events triggered in the pseudo-timeline is critical.

    The pseudo-timeline method has two main benefits:

    1. It will guarantee the sequence in which your events occur.
    2. It will guarantee a MINIMUM time between the events.

    You can make a button light up or something every time the loop goes around to get an idea of the timing.
  • ryanwwryanww Posts: 196
    So while I have started the topics of waiting, does each wait in a particular section build upon eachother, or do they start from the event beginning?

    Say I hit a push. then if I do a wait 10 on 1,1.. wait 20 on 1,2.. or could I just do wait 10 each time and then they just follow the previous wait.

    Ryan
  • DHawthorneDHawthorne Posts: 4,584
    ryanww wrote:
    So while I have started the topics of waiting, does each wait in a particular section build upon eachother, or do they start from the event beginning?

    Say I hit a push. then if I do a wait 10 on 1,1.. wait 20 on 1,2.. or could I just do wait 10 each time and then they just follow the previous wait.

    Ryan
    If they are nested, they will build on each other. If they are all on the same level, they will run independently and start from the beginning. For example with:
    WAIT 10 <do something>
    WAIT 10 <do second thing>
    
    <do something> and <do second thing> will both happen at essentially the same time. Whereas with,
    WAIT 10 
    {
        <do something>
        WAIT 10 <do second thing>
    }
    
    <do something> will happen after one second and <do second thing> will happen a second after that.
  • ryanwwryanww Posts: 196
    So if I did:
    Wait 10
    <do something>
    Wait 15
    <do something else>

    is that something that I shouldn't do? Does it put more strain on the processor because it is doing multiple waits at the same time?

    Ryan
  • DHawthorneDHawthorne Posts: 4,584
    ryanww wrote:
    So if I did:
    Wait 10
    <do something>
    Wait 15
    <do something else>

    is that something that I shouldn't do? Does it put more strain on the processor because it is doing multiple waits at the same time?

    Ryan
    That would work, but to be safe, I would give the WAITs unique names. Or you could nest them so the second wait is inside the first, depending on whetyher they need to be independent of each other. There is no extra processor load from one method to the next; the code is all there either way, and WAITs don't actually process until they fire, they are just a flag in an event table (or something like) until that point.
  • ryanwwryanww Posts: 196
    Awesome. Thanks!

    Yea, I name almost all of the waits. Some things use cancel waits so it works out nicely.

    Ryan
Sign In or Register to comment.