Project

General

Profile

Statistics
| Revision:

root / trunk / code / projects / colonet / utilities / manual_control / manualControlRobot / rangefinder.c @ 13

History | View | Annotate | Download (4.83 KB)

1
/*
2
Authors: James Kong and Greg Tress
3

4
Last Modified: 4/30/06 by James
5
-Started log_distance conversion function !!!NOT COMPLETE!!!
6
-Cleaning up comments
7

8
-----------------
9
rangefinder.c
10
Using Sharp GP2D02 IR Rangefinder
11

12
Vin is the input to the rangefinder, designated RANGE_CTRL.
13
Vout is the output from the rangefinder, designated RANGE_IN# where # is the rangefinder you are reading from
14

15
Expected Initial Conditions:
16
Vin is high and Vout should read high.
17

18
Usage:
19
1.) Set Vin low. Vout should read low.
20
2.) Wait for high on Vout.
21
3.) Begin clocking Vin and reading 8 bits from Vout (MSB first).
22
4.) Set Vin high for 2ms or more to turn off rangefinder
23

24
*/
25

    
26
#include "firefly+_lib.h"
27
#include "rangefinder.h"
28

    
29
/*
30
read_distance returns the 8-bit reading from the rangefinder
31
parameters:
32
range_id - dio pin set as the rangefinder Vout [i.e. RANGE_IN0]
33

34
NOTE:
35
The Sharp GD2D02 returns values on a decreasing logrithmic scale.
36
So higher values correspond to closer distances.  Use linearize_distance to convert to normal centimeter scale.
37
Also, when reading distances closer than 8cm, the Sharp GD2D02 will return lower values than the values at 8cm.
38
At this point, we are only reading from one rangefinder [RANGE_IN0].
39
*/
40

    
41
int read_distance (int range_id) {  
42
#ifndef FFPP
43
        int bitcount;
44
        int current = 0;
45
        digital_output(RANGE_CTRL, 0);                                                //set Vin Low
46
        while(digital_input(range_id) == 0);                                //waits until Vout reads high
47
        digital_output(RANGE_CTRL, 1);                                                //first Vin clock high transition
48
        
49
        for(bitcount = 8; bitcount != 0; bitcount--){
50
                digital_output(RANGE_CTRL, 0);                                        //Vin clock low transition
51
                //clock delay (unnecessary)
52
                current = current << 1;                                                        //shifts current 8-bit value left
53
                current |= digital_input(range_id);                                //LSB set to Vout value
54
                digital_output(RANGE_CTRL, 1);                                        //Vin clock high transition
55
                //clock delay (unnecessary)
56
        }                                                                                                        //repeats until all 8 bits are stored
57
        return current;
58
#else
59
        enable_IR();
60
        _delay_ms(5);                                                                                ///////Figure out what this should be!!!!!!  Maybe if not enabled already?
61
        return read_IR_val(range_id);
62
#endif
63
}
64

    
65
/*
66
linearize_distance converts an 8-bit rangefinder reading to a centimeter measurement (truncated to an integer)
67
parameters:
68
reading - 8-bit rangefinder reading
69

70
OFFSET, GAIN, and THRESHOLD are experimentally determined constants
71
The conversion is a piecewise defined function with a continuity fix at reading = THRESHOLD3
72

73
NOTE:
74
This function is ugly, but it gets the job done without spending a huge amount processing.
75
Ideally, you want to compare with the read_distance value directly.
76
*/
77

    
78
int linearize_distance (int reading) {
79
#ifndef FFPP
80
        int temp = reading;
81
        if(reading >  THRESHOLD1){
82
                temp = temp - OFFSET1;
83
                return GAIN1 / temp;
84
        }else if(reading > THRESHOLD2){
85
                temp = temp - OFFSET2;
86
                return GAIN2 / temp + 1;
87
        }else if(reading > THRESHOLD3){
88
                temp = temp - OFFSET2;
89
                return GAIN2 / temp;
90
        }else if(reading == THRESHOLD3){
91
                return CONTINUITY_FIX;
92
        }else if(reading > THRESHOLD4){
93
                temp = temp - OFFSET3;
94
                return GAIN3 / temp;
95
        }else{
96
                return MAX_DIST;
97
        }
98
#else
99
        return convert_IR_distance(reading);
100
#endif
101
}
102

    
103
/*
104
log_distance converts a centimeter value to a rangefinder comparable value
105
parameters:
106
distance - centimeter measurement
107

108
NOTE:
109
This is still incomplete, do not use it.
110
*/
111
int log_distance(int distance) {
112
#ifndef FFPP
113
        if(distance >= MAX_DIST){
114
                return THRESHOLD4;
115
        }
116
        if(distance <= MIN_DIST){
117
                return 255;
118
        }        
119

    
120
        switch(distance){                        //Incomplete need to fill out table
121
        case 60:                                
122
                return 56;
123
        case 59:
124
                return 89;
125
        }
126
#endif
127
        return 0;
128
}
129

    
130

    
131
#ifdef FFPP
132

    
133
static int IR_dist_conversion[114] = {
134
800,791,751,714,681,651,623,597,574,552,531,512,494,478,462,447
135
,434,421,408,397,386,375,365,356,347,338,330,322,315,307,301,294
136
,288,282,276,270,265,260,255,250,245,241,237,232,228,224,221,217
137
,213,210,207,203,200,197,194,191,189,186,183,181,178,176,173,171
138
,169,166,164,162,160,158,156,154,152,151,149,147,145,144,142,140
139
,139,137,136,134,133,131,130,129,127,126,125,124,122,121,120,119
140
,118,117,115,114,113,112,111,110,109,108,107,106,105,105,104,103
141
,102,101
142
};
143

    
144
void enable_IR()
145
{
146
  // active low, so set enable to low to turn on IR
147
  PORTC &= ~(_BV(IR_ENABLE));
148
  DDRC |= _BV(IR_ENABLE);
149
}
150

    
151
void disable_IR()
152
{
153
  // active low, so set line high and turn to input for good measure (line has pull-up)
154
  PORTC |= _BV(IR_ENABLE);
155
  DDRC &= ~(_BV(IR_ENABLE));
156
}
157

    
158
int read_IR_val(int which)
159
{
160
  return analog8(IR_READ + which);
161
}
162

    
163
int convert_IR_distance(int value)
164
{
165
  if(value < MIN_IR_ADC8)
166
  {
167
    return -1;
168
  }
169
  else if(value > MAX_IR_ADC8)
170
  {
171
    return -1;
172
  }
173
  else
174
  {
175
    return IR_dist_conversion[value - MIN_IR_ADC8];
176
  }
177
}
178

    
179
int get_IR_distance(int which)
180
{
181
  return convert_IR_distance(read_IR_val(which));
182
}
183
#endif