Home AMX User Forum NetLinx Studio

Timeline issues

ondrovicondrovic Junior MemberPosts: 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
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

  • a_riot42a_riot42 AMX Wizard Posts: 1,619
    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
  • dchristodchristo Junior Member Posts: 177
    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
  • jjamesjjames Just another dude Posts: 2,906
    dchristo wrote: »
    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.
  • a_riot42a_riot42 AMX Wizard Posts: 1,619
    jjames wrote: »
    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.
  • dchristodchristo Junior Member Posts: 177
    a_riot42 wrote: »
    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
  • jjamesjjames Just another dude Posts: 2,906
    LOL - love it when someone pulls out the "just cuz you can, doesn't mean you should" card. :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.
  • DHawthorneDHawthorne Old Timer Posts: 4,584
    a_riot42 wrote: »
    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.
  • ondrovicondrovic Junior Member Posts: 217
    Thanks for all the replys, I will rewrite it to not use the get last and see what happens

    Chris
  • ericmedleyericmedley Senior Member - 4000+ posts Posts: 4,177
    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.
  • ondrovicondrovic Junior Member Posts: 217
    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
  • ondrovicondrovic Junior Member Posts: 217
    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
  • a_riot42a_riot42 AMX Wizard Posts: 1,619
    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?
Sign In or Register to comment.