How to interface GP2D02 Proximity sensors

Control Systems & Robotics Topics
Post Reply
User avatar
Neo
Site Admin
Site Admin
Posts: 2642
Joined: Wed Jul 15, 2009 2:07 am
Location: Colombo

How to interface GP2D02 Proximity sensors

Post by Neo » Sun Nov 29, 2009 10:10 am

On Dilbert, my fire fighting robotics platform, I use three Sharp GP2D02 Proximity sensors. They are used for wall following and detecting end of walls and passages. The GP2D02 sensor takes approximately 50ms to complete a measurement. The actual time varies with a specified maximum of 70ms. In practice one can poll the return data line of the sensor to determine when it is ready to be read. When the sensor has completed a reading the Vout line is raised. Typically the sensors raise Vout in ~50ms. The exact timing varies with surface reflectivity, distance and other factors. Please refer to the GP2D02 data sheet to learn about the specifics of communicating with the sensors, and the sensor output vs. distance.

Note: the GP2D02 is no longer supported by Sharp. However, the linearisation formulas, below, will still work with the analogue units.
Connecting and reading the sensors

To conserve I/O ports on the Atmel 8515 AVR processor, I multiplexed the sensors by using one I/O bit to be the control line for all sensors and connecting the three return data lines to bits 0, 1 and 2 of an I/O port. The software initiates a reading by dropping the control line, then it polls the three data lines waiting for all three to become 1's (0x07 in my case), then it clocks the data into the CPU. Since the three sensors are connected to sequential bits of a port, the software simply rotate the bits through the carry bit and into their respective destination bytes.
GP2D02_Mux_Schematic.gif
GP2D02_Mux_Schematic.gif (8.17 KiB) Viewed 3386 times
Note, the Sharp sensors require 3v logic on the input pin,, hence R1 and R2.
Linearizing and calibrating the output of the sensors

The sensors have an output curve that is the inverse of the distance of the target. The farther away the target, the lower the output value. The following chart is from the Sharp GP2D02 Data Sheet.
SHARP.gif
SHARP.gif (17.43 KiB) Viewed 3386 times
It turns out that the curve has a 1/X relationship. In fact, the formula D = Kg/(X-Ko), where X is the output of the sensor, can give very accurate values for distance. This calibration is easy to perform: it involves one division and one subtract. On Dilbert, the results are calculated in 10th of an inch and returned in a byte value, so the maximum distance that can be measured is ~25".

Since the calibration calculation only involves two constants, one can figure out what those are using two measurements from the unit. For details on how I got these formulas, see Derivation Of GP2D02 linearization formulas.

For the linearization formula

D = Kg/(X-Ko)

Kg is the gain, or overall shape of the curve described by Kg/X
Ko is an offset, shifting the curve up or down.

Let D and X be the distance and output, respectively of your first measurement.
Let D' and X' be the distance and output, respectively, of the second measurement.

Kg = (X'-X) D'D/(D-D')
Ko = (D'X' - DX)/(D' - D)

For Dilbert, I measured the sensor output at 5" and 20", respectively. That translates into an X and X' of 50 and 200 (10th of an inch). I needed to calibrate each sensor separately. Below are the results for the three sensors on Dilbert. The values for Kg and Ko are similar, but different enough to warrant individual calibration.

hardware.inc

Code: Select all

;
; Heuristic values for our sensors. The output
; is =XXXX_FG/(SensorOutput-XXXX_FO)
;
; These values calibrate the sensor cooked output in 1/10's
; of an inch
;
FRONT_KG DEFINE 0x1DB0
FRONT_KO DEFINE 0x11
RIGHT_KG DEFINE 0x1CA5
RIGHT_KO DEFINE 0x25
LEFT_KG  DEFINE 0x1B9B
LEFT_KO  DEFINE 0x15
With the above numbers the GP2D02 is typically within .2" of the actual distance. At long distances, however, the results are chunkier than .2" so the maximum error does rise a bit.
Physical mounting issues

The case of the sensors is a conductive plastic material. Don't believe me, check it out with an ohm meter. To insure reliable, noise free measurements, make sure you ground the case. If the case is not grounded and there is no target, or the return signal is weak, the sensor sometimes "thinks" there is a target and that it is wandering around. Before I put in a grounded copper (pcb) top plate on Dilbert, the distance sensors would measure anything from 15-25" when there was no target (looking down a long hallway in the fire fighting case). Grounded the sensors became much more stable with reading no target, or targets at long distances (e.g. > 36" away).

A second issue is the mounting orientation. At first glance it seems like horizontal makes sense. However, as in the Fire Fighting contest, if you point the sensor towards a corner that is reflective, you can get false readings when the sensor picks up the reflected signal. This was expressed by Dilbert thinking he was much farther away from a wall or end of passage than he really was when nearing or going around corners. The solution to this problem is to mount the sensors in the vertical direction.
Software

The following software is for the Atmel AVR processor and is written to the IAR v1.40 assembler. Note, the freeware version of IAR v1.4 is no longer available on the IAR website, however, whatever is there should work fine. Go to products, then to the AVR section. There should be free & demo downloads available there.

Sensor is a stand-alone task under the AvrX RTOS, that Dilbert is based upon. The task definition uses the context save/restore fragment from another task to preserve registers R20-R31, SREG and R0. TASK() and TIMER() declarations are macros defined in AvrX.inc. The software routine div16x8u can be found on the Dilbert web page in the file math.asm (Get the zip file of all software).

Because the Sharp sensors consume quite a bit of current when running, the task has an Sram flag that it checks before activating the sensors. There must be a better way to do this, but, at the time polling made the most sense, hence the startup code of "Sensor" When activated I want to read the sensor as fast as possible, hence the endless loop of the task.

The essence of the multiplexing routine is contained between "WaitUntilReady" and "Cook and store results". Because of the speed of the AVR processors, I needed to introduce some delays when clocking out the data from the GP2D02 sensor. The specifications for the sensor imply a much slower clocking speed but experiments done by others in the SRS have shown that a 10-16us clock period works Ok. The symbol CPUCLK is defined in the file harware.inc and is simply the crystal frequency of the CPU. I use that define when calculating UART divisors and system clock tick values. Then I can change crystals, and one define, and have everything still work when I recompile.

If you want to use this code in your own application, just remove the AvrX stuff, replace the delays with hard coded loops and replace the rjmp at the end of the routine with a ret.

hardware.inc

Code: Select all

;
; PORTB Bit Definitions
;
; PB 0-2 are the Front, Right and Left Sharp Proximity Sensors
;
Vin DEFINE PB3 ; Control signal into Sharp Proximity Sensor
;
; Initialize Vin to 1 to force the sharp sensors to reset during power up
; sequence (see Drivers.asm)
;
PORTB_INIT   DEFINE 0 ; No pull up's needed
DDRB_INIT    DEFINE (1<<PB7 | 1<<PB6 | 1<<PB3 | 1<<PB4); Vin is output
SHARP DEFINE PORTB
Drivers.asm

    PUBLIC  SensorFlag Front Right Left FrontRaw RightRaw LeftRaw

    EXTERN  AvrXDelay 
    EXTERN  MctlContext
    EXTERN  div16x8u

    TASK(Sensor, 12, 2, MctlContext, 6)
    TIMER(SensorTimer)

    RSEG        DATA

    SensorFlag: DS 1 ; Flag to control activation of sensors
    Front:      DS 1
    FrontRaw:   DS 1
    Right:      DS 1
    RightRaw:   DS 1
    Left:       DS 1
    LeftRaw:    DS 1


    RSEG        CODE
;+
;-------------------------------------------------------
;
; ReadProximitySensor
;
; PASSED: Nothing
; RETURNS Nothing
; USES: R0, R20-31, flags
; STACK: 2
; NOTES: Linearizes the SHARP output and stuffs values
; into the Sensor Data Structure.
;-
Sensor:
    sbi SHARP, Vin

    AVRX_Delay SensorTimer, 3/2 ; 1.5 ms/loop

    tst     SharpEnable ; Flag to enable/disable 
    breq    Sensor

    cbi     SHARP, Vin ; Initiate Proximity Detection

    ldi     Zh, 40 ; Wait a maximum of 60ms for sensor

WaitTillReady
    rcall   AvrXDelay

    in      Xh, SHARP-2
    sbr     Xh, 0xF8 ; PB0-2 are our inputs 
    cpi     Xh, 0xFF
    breq    SensorReady
    dec     Zh
    brne    WaitTillReady
    rjmp    Sensor ; Reset and start again.

SensorReady
    ldi     Zh, 9    ; Use bit counter so having no
                     ; sensor wired up doesn't hang routine
ReadNextBit:
    in      R0, SHARP-2 ; Read pins, not pullups
    sbi     SHARP, Vin

    ror     R0 ; Bits 0-2 are Front, Right, Left
    rol     R20 ; R20 = Front
    ror     R0
    rol     R21 ; R21 = Right
    ror     R0
    rol     R22 ; R22 = Left

    ldi     Zl,(1*CPUCLK/3000000) ; 1 uS delay
    dec     Zl                    ; The loop is only 3 cycles long
    brne    $-2
    cbi     SHARP, Vin
    ldi     Zl, (16*CPUCLK/3000000) ; 16 uS delay
    dec     Zl
    brne    $-2
    dec     Zh
    brne    ReadNextBit
;
; Cook and Store results
;
    mov    Wl, R20
    ldi    Wh, FRONT_KO
    ldi    Xh, high(FRONT_KG)
    ldi    Xl, low (FRONT_KG)
    rcall  ProcessProximity
    sts    Front, Xl
    sts    FrontRaw, R20

    mov    Wl, R21
    ldi    Wh, RIGHT_KO
    ldi    Xh, high(RIGHT_KG)
    ldi    Xl, low (RIGHT_KG)
    rcall  ProcessProximity
    sts    Right, Xl
    sts    RightRaw, R21

    mov    Wl, R22
    ldi    Wh, LEFT_KO
    ldi    Xh, high(LEFT_KG)
    ldi    Xl, low (LEFT_KG)
    rcall  ProcessProximity
    sts    Left, Xl
    sts    LeftRaw, R22
;
    rjmp   Sensor

;+
;------------------------------------------------------------------
; ProcessProximity
;
; PASSED: X = Kg, Wh = Ko, Wl = Raw X
; RETURNS: Xl = processed value
; USES: R0, Flags
; STACK: 2
;
;-
ProcessProximity:
    sub    Wl, Wh
    brlo   PPX
    rcall  div16x8u
    tst    Xh
    breq   PPY
PPX:
    ser    Xl ; Over-range, limit to 0xFF
PPY:
    ret
Courtesy: Larry Barello
Post Reply

Return to “Control Systems & Robotics”