Timer implementation using a get_ms command

Hello,
My name is Ruslan and this is my first post on this forum. I’m trying to implement a script using the Micro Maestro Board. I need to implement a timeout in my script, like this:

goto start
sub TIMEOUT

	dup
	get_ms  
	minus 
	15000 greater_than  # 15 sec 
	if 
		drop
		2 1 greater_than  #puts "true" on stack
	else
		1 2 greater_than  #puts "false" on stack
	endif	
return

#program starts here
start:
	get_ms
	begin
                GENERATE_PWM
		TIMEOUT
		if
			goto some_place
		endif
	repeat

The code will generate a PWM pulse for a 15 seconds and then jumps to another place.
Is this the right way to implement the script? Do I need check if a get_ms timer overflows?

Thanks you,
Ruslan

Hello, Ruslan.

In the Maestro scripting language, “true” and “false” just mean 1 and 0, so you can simplify your TIMEOUT subroutine to the following:

sub TIMEOUT
   dup
   get_ms  
   minus 
   15000 greater_than  # 15 sec 
   if 
      drop
      1
   else
      0
   endif   
return

It make me nervous to see a subroutine that has a different effect on the stack level depending on what code path it travels down. That’s what you get because you have a “drop” in one code path but no “drop” in the other. That kind of subroutine is just asking for a stack overflow or underflow error. In my opinion, you should simplify the function to just be:

sub TIMEOUT
   dup
   get_ms  
   minus 
   15000 greater_than  # 15 sec 
  return

You still need to drop that timer value somewhere, so you could add a “drop” command right before “goto some_place”.

In general you do have to worry about get_ms timer overflowing, but if you use the function above it will handle the overflow correctly. Here’s an example of how that works: Suppose the timer value on the stack is 30000, but get_ms returns -30000. Then the “minus” operation will be -30000 - (30000), so that operation will overflow and yield a result of -30000 - (30000) + 2^16 = 5536, which is what you would want.

–David

Thank you David for a quick reply. Thank you for the suggestion about better programming practice, I will keep them in mind and rewrite the function. During the day I tried different ways of implementation and I run into this problem. I wrote a small script to blink the red LED (3 sec ON, 3 sec OFF) using a timeout function I posted later. This is the script (I will rewrite the script tomorrow as you suggested):


goto start

sub TIMEOUT

	dup
	get_ms  
	minus 
	3000 greater_than
	if 
		drop
		2 1 greater_than  #true
	else
		1 2 greater_than  #false
	endif	
return

#program starts here
start:
	get_ms
	begin
		TIMEOUT
		if
			LED_ON
			goto timer
		endif
	repeat

timer:
	get_ms
	begin
		TIMEOUT
		if
			LED_OFF
			goto start
		endif
	repeat

Time-out is the same routine, but now the delay is 3sec. When the code runs, surprise, the LED blinks every 30sec (aprox) - 30 sec. ON, 30 sec. OFF. I’ve reviewed the code again and again, I was banding my head against the wall without understand what’s going on? Later, I’ve modificate the timeout routine this way:

sub TIMEOUT

	dup
	get_ms  
	minus 
	negate
	3000 greater_than
	if 
		drop
		2 1 greater_than  #true
	else
		1 2 greater_than  #false
	endif	

return

AND IT WORKS! And works good. I suspect why, but I’m not sure. I think the right way was the original version, I don’t understand why the old version does not work?

Can you help me please? Someone may think “OK, it works”, but I really need to understand what’s going on.

Thank you David,
Regards, Ruslan.

You needed to add that negate command because you are trying to compute elapsedTime = (now - startTime) and the minus command computes X - Y where Y is the value on top of the stack and X is just below it. If you have trouble understanding this, I recommend carefully reading the documentation of the mathematical script commands in the Maestro user’s guide and also using the “Step Script” button to step through your script and see what happens at every step.

So you will probably need to add a negate command in the subroutine I gave you above, or add a swap command just before minus.

–David