Project: Weave, Obstacle Avoiding Robot

Thread Starter

Barnaby Walters

Joined Mar 2, 2011
102
This post sums up the work outlined in a previous thread, http://forum.allaboutcircuits.com/showthread.php?t=53089.

Weave is my Modular, Expandable Obstacle Avoiding Robot. It currently consists of three circuit boards: Sensor Array, Brains and Motor Drivers. More detail about these boards are given in the previous thread, so I'll just outline them here:
The Sensor Array creates two selectable modulated IR beams at 38kHz, and a 38kHz IR sensor/demodulator.
The brains contain a PIC16F886 and supporting circuitry, as well as a mini breadboard for on-robot prototyping.
The motor driver board contains two MOSFET H-Bridges and a linear 5v regulator. It is built in dead-bug style and will be the first module to get replaced — in fact, split into motor control and power regulation, with low battery warning.

The program is written in ASM, and is attached for anyone who wants to have a look, copy, point out errors, etc. It essentially is fairly simple:

Constant Loop: Sends alternating pulses through each IR Led. After each set of two pulses, it checks to see if any signals were intercepted and sends motor control signals using a sort-of LUT.

Interrupt: The output of the IR detector is wired to RB0, the external interrupt pin. When a signal is intercepted, an ISR sees which IRED is currently emitting, and stores a result in that direction.

Demonstration video coming soon!

Thanks,
Barnaby

Rich (BB code):
;
;	Author: Barnaby Walters
;	Created: 27th March 2011
;	
;	For PIC: 16F886
;	Default Radix: Hex
;
;	Description:	Contains the IR enable/detect loop. Lights different LEDs to indicate which direction an object is seen in
;					Runs at 4MHz	
;	
;	Currently:		The interrupt handler gets called, but not all of the logic works properly
;
; * * * * * * * * * * * * * * * *

list p=16f886
include p16f886.inc
	
	; Set up 16F886 Config Registers
	__CONFIG	_CONFIG1, _MCLRE_OFF & _WDT_OFF & _INTRC_OSC_NOCLKOUT & _BOR_ON & _CP_OFF & _DEBUG_OFF & _LVP_OFF & _FCMEN_OFF & _IESO_OFF & _CPD_OFF
				; For Config Bank 1: No MCLR Reset, no WDT, int. Osc no clkout, BOR On, Code protection, Low voltage protection — essectially, very few features.
	__CONFIG	_CONFIG2, _BOR40V & _WRT_OFF
				; Set the BOR voltage to 4v, and we don't want any write protection
	
; Reserve Variables
tmr1	equ	20h			; Debug
tmr2	equ	tmr1 + 1
temp	equ	tmr2 + 1		
IRData	equ	temp + 1
w_temp	equ	IRData + 1
status_temp	equ	w_temp + 1

#define		ls	0
#define		rs	1
#define		ll	2
#define		rl	3	; IRData structure: 7:4 = N/A; 3 = Right Lit; 2 = Left Lit; 1 = Right Signal; 0 = Left Signal

;firstAvailableRegister	equ	0x20

	org 0h
	nop						; Allows ICD2 Debugger to work - not that I'm using that.
	goto	main			; Start main program
	org 4h
	goto	isrRoutine

include "/Users/barnabywalters/Documents/Electronics/PIC Programs/16F886/Weave.inc"		; Port/Useful Definitions

; Interrupt Service Routine	
isrRoutine
	movwf	w_temp
	movf	STATUS,w
	movwf	status_temp		; Save context
; Actual ISR
	btfsc	IRData,ll		; Is left emittor lit?
	bsf		IRData,ls		; If yes, store a signal received to the left
	
	btfsc	IRData,rl		; Is right emittor lit?
	bsf		IRData,rs		; If yes, store a signal received to the right
	
	bsf		portc,hb		; Light HB LED
	
	bcf		INTCON,INTF		; Clear interrupt flag
	
	movf	status_temp,w	; Restore context
	movwf	STATUS
	swapf	w_temp,f
	swapf	w_temp,w
	retfie					; Return
	
; * * * * * * * * * * *	SUBROUTINES	* * * * * * * * * * * * * * *

; Initalisation Routine
init
	clrf	PORTA
	clrf	PORTB
	clrf	PORTC
	banksel	OSCCON			; switches to bank 1. We need to be here to mess about with TRIS registers
	movlw	b'01100001'		; 
	movwf	OSCCON			; Osc Config: 0 (un) , 110 (4Mhz) , 000 (Rd Only) , 1 (Use internal Clk)
	
	movlw	b'00000000'		;
	movwf	TRISA			; PORTA = all outputs. A0 = Right indicator A1 = Left Indicator
	movlw	b'00000001'		;
	movwf	TRISB			; PORTB 0:3 used. B1 = Right Enable B2 = Left Enable B0 = Sensor Input
	movwf	WPUB			; Weak pull-up on RB0
	movlw	b'00000000'		;
	movwf	TRISC			; PORTC = outputs. C3 = HB LED. Motors not used in this app (yet)
	movlw	b'1000'
	movwf	TRISE			; PORTE 3 (MCLR) = Input
	
	banksel	ANSELH
	bcf		ANSELH,4
	
	banksel	OPTION_REG
	
	bcf		OPTION_REG,NOT_RBPU	; Enable RB Pull Ups
	bcf		OPTION_REG,INTEDG	; Interrupt triggered on falling edge @ RB0
	
	movlw	b'10010000'
	movwf	INTCON			; Enable unmasked interrupts, Enable interrupt on RB0
	
	banksel	PORTA		; Switch to bank 0 so we can move on with the program
	return					; Return to the program

; Delay Routines:

D30IRCycles					; Delays program flow for 30 cycles @ 38kHz — 'On' time for IREDs
	movlw	d'2'
	movwf	tmr2
	movlw	d'130'			; 30 IR Cycles = 780 instruction cycles. GOTO = 2 instruction cycles
	movwf	tmr1			; This timer will have to be completely decremented two times for the full 780 cycles
D30IR_Delay
	decfsz	tmr1,F
	goto	D30IR_Delay		; Cycle 195 times
	movwf	tmr1
	decfsz	tmr2,F
	goto	D30IR_Delay		; Go back and cycle twice
	return
	
D15IRCycles					; Delays program flow for 15 cycles @ 38kHz — 'Off' time for IREDs
	movlw	d'195'			; GOTO = 2 cycles. 2 * 195 = 390 instructions = 15 IR Cycles
	movwf	tmr1
D15IR_Delay
	decfsz	tmr1,f
	goto	D15IR_Delay
	return	

; Look-Up Tables:

motorControlLUT
	movf	IRData,w
	andlw	b'11'			; Mask off the bits we're interested in (1:0)
	movwf	temp			; Store offset
	
	movlw	high tableStart	; Get the high order part of address of tableStart
	movwf	PCLATH			;
	movlw	low tableStart	; Get low order address of tableStart
	addwf	temp, w			; Add the offset
	btfsc	STATUS, C		; Did it overflow?
	incf	PCLATH,f		; If yes, add one to PCLATH
	movwf	PCL				; Modify PCL and use the table…
tableStart	
	goto	forwards
	goto	softbackright
	goto	softbackleft
	goto	hardleft

; * * * * * * * * * *	Main Program	* * * * * * * * * *

main
	call 	init			; Set up ports, etc
	; Program structure: Constantly alternate between IR LEDs. Each one on for 30 cycles, the off for 15 cycles as per datasheet
	
sensorPollLoop

	bcf		portc,hb			; Turn of HB LED
	
	call	D15IRCycles		;  — — — — — — — Hold LEDs off for the required time — — — — — — —
	
	bsf		PORTB,2			; Turn on the left IRED (Robot perspective)
	bsf		IRData,ll		; Left IRED currently emitting.
	
	call	D30IRCycles		; Hold it on for a certain amount of time
	
	bcf		IRData,ll		; Left IRED not currently emitting
	bcf		PORTB,2			; Turn off the left IRED
	
	call	D15IRCycles		;  — — — — — — — Hold LEDs off for the required time — — — — — — —
	
	bsf		PORTB,1			; Turn on the right IRED (Robot perspective)
	bsf		IRData,rl		; Right IRED currently emitting
	
	call	D30IRCycles		; Hold it on for a certain amount of time
	
	bcf		IRData,rl		; Right IRED not currently emitting
	bcf		PORTB,1			; Turn off the right IRED
	
	;   — — — — — — — One complete sensor poll finished — — — — — — —
	; Now: See what data we have. For the moment, that means copying the data in IRData 3:2 to PORTA 3:2. How convenient…
	
	movf	IRData,w		; Pop value of IRData into the W. Reg…
	movwf	PORTA			; …and copy it into PORTA. Sorted! That's indicated the direction the signal was found in.
	
	bcf		INTCON,GIE		; Disable interrupts while sorting out motor control
	
	call	motorControlLUT	; Get the motor control signal required from the LUT
	movwf	PORTC			; Move the signal into PORTC
	
	bsf		INTCON,GIE		; Enable interrupts again
	clrf	IRData			; Clear data from last sensor poll loop execution
	
	goto	sensorPollLoop
	
	end
 

Wendy

Joined Mar 24, 2008
23,415
This probably should have been in the previous thread. The completed projects section is meant for Completed Projects Forum, otherwise you need to use the Projects Forum.
 

Thread Starter

Barnaby Walters

Joined Mar 2, 2011
102
Hello all,

This probably should have been in the previous thread. The completed projects section is meant for Completed Projects Forum, otherwise you need to use the Projects Forum.
Yep, sorry about the multiple post. The previous thread was entitled "Motor driver + Power Regulator" — I tried to change it but couldn't. This thread has a more accurate title.

Why did you program the PIC in assembly? There are high-level languages you can use.
As you know, whenever you program in higher languages it gets compiled into machine code. Anything that can be done more easily and efficiently in higher languages can still be done in asm. For my first project, I wanted to write in the lowest form I could feasibly do, to gain a better understanding of how the PIC is actually functioning.
In the future I will be programming in higher level languages, but I see no reason to whilst I'm doing projects that can be written in asm.

Thanks,
Barnaby
 

Georacer

Joined Nov 25, 2009
5,182
@Bill
Have you tried to write the same program in assembly and in C? The first will have ten times the length of the second, let alone be much less comprehensive. With modern compilers you won't even notice any difference in running time.

I personally find writing in assembly a waste of time in big projects, unless there's a good reason for it.
 

Thread Starter

Barnaby Walters

Joined Mar 2, 2011
102
Hey, let's not turn this into a C vs ASM thread please! I wrote the code in ASM as I wanted to get some experience writing as close to the hardware as I could (all my other programming has been very high level: Javascript, PHP, Objective-C).

On the comprehension note — I absolutely expect C to be far more comprehensive, when I do switch (that'll be when I start to do DSP work, or use things like USB/SD cards in my projects). To aid my own comprehension for Weave, I'm making myself a 'library' of sorts. The biggest problem I have had is remembering which bit of the motor control port does what, so I've made a whole set of subroutines that deal with changing motor direction. And, I make sure to comment everything extravagantly ;)

Thanks,
Barnaby
 

Georacer

Joined Nov 25, 2009
5,182
Nice video quality!
On the topic now, I like the construction, seems very robust. The system seems to respond very fast and is able to maneuver in high speeds.

Since you seem to have a problem with non reflective surfaces, two bumpers under the LEDs attached to two pushbuttons could help. A good practice I read once when using bumpers is to have them normally closing their switches (with a rubber band maybe) and on contact releasing it. That way you protect the switch from absorbing the collision force.
 

hgmjr

Joined Jan 28, 2005
9,027
Barnaby,

From your youtube video I perceive that your bot speed is a bit high. You may want to consider implementing a PWM scheme to give you a bit of speed control. Then you could throttle down as a function of the feedback from your collision avoidance sensors.

hgmjr
 

Georacer

Joined Nov 25, 2009
5,182
If you can sense analog in some way with your sensors, then you could slow down in the slightest sign of wall and then examine the new data more carefully.
 

hgmjr

Joined Jan 28, 2005
9,027
And if your sensor is not analog, you can, on detection, simply shift down to a slower speed commensurate with the distance sensitivity of your digital sensor. That way you would have some time to manuever your bot in a new direction that does not trigger your collision avoidance sensor.

hgmjr
 

Thread Starter

Barnaby Walters

Joined Mar 2, 2011
102
Hi there,

On the topic now, I like the construction, seems very robust. The system seems to respond very fast and is able to maneuver in high speeds.
Thanks, I'm pleased with how responsive the system is. Unfortunately, the fast speed changing has broken a tooth off one of the internal gears, which caused the rather horrible noises!

Since you seem to have a problem with non reflective surfaces, two bumpers under the LEDs attached to two pushbuttons could help. A good practice I read once when using bumpers is to have them normally closing their switches (with a rubber band maybe) and on contact releasing it. That way you protect the switch from absorbing the collision force.
That's a very interesting idea — I can't quite think how the manual NC switches would work? If they're held closed, I suppose I would have to build some extra mechanism that forces them open again. I'll have a play around with some microswitches and see if I can come up with something.

From your youtube video I perceive that your bot speed is a bit high. You may want to consider implementing a PWM scheme to give you a bit of speed control. Then you could throttle down as a function of the feedback from your collision avoidance sensors.
That is a very good idea indeed — in fact, I purposefully connected the PIC's two PWM out pins to the enable pins of my motor drivers. Once I've figured out how to get them running and integrated their control into my library, I'll replace the faulty motor and go from there.

Thanks a lot,
Barnaby
 

Georacer

Joined Nov 25, 2009
5,182
Check out these sketches:
In the first, a rubber band holds a lever on the switch. On the other side of the lever, a bumper is situated.

In the second picture a rubber band (not depicted) holds the bumper on the switch. The bumper is fitted in a linear guide.

I think that the first solution is easier to implement.
 

Attachments

Thread Starter

Barnaby Walters

Joined Mar 2, 2011
102
Thanks for those sketches, that cleared up what you meant — I didn't think to mount the touch sensors in reverse.

I've managed to give Weave PWM speed control, and build that into my 'software library' — so it runs at a much more forgiving speed now. I'll replace the broken motor at some point.

Thanks,
Barnaby
 
Top