Timeline issues
ondrovic
Posts: 217
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
0
Comments
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
--D
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.
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
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.
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.
Chris
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.
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
Thanks
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?