Timeline issues
ondrovic
Junior Member
I have written a timeline event to work as an auto exit for the Aprilaire thermostats. I am doing this because we are using a combine device with a virtual and the actual panel to display feedback, but since there are so many thermostats in this current job everything was dreadfully slow, the only catch is that we set only 1 max panel but if someone uses a panel and forgets to exit out of the HVAC page ( which uncombines the device ) the current panel will not have any control.
My issue with this timeline event is that it doesn't seem to work all the time
Thanks
My issue with this timeline event is that it doesn't seem to work all the time
Define_Constant
tlAuto_Exit = 1
Define_Function Auto_Exit()
{
debug("ITOA(__LINE__),' Auto Exit routine running'")
If(Timeline_Active(tlAuto_Exit))
{
debug("ITOA(__LINE__),' Timeline found : ',itoa(tlAuto_Exit),' resetting timeline timer : ',itoa(tlAuto_Exit)")
Timeline_Kill(tlAuto_exit)
}
Else
{
Timeline_Create(tlAuto_Exit,tlReset,1,Timeline_Absolute,Timeline_Once)
debug("ITOA(__LINE__),' Starting Timeline : ',itoa(tlAuto_Exit)")
}
}
Define_Event
Button_Event[dvPanel_a_Array,nEnvironment_Buttons]
{
Push:
{
Local_Var nPanel ;
Local_Var nButton ;
LOCAL_VAR LONG nNewIndex ;
LOCAL_VAR DEV dvTempArray[2] ;
Local_Var nCount ;
nPanel = GET_LAST(dvPanel_a_Array) //Set the Panel index number
nButton = GET_LAST(nEnvironment_Buttons)
debug("ITOA(__LINE__),' Environment Button Pushed: ',ITOA(nButton)")
Switch(nButton)
{
Case 1: //Lighting
{
Switch(nRoom_Index[nPanel])
{
Case 1:
{
}
}
}
#IF_DEFINED Aprilaire
Case 2: //HVAC
{
//Set the mode to 3 (HVAC)
//Send the panel index
//Send the HVAC zone
//Combine the panel
//Get the length of the dynamic array and add 1 to it
nNewIndex = (LENGTH_ARRAY(dvDynamic_Pnl_Array2) + 1) ;
//send_string 0,"'Array length: ',ITOA(nNewIndex)"
debug("ITOA(__LINE__),' Array length: ',ITOA(nNewIndex)")
If(nNewIndex < 3)
{
//Set the dynamic array to the new length
SET_LENGTH_ARRAY(dvDynamic_Pnl_Array2, nNewIndex) ;
//send_String 0,"'New array length: ',ITOA(LENGTH_ARRAY(dvDynamic_Pnl_Array2))"
debug("ITOA(__LINE__),' New array length: ',ITOA(LENGTH_ARRAY(dvDynamic_Pnl_Array2))")
//Add the indexed panel (nPanel_b_array[nPanel]) to the specified location in the dynamic array ()
dvDynamic_Pnl_Array2[nNewIndex] = dvPanel_c_Array[nPanel] ;
//send_string 0,"'Add panel ',dvPanel_c_Array[nPanel],' to the array'"
debug("ITOA(__LINE__),' Add panel ',dvPanel_c_Array[nPanel],' to the array'")
//Combine the modified dynamic array with the virtual device
COMBINE_DEVICES(vdvVirtual_Pnl_2, dvDynamic_Pnl_Array2) ;
Send_String vdvMaster_Comm,"'3,',ITOA(nRoom_Index[nPanel]),',',ITOA(sRoom[nRoom_Index[nPanel]].HVAC_Zone)"
/// Start Timer to Auto-Exit HVAC Page
debug("ITOA(__LINE__),' Auto Exit initiated'")
Auto_Exit()
}
Else
{
Send_Command dvPanel_a_Array[nPanel],"'@PPN-[Aprilaire] - Warning'"
}
}
#END_IF
Case 3:
{
}
#IF_DEFINED Aprilaire
Case 4: //HVAC Exit Button
{
debug("ITOA(__LINE__),' Auto Exit terminated'")
Timeline_Kill(tlAuto_exit)
UNCOMBINE_DEVICES(vdvVirtual_Pnl_2) ;
//Look throught the dynamic array for the specified device (panel)
FOR(nCount = 1, nNewIndex = 0; nCount <= LENGTH_ARRAY(dvDynamic_Pnl_Array2); nCount++)
{
//When the specifed device is found...
IF(dvDynamic_Pnl_Array2[nCount] <> dvPanel_c_Array[nPanel])
{
nNewIndex ++ ;
dvTempArray[nNewIndex] = dvDynamic_Pnl_Array2[nCount] ;
}
Else
{
send_string 0,"'Remove panel ',dvPanel_c_Array[nPanel],' From the array'"
}
}
dvDynamic_Pnl_Array2 = dvTempArray
SET_LENGTH_ARRAY(dvDynamic_Pnl_Array2, nNewIndex) ;
send_String 0,"'New array length: ',ITOA(LENGTH_ARRAY(dvDynamic_Pnl_Array2))"
SET_LENGTH_ARRAY(dvTempArray, nNewIndex) ;
IF(LENGTH_ARRAY(dvTempArray))
{
COMBINE_DEVICES(vdvVirtual_Pnl_2, dvTempArray) ;
}
}
#END_IF
Case 5: //Fan
{
Switch(nRoom_Index[nPanel])
{
Case 11: {LutronCmd(139) Break} //Her Master Bath
Case 12: {LutronCmd(138) Break} //His Master Bath
Case 16: {LutronCmd(52) Break} //Screen Porch
Case 18: {LutronCmd(51) Break} //Guest Screened Porch
}
}
}
}
}
Timeline_Event[tlAuto_Exit]
{
Local_Var Integer nPanel
nPanel = Get_Last(dvPanel_a_Array)
Do_Push(dvPanel_a_Array[nPanel],61)
debug("itoa(__Line__),' Doing virtual push to exit'")
debug("itoa(__Line__),' Determining which panel is being used'")
If(nPanel <= 19) /// CP4 Panels
debug("itoa(__Line__),' CP4 Panel Selected'")
Send_Command dvPanel_a_Array[nPanel],"'PAGE-Control Page'"
If(nPanel >= 20) /// MVP Panels
debug("itoa(__Line__),' MVP Panel Selected'")
Send_Command dvPanel_a_Array[nPanel],"'@PPF-[Aprilaire] - HVAC Control'"
}
Any ideas or suggestion or a way to do this better?Thanks
Comments
-
I didn't look over your code, but from your description it seems needlessly complicated. I am not seeing the purpose of a timeline, and I wonder if you are trying to solve a problem with another problem. I don't use combines, so I don't know much about that 'feature', but I don't trust it to be implemented efficiently at all.
The only time I ever send feedback to the panel is if someone is looking at the HVAC page and/or something has actually changed. With HVAC, things don't change very often so I don't see how you can see so much of a slowdown. My guess would be the combine feature is letting you down and all I can suggest is to not use it.
Paul -
I agree with Paul, however, in looking at your code, I would put my money on the GET_LAST in the Timeline_Event. The value returned by that statement won't necessarily be what you expect. You can only trust the result of GET_LAST within the event that triggered it... in your case the Button_Event.
--D -
I agree with Paul, however, in looking at your code, I would put my money on the GET_LAST in the Timeline_Event. The value returned by that statement won't necessarily be what you expect. You can only trust the result of GET_LAST within the event that triggered it... in your case the Button_Event.
--D
I agree.
A GET_LAST should not be in a TIMELINE event. -
I agree.
A GET_LAST should not be in a TIMELINE event.
This is what I thought but the docs say different. Apparently you can use it anywhere and it will always return correctly.
From the docs:
The function can be called anywhere in code but is usually called from within an event handler. -
This is what I thought but the docs say different. Apparently you can use it anywhere and it will always return correctly.
From the docs:
The function can be called anywhere in code but is usually called from within an event handler.
I think "can be called" and "should be called" are two different things. How do you know another button wasn't pressed between the time the Button_Event fired and the Timeline_Event fired. You may be able to call the function anywhere, but I personally don't trust it's result outside of the event that triggered it.
--D -
LOL - love it when someone pulls out the "just cuz you can, doesn't mean you should" card.

For the record - I agree 100% with Dave on his assessment of GET_LAST. To be honest, I can't quite even think of a time when I WANTED to use GET_LAST outside of the original event. It just doesn't make sense. -
This is what I thought but the docs say different. Apparently you can use it anywhere and it will always return correctly.
From the docs:
The function can be called anywhere in code but is usually called from within an event handler.
What that means is it will always return the last event in it's scope when called. What that does not mean is someone won't press another button meanwhile, making the "last" event something different. That's why you don't want to put them in a timeline - it works as advertised, but what you get isn't necessarily what you want. Ditto for WAITs. You just can't assure the value that triggered the timed event won't be overridden by a subsequent press. Only use GET_LAST in the actual event code that you need it in; if you must use that value elsewhere, assign it to a variable and pass that along instead. -
Thanks for all the replys, I will rewrite it to not use the get last and see what happens
Chris -
In addition to all this discussion about programming, one might add that the T-Stats are just plain slow. The issue might be that they are just slowa nd that's it.
On devices that are this slow, I'll typically store feedback from the device in a status variable and then update the panels. I don't mind the chatter on the network and have not really seen the pokeyness people complain about.
We regularly have systems with 20-30 panels and I've not seen too much feedback sluggishness unless it was the device itself. The Aprilaire T-Stats are not the quickest ships at sea. (particularly when you get several of them all gabbing on the same RS-422 line)
I tend to try and keep the number of T-Stats on an RS-422 buss down to 5-6. If I have more than that, I'll start a 2nd RS-422 buss on another NI serial port. -
Eric,
Thanks for the info, about splitting up the thermostats to different serial ports not sure thats going to fly on this job but I can use that information for the next on I do.
Currently there are 18 thermostats on a single 422 Bus is more than likely why its so sluggish.
Cheers -
So based on what I am trying to do can anyone point me in the right direct? should i add a variable to track weather or not a certain panel is using the HVAC and if the variable is true then use the trigger the exit function for that panel?
Thanks -
ericmedley wrote: »In addition to all this discussion about programming, one might add that the T-Stats are just plain slow. The issue might be that they are just slowa nd that's it.
On devices that are this slow, I'll typically store feedback from the device in a status variable and then update the panels. I don't mind the chatter on the network and have not really seen the pokeyness people complain about.
We regularly have systems with 20-30 panels and I've not seen too much feedback sluggishness unless it was the device itself. The Aprilaire T-Stats are not the quickest ships at sea. (particularly when you get several of them all gabbing on the same RS-422 line)
I tend to try and keep the number of T-Stats on an RS-422 buss down to 5-6. If I have more than that, I'll start a 2nd RS-422 buss on another NI serial port.
Interesting. I am doing a job with 6 Aprilaire tstats and 16 UIs right now and the set point field on the panel only gets updated from the data_event for the tstats. So the user pushes the up arrow, the request gets sent to the controller which then gets sent to the tstat, the tstat sends an update back to the controller since it changed its set point and then the controller updates the panel. There is no noticeable lag changing the set point at all, it is essentially instantaneous even when holding the button. Which tstats are you using that are so slow?
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