12-zone perimeter detection from 6 ultrasonic sensors

The proximity sensing in ‘An Accident Waiting to Happen’ was done by a PICAXE 28X2 microcontroller, reading 6 Devantech SRF-10 ultrasonic sensors mounted around the perimeter of the table. The PICAXE board was programmed in PBASIC using their proprietary IDE. The detection cones of the 6 sensors overlapped slightly, so there were area where an observer would only be detected by one sensor, and also areas in between these where they would be detected by 2 sensors. This gave us 12 ‘zones’ in which to detect objects. Proximity readings were taken by the 6 sensors in sequence, and this was output to the PLC as a 4-bit parallel signal representing which zone had the closest object.

Functionality overview

The code functions as follows:

  • Read sensor x
  • Read sensor y
    • if sensor y reading is less than sensor x reading, remember y
    • if sensor y reading is similar to sensor x, remember xy
  • repeat for all 6 sensors and recheck first sensor.
  • update output to PLC to represent the remembered sensor ‘zone’
  • loop forever

KAF table positioning2

Code

Declarations

'Ultrasonic control program for Accident Waiting to Happen (KAF 2011)
'For PICAXE 28X1 Board

'Last Revision: 03-01-2011

'Copyright 2011
'Autonomous Systems Lab
'Middlesex University
'United Kingdom

'****************** Constants **********************

symbol Range = 255		'SRF10 Range (MaxRange = Range x 43mm + 43mm)
symbol Gain = 16		'SRF10 Analogue Gain

symbol Sens1 = $E0		'Sensor 1 I2C Address
symbol Sens2 = $E2		'Sensor 2 I2C Address
symbol Sens3 = $E4		'Sensor 3 I2C Address
symbol Sens4 = $E6		'Sensor 4 I2C Address
symbol Sens5 = $E8		'Sensor 5 I2C Address
symbol Sens6 = $EA		'Sensor 6 I2C Address

' ***************** Variables **********************
' words and bytes: 0-01 1-23 3-45 4-67 5-89

symbol Sensread = w1		'Word variable holding reading
symbol Senslow = b2		'Low byte read
symbol Senshigh = b3		'High byte read

symbol CurrentSens = b1		'Current sensor being read
symbol SensNumber = b0		'Indicates sensor location of closest user
symbol minread = w2		'Lowest reading in detection loop
symbol prevread = w3		'Previous reading in detection loop
symbol readdif = w6		'Used in comparison calculation
symbol sensad = b8		'I2C Address of sensor
symbol prevsens = b9		'Previous sensor read

'******************** Inputs ***********************

'Input 3 = I2C scl
'Input 4 = I2C sda

'******************** Outputs **********************

'Pin0 to Pin3 reserved for comms with PLC

Initialisation

The SRF-10 sensors communicate on an I2C bus, each sensor is pre-configured to a different address (0xE0 – 0xEA) which enabled me to access readings individually.

Some sensors had a different range to prevent them from picking up fixtures in the exhibition stand, and to give us somewhere to stand where we wouldn’t trigger any movement!

'******************* Initialisation ****************

init:

pause 5000

	i2cslave $E0, i2cfast, i2cbyte		'Link PICAXE with SRF10 using i2c bus
	writei2c 2, (255)			'Set the Range
	writei2c 1, (16)			'Set the Analogue Gain
	pause 20

	i2cslave $E2, i2cfast, i2cbyte		'Link PICAXE with SRF10 using i2c bus
	writei2c 2, (255)			'Set the Range
	writei2c 1, (16)			'Set the Analogue Gain
	pause 20

	i2cslave $E4, i2cfast, i2cbyte		'Link PICAXE with SRF10 using i2c bus
	writei2c 2, (21)			'Set the Range
	writei2c 1, (16)			'Set the Analogue Gain
	pause 20

	i2cslave $E6, i2cfast, i2cbyte		'Link PICAXE with SRF10 using i2c bus
	writei2c 2, (40)			'Set the Range
	writei2c 1, (16)			'Set the Analogue Gain
	pause 20

	i2cslave $E8, i2cfast, i2cbyte		'Link PICAXE with SRF10 using i2c bus
	writei2c 2, (23)			'Set the Range
	writei2c 1, (16)			'Set the Analogue Gain
	pause 20

	i2cslave $EA, i2cfast, i2cbyte		'Link PICAXE with SRF10 using i2c bus
	writei2c 2, (255)			'Set the Range
	writei2c 1, (16)			'Set the Analogue Gain
	pause 20

Reading the sensors and sending the output signal

Each sensor is queried one by one (the address increments by 2 hence the “step 2” in the for loop). The value from each sensor is compared with the last value, and also the lowest value found in the current cycle using the ‘compare’ subroutine.

‘sensnumber’ holds the information about the zone which has the closest reading. A single digit, 1, 2, 3, 4, 5 or 6 means the closest reading was on one sensor. A two-digit number means the closest object was detected on two sensors at the same time e.g. 23 means the object was on sensors 2 and 3. ‘SwitchPLC’ switches the outputs to the PLC to represent the zone number as a 4-bit binary number.

'********************* Main Program *******************

main:

	let minread = 9999				'Reset Variable values
	let sensnumber = 0
	let currentsens = 0

	for SensAd = 224 to 234 step 2			'Cycle through each sensor to take readings
		inc currentsens

		gosub detect				'Take reading
		gosub compare

		let prevread = sensread			'Set variables for the next loop
		let prevsens = currentsens

	next SensAd

	if sensnumber = 6 then				'If lowest value is on sensor 6
		let sensAd = Sens1
		let currentsens = 1
		gosub detect				'Take final reading of sensor 1 for comparison
		gosub compare
	endif

SwitchPLC:						'Sets outputs to control PLC

	select case sensnumber

		case 1  pins = %00010000
		case 12 pins = %00100000		'2-Digit sensnumber = user between sensors
		case 2  pins = %00110000
		case 23 pins = %01000000
		case 3  pins = %01010000
		case 34 pins = %01100000
		case 4  pins = %01110000
		case 45 pins = %10000000
		case 5  pins = %10010000
		case 56 pins = %10100000
		case 6  pins = %10110000
		case 61 pins = %11000000

		else pins = 0

	endselect

	debug

goto main

'********************* Subroutines *******************

detect:
	i2cslave SensAd, i2cfast, i2cbyte						'Link PICAXE with SRF10 using i2c bus
	writei2c 0, (81)								'Send command for ranging in cm
	pause 65									'wait for ranging to complete
	readi2c 2, (Senshigh, Senslow)							'Read in high byte and low byte
return

compare:
	if sensnumber > 0 and sensnumber < 10 and sensnumber = prevSens then		'If previous sensor is current lowest value
 		if sensread > 0 and sensread < prevread then				'Compare values between current reading
			let readdif = sensread - prevread				'and last reading to identify midpoint reading
											'If readings are similar, user is between sensors
			if readdif < 8 then
  				let sensnumber = sensnumber * 10			'Convert sensnumber to 2-digit number
 				let sensnumber = sensnumber + CurrentSens		'indicating user location
 			endif
 		endif
 		if sensread > 0 and sensread < prevread then				'Comparison as above
			let readdif = prevread - sensread
			if readdif < 8 then
  				let minread = sensread
 				let sensnumber = sensnumber * 10
 				let sensnumber = sensnumber + CurrentSens
 			endif
 		endif
 	elseif sensread > 0 and sensread < minread then					'If current reading is lowest then
		let minread = sensread							'user is on this sensor
		let sensnumber = CurrentSens
	endif
return

'************************************ end of program **********************************
Advertisements

Tell me what you think...

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s