David's dead reckoning code for the LVBots competition on March 6th. Uses the mbed LPC1768, DRV8835, QTR-3RC, and two DC motors with encoders.

Dependencies:   PololuEncoder Pacer mbed GeneralDebouncer

Committer:
DavidEGrayson
Date:
Sat Mar 01 01:46:35 2014 +0000
Revision:
27:2456f68be679
Parent:
24:fc01d9125d3b
Child:
31:739b91331f31
Fixed a major bug in the line following (reduceSpeed return value was not used).  Made finalSettleIn better by adding an integral term and increasing the settleSpeed from 200 to 300.

Who changed what in which revision?

UserRevisionLine numberNew contents of line
DavidEGrayson 21:c279c6a83671 1 #include "line_tracker.h"
DavidEGrayson 21:c279c6a83671 2
DavidEGrayson 21:c279c6a83671 3 static uint16_t readSensor(uint8_t index)
DavidEGrayson 21:c279c6a83671 4 {
DavidEGrayson 21:c279c6a83671 5 return lineSensorsAnalog[index].read_u16();
DavidEGrayson 21:c279c6a83671 6 }
DavidEGrayson 21:c279c6a83671 7
DavidEGrayson 21:c279c6a83671 8 LineTracker::LineTracker()
DavidEGrayson 21:c279c6a83671 9 {
DavidEGrayson 21:c279c6a83671 10 for(uint8_t s = 0; s < LINE_SENSOR_COUNT; s++)
DavidEGrayson 21:c279c6a83671 11 {
DavidEGrayson 21:c279c6a83671 12 calibratedMaximum[s] = 0;
DavidEGrayson 21:c279c6a83671 13 calibratedMinimum[s] = 0xFFFF;
DavidEGrayson 21:c279c6a83671 14 }
DavidEGrayson 22:44c032e59ff5 15 calibrationState = 0;
DavidEGrayson 21:c279c6a83671 16 }
DavidEGrayson 21:c279c6a83671 17
DavidEGrayson 21:c279c6a83671 18 void LineTracker::read()
DavidEGrayson 21:c279c6a83671 19 {
DavidEGrayson 21:c279c6a83671 20 readRawValues();
DavidEGrayson 21:c279c6a83671 21 updateCalibratedValues();
DavidEGrayson 21:c279c6a83671 22 updateLineStatus();
DavidEGrayson 21:c279c6a83671 23 }
DavidEGrayson 21:c279c6a83671 24
DavidEGrayson 21:c279c6a83671 25 void LineTracker::readRawValues()
DavidEGrayson 21:c279c6a83671 26 {
DavidEGrayson 21:c279c6a83671 27 for(uint8_t s = 0; s < LINE_SENSOR_COUNT; s++)
DavidEGrayson 21:c279c6a83671 28 {
DavidEGrayson 21:c279c6a83671 29 rawValues[s] = readSensor(s);
DavidEGrayson 21:c279c6a83671 30 }
DavidEGrayson 21:c279c6a83671 31 }
DavidEGrayson 21:c279c6a83671 32
DavidEGrayson 21:c279c6a83671 33 void LineTracker::updateCalibratedValues()
DavidEGrayson 21:c279c6a83671 34 {
DavidEGrayson 21:c279c6a83671 35 for(uint8_t s = 0; s < LINE_SENSOR_COUNT; s++)
DavidEGrayson 21:c279c6a83671 36 {
DavidEGrayson 21:c279c6a83671 37 uint16_t calmin = calibratedMinimum[s];
DavidEGrayson 21:c279c6a83671 38 uint16_t calmax = calibratedMaximum[s];
DavidEGrayson 21:c279c6a83671 39 uint16_t denominator = calmax - calmin;
DavidEGrayson 22:44c032e59ff5 40 int32_t x = 0;
DavidEGrayson 21:c279c6a83671 41 if(denominator != 0)
DavidEGrayson 21:c279c6a83671 42 {
DavidEGrayson 21:c279c6a83671 43 x = ((int32_t)rawValues[s] - calmin) * 1000 / denominator;
DavidEGrayson 21:c279c6a83671 44 if(x < 0)
DavidEGrayson 21:c279c6a83671 45 {
DavidEGrayson 21:c279c6a83671 46 x = 0;
DavidEGrayson 21:c279c6a83671 47 }
DavidEGrayson 21:c279c6a83671 48 else if(x > 1000)
DavidEGrayson 21:c279c6a83671 49 {
DavidEGrayson 21:c279c6a83671 50 x = 1000;
DavidEGrayson 21:c279c6a83671 51 }
DavidEGrayson 21:c279c6a83671 52 }
DavidEGrayson 21:c279c6a83671 53 calibratedValues[s] = x;
DavidEGrayson 21:c279c6a83671 54 }
DavidEGrayson 21:c279c6a83671 55 }
DavidEGrayson 21:c279c6a83671 56
DavidEGrayson 21:c279c6a83671 57 void LineTracker::updateLineStatus()
DavidEGrayson 21:c279c6a83671 58 {
DavidEGrayson 21:c279c6a83671 59 uint32_t avg = 0;
DavidEGrayson 21:c279c6a83671 60 uint32_t sum = 0;
DavidEGrayson 21:c279c6a83671 61
DavidEGrayson 24:fc01d9125d3b 62 lineVisible = false;
DavidEGrayson 21:c279c6a83671 63 for(uint8_t s = 0; s < LINE_SENSOR_COUNT; s++)
DavidEGrayson 21:c279c6a83671 64 {
DavidEGrayson 21:c279c6a83671 65 // keep track of whether we see the line at all
DavidEGrayson 21:c279c6a83671 66 uint16_t value = calibratedValues[s];
DavidEGrayson 24:fc01d9125d3b 67 if (value > 500)
DavidEGrayson 21:c279c6a83671 68 {
DavidEGrayson 21:c279c6a83671 69 lineVisible = true;
DavidEGrayson 21:c279c6a83671 70 }
DavidEGrayson 21:c279c6a83671 71
DavidEGrayson 21:c279c6a83671 72 // only average in values that are above a noise threshold
DavidEGrayson 21:c279c6a83671 73 if (value > 50)
DavidEGrayson 21:c279c6a83671 74 {
DavidEGrayson 21:c279c6a83671 75 avg += (uint32_t)(value) * s * 1000;
DavidEGrayson 21:c279c6a83671 76 sum += value;
DavidEGrayson 21:c279c6a83671 77 }
DavidEGrayson 21:c279c6a83671 78 }
DavidEGrayson 21:c279c6a83671 79
DavidEGrayson 21:c279c6a83671 80 if (lineVisible)
DavidEGrayson 21:c279c6a83671 81 {
DavidEGrayson 21:c279c6a83671 82 linePosition = avg/sum;
DavidEGrayson 21:c279c6a83671 83 }
DavidEGrayson 21:c279c6a83671 84 else
DavidEGrayson 21:c279c6a83671 85 {
DavidEGrayson 21:c279c6a83671 86 // We cannot see the line, so just snap the position to the left-most or right-most
DavidEGrayson 21:c279c6a83671 87 // depending on what we saw previousl.
DavidEGrayson 21:c279c6a83671 88
DavidEGrayson 21:c279c6a83671 89 const uint32_t max = (LINE_SENSOR_COUNT-1)*1000;
DavidEGrayson 21:c279c6a83671 90 if(linePosition < max/2)
DavidEGrayson 21:c279c6a83671 91 {
DavidEGrayson 21:c279c6a83671 92 linePosition = 0;
DavidEGrayson 21:c279c6a83671 93 }
DavidEGrayson 21:c279c6a83671 94 else
DavidEGrayson 21:c279c6a83671 95 {
DavidEGrayson 21:c279c6a83671 96 linePosition = max;
DavidEGrayson 21:c279c6a83671 97 }
DavidEGrayson 21:c279c6a83671 98 }
DavidEGrayson 21:c279c6a83671 99 }
DavidEGrayson 21:c279c6a83671 100
DavidEGrayson 21:c279c6a83671 101 // The return value of this should only be heeded if the calibration seems to be OK.
DavidEGrayson 21:c279c6a83671 102 bool LineTracker::getLineVisible()
DavidEGrayson 21:c279c6a83671 103 {
DavidEGrayson 21:c279c6a83671 104 return lineVisible;
DavidEGrayson 21:c279c6a83671 105 }
DavidEGrayson 21:c279c6a83671 106
DavidEGrayson 21:c279c6a83671 107 uint16_t LineTracker::getLinePosition()
DavidEGrayson 21:c279c6a83671 108 {
DavidEGrayson 21:c279c6a83671 109 return linePosition;
DavidEGrayson 22:44c032e59ff5 110 }
DavidEGrayson 22:44c032e59ff5 111
DavidEGrayson 22:44c032e59ff5 112 void LineTracker::updateCalibration()
DavidEGrayson 22:44c032e59ff5 113 {
DavidEGrayson 22:44c032e59ff5 114 if(calibrationState == 0)
DavidEGrayson 22:44c032e59ff5 115 {
DavidEGrayson 22:44c032e59ff5 116 for(uint8_t s = 0; s < LINE_SENSOR_COUNT; s++)
DavidEGrayson 22:44c032e59ff5 117 {
DavidEGrayson 22:44c032e59ff5 118 recentValuesMin[s] = 0xFFFF;
DavidEGrayson 22:44c032e59ff5 119 recentValuesMax[s] = 0;
DavidEGrayson 22:44c032e59ff5 120 }
DavidEGrayson 22:44c032e59ff5 121 }
DavidEGrayson 22:44c032e59ff5 122
DavidEGrayson 22:44c032e59ff5 123 for(uint8_t s = 0; s < LINE_SENSOR_COUNT; s++)
DavidEGrayson 22:44c032e59ff5 124 {
DavidEGrayson 22:44c032e59ff5 125 uint16_t value = rawValues[s];
DavidEGrayson 22:44c032e59ff5 126 if (value < recentValuesMin[s]) { recentValuesMin[s] = value; }
DavidEGrayson 22:44c032e59ff5 127 if (value > recentValuesMax[s]) { recentValuesMax[s] = value; }
DavidEGrayson 22:44c032e59ff5 128 }
DavidEGrayson 22:44c032e59ff5 129
DavidEGrayson 22:44c032e59ff5 130 calibrationState = calibrationState + 1;
DavidEGrayson 22:44c032e59ff5 131
DavidEGrayson 22:44c032e59ff5 132 if (calibrationState == 9)
DavidEGrayson 22:44c032e59ff5 133 {
DavidEGrayson 22:44c032e59ff5 134 calibrationState = 0;
DavidEGrayson 22:44c032e59ff5 135
DavidEGrayson 22:44c032e59ff5 136 for(uint8_t s = 0; s < LINE_SENSOR_COUNT; s++)
DavidEGrayson 22:44c032e59ff5 137 {
DavidEGrayson 22:44c032e59ff5 138 if (recentValuesMin[s] > calibratedMaximum[s]) { calibratedMaximum[s] = recentValuesMin[s]; }
DavidEGrayson 22:44c032e59ff5 139 if (recentValuesMax[s] < calibratedMinimum[s]) { calibratedMinimum[s] = recentValuesMax[s]; }
DavidEGrayson 22:44c032e59ff5 140 }
DavidEGrayson 22:44c032e59ff5 141 }
DavidEGrayson 22:44c032e59ff5 142 }