-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathlinesensor.h
More file actions
301 lines (240 loc) · 10.1 KB
/
linesensor.h
File metadata and controls
301 lines (240 loc) · 10.1 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
// this #ifndef stops this file
// from being included mored than
// once by the compiler.
#ifndef _LINESENSOR_H
#define _LINESENSOR_H
#define NB_LS_PINS 3
#define LS_LEFT_PIN 18
#define LS_CENTRE_PIN 20
#define LS_RIGHT_PIN 21
#define RIGHT true
#define LEFT false
#define WHITE false
#define BLACK true
#define EMIT_PIN 11
#define TIME_OUT 4000 // After 4ms, report a time-out
#define LED_PIN 13 // Pin to activate the orange LED of the LED, and toggle it.
#define SAMPLING_TIME BIT_SIZE/OFFSET_SPEED // s
#define OFFSET_SPEED 60 // mm/s Possible speeds : 60, 100, 140, 180, 220
#define BIT_SIZE 8. // mm
#define STATE_INITIALISE 'I'
#define STATE_READ_CODE 'C'
#define STATE_FOLLOW_LINE 'L'
#define STATE_DEBUG 'D'
#define STATE_FAILED 'F'
volatile boolean read_bit = false;
volatile boolean DEBUG_LED_STATE = false;
static char state=STATE_INITIALISE;
//The following could possibly be moved as a privte class variable:
static uint8_t ls_pin[NB_LS_PINS] = {LS_LEFT_PIN, LS_CENTRE_PIN, LS_RIGHT_PIN};
// The ISR routine.
// The name TIMER3_COMPA_vect is a special flag to the
// compiler. It automatically associates with Timer3 in
// CTC mode.
ISR( TIMER3_COMPA_vect ){
if(state==STATE_READ_CODE) read_bit=true;
}
void setupBarCodeReader(){
// disable global interrupts
cli();
// Reset timer3 to a blank condition.
// TCCR = Timer/Counter Control Register
TCCR3A = 0; // set entire TCCR3A register to 0
TCCR3B = 0; // set entire TCCR3B register to 0
// First, turn on CTC mode. Timer3 will count up
// and create an interrupt on a match to a value.
// See table 14.4 in manual, it is mode 4.
TCCR3B = TCCR3B | (1 << WGM32);
// For a cpu clock precaler of 256:
// Shift a 1 up to bit CS32 (clock select, timer 3, bit 2)
// Table 14.5 in manual.
TCCR3B = TCCR3B | (1 << CS32);
// set compare match register to desired timer count.
// CPU Clock = 16000000 (16mhz).
// Prescaler = 256
// Timer freq = 16000000/256 = 62500
// We can think of this as timer3 counting up to 62500 in 1 second.
// compare match value = 62500 / 5 (we desire 5hz).
OCR3A = 62500*SAMPLING_TIME;
// enable timer compare interrupt:
TIMSK3 = TIMSK3 | (1 << OCIE3A);
// enable global interrupts:
sei();
}
// Class to operate the linesensor(s).
class LineSensor_c {
private:
double ls_values_percentage[NB_LS_PINS];
double ls_conditioned_data[NB_LS_PINS]; //Sensor time values
void reset(){
// Charge capacitor by setting input pin
// temporarily to output and HIGH
pinMode( LS_LEFT_PIN, OUTPUT );
pinMode( LS_CENTRE_PIN, OUTPUT );
pinMode( LS_RIGHT_PIN, OUTPUT );
digitalWrite( LS_LEFT_PIN, HIGH );
digitalWrite( LS_CENTRE_PIN, HIGH );
digitalWrite( LS_RIGHT_PIN, HIGH );
// Tiny delay for capacitor to charge.
delayMicroseconds(10);
// Turn input pin back to an input
pinMode( LS_LEFT_PIN, INPUT );
pinMode( LS_RIGHT_PIN, INPUT );
pinMode( LS_CENTRE_PIN, INPUT );
}
/*
* Calculates the percentage values of the 3 central line sensors
*/
void calc_values_percentage(){
double total_conditioned_data = 0.;
for(uint8_t i=0; i<NB_LS_PINS; i++){
total_conditioned_data += ls_conditioned_data[i];
}
for(uint8_t i=0; i<NB_LS_PINS; i++){
if(total_conditioned_data<0.01) ls_values_percentage[i]=0;
else ls_values_percentage[i]=ls_conditioned_data[i] / total_conditioned_data;
}
}
/*
* Calculates the conditioned date from raw data, thus taking into account calibration
*/
void calc_conditioned_data(){
for(uint8_t i=0;i<NB_LS_PINS;i++){
if(ls_raw_data[i]<=ls_min_values[i]) ls_conditioned_data[i]=0;
else{
ls_conditioned_data[i]=(ls_raw_data[i]-ls_min_values[i])*scaling_factors[i];
}
}
}
public:
uint32_t ls_raw_data[NB_LS_PINS]; //Sensor time values
uint32_t ls_max_values[NB_LS_PINS]; //max values for calibration
uint32_t ls_min_values[NB_LS_PINS]; //min values for calibration
double scaling_factors[NB_LS_PINS];
bool turn_direction;
double ls_1 = ls_conditioned_data[1];//GAFF
// Constructor, must exist.
LineSensor_c() {
for(uint8_t i=0;i<NB_LS_PINS;i++){
ls_values_percentage[i]=0.;
ls_raw_data[i]=0;
ls_conditioned_data[i]=0;
ls_max_values[i]=0;
ls_min_values[i]=2000;
scaling_factors[i]=0.;
turn_direction=LEFT;
}
}
// Initialises the pins and state of linesensorss
void initialise(){
pinMode(EMIT_PIN, OUTPUT );
pinMode(LS_LEFT_PIN, INPUT );
pinMode(LS_CENTRE_PIN, INPUT );
pinMode(LS_RIGHT_PIN, INPUT );
digitalWrite(EMIT_PIN, HIGH); //enables the IR LEDs
}
double getPositionError(){
return (ls_values_percentage[NB_LS_PINS-1]-ls_values_percentage[0]);
}
/*
* Detects if the frontmost sensor is on a black line
*/
bool on_line(){
return numerical_measure();
}
/*
* Measures the raw, conditioned and percentage values for all the sensors
*/
void measure(){
uint8_t done=0; // The number of sensors that already have recorded a value
// Places to store microsecond count:
uint32_t ls_temp_times[NB_LS_PINS] = {0}; //initialised at 0 (if ≠ than 0, then it means a value has already been read)
uint32_t start_time; // t_1
reset();
start_time = micros();// Store current microsecond count
// Stay in a loop whilst the capacitor
// is still registering as "HIGH".
while(done<NB_LS_PINS && (micros()-start_time)<TIME_OUT){
// Read all three sensors. Happens very quickly.
// The while() above will repeat this process, until
// all the sensors have been read or timed out
for(uint8_t i = 0; i < NB_LS_PINS; i++ ) {
if( digitalRead(ls_pin[i] ) == LOW && ls_temp_times[i]==0) {
// Store the time elapsed for this sensor
ls_temp_times[i]=micros()-start_time;
done++;
}
}
}
for(uint8_t i=0; i<NB_LS_PINS;i++){
ls_raw_data[i] = ls_temp_times[i];
}
if(scaling_factors[NB_LS_PINS-1]!=0) {
calc_conditioned_data(); //Calculate the conditioned data only if calibration has happenned
}
calc_values_percentage();
}
/*
* Returns 1 if the front sensor senses black and 0 if it senses white
*/
boolean numerical_measure(){
bool done=false;
uint32_t start_time; // t_1
uint32_t ls_temp_time = 0; //initialised at 0 (if ≠ than 0, then it means a value has already been read)
reset();
start_time = micros();// Store current microsecond count
while(!done && (micros()-start_time)<TIME_OUT){
// Read the central sensor. Happens very quickly.
// The while() above will repeat this process, until it hasnt been read or timed out
if( digitalRead(ls_pin[1]) == LOW && ls_temp_time==0) {
// Store the time elapsed for this sensor
ls_temp_time=micros()-start_time;
done=true;
}
}
ls_raw_data[1]=ls_temp_time;
if(scaling_factors[NB_LS_PINS-1]!=0) {
calc_conditioned_data(); //Calculates the conditioned data only if calibration has happenned
}
if(ls_conditioned_data[1]>=0.35) return BLACK;
else return WHITE;
}
/*
* Printing functions below
*/
void print_LS_raw_data(){
Serial.print("Left line sensor raw value: " );
Serial.println( ls_raw_data[0] );
Serial.print("Center line sensor raw value: " );
Serial.println(ls_raw_data[1] );
Serial.print("Right line sensor raw value: " );
Serial.println( ls_raw_data[2] );
}
void print_LS_conditioned_data(){
Serial.print("Left line sensor conditioned value: " );
Serial.println(ls_conditioned_data[0],6);
Serial.print("Center line sensor conditioned value: " );
Serial.println(ls_conditioned_data[1],6);
Serial.print("Right line sensor conditioned value: " );
Serial.println(ls_conditioned_data[2],6);
}
void print_LS_percentage_data(){
Serial.print("Left line sensor percentage value: " );
Serial.println(ls_values_percentage[0],6);
Serial.print("Center line sensor percentage value: " );
Serial.println(ls_values_percentage[1],6);
Serial.print("Right line sensor percentage value: " );
Serial.println(ls_values_percentage[2],6);
}
void print_LS_min_max_data(){
Serial.println("Min values : ");
Serial.println(ls_min_values[0]);
Serial.println(ls_min_values[1]);
Serial.println(ls_min_values[2]);
Serial.println("Max values : ");
Serial.println(ls_max_values[0]);
Serial.println(ls_max_values[1]);
Serial.println(ls_max_values[2]);
}
};
#endif