Moved to Team 9.
Fork of LineScan by
LineScan.cpp
- Committer:
- dnleek
- Date:
- 2015-04-18
- Revision:
- 23:a1a671d3c9e5
- Parent:
- 22:0136520fe249
File content as of revision 23:a1a671d3c9e5:
/* AnalogIn cam1(CAM1_IN); DigitalOut camSi(CAM_SI); DigitalOut camClk(CAM_CLK); // Definining camera pins. These are actually defined in Main... */ #include "LineScan.h" #define THRESH 5000 #define MEAN_REF 20000 //ideal mean we should see #define BRIGHTEST_REF 50000 #define CAM_CTRL_GAIN 0.0003 //should be small uint16_t read1Bit(AnalogIn cam, DigitalOut *camClk){ uint16_t pixel; //read pixel n pixel = cam.read_u16(); //clock pulse for next pixel n + 1 *camClk = 1; *camClk = 0; // Apparently there is no need for any delay. It may be desireable to flatten this, or perhaps the compiler does it. return pixel; //return result as an uint16_t (16 bit integer) } void startRead(DigitalOut *camSi, DigitalOut *camClk){ //pulse first clock cycle and start integral pin *camSi = 1; *camClk = 1; *camSi = 0; *camClk = 0; } float processFn(uint16_t *array, int arraySz, int* exposure){ const static int frameLen = NUM_PIX - 2 * SKIP; int avg[frameLen]; int diff[frameLen]; int highest = 0; int lowest = 0; int total = 0; int h_idx = frameLen/2; int l_idx = frameLen/2; int left_bound = SKIP; int right_bound = NUM_PIX - SKIP; uint16_t brightest = 0; //for AGC float exposureChange; //Just finds line center, does not track crossings (needs this feature) if(array){ avg[0] = array[SKIP - 1]/2 + array[SKIP]/2; diff[0] = 0; brightest = avg[0]; total += avg[0]; //AGC for(int i = 1; i < frameLen; i++){ avg[i] = array[i - 1 + SKIP]/2 + array[i + SKIP]/2; //smoothing diff[i] = avg[i - 1] - avg[i]; //differential //total = avg[i]; //AGC if (avg[i] > brightest) { brightest = avg[i]; } if(diff[i] > highest){ highest = diff[i]; h_idx = i; } else if(diff[i] < lowest){ lowest = diff[i]; l_idx = i; } } //AGC, simple proportional controller //total = total / frameLen; exposureChange = ((float)(BRIGHTEST_REF - brightest)) * CAM_CTRL_GAIN; *exposure += (int)exposureChange; if(*exposure < 1) *exposure = 1; else if(*exposure > 30) *exposure = 30; } //valid if white line on black and not blinded if (highest > THRESH && -1 * lowest > THRESH) return ((float) h_idx + (float) l_idx) / (2*(float)frameLen); else if(highest > THRESH && -1 * lowest < THRESH ) return ((float) h_idx + (float)left_bound - 1.5*(float)(right_bound - h_idx)) / (2*(float)frameLen); //0.5 is center else if (-1*lowest > THRESH && highest < THRESH ) return ((float) l_idx + (float)right_bound + 1.5*(float)(l_idx - left_bound)) / (2*(float)frameLen); else return -1.0; //invalid read } //call after integration time is done, returns index of array line is expected to be at and new exposure time float getLinePos(AnalogIn cam, DigitalOut *camSi, DigitalOut *camClk, int *exposure, telemetry::NumericArray<uint16_t, 128> &tele_linescan){ uint16_t lineAry[NUM_PIX]; float position; //read startRead(camSi, camClk); for(int i = 0; i < NUM_PIX; i++){ lineAry[i] = read1Bit(cam, camClk); tele_linescan[i] = lineAry[i]; } //process line scan data position = processFn(lineAry, NUM_PIX, exposure); return position; } /* sample call (handler thread): while(1){ linePos = getLinePos(cameraIn1, si, clk, &exposureTime); //volatile linePos, replace with steering angle and read 2 cameras? Thread::wait(exposureTime); //sleep for 14 us } */