Arduino + OV7670 - 无FIFO - 读取快照

时间:2014-01-19 18:22:26

标签: camera arduino clock

我知道有很多关于OV7670的互联网(例如http://forum.arduino.cc/index.php?topic=159557.0),我读了很多关于它的内容,但似乎缺少了一些东西。

首先,我研究了如何从相机逐像素读取以构建矩形600 X 480图像的方式,考虑到文档中描述的HREF,VSYNCH和PCLOCK,这很容易理解: http://www.voti.nl/docs/OV7670.pdf。我理解XCLOCK是一个输入,我需要将OV7670作为一种循环控制器给出,RESET可以重置它。

所以在这一点上,我认为通过连接以下引脚可以覆盖这种相机的功能:

  • D0..D7 - 用于连接arduino数字引脚0到7的数据(像素)作为arduino板上的INPUT
  • XCLK - 用于连接到arduino数字引脚8的相机时钟作为来自arduino板的OUTPUT
  • PCLK - 用于连接到arduino数字引脚9的像素时钟作为arduino板上的INPUT
  • HREF - 定义线路何时开始/结束连接到arduino数字引脚10作为arduino板上的INPUT
  • VSYCH - 定义帧何时开始/结束连接到arduino数字引脚11作为arduino板上的INPUT
  • GRD - 与arduino GRD相关的地址
  • 3V3 - 3,3 INPUT连接到arduino 3,3v
  • RESET - 连接到arduino RESET
  • PWDN - 连接到arduino GRD

从我的观点来看,这种方法的实现将是这样的: 代码:

for each loop function do
   write high to XCLK

   if VSYNCH is HIGH 
      return;

   if HREF is LOW 
      return;

   if lastPCLOCK was HIGH and currentPCLOCK is LOW 
      readPixelFromDataPins();

end for

我的readPixelFromDataPins()基本上只读取了第一个字节(因为我只是在测试我是否能从相机中读取内容),其编写如下:

代码:

byte readPixelFromDataPins() {
  byte result = 0;
  for (int i = 0; i < 8; i++) {
    result = result << 1 | digitalRead(data_p[i]);
  }
  return result;
}

为了检查是否正在从相机读取某些东西,我只需将其打印到Serial 9600,从数据引脚读取的字节为数字。但目前我只收到零值。我用来检索图片的代码存储在此处:https://gist.github.com/franciscospaeth/8503747

让OV7670与Arduino合作的人是否已经弄清楚我做错了什么?我想我错误地使用了XCLOCK吗?我该怎么办才能让它发挥作用?

我搜索了很多,而且我没有使用arduino为这台相机找到任何SSCCE(http://sscce.org/),如果有人有,请告诉我。


此问题也存在于arduino论坛(http://forum.arduino.cc/index.php?topic=211741.0)上。

3 个答案:

答案 0 :(得分:5)

你的想法不错但是...... xclock需要是一个时钟(在你的程序中只是从0到1的转换,并在那里冻结) 你还需要使用带有SIOC和SIOD的I2C来配置摄像头(或者你可以使用默认设置,但我不确定你的输出格式是否正确,30F / s,VGA,YUV格式....)

使用读取数据的同一循环中的串行输出,您的代码执行速度会变慢 我建议你切换xclock引脚并在if()中移动像素打印。此外,您只能在非常精确的时间内读取数据,如果您只想读取一个字节,那么在从0到1的HREF转换之后,您需要等待从PCLK的0到1的新转换(您在PCLK的784x2转换之后,将只能看到HREF的一个0-1转换(640个有效像素+每个线144个死区时间)x 2(对于YUV或RGB,每个像素接收2个字节))

答案 1 :(得分:2)

你好,我是来自arduino论坛的Mr_Arduino。你的问题是你读的像素太慢请不要使用数字读取来做这样的事情。此外,如果您坚持使用单独的函数只是为了读取一个字节,请确保该函数是内联的。您可以通过将函数声明为静态内联来完成此操作。另外如上所述,你如何生成时钟。您可以在arduino上使用PWM生成XCLK。

我在这里创建了一个工作示例:

https://github.com/ComputerNerd/arduino-camera-tft/blob/master/captureimage.c

编辑:第三方已将上述链接中的部分但不是全部代码复制到此处的答案中。但是,链接必须保留,因为下面发布的代码需要来自该源的其他文件才能实际工作。 编辑2:删除了不相关的代码。您需要修改对数据执行的操作。

void capImg(void){
    cli();
    uint8_t w,ww;
    uint8_t h;
    w=160;
    h=240;
    tft_setXY(0,0);
    CS_LOW;
    RS_HIGH;
    RD_HIGH;
    DDRA=0xFF;
    //DDRC=0;
    #ifdef MT9D111
        while (PINE&32){}//wait for low
        while (!(PINE&32)){}//wait for high
    #else
        while (!(PINE&32)){}//wait for high
        while (PINE&32){}//wait for low
    #endif
    while (h--){
        ww=w;
        while (ww--){
            WR_LOW;
            while (PINE&16){}//wait for low
            PORTA=PINC;
            WR_HIGH;
            while (!(PINE&16)){}//wait for high
            WR_LOW;
            while (PINE&16){}//wait for low
            PORTA=PINC;
            WR_HIGH;
            while (!(PINE&16)){}//wait for high
            WR_LOW;
            while (PINE&16){}//wait for low
            PORTA=PINC;
            WR_HIGH;
            while (!(PINE&16)){}//wait for high
            WR_LOW;
            while (PINE&16){}//wait for low
            PORTA=PINC;
            WR_HIGH;
            while (!(PINE&16)){}//wait for high
        }

    }
    CS_HIGH;
    sei();
}

您也可以在github上找到它。

答案 2 :(得分:-1)

您可以使用我的说明:how to retrieve image from ov7670它包含您需要的所有步骤。还有设置FrameGrabber的设置:how to run framegrabber