TI RSLK Library 0.2.2
Loading...
Searching...
No Matches
QTRSensors.cpp
1#include "QTRSensors.h"
2#include <Arduino.h>
3
5{
6 _type = QTRType::RC;
7 _maxValue = _timeout;
8}
9
10void QTRSensors::setTypeAnalog(uint16_t maxVal)
11{
12 _type = QTRType::Analog;
13 _maxValue = maxVal;
14}
15
16void QTRSensors::setSensorPins(const uint8_t *pins, uint8_t sensorCount)
17{
18 if (sensorCount > QTRMaxSensors) {
19 sensorCount = QTRMaxSensors;
20 }
21
22 // (Re)allocate and initialize the array if necessary.
23 uint8_t *oldSensorPins = _sensorPins;
24 _sensorPins = (uint8_t *)realloc(_sensorPins, sizeof(uint8_t) * sensorCount);
25 if (_sensorPins == nullptr) {
26 // Memory allocation failed; don't continue.
27 free(oldSensorPins); // deallocate any memory used by old array
28 return;
29 }
30
31 for (uint8_t i = 0; i < sensorCount; i++) {
32 _sensorPins[i] = pins[i];
33 }
34
35 _sensorCount = sensorCount;
36
37 // Any previous calibration values are no longer valid, and the calibration
38 // arrays might need to be reallocated if the sensor count was changed.
41}
42
43void QTRSensors::setTimeout(uint16_t timeout)
44{
45 if (timeout > 32767) {
46 timeout = 32767;
47 }
48 _timeout = timeout;
49 if (_type == QTRType::RC) {
50 _maxValue = timeout;
51 }
52}
53
55{
56 if (samples > 64) {
57 samples = 64;
58 }
59 _samplesPerSensor = samples;
60}
61
62void QTRSensors::setEmitterPin(uint8_t emitterPin)
63{
65
66 _oddEmitterPin = emitterPin;
67 pinMode(_oddEmitterPin, OUTPUT);
68
69 _emitterPinCount = 1;
70}
71
72void QTRSensors::setEmitterPins(uint8_t oddEmitterPin, uint8_t evenEmitterPin)
73{
75
76 _oddEmitterPin = oddEmitterPin;
77 _evenEmitterPin = evenEmitterPin;
78 pinMode(_oddEmitterPin, OUTPUT);
79 pinMode(_evenEmitterPin, OUTPUT);
80
81 _emitterPinCount = 2;
82}
83
85{
86 if (_oddEmitterPin != QTRNoEmitterPin) {
87 pinMode(_oddEmitterPin, INPUT);
88 _oddEmitterPin = QTRNoEmitterPin;
89 }
90
91 if (_evenEmitterPin != QTRNoEmitterPin) {
92 pinMode(_evenEmitterPin, INPUT);
93 _evenEmitterPin = QTRNoEmitterPin;
94 }
95
96 _emitterPinCount = 0;
97}
98
99void QTRSensors::setDimmingLevel(uint8_t dimmingLevel)
100{
101 if (dimmingLevel > 31) {
102 dimmingLevel = 31;
103 }
104 _dimmingLevel = dimmingLevel;
105}
106
107// emitters defaults to QTREmitters::All; wait defaults to true
108void QTRSensors::emittersOff(QTREmitters emitters, bool wait)
109{
110 bool pinChanged = false;
111
112 // Use odd emitter pin in these cases:
113 // - 1 emitter pin, emitters = all
114 // - 2 emitter pins, emitters = all
115 // - 2 emitter pins, emitters = odd
116 if (emitters == QTREmitters::All ||
117 (_emitterPinCount == 2 && emitters == QTREmitters::Odd)) {
118 // Check if pin is defined and only turn off if not already off
119 if ((_oddEmitterPin != QTRNoEmitterPin) &&
120 (digitalRead(_oddEmitterPin) == HIGH)) {
121 digitalWrite(_oddEmitterPin, LOW);
122 pinChanged = true;
123 }
124 }
125
126 // Use even emitter pin in these cases:
127 // - 2 emitter pins, emitters = all
128 // - 2 emitter pins, emitters = even
129 if (_emitterPinCount == 2 &&
130 (emitters == QTREmitters::All || emitters == QTREmitters::Even)) {
131 // Check if pin is defined and only turn off if not already off
132 if ((_evenEmitterPin != QTRNoEmitterPin) &&
133 (digitalRead(_evenEmitterPin) == HIGH)) {
134 digitalWrite(_evenEmitterPin, LOW);
135 pinChanged = true;
136 }
137 }
138
139 if (wait && pinChanged) {
140 if (_dimmable) {
141 // driver min is 1 ms
142 delayMicroseconds(1200);
143 } else {
144 delayMicroseconds(200);
145 }
146 }
147}
148
149void QTRSensors::emittersOn(QTREmitters emitters, bool wait)
150{
151 bool pinChanged = false;
152 uint16_t emittersOnStart;
153
154 // Use odd emitter pin in these cases:
155 // - 1 emitter pin, emitters = all
156 // - 2 emitter pins, emitters = all
157 // - 2 emitter pins, emitters = odd
158 if (emitters == QTREmitters::All ||
159 (_emitterPinCount == 2 && emitters == QTREmitters::Odd)) {
160 // Check if pin is defined, and only turn on non-dimmable sensors if not
161 // already on, but always turn dimmable sensors off and back on because
162 // we might be changing the dimming level (emittersOnWithPin() should take
163 // care of this)
164 if ((_oddEmitterPin != QTRNoEmitterPin) &&
165 (_dimmable || (digitalRead(_oddEmitterPin) == LOW))) {
166 emittersOnStart = emittersOnWithPin(_oddEmitterPin);
167 pinChanged = true;
168 }
169 }
170
171 // Use even emitter pin in these cases:
172 // - 2 emitter pins, emitters = all
173 // - 2 emitter pins, emitters = even
174 if (_emitterPinCount == 2 &&
175 (emitters == QTREmitters::All || emitters == QTREmitters::Even)) {
176 // Check if pin is defined, and only turn on non-dimmable sensors if not
177 // already on, but always turn dimmable sensors off and back on because
178 // we might be changing the dimming level (emittersOnWithPin() should take
179 // care of this)
180 if ((_evenEmitterPin != QTRNoEmitterPin) &&
181 (_dimmable || (digitalRead(_evenEmitterPin) == LOW))) {
182 emittersOnStart = emittersOnWithPin(_evenEmitterPin);
183 pinChanged = true;
184 }
185 }
186
187 if (wait && pinChanged) {
188 if (_dimmable) {
189 // Make sure it's been at least 300 us since the emitter pin was first set
190 // high before returning. (Driver min is 250 us.) Some time might have
191 // already passed while we set the dimming level.
192 while ((uint16_t)(micros() - emittersOnStart) < 300) {
193 delayMicroseconds(10);
194 }
195 } else {
196 delayMicroseconds(200);
197 }
198 }
199}
200
201// assumes pin is valid (not QTRNoEmitterPin)
202// returns time when pin was first set high (used by emittersSelect())
203uint16_t QTRSensors::emittersOnWithPin(uint8_t pin)
204{
205 if (_dimmable && (digitalRead(pin) == HIGH)) {
206 // We are turning on dimmable emitters that are already on. To avoid messing
207 // up the dimming level, we have to turn the emitters off and back on. This
208 // means the turn-off delay will happen even if wait = false was passed to
209 // emittersOn(). (Driver min is 1 ms.)
210 digitalWrite(pin, LOW);
211 delayMicroseconds(1200);
212 }
213
214 digitalWrite(pin, HIGH);
215 uint16_t emittersOnStart = micros();
216
217 if (_dimmable && (_dimmingLevel > 0)) {
218 noInterrupts();
219
220 for (uint8_t i = 0; i < _dimmingLevel; i++) {
221 delayMicroseconds(1);
222 digitalWrite(pin, LOW);
223 delayMicroseconds(1);
224 digitalWrite(pin, HIGH);
225 }
226
227 interrupts();
228 }
229
230 return emittersOnStart;
231}
232
234{
235 QTREmitters offEmitters;
236
237 switch (emitters) {
238 case QTREmitters::Odd:
239 offEmitters = QTREmitters::Even;
240 break;
241
242 case QTREmitters::Even:
243 offEmitters = QTREmitters::Odd;
244 break;
245
246 case QTREmitters::All:
247 emittersOn();
248 return;
249
250 case QTREmitters::None:
251 emittersOff();
252 return;
253
254 default: // invalid
255 return;
256 }
257
258 // Turn off the off-emitters; don't wait before proceeding, but record the time.
259 emittersOff(offEmitters, false);
260 uint16_t turnOffStart = micros();
261
262 // Turn on the on-emitters and wait.
263 emittersOn(emitters);
264
265 if (_dimmable) {
266 // Finish waiting for the off-emitters emitters to turn off: make sure it's been
267 // at least 1200 us since the off-emitters was turned off before returning.
268 // (Driver min is 1 ms.) Some time has already passed while we waited for
269 // the on-emitters to turn on.
270 while ((uint16_t)(micros() - turnOffStart) < 1200) {
271 delayMicroseconds(10);
272 }
273 }
274}
275
277{
278 for (uint8_t i = 0; i < _sensorCount; i++) {
280 calibrationOn.maximum[i] = 0;
281 }
283 calibrationOff.maximum[i] = 0;
284 }
286 calibrationOn.minimum[i] = _maxValue;
287 }
289 calibrationOff.minimum[i] = _maxValue;
290 }
291 }
292}
293
295{
296 // manual emitter control is not supported
297 if (mode == QTRReadMode::Manual) {
298 return;
299 }
300
301 if (mode == QTRReadMode::On ||
302 mode == QTRReadMode::OnAndOff) {
303 calibrateOnOrOff(calibrationOn, QTRReadMode::On);
304 } else if (mode == QTRReadMode::OddEven ||
306 calibrateOnOrOff(calibrationOn, QTRReadMode::OddEven);
307 }
308
309 if (mode == QTRReadMode::OnAndOff ||
311 mode == QTRReadMode::Off) {
312 calibrateOnOrOff(calibrationOff, QTRReadMode::Off);
313 }
314}
315
316void QTRSensors::calibrateOnOrOff(CalibrationData &calibration, QTRReadMode mode)
317{
318 uint16_t sensorValues[QTRMaxSensors];
319 uint16_t maxSensorValues[QTRMaxSensors];
320 uint16_t minSensorValues[QTRMaxSensors];
321
322 // (Re)allocate and initialize the arrays if necessary.
323 if (!calibration.initialized) {
324 uint16_t *oldMaximum = calibration.maximum;
325 calibration.maximum = (uint16_t *)realloc(calibration.maximum,
326 sizeof(uint16_t) * _sensorCount);
327 if (calibration.maximum == nullptr) {
328 // Memory allocation failed; don't continue.
329 free(oldMaximum); // deallocate any memory used by old array
330 return;
331 }
332
333 uint16_t *oldMinimum = calibration.minimum;
334 calibration.minimum = (uint16_t *)realloc(calibration.minimum,
335 sizeof(uint16_t) * _sensorCount);
336 if (calibration.minimum == nullptr) {
337 // Memory allocation failed; don't continue.
338 free(oldMinimum); // deallocate any memory used by old array
339 return;
340 }
341
342 // Initialize the max and min calibrated values to values that
343 // will cause the first reading to update them.
344 for (uint8_t i = 0; i < _sensorCount; i++) {
345 calibration.maximum[i] = 0;
346 calibration.minimum[i] = _maxValue;
347 }
348
349 calibration.initialized = true;
350 }
351
352 for (uint8_t j = 0; j < 10; j++) {
353 read(sensorValues, mode);
354
355 for (uint8_t i = 0; i < _sensorCount; i++) {
356 // set the max we found THIS time
357 if ((j == 0) || (sensorValues[i] > maxSensorValues[i])) {
358 maxSensorValues[i] = sensorValues[i];
359 }
360
361 // set the min we found THIS time
362 if ((j == 0) || (sensorValues[i] < minSensorValues[i])) {
363 minSensorValues[i] = sensorValues[i];
364 }
365 }
366 }
367
368 // record the min and max calibration values
369 for (uint8_t i = 0; i < _sensorCount; i++) {
370 // Update maximum only if the min of 10 readings was still higher than it
371 // (we got 10 readings in a row higher than the existing maximum).
372 if (minSensorValues[i] > calibration.maximum[i]) {
373 calibration.maximum[i] = minSensorValues[i];
374 }
375
376 // Update minimum only if the max of 10 readings was still lower than it
377 // (we got 10 readings in a row lower than the existing minimum).
378 if (maxSensorValues[i] < calibration.minimum[i]) {
379 calibration.minimum[i] = maxSensorValues[i];
380 }
381 }
382}
383
384void QTRSensors::read(uint16_t *sensorValues, QTRReadMode mode)
385{
386 switch (mode) {
387 case QTRReadMode::Off:
388 emittersOff();
389 // fall through
391 readPrivate(sensorValues);
392 return;
393
394 case QTRReadMode::On:
396 emittersOn();
397 readPrivate(sensorValues);
398 emittersOff();
399 break;
400
403 // Turn on odd emitters and read the odd-numbered sensors.
404 // (readPrivate takes a 0-based array index, so start = 0 to start with
405 // the first sensor)
406 emittersSelect(QTREmitters::Odd);
407 readPrivate(sensorValues, 0, 2);
408
409 // Turn on even emitters and read the even-numbered sensors.
410 // (readPrivate takes a 0-based array index, so start = 1 to start with
411 // the second sensor)
412 emittersSelect(QTREmitters::Even);
413 readPrivate(sensorValues, 1, 2);
414
415 emittersOff();
416 break;
417
418 default: // invalid - do nothing
419 return;
420 }
421
422 if (mode == QTRReadMode::OnAndOff ||
424 // Take a second set of readings and return the values (on + max - off).
425
426 uint16_t offValues[QTRMaxSensors];
427 readPrivate(offValues);
428
429 for (uint8_t i = 0; i < _sensorCount; i++) {
430 sensorValues[i] += _maxValue - offValues[i];
431 if (sensorValues[i] > _maxValue) {
432 // This usually doesn't happen, because the sensor reading should
433 // go up when the emitters are turned off.
434 sensorValues[i] = _maxValue;
435 }
436 }
437 }
438}
439
440void QTRSensors::readCalibrated(uint16_t *sensorValues, QTRReadMode mode)
441{
442 // manual emitter control is not supported
443 if (mode == QTRReadMode::Manual) {
444 return;
445 }
446
447 // if not calibrated, do nothing
448
449 if (mode == QTRReadMode::On ||
450 mode == QTRReadMode::OnAndOff ||
453 return;
454 }
455 }
456
457 if (mode == QTRReadMode::Off ||
458 mode == QTRReadMode::OnAndOff ||
461 return;
462 }
463 }
464
465 // read the needed values
466 read(sensorValues, mode);
467
468 for (uint8_t i = 0; i < _sensorCount; i++) {
469 uint16_t calmin, calmax;
470
471 // find the correct calibration
472 if (mode == QTRReadMode::On ||
473 mode == QTRReadMode::OddEven) {
474 calmax = calibrationOn.maximum[i];
475 calmin = calibrationOn.minimum[i];
476 } else if (mode == QTRReadMode::Off) {
477 calmax = calibrationOff.maximum[i];
478 calmin = calibrationOff.minimum[i];
479 } else { // QTRReadMode::OnAndOff, QTRReadMode::OddEvenAndOff
481 // no meaningful signal
482 calmin = _maxValue;
483 } else {
484 // this won't go past _maxValue
485 calmin = calibrationOn.minimum[i] + _maxValue - calibrationOff.minimum[i];
486 }
487
489 // no meaningful signal
490 calmax = _maxValue;
491 } else {
492 // this won't go past _maxValue
493 calmax = calibrationOn.maximum[i] + _maxValue - calibrationOff.maximum[i];
494 }
495 }
496
497 uint16_t denominator = calmax - calmin;
498 int16_t value = 0;
499
500 if (denominator != 0) {
501 value = (((int32_t)sensorValues[i]) - calmin) * 1000 / denominator;
502 }
503
504 if (value < 0) {
505 value = 0;
506 } else if (value > 1000) {
507 value = 1000;
508 }
509
510 sensorValues[i] = value;
511 }
512}
513
514// Reads the first of every [step] sensors, starting with [start] (0-indexed, so
515// start = 0 means start with the first sensor).
516// For example, step = 2, start = 1 means read the *even-numbered* sensors.
517// start defaults to 0, step defaults to 1
518void QTRSensors::readPrivate(uint16_t *sensorValues, uint8_t start, uint8_t step)
519{
520 if (_sensorPins == nullptr) {
521 return;
522 }
523
524 switch (_type) {
525 case QTRType::RC:
526 for (uint8_t i = start; i < _sensorCount; i += step) {
527 sensorValues[i] = _maxValue;
528 // make sensor line an output (drives low briefly, but doesn't matter)
529 pinMode(_sensorPins[i], OUTPUT);
530 // drive sensor line high
531 digitalWrite(_sensorPins[i], HIGH);
532 }
533
534 delayMicroseconds(10); // charge lines for 10 us
535
536 {
537 // disable interrupts so we can switch all the pins as close to the same
538 // time as possible
539 noInterrupts();
540
541 // record start time before the first sensor is switched to input
542 // (similarly, time is checked before the first sensor is read in the
543 // loop below)
544 uint32_t startTime = micros();
545 uint16_t time = 0;
546
547 for (uint8_t i = start; i < _sensorCount; i += step) {
548 // make sensor line an input (should also ensure pull-up is disabled)
549 pinMode(_sensorPins[i], INPUT);
550 }
551
552 interrupts(); // re-enable
553
554 while (time < _maxValue) {
555 // disable interrupts so we can read all the pins as close to the same
556 // time as possible
557 noInterrupts();
558
559 time = micros() - startTime;
560 for (uint8_t i = start; i < _sensorCount; i += step) {
561 if ((digitalRead(_sensorPins[i]) == LOW) && (time < sensorValues[i])) {
562 // record the first time the line reads low
563 sensorValues[i] = time;
564 }
565 }
566
567 interrupts(); // re-enable
568 }
569 }
570 return;
571
572 case QTRType::Analog:
573 // reset the values
574 for (uint8_t i = start; i < _sensorCount; i += step) {
575 sensorValues[i] = 0;
576 }
577
578 for (uint8_t j = 0; j < _samplesPerSensor; j++) {
579 for (uint8_t i = start; i < _sensorCount; i += step) {
580 // add the conversion result
581 sensorValues[i] += analogRead(_sensorPins[i]);
582 }
583 }
584
585 // get the rounded average of the readings for each sensor
586 for (uint8_t i = start; i < _sensorCount; i += step) {
587 sensorValues[i] = (sensorValues[i] + (_samplesPerSensor >> 1)) /
588 _samplesPerSensor;
589 }
590 return;
591
592 default: // QTRType::Undefined or invalid - do nothing
593 return;
594 }
595}
596
597uint16_t QTRSensors::readLinePrivate(uint16_t *sensorValues, QTRReadMode mode,
598 bool invertReadings)
599{
600 bool onLine = false;
601 uint32_t avg = 0; // this is for the weighted total
602 uint16_t sum = 0; // this is for the denominator, which is <= 64000
603
604 // manual emitter control is not supported
605 if (mode == QTRReadMode::Manual) {
606 return 0;
607 }
608
609 readCalibrated(sensorValues, mode);
610
611 for (uint8_t i = 0; i < _sensorCount; i++) {
612 uint16_t value = sensorValues[i];
613 if (invertReadings) {
614 value = 1000 - value;
615 }
616
617 // keep track of whether we see the line at all
618 if (value > 200) {
619 onLine = true;
620 }
621
622 // only average in values that are above a noise threshold
623 if (value > 50) {
624 avg += (uint32_t)value * (i * 1000);
625 sum += value;
626 }
627 }
628
629 if (!onLine) {
630 // If it last read to the left of center, return 0.
631 if (_lastPosition < (_sensorCount - 1) * 1000 / 2) {
632 return 0;
633 }
634 // If it last read to the right of center, return the max.
635 else {
636 return (_sensorCount - 1) * 1000;
637 }
638 }
639
640 _lastPosition = avg / sum;
641 return _lastPosition;
642}
643
644// the destructor frees up allocated memory
645QTRSensors::~QTRSensors()
646{
648
649 if (_sensorPins) {
650 free(_sensorPins);
651 }
654 }
657 }
660 }
663 }
664}
const uint8_t QTRNoEmitterPin
Represents an undefined emitter control pin.
Definition QTRSensors.h:68
QTRReadMode
Emitter behavior when taking readings.
Definition QTRSensors.h:14
QTREmitters
Emitters selected to turn on or off.
Definition QTRSensors.h:60
const uint8_t QTRMaxSensors
The maximum number of sensors supported by an instance of this class.
Definition QTRSensors.h:74
void calibrate(QTRReadMode mode=QTRReadMode::On)
Reads the sensors for calibration.
void setDimmingLevel(uint8_t dimmingLevel)
Sets the dimming level.
void setTypeRC()
Specifies that the sensors are RC.
Definition QTRSensors.cpp:4
void setEmitterPin(uint8_t emitterPin)
Sets the emitter control pin for the sensors.
void setEmitterPins(uint8_t oddEmitterPin, uint8_t evenEmitterPin)
Sets separate odd and even emitter control pins for the sensors.
void setSamplesPerSensor(uint8_t samples)
Sets the number of analog readings to average per analog sensor.
void setTypeAnalog(uint16_t maxVal=1023)
Specifies that the sensor type is analog.
void emittersOn(QTREmitters emitters=QTREmitters::All, bool wait=true)
Turns the IR LEDs on.
void emittersOff(QTREmitters emitters=QTREmitters::All, bool wait=true)
Turns the IR LEDs off.
CalibrationData calibrationOff
Data from calibrating with emitters off.
Definition QTRSensors.h:550
void read(uint16_t *sensorValues, QTRReadMode mode=QTRReadMode::On)
Reads the raw sensor values into an array.
void readCalibrated(uint16_t *sensorValues, QTRReadMode mode=QTRReadMode::On)
Reads the sensors and provides calibrated values between 0 and 1000.
void resetCalibration()
Resets all calibration that has been done.
void setTimeout(uint16_t timeout)
Sets the timeout for RC sensors.
void emittersSelect(QTREmitters emitters)
Turns on the selected emitters and turns off the other emitters with optimized timing.
CalibrationData calibrationOn
Data from calibrating with emitters on.
Definition QTRSensors.h:547
void releaseEmitterPins()
Releases emitter pin/pins that have been set.
void setSensorPins(const uint8_t *pins, uint8_t sensorCount)
Sets the sensor pins.
uint16_t * minimum
Lowest readings seen during calibration.
Definition QTRSensors.h:532
uint16_t * maximum
Highest readings seen during calibration.
Definition QTRSensors.h:534
bool initialized
Whether array pointers have been allocated and initialized.
Definition QTRSensors.h:530