forked from exshonda/ZumoShield
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathZumoReflectanceSensorArray.h
408 lines (387 loc) · 18.1 KB
/
ZumoReflectanceSensorArray.h
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
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
/*! \file ZumoReflectanceSensorArray.h
*
* See the ZumoReflectanceSensorArray class reference for more information about
* this library.
*
* \class ZumoReflectanceSensorArray ZumoReflectanceSensorArray.h
* \brief Read from reflectance sensor array
*
* The ZumoReflectanceSensorArray library provides an interface for using a
* [Zumo Reflectance Sensor Array](http://www.pololu.com/product/1419) connected
* to a Zumo robot. The library provides access to the raw sensor values as well
* as to high level functions including calibration and line-tracking.
*
* For calibration, memory is allocated using the `malloc()` function. This
* conserves RAM: if all six sensors are calibrated with the emitters both on
* and off, a total of 48 bytes is dedicated to storing calibration values.
* However, for an application where only two sensors are used, and the
* emitters are always on during reads, only 4 bytes are required.
*
* Internally, this library uses all standard Arduino functions such as
* `micros()` for timing and `digitalRead()` for getting the sensor values, so
* it should work on all Arduinos without conflicting with other libraries.
*
* ### Calibration ###
*
* This library allows you to use the `calibrate()` method to easily calibrate
* your sensors for the particular conditions it will encounter. Calibrating
* your sensors can lead to substantially more reliable sensor readings, which
* in turn can help simplify your code. As such, we recommend you build a
* calibration phase into your Zumo's initialization routine. This can be as
* simple as a fixed duration over which you repeatedly call the `calibrate()`
* method.
*
* During this calibration phase, you will need to expose each of your
* reflectance sensors to the lightest and darkest readings they will encounter.
* For example, if your Zumo is programmed to be a line follower, you will want
* to slide it across the line during the calibration phase so the each sensor
* can get a reading of how dark the line is and how light the ground is (or you
* can program it to automatically turn back and forth to pass all of the
* sensors over the line). The **SensorCalibration** example included with this
* library demonstrates a calibration routine.
*
* ### Reading the sensors
*
*
* This library gives you a number of different ways to read the sensors.
*
* - You can request raw sensor values using the `read()` method.
*
* - You can request calibrated sensor values using the `readCalibrated()`
* method. Calibrated sensor values will always range from 0 to 1000, with the
* extreme values corresponding to the most and least reflective surfaces
* encountered during calibration.
*
* - For line-detection applications, you can request the line location using
* the `readLine()` method. This function provides calibrated values
* for each sensor and returns an integer that tells you where it thinks the
* line is.
*
* ### Class Inheritance ###
*
* The ZumoReflectanceSensorArray class is derived from the QTRSensorsRC class,
* which is in turn derived from the QTRSensors base class. The QTRSensorsRC and
* QTRSensors classes are part of the \ref QTRSensors.h "QTRSensors" library,
* which provides more general functionality for working with reflectance
* sensors and is included in the Zumo Shield libraries as a dependency for this
* library.
*
* We recommend using the ZumoReflectanceSensorArray library instead of
* the \ref QTRSensors.h "QTRSensors" library when programming an Arduino on a
* Zumo. For documentation specific to the %QTRSensors library, please see its
* [user's guide](http://www.pololu.com/docs/0J19) on Pololu's website.
*/
#ifndef ZumoReflectanceSensorArray_h
#define ZumoReflectanceSensorArray_h
#include <QTRSensors.h>
#include <Arduino.h>
#if defined(__AVR_ATmega32U4__)
// Arduino Leonardo
#define ZUMO_SENSOR_ARRAY_DEFAULT_EMITTER_PIN A4
#else
// Arduino UNO and other ATmega328P/168 Arduinos
#define ZUMO_SENSOR_ARRAY_DEFAULT_EMITTER_PIN 2
#endif
class ZumoReflectanceSensorArray : public QTRSensorsRC
{
public:
/*! \brief Minimal constructor.
*
* This version of the constructor performs no initialization. If it is used,
* the user must call init() before using the methods in this class.
*/
ZumoReflectanceSensorArray() {}
/*! \brief Constructor; initializes with given emitter pin and defaults for
* other settings.
*
* \param emitterPin Pin that turns IR emitters on or off.
*
* This constructor calls `init(unsigned char emitterPin)` with the specified
* emitter pin and default values for other settings.
*/
ZumoReflectanceSensorArray(unsigned char emitterPin)
{
init(emitterPin);
}
/*! \brief Constructor; initializes with all settings as given.
*
* \param pins Array of pin numbers for sensors.
* \param numSensors Number of sensors.
* \param timeout Maximum duration of reflectance reading in microseconds.
* \param emitterPin Pin that turns IR emitters on or off.
*
* This constructor calls `init(unsigned char * pins, unsigned char
* numSensors, unsigned int timeout, unsigned char emitterPin)` with all
* settings as given.
*/
ZumoReflectanceSensorArray(unsigned char * pins, unsigned char numSensors, unsigned int timeout = 2000,
unsigned char emitterPin = ZUMO_SENSOR_ARRAY_DEFAULT_EMITTER_PIN)
{
QTRSensorsRC::init(pins, numSensors, timeout, emitterPin);
}
/*! \brief Initializes with given emitter pin and and defaults for other
* settings.
*
* \param emitterPin Pin that turns IR emitters on or off.
*
* This function initializes the ZumoReflectanceSensorArray object with the
* specified emitter pin. The other settings are set to default values: all
* six sensors on the array are active, and a timeout of 2000 microseconds is
* used.
*
* \a emitterPin is the Arduino digital pin that controls whether the IR LEDs
* are on or off. This pin is optional; if a valid pin is specified, the
* emitters will only be turned on during a reading. If \a emitterPin is not
* specified, the emitters will be controlled with pin 2 on the Uno (and other
* ATmega328/168 boards) or pin A4 on the Leonardo (and other ATmega32U4
* boards). (The "LED ON" jumper on the Zumo Reflectance Sensor Array must be
* configured correctly for this to work.) If the value `QTR_NO_EMITTER_PIN`
* (255) is used, you can leave the emitter pin disconnected and the IR
* emitters will always be on.
*/
void init(unsigned char emitterPin = ZUMO_SENSOR_ARRAY_DEFAULT_EMITTER_PIN)
{
unsigned char sensorPins[] = { 4, A3, 11, A0, A2, 5 };
QTRSensorsRC::init(sensorPins, sizeof(sensorPins), 2000, emitterPin);
}
/*! \brief Initializes with all settings as given.
*
* \param pins Array of pin numbers for sensors.
* \param numSensors Number of sensors.
* \param timeout Maximum duration of reflectance reading in microseconds.
* \param emitterPin Pin that turns IR emitters on or off.
*
* This function initializes the ZumoReflectanceSensorArray object with all
* settings as given.
*
* The array \a pins should contain the Arduino digital pin numbers for each
* sensor.
*
* \a numSensors specifies the length of the \a pins array (the number of
* reflectance sensors you are using).
*
* \a timeout specifies the length of time in microseconds beyond which you
* consider the sensor reading completely black. That is to say, if the pulse
* length for a pin exceeds \a timeout, pulse timing will stop and the reading
* for that pin will be considered full black. It is recommended that you set
* \a timeout to be between 1000 and 3000 us, depending on factors like the
* height of your sensors and ambient lighting. This allows you to shorten the
* duration of a sensor-reading cycle while maintaining useful measurements of
* reflectance. If \a timeout is not specified, it defaults to 2000 us. (See
* the [product page](http://www.pololu.com/product/1419) for the Zumo
* Reflectance Sensor Array on Pololu's website for an overview of the
* sensors' principle of operation.)
*
* \a emitterPin is the Arduino digital pin that controls whether the IR LEDs
* are on or off. This pin is optional; if a valid pin is specified, the
* emitters will only be turned on during a reading. If \a emitterPin is not
* specified, the emitters will be controlled with pin 2 on the Uno (and other
* ATmega328/168 boards) or pin A4 on the Leonardo (and other ATmega32U4
* boards). (The corresponding connection should be made with the "LED ON"
* jumper on the Zumo Reflectance Sensor Array.) If the value
* `QTR_NO_EMITTER_PIN` (255) is used, you can leave the emitter pin
* disconnected and the IR emitters will always be on.
*
* This version of `%init()` can be useful if you only want to use a subset
* of the six reflectance sensors on the array. For example, using the
* outermost two sensors (on pins 4 and 5 by default) is usually enough for
* detecting the ring border in sumo competitions:
*
* ~~~{.ino}
* ZumoReflectanceSensorArray reflectanceSensors;
*
* ...
*
* reflectanceSensors.init((unsigned char[]) {4, 5}, 2);
* ~~~
*
* Alternatively, you can use \ref ZumoReflectanceSensorArray(unsigned char * pins, unsigned char numSensors, unsigned int timeout, unsigned char emitterPin)
* "a different constructor" to declare and initialize the object at the same
* time:
*
* ~~~{.ino}
*
* ZumoReflectanceSensorArray reflectanceSensors((unsigned char[]) {4, 5}, 2);
* ~~~
*
*/
void init(unsigned char * pins, unsigned char numSensors, unsigned int timeout = 2000,
unsigned char emitterPin = ZUMO_SENSOR_ARRAY_DEFAULT_EMITTER_PIN)
{
QTRSensorsRC::init(pins, numSensors, timeout, emitterPin);
}
};
// documentation for inherited functions
/*! \fn void QTRSensors::read(unsigned int *sensor_values, unsigned char readMode = QTR_EMITTERS_ON)
\memberof ZumoReflectanceSensorArray
* \brief Reads the raw sensor values into an array.
*
* \param sensorValues Array to populate with sensor readings.
* \param readMode Read mode (`QTR_EMITTERS_OFF`, `QTR_EMITTERS_ON`, or
* `QTR_EMITTERS_ON_AND_OFF`).
*
* There **must** be space in the \a sensorValues array for as many values as
* there were sensors specified in the constructor. The values returned are
* measures of the reflectance in units of microseconds. They will be raw
* readings between 0 and the \a timeout argument (in units of microseconds)
* provided in the constructor (which defaults to 2000).
*
* The \a readMode argument specifies the kind of read that will be performed.
* Several options are defined:
*
* - `QTR_EMITTERS_OFF` specifies that the reading should be made without
* turning on the infrared (IR) emitters, in which case the reading represents
* ambient light levels near the sensor.
* - `QTR_EMITTERS_ON` specifies that the emitters should be turned on for the
* reading, which results in a measure of reflectance.
* - `QTR_EMITTERS_ON_AND_OFF` specifies that a reading should be made in both
* the on and off states. The values returned when this option is used are
* given by the formula **on + max − off**, where **on** is the reading
* with the emitters on, **off** is the reading with the emitters off, and
* **max** is the maximum sensor reading. This option can reduce the amount of
* interference from uneven ambient lighting.
*
* Note that emitter control will only work if you specify a valid emitter pin
* in the constructor and make the corresponding connection (with the "LED ON"
* jumper or otherwise).
*
* The ZumoReflectanceSensorArray class inherits this function from the
* QTRSensors class.
*/
/*! \fn void QTRSensors::emittersOff()
* \brief Turns the IR LEDs off.
*
* This is mainly for use by the `read()` method, and calling this function
* before or after reading the sensors will have no effect on the readings, but
* you might wish to use it for testing purposes. This method will only do
* something if the emitter pin specified in the constructor is valid (i.e. not
* `QTR_NO_EMITTER_PIN`) and the corresponding connection is made.
*
* The ZumoReflectanceSensorArray class inherits this function from the
* QTRSensors class.
*/
/*! \fn void QTRSensors::emittersOn()
* \brief Turns the IR LEDs on.
* \copydetails emittersOff
*/
/*! \fn void QTRSensors::calibrate(unsigned char readMode = QTR_EMITTERS_ON)
* \brief Reads the sensors for calibration.
*
* \param readMode Read mode (`QTR_EMITTERS_OFF`, `QTR_EMITTERS_ON`, or
* `QTR_EMITTERS_ON_AND_OFF`).
*
* The sensor values read by this function are not returned; instead, the
* maximum and minimum values found over time are stored internally and used for
* the `readCalibrated()` method. You can access the calibration (i.e raw max
* and min sensor readings) through the public member pointers
* `calibratedMinimumOn`, `calibratedMaximumOn`, `calibratedMinimumOff`, and
* `calibratedMaximumOff`. Note that these pointers will point to arrays of
* length \a numSensors, as specified in the constructor, and they will only be
* allocated **after** `calibrate()` has been called. If you only calibrate with
* the emitters on, the calibration arrays that hold the off values will not be
* allocated.
*
* The ZumoReflectanceSensorArray class inherits this function from the
* QTRSensors class.
*/
/*! \fn void QTRSensors::resetCalibration()
* \brief Resets all calibration that has been done.
*
* This function discards the calibration values that have been previously
* recorded, resetting the min and max values.
*
* The ZumoReflectanceSensorArray class inherits this function from the
* QTRSensors class.
*/
/*! \fn void QTRSensors::readCalibrated(unsigned int *sensor_values, unsigned char readMode = QTR_EMITTERS_ON)
* \brief Returns sensor readings normalized to values between 0 and 1000.
*
* \param sensorValues Array to populate with sensor readings.
* \param readMode Read mode (`QTR_EMITTERS_OFF`, `QTR_EMITTERS_ON`, or
* `QTR_EMITTERS_ON_AND_OFF`).
*
* 0 corresponds to a reading that is less than or equal to the minimum value
* read by `calibrate()` and 1000 corresponds to a reading that is greater than
* or equal to the maximum value. Calibration values are stored separately for
* each sensor, so that differences in the sensors are accounted for
* automatically.
*
* The ZumoReflectanceSensorArray class inherits this function from the
* QTRSensors class.
*/
/*! \fn int QTRSensors::readLine(unsigned int *sensor_values, unsigned char readMode = QTR_EMITTERS_ON, unsigned char whiteLine = 0)
* \brief Returns an estimated position of a line under the sensor array.
*
* \param sensorValues Array to populate with sensor readings.
* \param readMode Read mode (`QTR_EMITTERS_OFF`, `QTR_EMITTERS_ON`, or
* `QTR_EMITTERS_ON_AND_OFF`).
* \param whiteLine 0 to detect a dark line on a light surface; 1 to detect
* a light line on a dark surface.
* \return An estimated line position.
*
* This function operates the same as `readCalibrated()`, but with a feature
* designed for line following: it returns an estimated position of the line.
* The estimate is made using a weighted average of the sensor indices
* multiplied by 1000, so that a return value of 0 indicates that the line is
* directly below sensor 0 (or was last seen by sensor 0 before being lost), a
* return value of 1000 indicates that the line is directly below sensor 1, 2000
* indicates that it's below sensor 2, etc. Intermediate values indicate that
* the line is between two sensors. The formula is:
*
* \f[
* \newcommand{sv}[1]{\mathtt{sensorValues[#1]}}
* \text{return value} =
* \frac{(0 \times \sv{0}) + (1000 \times \sv{1}) + (2000 \times \sv{2}) + \ldots}
* {\sv{0} + \sv{1} + \sv{2} + \ldots}
* \f]
*
* As long as your sensors aren't spaced too far apart relative to the line,
* this returned value is designed to be monotonic, which makes it great for use
* in closed-loop PID control. Additionally, this method remembers where it last
* saw the line, so if you ever lose the line to the left or the right, its line
* position will continue to indicate the direction you need to go to reacquire
* the line. For example, if sensor 5 is your rightmost sensor and you end up
* completely off the line to the left, this function will continue to return
* 5000.
*
* By default, this function assumes a dark line (high values) on a light
* background (low values). If your line is light on dark, set the optional
* second argument \a whiteLine to true. In this case, each sensor value will be
* replaced by the maximum possible value minus its actual value before the
* averaging.
*
* The ZumoReflectanceSensorArray class inherits this function from the
* QTRSensors class.
*/
// documentation for inherited member variables
/*!
* \property unsigned int * QTRSensors::calibratedMinimumOn
* \brief The calibrated minimum values measured for each sensor, with emitters
* on.
*
* This pointer is unallocated and set to 0 until `calibrate()` is called, and
* then allocated to exactly the size required. Depending on the \a readMode
* argument to `calibrate()`, only the On or Off values might be allocated, as
* required. This variable is made public so that you can use the calibration
* values for your own calculations and do things like saving them to EEPROM,
* performing sanity checking, etc.
*
* The ZumoReflectanceSensorArray class inherits this variable from the
* QTRSensors class.
*
* \property unsigned int * QTRSensors::calibratedMaximumOn
* \brief The calibrated maximum values measured for each sensor, with emitters
* on.
* \copydetails QTRSensors::calibratedMinimumOn
*
* \property unsigned int * QTRSensors::calibratedMinimumOff
* \brief The calibrated minimum values measured for each sensor, with emitters
* off.
* \copydetails QTRSensors::calibratedMinimumOn
*
* \property unsigned int * QTRSensors::calibratedMaximumOff
* \brief The calibrated maximum values measured for each sensor, with emitters
* off.
* \copydetails QTRSensors::calibratedMinimumOn
*/
#endif