SmartWheels self-driving race car. Designed for NXP Cup. Uses FRDM-KL25Z, area-scan camera, and simple image processing to detect and navigate any NXP spec track.
Dependencies: TSI USBDevice mbed-dev
Fork of SmartWheels by
Diff: Hardwares/ArduCAM.cpp
- Revision:
- 44:15de535c4005
- Parent:
- 43:0d1886f4848a
- Child:
- 46:a5eb9bd3bb55
--- a/Hardwares/ArduCAM.cpp Mon Mar 27 22:09:22 2017 +0000 +++ b/Hardwares/ArduCAM.cpp Wed Mar 29 21:19:27 2017 +0000 @@ -10,10 +10,23 @@ #include <string> +#define CAM_ROI_UPPER_LIMIT 15 +#define CAM_BLK_CAL_LEFT 75 +#define CAM_BLK_CAL_RIGHT 85 + + extern SPI g_spi_port; DigitalOut cam_cs(PIN_ACC_CS, 1); +uint8_t temp_mid_pos = RESOLUTION_WIDTH / 2; +uint8_t black_calibrate = 70; +volatile uint8_t centerLine[CAM_ROI_UPPER_LIMIT]; +//volatile const uint8_t* outCenterLine = centerLine; +Thread * m_imgProcessThread = NULL; + +void image_processing(); +void cal_black_calibrate(); inline void ardu_cam_spi_write_8(int address, int value) { @@ -70,7 +83,7 @@ camReg->WriteRegSet(ResetProg); wait_ms(5); camReg->WriteRegSet(QVGA); - wait_ms(100); + wait_ms(10); #if defined(ARDUCAM_OV2640) camReg->SCCBWrite(0xff, 0x01); @@ -108,9 +121,9 @@ //ardu_cam_set_mode(MCU2LCD_MODE); ardu_cam_spi_write_8(ARDUCHIP_CAP_CTRL, 0x00); - ardu_cam_start_capture(); + //ardu_cam_start_capture(); - wait(0.1); + //wait(0.1); //unsigned char tempV = ardu_cam_read_reg(ARDUCHIP_MODE); @@ -120,6 +133,8 @@ //tempV = ardu_cam_read_reg(ARDUCHIP_CAP_CTRL); //sprintf(buf, "Ardu FS1 %#x", tempV); //g_core.GetUSBServer().PushReliableMsg('D', buf); + cal_black_calibrate(); + m_imgProcessThread = new Thread(callback(image_processing)); return true; } @@ -229,22 +244,115 @@ } +uint8_t ardu_cam_is_capture_finished() +{ + return (ardu_cam_spi_read_8(ARDUCHIP_TRIG) & CAP_DONE_MASK); +} + +void cal_black_calibrate() +{ + ardu_cam_start_capture(); + + while (!(ardu_cam_spi_read_8(ARDUCHIP_TRIG) & CAP_DONE_MASK)); + + float temp = 0.0f; + static uint16_t pixel = 0x00; + for (uint8_t j = 0; j < RESOLUTION_WIDTH; ++j) + { + pixel = static_cast<uint16_t>(ardu_cam_spi_read_8(SINGLE_FIFO_READ)) << 8; + pixel = pixel | ardu_cam_spi_read_8(SINGLE_FIFO_READ); + + if(CAM_BLK_CAL_LEFT < j && j <= CAM_BLK_CAL_RIGHT) + { + temp += static_cast<uint8_t>((pixel >> 3) & 0x00FF); + } + } + temp = temp / (CAM_BLK_CAL_RIGHT - CAM_BLK_CAL_LEFT); + black_calibrate = temp * 0.7f; +} + +inline void get_img_row_info(const uint8_t display, const uint8_t rowI, uint8_t * left, uint8_t * right) +{ + *left = 0; + *right = RESOLUTION_WIDTH; + uint8_t isRightFound = 0; +/* +#ifdef IMAGE_DISPLAY_TO_SCREEN + if(display) + { + ardu_utft_set_camimg_row(CAM_ROI_UPPER_LIMIT - rowI); + } +#endif +*/ + static uint16_t pixel = 0x0000; + static uint8_t pGreen = 0x00; + + for (uint8_t j = 0; j < RESOLUTION_WIDTH; ++j) + { + pixel = static_cast<uint16_t>(ardu_cam_spi_read_8(SINGLE_FIFO_READ)) << 8; + pixel = pixel | ardu_cam_spi_read_8(SINGLE_FIFO_READ); + + pGreen = static_cast<uint8_t>((pixel >> 3) & 0x00FF); + if((pGreen < black_calibrate)) + { + if(j < temp_mid_pos) + { + *left = j; + } + else if(!isRightFound) + { + *right = j; + isRightFound = 1; + } + } + } +} + +volatile const uint8_t* ardu_cam_get_center_array() +{ + return centerLine; +} + +void image_processing() +{ + while(true) + { + ardu_cam_start_capture(); + + while (!(ardu_cam_spi_read_8(ARDUCHIP_TRIG) & CAP_DONE_MASK)); + + temp_mid_pos = RESOLUTION_WIDTH / 2; + //cal_black_calibrate(); + uint8_t leftPos = 0; + uint8_t rightPos = 0; + for (uint8_t i = 0; i < CAM_ROI_UPPER_LIMIT; ++i) + { + get_img_row_info(0, i, &leftPos, &rightPos); + temp_mid_pos = (leftPos + rightPos) / 2; +/* +#ifdef DEBUG_DISPLAY_TO_SCREEN + ardu_utft_set_camimg_rowcol(CAM_ROI_UPPER_LIMIT - i, temp_mid_pos); + ardu_utft_write_DATA(0xF8, 0x00); +#endif +*/ + centerLine[CAM_ROI_UPPER_LIMIT - i - 1] = temp_mid_pos; + } + } +} +/* void ardu_cam_display_img_utft() { ardu_cam_start_capture(); - wait(0.2); - while(ardu_cam_get_fifo_length() < (RESOLUTION_WIDTH * RESOLUTION_HEIGHT * 2)) - { - } - for (uint8_t i = 0; i < RESOLUTION_HEIGHT; ++i) + + while (!(ardu_cam_spi_read_8(ARDUCHIP_TRIG) & CAP_DONE_MASK)); + + temp_mid_pos = RESOLUTION_WIDTH / 2; + cal_black_calibrate(); + uint8_t leftPos = 0; + uint8_t rightPos = 0; + for (uint8_t i = 0; i < CAM_ROI_UPPER_LIMIT; ++i) { - ardu_utft_set_xy(0, i + 20, 300, i + 20); - for (int j = 0; j < RESOLUTION_WIDTH; ++j) - { - uint8_t VH = ardu_cam_spi_read_8(SINGLE_FIFO_READ); - uint8_t VL = ardu_cam_spi_read_8(SINGLE_FIFO_READ); - - ardu_utft_write_DATA(VH, VL); - } + } -} \ No newline at end of file +} +*/ \ No newline at end of file