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 haofan Zheng

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