Increasing IR Ranger Resolution

I have code that can read any number of Sharp IR Rangers, only limited by how many ADCs you have available.

Here is my current code for the IR Rangers:

[code]’
’ IR Ranger Configuration

IR_Max con 3 ’ How many IR Rangers we have
IR_Threshld_Dist con 20 ’ Distance Threshold in cm for closeness checks
IR_Threshld_RFrnt con 25 ’ Front RIGHT Detection threshold in cm
IR_Threshld_LFrnt con 25 ’ Front LEFT Detection threshold in cm
IR_Threshld_Tur con 35 ’ Detection threshold for Pan/Tilt Turret IR Ranger in cm

’ IR Sensor Numbers

IR_LF con 0 ’ Left Front
IR_RF con 1 ’ Right Front
IR_TU con 2 ’ Pan/Tilt Turret
’ Future expansion
IR_LW con 3 ’ Wheel Left
IR_RW con 4 ’ Wheel Right

’ Bits for IR_Status checking

IR_LeftFront con 1
IR_RightFront con 2
IR_BothFront con 3
IR_Turret con 4
’ For future expansion
IR_LeftWheel con 8 ’ Left Side (across wheel)
IR_RightWheel con 16 ’ Right Side (across wheel)
IR_BothWheels con 24 ’ Both Sides (across wheels)

'---- Table Setup for IR Ranging Routine ] ----------------------------------------------------------

scantable bytetable 80,80,80,80,80,80,80,80,80,78, |
76,74,72,70,68,66,64,62,60,59, |
58,57,55,53,52,51,50,49,48,47, |
45,43,42,41,40,39,38,37,35,33, |
32,31,30,30,29,29,28,28,27,27, |
26,26,26,25,25,25,24,24,24,23, |
23,22,22,21,21,20,20,20,19,19, |
18,18,18,17,17,16,16,16,15,15, |
15,14,14,13,13,13,12,12,11,11, |
11,10,10,10,10,10,10,10,10,10


’ IR Rangers

IR_Distance var word(8) ’ Distance object was detected at
IR_Detected var bit(8) ’ Was object detected? 0 = No, 1 = Yes
IR_Threshold var word(8) ’ Detection threshold for each IR Ranger
IR_Status var word ’ IR Detection status - 1 = Left Front, 2 = Right Front, 3 = BOTH Front, 4 = Turret IR
’ Expansion: 8 = Left Side (across wheel), 16 = Right Side (across wheel), 24 = BOTH
’ Sides (across wheels).

distance var byte ’ Shortest distance to any obstacle from any IR sensor
scanrange var word ’ A/D result variable

’ Read up to three IR Ranging sensors - based on code written by Nathan Scherdin
’ and Chuck Hellebuyck in their Range.Bas module. This routine can read any
’ number of IR Rangers without modification, controlled by the constant IR_Max.
Read_IR_Rangers:
IR_Status = 0

for index = 0 to IR_Max - 1
	IR_Detected(index) = 0
	
	' Read the sensor value
		if index = IR_LF then							' Left Wheel
			adin AX0, 2, AD_RON, scanrange
		elseif index = IR_RF							' Right Wheel
			adin AX2, 2, AD_RON, scanrange
		elseif index = IR_TU							' Front Pan/Tilt Turret
			adin AX3, 2, AD_RON, scanrange
		else
			exception Invalid_Sensor
		endif

	tfloat = TOFLOAT scanrange / 5.12					' Limit value to < 200 values
	IR_Distance(index) = scantable(TOINT tfloat)		' Convert A/D to measurement
	
	if sendoutput then
		serout S_OUT, I8N1_9600, "Read_IR_Rangers 1: index = ", DEC index, ", IR_Status = ", DEC IR_Status, ", Threshold = ", DEC IR_Threshold(index), ", Distance = ", DEC IR_Distance(index), ", Distance = ", DEC IR_Distance(index), 13]
	endif
	
	if (scanrange > 512) OR (IR_Distance(index) < IR_Threshold(index)) then
		IR_Detected(index) = 1
	
		' Add bit value for the current sensor to IR_Status
		'	Bit 0 = 1, Sensor 0 Detect		0 0 0 0 0 0 0 1 Left Wheel
		'	Bit 1 = 1, Sensor 1 Detect		0 0 0 0 0 0 1 0 Right Wheel
		'	Bit 2 = 1, Sensor 2 Detect		0 0 0 0 0 1 0 0 Turret
		'	Bit 3 = 1, Sensor 3 Detect		0 0 0 0 1 0 0 0 Left Front
		'	Bit 4 = 1, Sensor 4 Detect		0 0 0 1 0 0 0 0 Right Front

		gosub Power_Of_2								' Calculate bit value for sensor index

		IR_Status = IR_Status + power2					' Add the correct bit value to the IR Status
		
		if sendoutput then
			serout S_OUT, I8N1_9600, "Read_IR_Rangers 2: index = ", DEC index, ", IR_Status = ", DEC IR_Status, ", Power2 = ", DEC power2, ", Detected = ", DEC IR_Detected(index), 13]
		endif

		if makenoise then	
			if index = IR_LF then						' Front Left Side
				sound speaker, [dur\note5,dur\note6,dur\note7,dur\note8]
			elseif index = IR_RF						' Front Right Side
				sound speaker, [dur\note8,dur\note7,dur\note6,dur\note5]
			elseif index = IR_TU						' Turret
				sound speaker, [dur\note9,dur\note10,dur\note11,dur\note12]
			endif
		endif
	endif
next

Invalid_Sensor:
return

’ Calculate the correct power of 2 for a bit index
’ Parameter: index. Returns: power2 with the correct power of 2
Power_Of_2:
power2 = 1

if index > 0 then
	for loop = 1 to index
		power2 = power2 * 2
	next
endif

return[/code]

I don’t fully understand what this code is doing to calculate the distance to an obstacle though, and would like to at least double the resolution if possible. How does the bytetable fit into this picture? Would it be hard to double the number of entries and increase resolution of the readings? I have been reading up a bit on this sensor and various ways to processing the readings, but it still doesn’t click for me.

8-Dale

You can change the “resolution” by changing this line:

tfloat = TOFLOAT scanrange / 5.12               ' Limit value to < 200 values 

You could even completely remove the floating point code and divide scanrange by a multiple of 2. “scanrange” can be any number from 0 to 1023. Divide by 4 and you’ll need a scantable of 256 values.

Ahhhh, OK, thanks!

If I just leave the code as is and divide by 2.56 instead of 5.12, would that require a table with twice as many entries as it has now?

So all I would need to do then is gather more data points and convert them to distances for the larger table. It would just be a matter of whether I have enough memory to handle the larger table.

I’m down to about 800 bytes of program memory free now, but that includes all my serout debugging output that I turn on or off with a variable switch. I’m not quite ready to comment them out.

8-Dale

Yes it would though if you can get ridd of the floating point in your program you can free up a lot of code space.

Ah, OK, I think I am starting to understand how the code works. I just need to just do scanrange / 4 to get the result I want. That does get rid of the floating point and shouldn’t impact the rest of the code too much if I am lucky.

8-Dale

hi, you can add a loop, and increment somes averages.

'sample to read one sharp :
     sensor var word
     sensors var word '(long if averages > 64)
     i var byte
     averages con 64 'slow but very hi-res!

     sensors = 0
     for i = 1 to averages
      adin p17, sensor
      sensors = sensors + sensor
     next
     sensor = sensors / averages

act as digital “low pass filter” and remove many sharp noise

(I linearise after, on linux server/PHP with $cm = pow($sensor, -1.1) * $ratio; you can convert math to atom and adjust $ratio)

Pascal