Home AMX User Forum NetLinx Studio

Level/Bargraph Question

Hey Everyone,

I have not worked with levels very much...That being said, All the examples in my prog 2 book are using vol cards so I didnt know if you could only use amx devices that support levels? I have an Extron Device that is handling the volume control and have parsed volume level reponses from that device in a variable to keep track of the level. I was hoping there was a way to tie a bargraph to that variable. I was gonna give it a try at work but wanted to be armed with a little direction first...ANY help is appreciated.

Comments

  • Hi.
    Something like this, maybe?
    DEFINE_PROGRAM
    
    SEND_LEVEL dvTP, BargraphLevelCode, YourVariable
    

    Or, if you don't want to permanently update the bar graph (if the variable hasn't changed), then you set the new level only when such feedback comes from the device
    DATA_EVENT [dvYourControlledDevice]//When receiving a volume update from your device
    {
         STRING:
         {
              IF (FIND_STRING(DATA.TEXT, 'VOLUME=', 1) //'VOLUME=' is arbitrary. Each device sends the volume value differently.
              YourVariable = ATOI(Text Parsed From the Incoming String) // Obviously, different from device to device
              SEND_LEVEL dvTP, BargraphLevelCode, YourVariable
         }
    }
    
  • a_riot42a_riot42 Posts: 1,624
    Or, if you don't want to permanently update the bar graph (if the variable hasn't changed), then you set the new level only when such feedback comes from the device

    A level event won't execute unless the level has changed and many devices don't send feedback unless the data has changed. What do you mean by 'permanently update'?
    Paul
  • a_riot42 wrote: »
    What do you mean by 'permanently update'?
    Paul

    The SEND_LEVEL (first case scenario) above is in the DEFINE_PROGRAM section, not in LEVEL_EVENT. That makes that SEND_LEVEL to be called every time the execution gets to that line, even if the value of the level sent is the same. At least this is my understanding...

    And, yes, it won't create a new LEVEL_EVENT on the bargraph itself unless the level value is different.
  • a_riot42a_riot42 Posts: 1,624
    The SEND_LEVEL (first case scenario) above is in the DEFINE_PROGRAM section, not in LEVEL_EVENT. That makes that SEND_LEVEL to be called every time the execution gets to that line, even if the value of the level sent is the same. At least this is my understanding...

    And, yes, it won't create a new LEVEL_EVENT on the bargraph itself unless the level value is different.

    I don't think you ever want a send_xxx in define_program. Running send_xxx in define_program will slow the system to a crawl.
    Paul
  • a_riot42 wrote: »
    Running send_xxx in define_program will slow the system to a crawl.
    Paul

    I agree and disagree. Simply using SEND_LEVEL in DEFINE_PROGRAM will not bring everything to a crawl. But, yes, using ANYTHING in the program for no reason cannot speed it up either...

    I only thought that it's relevant to offer a "generic" example for the question (something that gets executed every time), and one conditioned by a certain data event, which might be a "step two" exercise, given the nature of the question.
  • TurnipTruckTurnipTruck Posts: 1,485
    Update UIs when they come online
    DATA_EVENT [dvTP]
    {
    ONLINE:
      SEND_LEVEL DATA.DEVICE,nLevelNumber,nLevel
    }
    
    Update variable and UIs when a new level comes in from hardware
    DATA_EVENT [dvDevice]
    {
    STRING:
      {
      //Parsing of new level value done here
      IF (nLevel<>nNewLevelValue)
        {
        nLevel=nNewLevelValue
        SEND_LEVEL dvTP,nLevelNumber,nLevel
        }
      }
    }
    

    The above example does the absolute minimum amount of send_levels necessary to maintain your bargraph. This works especially well in polling situations where a device may send the same level value repeatedly.
  • viningvining Posts: 4,368
    Regardless of where you put your send_level, because the master tracks all levels if the value has not changed from what the master has on file the value will not be re-sent. Even if you have send_level in define_program and the value is the same it's not sent. Try looking at notification in NS2 for the TP your sending the level to.

    If you what to force a refresh when a TP comes online you might have to try something like (level range 1-100):
    DATA_EVENT [dvTP]
    {
    ONLINE:
      SEND_LEVEL DATA.DEVICE,nLevelNumber,0 ;
      SEND_LEVEL DATA.DEVICE,nLevelNumber,nLevel
    }
    
  • vining wrote: »
    Regardless of where you put your send_level, because the master tracks all levels if the value has not changed from what the master has on file the value will not be re-sent.]

    Doesn't this mean that the Master still has to check whether the level is different from what it has stored every time it runs the mainline? And then decide whether to re-send or not?
    This option still seems more resource intensive than strictly using the SEND_LEVEL in the EVENT section that initializes/changes the level variable.
  • DHawthorneDHawthorne Posts: 4,584
    Doesn't this mean that the Master still has to check whether the level is different from what it has stored every time it runs the mainline? And then decide whether to re-send or not?
    This option still seems more resource intensive than strictly using the SEND_LEVEL in the EVENT section that initializes/changes the level variable.

    Yes, but it's done at a very low level, and it's all internal to the processor, not requiring messages, queuing, handshake with the device, or any of the other things that bog a processor down. Checking the value of an internal register is very fast and uses very few resources. In fact, it's done anyway, whether you use it or not. One caveat: this is only true of real devices. Virtuals are sent the level no matter what when the send_level is executed. If your "real" device is on another master in the system, it is treated like a virtual (and in fact, actually is a hidden virtual on the local system). So there are times where you have to track the change yourself. But the lion's share of the times, it is perfectly safe to just send the level as much as you please; it won't go out unless there is a change.
  • TurnipTruckTurnipTruck Posts: 1,485
    DHawthorne wrote: »
    But the lion's share of the times, it is perfectly safe to just send the level as much as you please; it won't go out unless there is a change.

    Understood. I do beleive though that it is a good habit as a programmer to always do whatever you can to minimize processor usage and make the operations of your systems as lean as possible. As shown in my code example, I don't know of any way to further minimize processing in the situation the original poster asked about than what I posted. Further, if the UI ever became an array including a virtual device, there would not be the constant updating as you mentioned.

    Nice thread here, especially for newer programmers that are trying to learn the basics!
  • Thanks Turnip that worked great....Im doing a active bargraph, so now Im trying to make the volume level change if you touch the bargraph as well. I saw something in the book like define_connect_level and combine_level, Im guessing one of those would do the trick??? Again thankyou everyone, Almost everything Ive learned has been through this forum...and hopefully someday I'll be ready to give back.
  • I don't know of any way to further minimize processing in the situation the original poster asked about than what I posted.

    On a Friday afternoon note, there would be something even less processor intensive:
    IF (YouWantNewLevels)
    {
         SEND_COMMAND dvWife, "'GoTurnOnTheAMXProcessor'"
    }
    
  • If you don't want to worry about updating bargraph levels when a TP comes online, send your levels to a vTP in the string event. Combine the vTP with the TP and the bargraph will be always reflective of what is in the code.

    DEFINE_COMBINE
    (vTP,TP) //The vTP must be the root or first device.
  • TurnipTruckTurnipTruck Posts: 1,485
    SCOTTYP wrote: »
    Im doing a active bargraph, so now Im trying to make the volume level change if you touch the bargraph as well.

    No need to do any connect_levels or such.
    LEVEL_EVENT[dvTP,1]
    {
    nTouchedLevel=LEVEL.VALUE
    }
    
    nTouchedLevel will be equal to the value of the active bargraph at the point where it was touched. There are some other problems that you may run into, but you'll cross those bridges when you get to them.
  • jweatherjweather Posts: 320
    Understood. I do beleive though that it is a good habit as a programmer to always do whatever you can to minimize processor usage and make the operations of your systems as lean as possible.

    It might be faster to call SEND_LEVEL every time rather than testing it yourself... depends on what happens internally. If the system SEND_LEVEL call can check whether the value has changed faster than your NetLinx code, then you're actually slowing things down. Hard to say unless you know more about the internals than the rest of us... and probably doesn't matter anyway.
  • viningvining Posts: 4,368
    jweather wrote: »
    It might be faster to call SEND_LEVEL every time rather than testing it yourself... depends on what happens internally. If the system SEND_LEVEL call can check whether the value has changed faster than your NetLinx code, then you're actually slowing things down. Hard to say unless you know more about the internals than the rest of us... and probably doesn't matter anyway.
    I believe TurnipTruck was comparing event driven feedback to timeline or define_program type feedback. One is constantly running and checking and the other only checks & updates when something happens/changes. The latter is the AMX preferred approach since for the most part things seldom happen for hours and quite often days.

    As long as you have a function to refresh your TPs when they come online event driven feedback is the way to go. Which now makes me wonder if the master is smart enough to update a TPs channels & levels after a panels has been rebooted or falls offline and then on again? I know we would definitely need to update VText and I always have been doing levels and channels myself in code but do I have to? Hmmm....... It seems easy enough for the master to check and refresh levels and channels automatically and I've never given it any mind, so does it?
  • a_riot42a_riot42 Posts: 1,624
    vining wrote: »
    As long as you have a function to refresh your TPs when they come online event driven feedback is the way to go. Which now makes me wonder if the master is smart enough to update a TPs channels & levels after a panels has been rebooted or falls offline and then on again? I know we would definitely need to update VText and I always have been doing levels and channels myself in code but do I have to? Hmmm....... It seems easy enough for the master to check and refresh levels and channels automatically and I've never given it any mind, so does it?

    I don't think 'smart enough' is the issue. I think its more that you do not want to try and send lots of feedback to a touch panel as soon as it comes online. I don't do this and I don't really see the need. When a touch panel comes online, it will go to the default page set up in the properties. You only need to update things that occur there. Updating every button, text field, image etc, once its online even though none of those are seen by the user would be silly wouldn't it?

    I have seen touch panels that are done so that everything is updated all the time and the user experience is frustrating due to all the lag. I use a lazy approach that basically means that if the user can't see it, and/or if the feedback hasn't changed, I don't update it. It makes the system much zippier due to less wireless traffic. With wireless, things tend to slow down if you send small bits of data many times rather than large chunks of data a few times. So you will see more lag on a elapsed time field sent once a second than a field with lots of text but that gets sent only once.
    Paul
  • viningvining Posts: 4,368
    a_riot42 wrote:
    I think its more that you do not want to try and send lots of feedback to a touch panel as soon as it comes online. I don't do this and I don't really see the need. When a touch panel comes online, it will go to the default page set up in the properties. You only need to update things that occur there. Updating every button, text field, image etc, once its online even though none of those are seen by the user would be silly wouldn't it?
    I'll agree with that and to some extent it's also what I do. With my newer modules where I regulate feedback based what device page a TP is on, I'll stop feedback if active when a TP falls offline and won't update or resume feedback until you push a button flipping once again to that device page. Unfortunately I'm still dealing with older modules for devices that I've yet to go back to and update.

    Also in the scope of this thread I try to keep things simple since there's only a handfull of folks here that indeed start/stop feedback or update device pages based on what the TP is doing and figure the guys/gals asking the questions can get to that level of programming when they're ready. Just look at how many are not doing event "only" driven feedback yet.

    For a single panel to come online it's not such a burden on the system to update that TP * X amount of devices but when the master's rebooted and you then update every TP * X amount of devices that can take some time but at least that usually only when we do a program transfer so I can live with too.

    I still think simple event driven feedback & updating when a TP returns online is still better than keeping feedback in define_program or in a timeline that doesn't start/stop based on feedback needs.
  • DHawthorneDHawthorne Posts: 4,584
    I have a slightly different take on it. I agree that sending too much feedback on startup is a bad thing, but sometimes sending some it makes sense to do. For example, I frequently label navigation buttons in code - like to select a thermostat or a camera. This makes it easier for me to change names if the customer prefers it, without needing to run out to the job (I just telnet the master and update it there). In a situation like that, there is no event to trigger an update, but if the panel gets rebooted, the text isn't going to be correct. So that kind of update you pretty much have to do when the panel comes online. I don't think it's too much of a load if you don't go ape with it.

    But this would apply to any data that might not have changed, but the default panel isn't going to display. A thermostat in a relatively temperature-stable area is potentially going to read the same for a long time. If the panel resets, it may not get a state change from the thermostat, but the default text from the panel is going to be wrong. You have to have some way to force an update. You can do it when the page comes up, but in my mind, that is more traffic intensive than once on startup.

    The bottom line, as it often is, is that there is no single best way ... you have to evaluate all the circumstances involved, and pick what is best for the project (yet another reason why drag-and-drop "programming" often doesn't cut the mustard).
Sign In or Register to comment.