Flashing an led alongside several sub-routines.

pjl83

Member
Hi all,

I've finally got my first robot working. I've described it previously elsewhere but for those that don't know it's just a simple "car" that drives until it sees something in its path, then it decides which way to turn by looking both ways and turning towards the furthest distance. If both ways are too short then it reverses.

The code is here:

Code:
symbol dangerlevel=50 'how far away should things be before we react?
symbol turn=750 'this sets how much should be turned
symbol servo_turn= 300 'this sets for how long time we should wait for the servo to turn
symbol trig= 3 'define output pin for trigger pulse
symbol echo= 6 'define input pin for echo pulse
symbol range= w1 '16 bit word variable for range


servo 0, 150
wait 1

main: ' the main loop
	pulsout trig,2 'produce 20uS trigger pulse (must be minimum of 10Us)
	pulsin echo,1,range 'measures the range in 10uS steps
	pause 10 'recahrge period after ranging completes
	'now convert range to cm (divide by 5.8) or inches (divide by 14.8)	 
	'as picaxe cannot use 5.8, multiply by 10 then divide by 58 instead
	let range = range*10/58 ' multiply by 10 then divide by 58
	debug range 'display range via debug command
	if range > dangerlevel then
	gosub nodanger 'if nothing ahead, drive forward
	else
	gosub whichway 'if obstacle ahead then decide which way is better
	end if 
	goto main 'end of main loop, all others are sub-routines
	
nodanger: 'drive forward
	high 4 : low 5 : high 6 : low 7
	return

whichway:
	gosub totalhalt 'first stop!

'look one way
	gosub lturn 'look to one side
	pause servo_turn ' wait for the servo to be finished turning
	pulsout trig,2 'produce 20uS trigger pulse (must be minimum of 10Us)
	pulsin echo,1,range 'measures the range in 10uS steps
	pause 10 'recahrge period after ranging completes
	'now convert range to cm (divide by 5.8) or inches (divide by 14.8)	 
	'as picaxe cannot use 5.8, multiply by 10 then divide by 58 instead
	let range = range*10/58 ' multiply by 10 then divide by 58
	debug range
	w2 = range
	gosub totalhalt
	
'look the other way
	gosub rturn 'to another side
	pause servo_turn 
	pulsout trig,2 'produce 20uS trigger pulse (must be minimum of 10Us)
	pulsin echo,1,range 'measures the range in 10uS steps
	pause 10 'recahrge period after ranging completes
	'now convert range to cm (divide by 5.8) or inches (divide by 14.8)	 
	'as picaxe cannot use 5.8, multiply by 10 then divide by 58 instead
	let range = range*10/58 ' multiply by 10 then divide by 58
	debug range
	w3 = range
	gosub totalhalt

'decide which is the better way
	if w2<dangerlevel and w3<dangerlevel then
	gosub backwards
	else
	gosub decide
	end if
	return
	
decide:
	if w2<w3 then
	gosub body_lturn
	else
	gosub body_rturn
	end if 
	return

rturn:
	servo 0, 200
	return

lturn:
	servo 0, 100
	return

body_lturn:
	high 4 : low 5 : high 7 : low 6
	pause turn : gosub totalhalt
	return

body_rturn:
	high 5 : low 4 : high 6 : low 7
	pause turn : gosub totalhalt
	return

totalhalt:
	low 4 : low 5 : low 6 : low 7
	servo 0, 150
	pause servo_turn
	return

backwards:
	high 5 : low 4 : high 7 : low 6
	pause turn
	return
I wanted to add an led on pin2 that flashes whilst the robot is deciding which way to go or is reversing. So basically it needs to be off during the main loop and the nodanger sub, but on during any of the other sub-routines. I can do it with a simple on or off led using a high 2 at the start of "whichway" and then a low 2 at the start of "main" but I can't work out the flashing bit.

I could add this in between every line of code in the sub-routines but this would slow things right down and I thought that there must be an easier/smarter way?

Code:
	high 2
	pause 150
	low 2
	pause 150
I'm using the 28x1 project board.

Thanks
Paul
 

nickpatts

Member
Keeping it simple how about use a led with a built in flasher unit?. Im sure other will be able to help with a coding routine.
 

inglewoodpete

Senior Member
One way would be to use the internal Timer 0 with timer interrupts enabled. Within the interrupt routine, you would test a variable to determine if the LED should be toggled or not. If yes, then toggle the LED. The variable would be controlled by your main code to only let the interrupt routine to flash the LED when required.

Have a look at post #4 in this thread for some demo code for background interrupts.

Peter
 

SAborn

Senior Member
You could do something like using a counter with a 10Ms pause either in you main subroutines or in a seperate sub routine.

Something like this.......

Code:
Led_flash:

pause 10
inc counter  '(b?)
if counter = 15 then
toggle led
counter =0
endif

return
As the counter may not be at zero at the start of the next time the routine is called the first toggle might not be 150Ms but who cares, and if so then set a counter = 0 in the main routine.

You will also need to add a led = low in the main routine to ensure the led is off when its not needed to be flashing.
 

hippy

Ex-Staff (retired)
For the 18M2 one could simply run in multi-tasking mode and have a task which flashes a LED controlled by some variable set high or low.
 

pjl83

Member
One way would be to use the internal Timer 0 with timer interrupts enabled. Within the interrupt routine, you would test a variable to determine if the LED should be toggled or not. If yes, then toggle the LED. The variable would be controlled by your main code to only let the interrupt routine to flash the LED when required.

Have a look at post #4 in this thread for some demo code for background interrupts.

Peter
You could do something like using a counter with a 10Ms pause either in you main subroutines or in a seperate sub routine.

Something like this.......

Code:
Led_flash:

pause 10
inc counter  '(b?)
if counter = 15 then
toggle led
counter =0
endif

return
As the counter may not be at zero at the start of the next time the routine is called the first toggle might not be 150Ms but who cares, and if so then set a counter = 0 in the main routine.

You will also need to add a led = low in the main routine to ensure the led is off when its not needed to be flashing.
Thankyou. Where could I find any examples of these commands in the manual? I've looked for timer, inc, counter, interrupt...... in manual 2 but found nothing?

There's a similar example on page 77 of manual 1 but doesn't go into much detail.
 

hippy

Ex-Staff (retired)
Thankyou. Where could I find any examples of these commands in the manual? I've looked for timer, inc, counter, interrupt...... in manual 2 but found nothing?
The 'inc' is a command described in Manual 2 and 'counter' is just a variable, defined by using a 'symbol' command similar to -

Symbol counter = b9

Interrupts are a part of the 'PICAXE programming paradigm' with more information in Manual 2 under the 'setint' command. Likewise 'timer', which can also be a variety of things depending upon context, from the 'settimer' command to referring to other advanced internal timer uses.
 
Top