Home AMX User Forum NetLinx Studio

Fire alarm interface help!

Hi all,

I'm implementing an interface between a show controller (AMX NI-4100) and a fire alarm system via a NC (Normally Closed) circuit from the fire alarm system. I've wired the channel 1 port and ground together with a jumper for now, the channel 1 LED lights on the front panel.

On the notifications tab, the channel 1 registers to be on and off when the jumper is connected and removed. I've programmed a channel event to perform actions for OFF and ON events. Code as follows:

CHANNEL_EVENT [dvIO,1]
{
ON:
{
SEND_STRING 0,'FIRE ALARM IS HEALTHY'
FIRE_ALARM_HEALTHY = 1
CALL 'FIRE_ALARM_RELEASE'
}
OFF:
{
SEND_STRING 0,'FIRE ALARM IS ACTIVE!'
FIRE_ALARM_HEALTHY = 0
CALL 'FIRE_ALARM_ACTIVE'
}
}

I get no compiler errors or warnings.

Anyone have any idea why this might not be calling the calls as it should?

Thanks,

Nick

Comments

  • ericmedleyericmedley Posts: 4,177
    what do the calls look like?
  • nhighton wrote: »
    Hi all,

    I'm implementing an interface between a show controller (AMX NI-4100) and a fire alarm system via a NC (Normally Closed) circuit from the fire alarm system. I've wired the channel 1 port and ground together with a jumper for now, the channel 1 LED lights on the front panel.

    On the notifications tab, the channel 1 registers to be on and off when the jumper is connected and removed. I've programmed a channel event to perform actions for OFF and ON events. Code as follows:

    CHANNEL_EVENT [dvIO,1]
    {
    ON:
    {
    SEND_STRING 0,'FIRE ALARM IS HEALTHY'
    FIRE_ALARM_HEALTHY = 1
    CALL 'FIRE_ALARM_RELEASE'
    }
    OFF:
    {
    SEND_STRING 0,'FIRE ALARM IS ACTIVE!'
    FIRE_ALARM_HEALTHY = 0
    CALL 'FIRE_ALARM_ACTIVE'
    }
    }

    I get no compiler errors or warnings.

    Anyone have any idea why this might not be calling the calls as it should?

    Thanks,

    Nick

    Do you get the strings in the diagnostics window?
  • DarksideDarkside Posts: 345
    Use a button_event with push: and release: instead
  • viningvining Posts: 4,368
    Use a button_event with push: and release: instead
    Not that I've ever tried but IO's issue channel events not button_events.

    Do you see the send_string 0's in diagnostics? If so put one in each of the calls to see if they fire.

    If not is dvIO defined properly? dvIO = 5001:17:0; for your NI-4100.
  • nhightonnhighton Posts: 18
    dvIO = 5001:17:0 is the definition.

    The calls are:

    DEFINE_CALL 'FIRE_ALARM_ACTIVE'
    {
    CALL 'STOP_SHOW'
    SEND_COMMAND dvEPC,'VOLUME-MUTE'
    SEND_COMMAND dvEPC,'BLANK-ON'
    SEND_STRING 0,'FIRE ALARM ACTIVE! AUDITORIUM AND EXHIBIT A + V STOPPED!'

    WAIT 30000 'EQUIPMENT_OFF' //WAIT 5 MINS, IF STILL ACTIVE THEN SHUTDOWN EQUIPMENT
    {
    IF (FIRE_ALARM_HEALTHY == 0)
    {
    CALL 'POWER_OFF_ALL_PROJECTORS'
    CALL 'SHUTDOWN_PC'
    }
    }
    }

    DEFINE_CALL 'FIRE_ALARM_RELEASE'
    {
    SEND_COMMAND dvEPC,'VOLUME-UNMUTE'
    SEND_COMMAND dvEPC,'BLANK-OFF'
    SEND_COMMAND 0,'FIRE ALARM NO LONGER ACTIVE, EXHIBIT PCS A + V RESTORED'
    }


    and


    DEFINE_CALL 'FIRE_ALARM_RELEASE'
    {
    SEND_COMMAND dvEPC,'VOLUME-UNMUTE'
    SEND_COMMAND dvEPC,'BLANK-OFF'
    SEND_COMMAND 0,'FIRE ALARM NO LONGER ACTIVE, EXHIBIT PCS A + V RESTORED'
    }


    No, the SEND_STRING 0 messages aren't shown in diagnostics so I guess the calls aren't being executed.

    Very strange,

    Thanks,

    Nick
  • ericmedleyericmedley Posts: 4,177
    nhighton wrote: »
    dvIO = 5001:17:0 is the definition.

    The calls are:

    DEFINE_CALL 'FIRE_ALARM_ACTIVE'
    {
    CALL 'STOP_SHOW'
    SEND_COMMAND dvEPC,'VOLUME-MUTE'
    SEND_COMMAND dvEPC,'BLANK-ON'
    SEND_STRING 0,'FIRE ALARM ACTIVE! AUDITORIUM AND EXHIBIT A + V STOPPED!'

    WAIT 30000 'EQUIPMENT_OFF' //WAIT 5 MINS, IF STILL ACTIVE THEN SHUTDOWN EQUIPMENT
    {
    IF (FIRE_ALARM_HEALTHY == 0)
    {
    CALL 'POWER_OFF_ALL_PROJECTORS'
    CALL 'SHUTDOWN_PC'
    }
    }
    }

    DEFINE_CALL 'FIRE_ALARM_RELEASE'
    {
    SEND_COMMAND dvEPC,'VOLUME-UNMUTE'
    SEND_COMMAND dvEPC,'BLANK-OFF'
    SEND_COMMAND 0,'FIRE ALARM NO LONGER ACTIVE, EXHIBIT PCS A + V RESTORED'
    }


    and


    DEFINE_CALL 'FIRE_ALARM_RELEASE'
    {
    SEND_COMMAND dvEPC,'VOLUME-UNMUTE'
    SEND_COMMAND dvEPC,'BLANK-OFF'
    SEND_COMMAND 0,'FIRE ALARM NO LONGER ACTIVE, EXHIBIT PCS A + V RESTORED'
    }


    No, the SEND_STRING 0 messages aren't shown in diagnostics so I guess the calls aren't being executed.

    Very strange,

    Thanks,

    Nick



    in the first call your very first command is going to another call.
    DEFINE_CALL 'FIRE_ALARM_ACTIVE'
    {
        CALL 'STOP_SHOW'
    etc...
    

    it would be my guess that that call might be dumping you out somewhere. Bear in mind that the way the call works is that it leaves the current routine, goes off and does the call being called and then comes back to the next position in the stack of commands. So, something in that call might be causing the issue. I tend to not put calls within calls or functions within functions per se. About the only time I do allow myself to do this is if the sub-function being called is a quick 'one-off' kind of routine that is straight-through with no loops or anything messy. But, that's me.

    On another note, I've always been a little itchy about putting waits in calls. I would probably do what you're doing in a timeline myself since I can know where I am in the sequence of events happing at all times. A Call or a Function is kind of a black box. You can put all kinds of traces in the code but now you're adding coce. A timeline can be watched at any point fairly easily and can be paused, killed or restarted.

    that's my 2 cents.
  • nhighton wrote: »
    Hi all,

    I'm implementing an interface between a show controller (AMX NI-4100) and a fire alarm system via a NC (Normally Closed) circuit from the fire alarm system. I've wired the channel 1 port and ground together with a jumper for now, the channel 1 LED lights on the front panel.

    One thing to note is that the IO's on the AMX processors are open collector designs. What this means is that when the contact you are connected to is closed (the circuit is completed) the ground sinks 5V and registers as a PUSH statement and then when the circuit opens the input pin floats at 5V and registers as a RELEASE. I thought it was a channel event as well, but in reading the documentation for both the hardware side and the programming side it says push and release, not on and off.

    So, a couple of things I would try. First, send the following command to the input you are using: send_command dvIO, 'SET INPUT 1 HIGH'. This command should set the input to detect the opposite of what it normally does, which should help in your situation. Second, try a button event with push and release instead of a channel event with on and off. It can't hurt to try since it should be relatively simple to change the code.

    Hopefully that helps!
  • viningvining Posts: 4,368
    One thing to note is that the IO's on the AMX processors are open collector designs. What this means is that when the contact you are connected to is closed (the circuit is completed) the ground sinks 5V and registers as a PUSH statement and then when the circuit opens the input pin floats at 5V and registers as a RELEASE. I thought it was a channel event as well, but in reading the documentation for both the hardware side and the programming side it says push and release, not on and off.

    So, a couple of things I would try. First, send the following command to the input you are using: send_command dvIO, 'SET INPUT 1 HIGH'. This command should set the input to detect the opposite of what it normally does, which should help in your situation. Second, try a button event with push and release instead of a channel event with on and off. It can't hurt to try since it should be relatively simple to change the code.

    Hopefully that helps!
    I'd also like to know if that does work since I always use channel events. I would think but buttons event would be just for things like "buttons" :) but anything is possible.

    Also do the channel event send strong 0 ever show in doagnostics or just not the calls.
  • jjamesjjames Posts: 2,908
    vining wrote: »
    I'd also like to know if that does work since I always use channel events. I would think but buttons event would be just for things like "buttons" :) but anything is possible.

    Also do the channel event send strong 0 ever show in doagnostics or just not the calls.
    I'll take a bite at this.

    In the protocol, there is no "button" push, release, or hold - just simple channel output & inputs for on & off. At the bare bones, my conclusion to be made is that you COULD write your entire program like (not tested):
    channel_event[dv_tp,1] // Touch panel, button 1
    {
    	on:
    	{
    		send_string 0,"'Button pressed'";
    		wait 20 'hold'
    		{
    			send_string 0,"'Button held for 2 seconds'"
    		}
    	}
    	
    	off:
    	{
    		cancel_wait 'hold'
    		send_string 0,"'Button released'"
    	}
    }
    
    But why would you want to do that? You wouldn't if you've been exposed to button_events. To the master there is no difference between a button_event or a channel_event - they're merely synonyms, much like "scorching" and "blazing". Either way, you can use button_events for IOs, I do it quite often. What's there difference to us programmers? There really isn't much of one - except you can use the HOLD event instead of a wait in a channel_event.
  • ericmedleyericmedley Posts: 4,177
    jjames wrote: »
    As my understanding of ICSP is growing exponentially and very quickly - I'll take a bite at this.

    In the protocol, there is no "button" push, release, or hold - just simple channel output & inputs for on & off. At the bare bones, my conclusion to be made is that you COULD write your entire program like (not tested):
    channel_event[dv_tp,1] // Touch panel, button 1
    {
    	on:
    	{
    		send_string 0,"'Button pressed'";
    		wait 20 'hold'
    		{
    			send_string 0,"'Button held for 2 seconds'"
    		}
    	}
    	
    	off:
    	{
    		cancel_wait 'hold'
    		send_string 0,"'Button released'"
    	}
    }
    
    But why would you want to do that? You wouldn't if you've been exposed to button_events. To the master there is no difference between a button_event or a channel_event - they're merely synonyms, much like "scorching" and "blazing". Either way, you can use button_events for IOs, I do it quite often. What's there difference to us programmers? There really isn't much of one - except you can use the HOLD event instead of a wait in a channel_event.

    Is this right? I've always understood that button channel feedback and button pushes were two different animals. In other words, I can turn TPs channel 1 on and the button number one will light up but it doesn't equal a pushed button. Likewise, I can push a button but the channel doesn't turn on unless It's handled by the TP itself as a momentary feedback or I put that in code as (paraphrasing...) button push=button feedback

    Now, if you've set up feedback for a button in a program you will indeed see both a button push and a channel on in diagnostics. But, they are indeed separate events.

    regarding the IO, I've always programmed them as channel events. The thought never occured to me to handle it any other way.
  • jjamesjjames Posts: 2,908
    ericmedley wrote: »
    Is this right? I've always understood that button channel feedback and button pushes were two different animals. In other words, I can turn TPs channel 1 on and the button number one will light up but it doesn't equal a pushed button. Likewise, I can push a button but the channel doesn't turn on unless It's handled by the TP itself as a momentary feedback or I put that in code as (paraphrasing...) button push=button feedback
    I'd assume that's why there are two different commands for the input and the output of a channel for a device.
  • viningvining Posts: 4,368
    Button event on IO's seem to work just fine, go figure. This could be useful to know cuz as JJ said it does add a few tricks like holds that the CE doesn't have. I'll actually have to think about this now and see which will suit my wants and needs better.
  • DHawthorneDHawthorne Posts: 4,584
    I've *always* used channel events for IOs and never had a problem. The thing to keep in mind though, is the event only trigger on a state change. On normally closed circuits, I've always had to remove the connection then restore it to get an event trigger.
  • nhightonnhighton Posts: 18
    Hey thanks for the reponses, all good suggestions.

    I tried using a button event when the channel event didn't work; PUSH: in place of the ON: and RELEASE: in place of the OFF: Same result.

    The send string 0 messages don't appear in the diagnostic window. The notification window registers channel 1 on and off, but no code is executed.

    I'll try not calling a call inside another call when I get back there. I can't try too much as it's a working museum with guests etc... I thought the because I'm using a jumper, when I remove it - it doesn't register as a channel 1 OFF event because I take the jumper out of the channel 1 port as well as the ground?

    Maybe I'll just have send string 0 commands under ON and OFF - keep it simple to see if removing the jumper executes that.

    Thanks a lot,

    Nick
  • viningvining Posts: 4,368
    nhighton wrote: »
    Maybe I'll just have send string 0 commands under ON and OFF - keep it simple to see if removing the jumper executes that.
    Nick
    Usually when you hit a brick wall it's best not to presume anything and make sure the first step is working and if it is then move on to the next step. First verify the CE or BE triggers using the Send String O. Often when I'm really at a loss to determine what the F' is working I'll put a Send_String 0 before and after calls, the beginning and end of code blocks just to see at what point an error occurs. In this case you're not getting errors but maybe your codes not returning from a call or function. I've had situations where I have an #IF_NOT_DEFINE and forget the #END_IF and then scratch my head trying to figure why entire sections of code wasn't running and then occasional I'd copy and paste when I add a line to call function not yet created, copy the call line and then use that to start creating my function. I end up with this somewhere in my code:
    if(?)
      fnSomeFunction(cSomething) ;
    
    copy it and then create a function for it to save myself from typing a dozen letters.
    DEFINE_FUNCTION fnSomeFunction(CHAR iSomething[]) ;
    
    Forgetting about the semi-colon and I would look at that line several times and never notice it. It will compile fine but if I recall when the function is called it won't run and won't return.

    Anyway when you get a stumper add send_string 0's every where you can even if you think it will be a waste of time. You should also add the line number to the send_string 0 just so you quickly no where to look.

    I create a function so I can turn the send_strings on and off and call it like this. (It also will print what ever line its on):
    fnMasters_DeBug("'Master No.',itoa(nIndx),', Unique ID = ',cUniqueID_Str,' :DEBUG <',itoa(__LINE__),'>'") ;
    
    BY adding the ":DEBUG " I can also use this as a filter for a logging function that Dave H provided so all these testing lines will be displayed in diagnostics but not logged (written to file).


    becaus
  • jcereckejcerecke Posts: 40
    From memory I've used a HOLD event for a PIR input into an IO port. Pretty easy way of doing a basic "If no one has moved in the last n minutes".
  • DarksideDarkside Posts: 345
    vining wrote: »
    Button event on IO's seem to work just fine, go figure. This could be useful to know cuz as JJ said it does add a few tricks like holds that the CE doesn't have. I'll actually have to think about this now and see which will suit my wants and needs better.
    As always, great to have these discussions.

    I've always used B_E for PIR's on IO's - certainly had use for 'hold' particularly in security code.

    Nick, send_string 0 is your friend. Stick it everywhere as suggested, and in your case, in the 'stop show' call I now see included in your recent code block post.

    In this more recent code post I also notice a couple of the calls are using send_command 0 not send_string 0 . This is certainly going to be a problem with your debug.
    DEFINE_CALL 'FIRE_ALARM_RELEASE'
    {
    SEND_COMMAND dvEPC,'VOLUME-UNMUTE'
    SEND_COMMAND dvEPC,'BLANK-OFF'
    SEND_COMMAND 0,'FIRE ALARM NO LONGER ACTIVE, EXHIBIT PCS A + V RESTORED'
    }

    I don't know what dvEPC physically is, but it looks a bit like a serial device, and therefore send_command won't work here either. It would need to be send_string dvEPC to get it to go to the real world.
    No, the SEND_STRING 0 messages aren't shown in diagnostics so I guess the calls aren't being executed.
    ....because in this example from your post it's using send_command.

    hope it helps
  • nhightonnhighton Posts: 18
    As always, great to have these discussions.

    I've always used B_E for PIR's on IO's - certainly had use for 'hold' particularly in security code.

    Nick, send_string 0 is your friend. Stick it everywhere as suggested, and in your case, in the 'stop show' call I now see included in your recent code block post.

    In this more recent code post I also notice a couple of the calls are using send_command 0 not send_string 0 . This is certainly going to be a problem with your debug.



    I don't know what dvEPC physically is, but it looks a bit like a serial device, and therefore send_command won't work here either. It would need to be send_string dvEPC to get it to go to the real world.

    ....because in this example from your post it's using send_command.

    hope it helps

    Thanks for that observation Stephen, I completely missed the SEND_COMMAND 0!

    As for dvEPC, it's an array of exhibit PCs running i!PCWebLink clients, this works fine.

    Thanks everyone,

    Nick
  • nhightonnhighton Posts: 18
    Ok now I'm stumped. I tried the simple channel event:

    BUTTON_EVENT [dvIO,1] //READS JCI'S NC CIRCUIT. ON = HEALTHY & OFF = ACTIVE ALARM
    {
    HOLD:
    {
    SEND_STRING 0,'FIRE ALARM IS HEALTHY'
    }
    RELEASE:
    {
    SEND_STRING 0,'FIRE ALARM IS ACTIVE!'
    }
    }

    which didn't work. No strings were sent to the diagnostic window. So I checked out the Notifications tab which contained:

    Input Status:Pushed [5001:1:17] - Channel 1
    Output Channel:On [5001:1:17] - Channel 1

    then

    Input Status:Released [5001:1:17] - Channel 1
    Output Channel:Off [5001:1:17] - Channel 1

    So I changed the above code to a button event with a push and release, with the same send_string 0 commands - still nothing coming up in the diagnostics window!

    Just this second I've noticed that I've got the device names as 5001:17:0 when the notifications are telling me 5001:17:1 (as above)! Perhaps this could be it, this is completely summed up by this: http://www.reallifecomics.com/comics/2011/20110606_2690.png

    Cheers,

    Nick
  • DarksideDarkside Posts: 345
    Hi Nick,

    rotten comma! :-) (great cartoon)

    Ok. firstly, if you have actually copied these lines from the notifications window, then one problem you have is your ports and systems are back to front!
    Input Status:Pushed [5001:1:17] - Channel 1
    Output Channel:On [5001:1:17] - Channel 1
    This tells me Device 5001 Port 1 System 17 - which is serial port 1 on an ni set as 5001 configured as system 17.

    How it even shows this is interesting because according to your earlier post, dvIO is 5001:17:0 so something must have physically 'pushed' port 1 on sys 17 to make the above even work! Huh?? I'll have to think about that! :-)

    Here's a couple of quick things that might help you.

    Check your system setup by refreshing your online tree. Top line should tell you the NI's system number.

    if it is system 1 then:
    Check your dvIO define_device declaration. make sure it is 5001:17:1 (ni 3100).
    Check your code has a button_event for dvIO,1 with a PUSH and RELEASE only. stick a send_string 0 in each.
    Watch the code by clicking your friend 'the hammer'!
    place a short on io1 and ground
    you should see your string

    if it is system 17 then:
    Check your dvIO define_device declaration. make sure it is 5001:17:17 (ni 3100)
    Check your code has a button_event for dvIO,1 with a PUSH and RELEASE only. stick a send_string 0 in each
    Watch the code by clicking your friend 'the hammer'!
    place a short on io1 and ground
    you should see your string.

    if not - post your whole code!

    Btw, it is quite ok to define_device dvIO as 5001:17:0 everything should work the same.

    When watching in notifications, you *must* set the system number. leaving it as 0 is not an option. In your case you will need to watch 5001:17:1 or 5001:17:17 - depending what you find in your online tree!
  • nhighton wrote: »
    Ok now I'm stumped. I tried the simple channel event:

    BUTTON_EVENT [dvIO,1] //READS JCI'S NC CIRCUIT. ON = HEALTHY & OFF = ACTIVE ALARM
    {
    HOLD:
    {
    SEND_STRING 0,'FIRE ALARM IS HEALTHY'
    }
    RELEASE:
    {
    SEND_STRING 0,'FIRE ALARM IS ACTIVE!'
    }
    }

    Also, you need to have a hold time in the hold statement. otherwise it'll never fire since it doesn't know how long after the push to fire the statement.
  • viningvining Posts: 4,368
    Good catch! With my dyslexia it looked completely normal. 5001:1:17 vs 5001:17:1

    I would still use 5001:17:0 since using system 0 means the system the code is running on. Using 1 in when defining is another one of those things that may bite you in the a$$.
  • ericmedleyericmedley Posts: 4,177
    vining wrote: »
    Good catch! With my dyslexia it looked completely normal. 5001:1:17 vs 5001:17:1

    I would still use 5001:17:0 since using system 0 means the system the code is running on. Using 1 in when defining is another one of those things that may bite you in the a$$.

    This does bite me on occasion since I never make any of my systems '1' They are all setup by project number which helps me since I have a lot of systems talking to each other all over the place. The zero is a good thing...
  • nhightonnhighton Posts: 18
    Solution

    Turns out in the end it was nothing to do with device definitions or code! Yeah I meant 5001:17:1. For some reason I have it defined as 5001:17:0 (yes I have system as 0) but when its state changes, it says 5001:17:1 in the notifications tab.

    I'm just using a channel event - it works perfectly so no need for a button event. The fix was to add a wait:

    CHANNEL_EVENT[dvIO,1]
    {
    ON:
    {
    WAIT 5
    code
    }
    ...

    So apparently the controller can't handle code straight after a channel event change. It's the NI-4100 and this works consistently.

    Thanks for everyone's input,

    Nick
  • DarksideDarkside Posts: 345
    nhighton wrote: »
    So apparently the controller can't handle code straight after a channel event change. It's the NI-4100 and this works consistently.

    Thanks for everyone's input,

    Nick
    Mmm... surprises me a bit to be honest - i'll have a play and see if I can replicate it out of curiosity...

    I only used button_events for my PIRs on dvIO and never had to place a wait in there!

    :-)

    At least you're up and running!
  • viningvining Posts: 4,368
    Mmm... surprises me a bit to be honest - i'll have a play and see if I can replicate it out of curiosity...

    I only used button_events for my PIRs on dvIO and never had to place a wait in there!

    :-)

    At least you're up and running!
    I concur, this makes no sense what so ever. If the event triggers, it triggers and any code should run. Why would notifications kick the number? Why would CE work and not BE? Why would a wait have any affect what so ever unless it were the typical negative affect like the value changing before execution? There's more to this mystery then meets the eye. :)
  • nhightonnhighton Posts: 18
    I'm sure a button event would work too, but I don't need the HOLD so I've used a channel event because it's what describes the code best - a voltage drop/restoration on an IO channel. Also for my purposes I didn't want to use HOLD because I can't specify a time; it's an NC fire alarm interface circuit so I'm hoping it'll be held forever!

    A colleague suggested trying the wait and it worked first time - after me ripping hair our messing around very subtly with the CE/BE syntax and being quite superstitious as we are in these situations.

    I literally had a CE/BE with ON: and OFF: then a simple send_string 0 under each. This didn't work. With the exact same syntax and action to remove the jumper as before, only with a WAIT 5 - it worked first time.

    Anyhow, it remains shrouded in mystery, and yes at least it's up and running.

    Thanks everyone,

    Nick
Sign In or Register to comment.