Home AMX User Forum AMX Technical Discussion

Need some help on timelines

I'm a newbie to programming and am trying to get used to using timelines. I have 2 cameras I'm controlling from the same panel. I want to repeat sending the command on a push but I need it to stop when I release the button. It's not stopping. I just keeps sending the commands.

Here's the code with the TIMELINE_KILL command"

BUTTON_EVENT[dvTP,nCAM_BUTTONS]
{
HOLD[3]:
{
TIMELINE_CREATE(TL1,tCAM_HOLD,1,TIMELINE_ABSOLUTE,TIMELINE_REPEAT)
}

RELEASE:
{
IF (TIMELINE_ACTIVE(TL1))
TIMELINE_KILL(TL1)
}
}

TIMELINE_EVENT[TL1]
{
IF(nCAMERA_LOCALE = 0)
{
WHILE(TIMELINE_ACTIVE(TL1))
{
SWITCH(GET_LAST(nCAM_BUTTONS))
{
CASE 1:
{
SEND_STRING dvLOC_CAM,'PR'
}
CASE 2:
{
SEND_STRING dvLOC_CAM,'PL'
}
CASE 3:
{
SEND_STRING dvLOC_CAM,'TU'
}
CASE 4:
{
SEND_STRING dvLOC_CAM,'TD'
}
CASE 5:
{
SEND_STRING dvLOC_CAM,'Z+'
}
CASE 6:
{
SEND_STRING dvLOC_CAM,'Z-'
}
CASE 7:
{
SEND_STRING dvLOC_CAM,'F+'
}
CASE 8:
{
SEND_STRING dvLOC_CAM,'F-'
}
}
}
}
ELSE
{
WHILE(TIMELINE_ACTIVE(TL1))
{
SWITCH(GET_LAST(nCAM_BUTTONS))
{
CASE 1:
{
SEND_STRING dvREM_CAM,'PR'
}
CASE 2:
{
SEND_STRING dvREM_CAM,'PL'
}
CASE 3:
{
SEND_STRING dvREM_CAM,'TU'
}
CASE 4:
{
SEND_STRING dvREM_CAM,'TD'
}
CASE 5:
{
SEND_STRING dvREM_CAM,'Z+'
}
CASE 6:
{
SEND_STRING dvREM_CAM,'Z-'
}
CASE 7:
{
SEND_STRING dvREM_CAM,'F+'
}
CASE 8:
{
SEND_STRING dvREM_CAM,'F-'
}
}
}
}
}

So why won't this thing stop when I release the button? Thanks.

Comments

  • Spire_JeffSpire_Jeff Posts: 1,917
    My immediate guess would be the WHILE statement. The WHILE statement is running as fast as the processor can handle and it is queuing up a bunch of the commands, instead of only sending one command every time the timeline event occurs. Remove the While statements and that might fix your problem. You may also want to think about creating a variable to hold the current active camera button as GET_LAST might not always function the way you want (especially when you have more than 1 touch panel).

    You may also need to increase the time interval of the timeline to prevent commands from being queued.

    Personally I would create an active camera button variable for each camera to allow both of them to function simultaneously and set the variable to 0 when not in use.

    Jeff
  • Two things... first, Get_Last is probably not returning what you expect; by the time you get to the Timeline_Event, it may have changed from what you are expecting. Second, it's most likely not stopping because of the While loop... it will never be false, because it will never exit the loop to process the Release event.

    Third, you could simplify this and do everything in the Button_Event:
    BUTTON_EVENT[dvTP,nCAM_BUTTONS]
    {
    	HOLD[3,Repeat]:
    	{
    	        SWITCH(GET_LAST(nCAM_BUTTONS))
    		{
    			CASE 1:
    			{
    				SEND_STRING dvLOC_CAM,'PR'
    			}
    			CASE 2:
    			{
    				SEND_STRING dvLOC_CAM,'PL'
    			}
    			CASE 3:
    			{
    				SEND_STRING dvLOC_CAM,'TU'
    			}
    						
    		}
    	}
    }
    

    --D
  • You were right!

    Both of you guys were right, it was the while statement. I know it might be asking too much, but if someone is bored and can explain why that can't be used there, I would love to learn more about it. I assumed that as soon as you release the button, the timeline would be killed and the while statement would become false and that would stop the send commands. Obviously not!

    One more newbie question - how do you post your code in the blue inset box?

    Thanks tremendously guys!
  • kmenshouse wrote:
    Both of you guys were right, it was the while statement. I know it might be asking too much, but if someone is bored and can explain why that can't be used there, I would love to learn more about it. I assumed that as soon as you release the button, the timeline would be killed and the while statement would become false and that would stop the send commands. Obviously not!
    Your TIMELINE_EVENT function is automatically called every X milliseconds, depending on the interval you put in your timeline. Each time it is called, you only need to send the command once. If you have:
    DEFINE_VARIABLE
    LONG tCAM_HOLD[1]
    
    DEFINE_START
    tCAM_HOLD[1] = 100
    
    Then your TIMELINE_EVENT will be called once every 100 milliseconds. As soon as you kill the timeline, the event will no longer be called -- so, you don't need to loop, and you don't need to test TIMELINE_ACTIVE in the event.

    Relative to GET_LAST, it is only valid inside the event handler for the button, and even that can get screwed up if you use it inside a WAIT. If you'll need the button number later, store it in a global variable.
    kmenshouse wrote:
    One more newbie question - how do you post your code in the blue inset box?
    {code}type code here{/code}, except use square brackets [] instead of {}
  • Spire_JeffSpire_Jeff Posts: 1,917
    The reason the while statement caused so many problems is because it executes until it evaluates as false. I don't think the processor handles incoming events during the execution of a while statement, it just queues them. This would mean that it keeps executing the while command as fast as it possibly can which is sending a continuous stream of commands to your camera. Because it never processes the release command, the while statement always evaluates as true.

    Hope this helps,
    Jeff
  • That makes sense

    Thanks Jeff. I wasn't aware of that but it's certainly how the program acted - as if I never released the button.

    Keith
  • DHawthorneDHawthorne Posts: 4,584
    For what its worth, you could accomplish this easily without a timeline by just using a REPEAT keyword on your HOLD handler.
  • JeffJeff Posts: 374
    I realize you got it working with timelines, but I just wanted to show you another way to do it. This is basically what DHawthorne was referring to.
    define_device
    
    dvTP	=	10001:1:0
    dvCam1	=	05001:1:0
    dvCam2	=	05001:2:0
    
    define_variable
    
    non_volatile integer nActiveCam
    non_volatile dev dvCameras[]=
    {
    	dvCam1,
    	dvCam2
    }
    
    non_volatile integer nCamBtns[]=
    {
    	3,
    	4,
    	5,
    	6,
    	7,
    	8,
    	9,
    	10
    }
    
    define_event
    
    button_event[dvTP,1] // Select Camera 1
    {
    	push:
    	{
    		nActiveCam=1
    	}
    }
    
    button_event[dvTP,2] //Select Camera 2
    {
    	push:
    	{
    		nActiveCam=2
    	}
    }
    
    button_event[dvTP,nCamBtns]
    {
    	push:
    	{
    		switch(get_last(nCamBtns))
    		{
    			case 1: send_string dvCameras[nActiveCam],"'PR'"
    			case 2: send_string dvCameras[nActiveCam],"'PL'"
    			case 3: send_string dvCameras[nActiveCam],"'TU'"
    			case 4: send_string dvCameras[nActiveCam],"'TD'"
    			case 5: send_string dvCameras[nActiveCam],"'Z+'"
    			case 6: send_string dvCameras[nActiveCam],"'Z-'"
    			case 7: send_string dvCameras[nActiveCam],"'F+'"
    			case 8: send_string dvCameras[nActiveCam],"'F-'"
    		}        
    	}
    	hold[3,repeat]:
    	{
    		switch(get_last(nCamBtns))
    		{
    			case 1: send_string dvCameras[nActiveCam],"'PR'"
    			case 2: send_string dvCameras[nActiveCam],"'PL'"
    			case 3: send_string dvCameras[nActiveCam],"'TU'"
    			case 4: send_string dvCameras[nActiveCam],"'TD'"
    			case 5: send_string dvCameras[nActiveCam],"'Z+'"
    			case 6: send_string dvCameras[nActiveCam],"'Z-'"
    			case 7: send_string dvCameras[nActiveCam],"'F+'"
    			case 8: send_string dvCameras[nActiveCam],"'F-'"
    		}  
    	}
    }
    

    I prefer the camera device array to the if statement you were using. This will let you control more than 2 cameras easily. You'll also notice that this one starts sending move commands immediately, not only after you've held for .3 seconds.

    Hope this helps

    J
Sign In or Register to comment.