# Project: Weave, Obstacle Avoiding Robot

#### Barnaby Walters

Joined Mar 2, 2011
102

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
;
;	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

; 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
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,107
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.

#### Georacer

Joined Nov 25, 2009
5,182
Why did you program the PIC in assembly? There are high-level languages you can use.

#### Wendy

Joined Mar 24, 2008
23,107
Why not, if you can? Assembly is a much more efficient language.

#### 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.

#### 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

#### 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

• 9 KB Views: 67

#### 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

#### Prinz

Joined Nov 16, 2014
16
Hello there, would like to have a look @ d complete asm code and d circuit diagrams. Nice job!