【问题标题】:Arduino + OV7670 - Without FIFO - Reading SnapshotArduino + OV7670 - 没有 FIFO - 读取快照
【发布时间】:2020-09-25 21:21:18
【问题描述】:

我知道互联网上有很多关于 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;
}

为了检查是否正在从相机读取某些内容,我只是将其打印到串行 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) 上。

【问题讨论】:

    标签: camera arduino clock


    【解决方案1】:

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

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

    【讨论】:

      【解决方案2】:

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

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

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

      编辑:第 3 方已将上述链接中的部分但不是全部代码复制到此处的答案中。但是,该链接必须保留,因为下面发布的代码需要该来源的其他文件才能实际工作。 编辑 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 上找到它。

      【讨论】:

      • @XaverKapeller - 请在编辑时更加小心。您只用其中一个文件的内容替换了指向工作存储库的链接。
      • @ChrisStratton 我没有删除链接,我只是将它移到了底部。他只链接到一个文件,所以我把它的内容复制到这里。
      • 我承认我只是从我的存储库中发布一个链接有点懒惰。您需要的所有代码都在 capImg() 中。您将需要为您的应用程序修改它。重要的是我使用 cli() 禁用中断,而不是使用 digitalRead 来获取数据,而是使用端口映射。
      【解决方案3】:

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

      【讨论】:

      • 我一直在解决这个问题,并在多个地方看到了指向您博客的链接。你真的应该把它翻译成英文。我唯一能理解的就是代码,但即便如此我也有很多关于...的问题
      • instructables上有翻译版本。
      猜你喜欢
      • 2023-03-23
      • 2022-11-01
      • 1970-01-01
      • 1970-01-01
      • 2014-01-03
      • 2011-02-14
      • 1970-01-01
      • 1970-01-01
      • 2013-07-01
      相关资源
      最近更新 更多