Sep 27, 2014

Arduvision (I): embedded computer vision with arduino

Ok, its time to share stuff again.
I've spent most of this year's (2014) summer learning how to use a CMOS sensor together with an arduino (ATmega328p) microcontroller, in the process of developing some personal projects.
This is the first of a series of articles to publish my experiencies, and hopefully save someone's time.

In this first post, I'll just release the minimal info that may let you start right away experimenting without reading about how things work. In further articles I'll make detailed explanations of the hardware and software, and the decisions and reasons that led me to my current setup. However, at the end of this post, you may find links to useful documentation.

My system is based on Linux, Ubuntu 14.04 x64. You may need to adapt things to your system. You are assumed to have some knowledge of the arduino platform and environment, and also the Processing.org development environment. If so, here is what you need to clone my current setup:




WARNING:

DO NOT USE AN ARDUINO THAT
OUTPUTS 5V ON THE DIGITAL PINS.


HARDWARE NEEDED:

- Arduino compatible development board with ATmega 328p, rated at 3.3 volts. I use a clone of a Sparkfun Arduino Pro Mini at 8MHz and 3.3v. This doesn't have USB, so I use a USB to serial adapter that works at 3.3vThere are other boards that should work too (not tested): Arduino Pro (3.3V version), OLIMEXINO-328Iteaduino UnoSeeeduinoFreaduinoYouduino, Bouno Lite, etc.


- A CMOS module with FIFO and an ov7670 or an ov7725 sensor (I've tried both, and setup the register parameters). At the moment I'm working only through the FIFO, but may try synchronize the microcontroller clock directly with the CMOS sensor, as int the AVRcam project.
For this setup the module must have the following available pins (numbering may differ):

                      GND --- 1     2 --- VCC3.3
                   OV_SCL --- 3     4 --- FIFO_WRST
                   OV_SDA --- 5     6 --- FIFO_RRST
                  FIFO_D0 --- 7     8 --- FIFO_OE
                  FIFO_D2 --- 9    10 --- FIFO_D1
                  FIFO_D4 --- 11   12 --- FIFO_D3
                  FIFO_D6 --- 13   14 --- FIFO_D5
                FIFO_RCLK --- 15   16 --- FIFO_D7
                 FIFO_WEN --- 17   18 --- OV_VSYNC

EDIT: some other modules have these pin numbers/labeling:

                      VCC --- 1     2 --- GND
                    SIO_C --- 3     4 --- SIO_D
                    VSYNC --- 5     6 --- HREF
                  FIFO_D7 --- 7     8 --- FIFO_D4
                  FIFO_D5 --- 9    10 --- FIFO_D2
                  FIFO_D3 --- 11   12 --- FIFO_D0
                  FIFO_D1 --- 13   14 --- FIFO_D6
                    RESET --- 15   16 --- PWDN
                   STROBE --- 17   18 --- FIFO_RCK
                  FIFO_WR --- 19   20 --- FIFO_OE
                FIFO_WRST --- 21   22 --- FIFO_RRST

ov7670-fifo-v3:

                      VCC --- 1     2 --- GND
                    SIO_C --- 3     4 --- SIO_D
                    VSYNC --- 5     6 --- HREF
                      WEN --- 7     8 --- XCLK
                FIFO_RRST --- 9    10 --- FIFO_OE
                  RCLK/WR --- 11   12 --- GND
                  FIFO_D0 --- 13   14 --- FIFO_D1
                  FIFO_D2 --- 15   16 --- FIFO_D3
                  FIFO_D4 --- 17   18 --- FIFO_D5
                  FIFO_D6 --- 19   20 --- FIFO_D7


I've tested an ELH 30w FIFO module and the Alientek OV7670 v2.2 module. Both use a 12MHz clock. Other modules use a 24MHz clock. While this affects only the framerate selection parameters, some newer versions have a different schematic/pinout which need VSYNC signal to be inverted, these will not work with this setup.

- Female to female jumper wires to connect the Arduino board to the CMOS module.


CONNECTIONS:


Connect the boards as follows:

    
                 OV+FIFO        ATMEGA 328P 3.3V/8MHz
                         GND ------ GND
                       3.3V  ------ VCC
                     FIFO_OE ------ GND
            FIFO_WR/FIFO_WEN ------ D8
          FIFO_RCK/FIFO_RCLK ------ D9
                   FIFO_WRST ------ D12
                   FIFO_RRST ------ D13
                SIO_D/OV_SDA ------ A4
                SIO_C/OV_SCL ------ A5
                    OV_VSYNC ------ D2
                     FIFO_D3 ------ D3
                     FIFO_D4 ------ D4
                     FIFO_D5 ------ D5
                     FIFO_D6 ------ D6
                     FIFO_D7 ------ D7
         (some modules) PWDN ------ GND / not connected
        (some modules) RESET ------ VCC / not connected
         (some modules) HREF ------ not connected
       (some modules) STROBE ------ not connected


You may edit the file IO_config.h of the arduino sketch if you want to make some changes, just pay attention on the VSYNC pin, that is tied to INT0 interruption.




SOFTWARE:

You can download from this repo the arduino sketch and the processing code to communicate with the arduino via USB:


The code will either stream a 80x60 pixels image, in different pixel depths, or detect the boundaries of the brightest/darkest blob within a threshold.

Edit: you get too much garbage in the processing console you may need to change the baudrate to match your system capabilities.


In the arduino sketch look for the line:
   static const unsigned long _BAUDRATE = 500000;

And in the processing sketch, in the globalDefinitions.java tab:
   public final static int BAUDRATE = 500000;

Try with substituting the 500000 for 115200.



NOTES ON THE ARDUINO SIDE:
Some people have added pullup resistors to the SDA and SCL lines and disabled the internal pullups. However, as I'm working with a 3.3v version, in this setup things worked straight away without these steps.

NOTES IN THE PROCESSING SIDE:
You will have to change the serial port name to match your system. In the processing code, look for the line:

   serialPort = new Serial(this, "/dev/ttyUSB0", G_DEF.BAUDRATE);

And chage the port name "/dev/ttyUSB0".

This is a video of the demo working with an Alientek ov7670 FIFO module and a Funduino UNO (with the voltage selection switch set at 3.3v !!!):



RESOUCES / LINKS:

I'll try that all the information published here is related only to 100% open hardware and software.

Two inspiring fully open hardware and software embedded computer vision projects:

AVRcam by John Orlando
One of the pioneers pushing the little microcontroller capabilities.

OpenMV by Ibrahim Abdelkader 
Currently in development, it will be an amazing and affordable platform with outstanding capabilities, and the only one in its class completely open.


Useful documentation


Source code related to microcontrollers and CMOS sensors/modules:




Forum discussion threads about microcontrollers and CMOS sensors/modules


115 comments:

  1. Hello ...
    I copied all files and made ​​the connections as pictured ...
    and sent the .ino for Arduino ...
    how do i see if it is working?

    ReplyDelete
    Replies
    1. Hi!

      To see the stream in your computer through the USB port, you have to download the Processing environment for your platform from https://processing.org/download/
      and install it (see: http://www.processing.org/tutorials/gettingstarted/ ).

      Then look for the folder "receive_stream" you got from the repo ( https://github.com/dasaki/arduvision/tree/master/arduvision_01/processing/receive_stream)
      and copy the entire folder inside your Processing sketchbook folder. Open the file receive_stream.pde with processing and run the sketch.
      Once running press the space key to toggle the stream modes.
      Whether you make it work or not, please give feedback! :)

      Regards

      Delete
    2. hello
      I'm not finding what folder should I copy the java files

      I thank

      Delete
    3. The first time you run processing, it creates a folder called "sketchbook" in your computer (the place depends if you use Mac, windows or Linux). Inside the sketchbook folder is where you should copy the folder "receive_stream" and its contents. So you have the files receive_stream.pde, global definitions.java, and simpleKalman.java inside the folder "sketchbook/receive_stream/".

      Please read the processing.org wiki and tutorials to inform yourself and learn how to use it.

      Delete
    4. Could not find the folder ...
      ran opened the screen, but that is so black ...
      squeezed space and went through all modes and nothing

      Delete
    5. What system are you using? Did you read the post?: "You will have to change the serial port name to match your system"

      In the processing code, look for the line:
      serialPort = new Serial(this, "/dev/ttyUSB0", G_DEF.BAUDRATE);

      And chage the port name "/dev/ttyUSB0" to your serial port...

      try:

      serialPort = new Serial(this, Serial.list()[0], G_DEF.BAUDRATE);

      This kind of experiments are not a good way for a noob to start learning. As I mentioned at the beginning of the post:

      "You are assumed to have some knowledge of the arduino platform and environment, and also the Processing.org development environment"

      Delete
    6. Yes, I did all the steps mentioned ...
      arduino communicating this with the processing ..
      so that it appears to envez the imagems this all black

      Delete
    7. Yes, I did all the steps mentioned ...
      arduino communicating this with the processing ..
      so that it appears to envez the imagems this all black

      Delete
    8. Hmmm... What arduino are you using? Did you see in the processing console these messages?:
      "Initializing sensor..."
      "inited OK, sensor PID: "

      Delete
    9. Arduino Nano... Atmega328p... yes the message appeared...
      aparece em cima tambem a contagem de FPS, mas a tela fica preta

      Delete
    10. Arduino Nano, according to the official specifications ( http://arduino.cc/en/Main/arduinoBoardNano ) works at 5v... As said in the post, the sensor can stand a maximum voltage of 3.3v... you may have destroyed the sensor...

      Delete
  2. Yes, pin 3.3v is just the power line, but the logic levels that go to the sensor (SDA, SCL and VSYNC) have to be also 3.3v or lower. A "3.3v arduino" means that the logic levels are 3.3v not 5v.
    You can still try to put resistors as explained here: http://nicolasfley.fast-page.org/wp-content/uploads/2013/09/schema_arduino_FIFO_OV7670.png and see if your sensor is still alive.

    ReplyDelete
  3. Hello
    Have a nice day! :D
    My name is Jim
    I got a school project, i should take pictures with OV7670 camera using my computer and an arduino pro mini.
    When i was connecting the camera on the arduino, i find out that my camera hasnt the following 4 pins: WEN, RCLK, SCL, SDA so cant continue with my project.

    here is the camera:

    http://i01.i.aliimg.com/wsphoto/v1/1881045091/640x480-VGA-CMOS-Camera-Module-OV7670-font-b-FIFO-b-font-Buffer-font-b-AL422B-b.jpg

    Any ideas?

    ReplyDelete
    Replies
    1. Hi Jim,

      I think this is the correspondence:
      SIOC = SCL
      SIOD = SDA
      RCK = RCLK
      WR = WEN
      ( "WE 11 (WR)" found in the code comments here: http://nicolasfley.fast-page.org/?page_id=35)

      Pay attention that some modules change their specifications for the sync pin. See:
      https://thinksmallthings.wordpress.com/2012/03/10/cf7670c-vs-cf7670c-v2/
      and
      https://my.st.com/public/STe2ecommunities/mcu/Lists/cortex_mx_stm32/Flat.aspx?RootFolder=%2Fpublic%2FSTe2ecommunities%2Fmcu%2FLists%2Fcortex_mx_stm32%2FSTM32%20port%20and%20OV7670&FolderCTID=0x01200200770978C69A1141439FE559EB459D7580009C4E14902C3CDE46A77F0FFD06506F5B&currentviews=934

      Regards

      Delete
  4. Hello
    Have a nice day! :D
    My name is Jim.

    I got a school project, i should take pictures with OV7670 camera using my computer and an arduino pro mini.

    When i was connecting the camera on the arduino, i find out that my camera hasnt the following 4 pins: WEN, RCLK, SCL, SDA so cant continue with my project.

    here is the camera:

    http://i01.i.aliimg.com/wsphoto/v1/1881045091/640x480-VGA-CMOS-Camera-Module-OV7670-font-b-FIFO-b-font-Buffer-font-b-AL422B-b.jpg

    What to do now? Any ideas? Thanks

    ReplyDelete
  5. Hello David.
    Have a nice day.

    I followed the instructions, downloaded the arduino sketch and the processing code

    then i compile/verify the code and the processing console show message :

    Sketch uses 7,818 bytes (25%) of program storage space. Maximum is 30,720 bytes.
    Global variables use 804 bytes (39%) of dynamic memory, leaving 1,244 bytes for local variables. Maximum is 2,048 bytes.

    compiling done
    then i did upload and upload done.

    Then i downloaded the Processing environment and followed alla the steps above and thats what the processing console message shows:
    "send 20
    The buffer passed to readBytesUntil() is to small to contain 11 bytes up to and including char 10
    The buffer passed to readBytesUntil() is to small to contain 11 bytes up to and including char 10
    thresh 130
    The buffer passed to readBytesUntil() is to small to contain 11 bytes up to and including char 10"

    I am using this arduino :
    http://www.ebay.com/itm/200914924969?_trksid=p2060353.m2749.l2649&ssPageName=STRK%3AMEBIDX%3AIT

    Why it does not show image?

    Thank you for your response.
    Regards

    ReplyDelete
    Replies
    1. Hi Seisin,
      Before the error message, did you see a message like this the processing console?:

      "inited OK, sensor PID:"...

      You can try to lower the baudrate:

      in the arduino file ov_fifo_test.ino change this:
      static const unsigned long _BAUDRATE = 500000;
      to this:
      static const unsigned long _BAUDRATE = 38400;

      int the processing file globalDefinitions.java change this:
      public final static int BAUDRATE = 500000;
      to this:
      public final static int BAUDRATE = 38400;

      Delete
  6. This comment has been removed by the author.

    ReplyDelete
  7. Hi!

    I wonder if the code is sensitive to cpu clock speed. I had succesful init using 16mhz arduino and it send something when running the processing scketch but nothing appeared. No image, just a dark screen and text. I kept hitting spacebar but no effect.

    ReplyDelete
    Replies
    1. Cpu clock speed shouldn't be a problem, but please be aware that the 16mhz arduino works with 5v and the sensor with 3.3v, so don't connect it to 5v logic directly. You would need a voltage translator or an arduino that works at 3.3v.

      Delete
  8. Thanks for fast response! My arduino runs 3.3v so that isn't problem. I have never had any problem with running 16mhz 3.3v and actually have never seen anybody to report problems so I use this setup all the time when prototyping.

    I tried lowering baudrate from 112500 to 57600 etc. and got something but not proper pictures. Screen was dark but when i aimed window i camera showed bright area. However after about a minute i started to have very messy and noisy picture that didn't react to camera moves. I had this also this "buffer passed to ..." error mentioned in earlier posts. I would be so grateful to get some advice...

    Do you happen to have any simplier codes that just get an image and send it to processing?

    ReplyDelete
    Replies
    1. Try to lower the baudrates to 38400 and change the mode (press space until you see say stream2ppb). Be patient because at that speed and pixel depth it takes a while to transfer the frame.

      Delete
    2. Transfer rate and stability are sometimes very sensitive to the good contacts and wiring.

      Delete
  9. I think there is still something wrong with code (processing or arduino?) because there is never pictures like in your video. If it were about bad contacts i think there wouldn't be the exactly same behaviour every time? No I have tested it with every possible baudrate many times and every time picture freezes to messy nonsense after running short time and never recovers. Before this camera detects only bright light but gives no real pictures. Do you think that error message isn't a probelm?


    ReplyDelete
    Replies
    1. This comment has been removed by the author.

      Delete
    2. Can you try this?:

      void serialEvent(Serial serialPort) {

      if (reqStatus == requestStatus_t.REQUESTED) {

      byte[] byteBuff = new byte[255];
      int numBytesRead = serialPort.readBytesUntil(G_DEF.LF, byteBuff);
      if ((numBytesRead >= 4) &&
      (byteBuff[numBytesRead-4] == 'A') &&
      (byteBuff[numBytesRead-3] == 'C') &&
      (byteBuff[numBytesRead-2] == 'K') ) {
      reqStatus = requestStatus_t.ARRIVING;
      } else if (millis() > waitTimeout) {
      reqStatus = requestStatus_t.TIMEOUT;
      }
      }
      else if (reqStatus == requestStatus_t.ARRIVING) {
      parseSerialData();
      }
      else {
      if (bSerialDebug) print(serialPort.readStringUntil(G_DEF.LF));
      }
      }

      Delete
  10. Thank you very much for your help! Your code solved the processing problem and now it streams pictures with any baudrate without freezing and giving error messages.

    However the pictures don't make any sense. Theyd are kind of fractal-like blobs changing their size a bit all the time even when camera isn't moving. Pattern are kind of images because they react going darker when i shade the camera lense.

    I have to investigate further whats wrong with my setting. I think it could about reading the FIFO because camera seems to work.

    ReplyDelete
    Replies
    1. It might still be some issue with the transfer: the bits are encoded in the bytes sent, if you see the function buff2pixFrame, the pixels are encoded in YUYV. The most consistent image should be at STREAM1PPB (one pixel per byte) because at least any byte received corresponds to one pixel each (even if it arrives in wrong order or some get lost).
      Also, sometimes twisting the wires from the arduino to the sensor helps to make the data more reliable.

      Delete
  11. Problem solved. After checking out connections many times and comparing schematics and my module with multimeter i couldn't find anything wrong. It came to my mind if the optics are bad. I found that holder of lense was misaligned and bad. I replaced it with lense and holder from my non-fifo module and everything is ok now :) Too much work because of one faulty crappy ebay module...

    Thank you very much for the support and code fix!

    ReplyDelete
    Replies
    1. Don't mention it! Thanks to this the code is better now :)

      Delete
  12. Hello David.

    can you help me !!!! my name's draka.

    I can't not show up the picture.

    here is the camera :

    http://bestcamcorder.trafficmanager.net/pet-camera/cf7670-v3-belt-fifo-ov7670-webcam-mcu-alx-1199157928-dp.html

    and i use this arduino :

    https://www.arduino.cc/en/Main/ArduinoBoardUno

    thanks.

    ReplyDelete
    Replies
    1. As you can see in the specs, that arduino has: "Operating Voltage 5V"

      If you connect it directly to the sensor (3.3v) you will probably harm it.

      You need a 3.3v arduino or convert your arduino's 5v signals to 3.3v with devices like this: https://www.adafruit.com/products/395

      Delete
  13. Hello David.

    can you help me !!!! my name's draka.

    I can't not show up the picture.

    here is the camera :

    http://bestcamcorder.trafficmanager.net/pet-camera/cf7670-v3-belt-fifo-ov7670-webcam-mcu-alx-1199157928-dp.html

    and i use this arduino :

    https://www.arduino.cc/en/Main/ArduinoBoardUno

    thanks.

    ReplyDelete
  14. Hello David.

    can you help me !!!! my name's draka.

    I can't not show up the picture.

    here is the camera :

    http://bestcamcorder.trafficmanager.net/pet-camera/cf7670-v3-belt-fifo-ov7670-webcam-mcu-alx-1199157928-dp.html

    and i use this arduino :

    https://www.arduino.cc/en/Main/ArduinoBoardUno

    thanks.

    ReplyDelete
    Replies
    1. DO NOT USE AN ARDUINO THAT
      OUTPUTS 5V ON THE DIGITAL PINS
      Use only 3.3v 8MHz arduino versions

      Delete
  15. This comment has been removed by the author.

    ReplyDelete
  16. Hey David, I'm using a DCCduino Nano which I believe is 3.3V.
    I've changed the baud rate to 115200 for both the Processing and Arduino code.

    I've gotten:
    Initializing sensor...
    inited OK, sensor PID: 7673

    Here's the album of the garbage stream I get with various stream speeds:
    http://imgur.com/a/6oAvY

    Please help! Thank you!

    ReplyDelete
    Replies
    1. DCcduino Nano is an Arduino Nano clone, which is 16MHz and 5v, not 8MHz and 3.3v

      Delete
  17. Hi David,
    I'm using a GCCduino Nano which I believe is 3.3V. I set the baud rate for both the Processing and Arduino code to 115200.

    I get:
    Initializing sensor...
    inited OK, sensor PID: 7673

    But no images. Here's the garbage output I get with different stream speeds:
    http://imgur.com/a/6oAvY

    ReplyDelete
    Replies
    1. DCcduino Nano is an Arduino Nano clone, which is 16MHz and 5v, not 8MHz and 3.3v

      Delete
  18. Would you be able to use a bluetooth module as opposed to a usb cable to view this? I'm trying to build a small short distance wireless module with my pro mini.

    ReplyDelete
    Replies
    1. It should work, if you use a serial bluetooth module it will send over bluetooth anything you send to the tx line. However, the maximum baudrate (I think 38400) may be very low compared to the USB wired serial connection.

      Delete
  19. The nicolasfley site is down, and I'm not sure what the schematic for pulling down 5V to 3V3 is. Is it for SIOC and SIOD only? Do I also need VSYNC?

    What values of resistors are needed - 10k from SIOC to 3V3?

    ReplyDelete
    Replies
    1. Google for: "i2c 5v 3.3v divider"
      However, I recommend you to use a level shifter instead of a voltage divider: http://www.adafruit.com/product/395
      The divider is unidirectional, as you can only send commands to the sensor but not read registers. Also, if you read the sensor's pixel data lines directly with the Arduino pins you risk sending 5v by mistake.

      Delete
    2. http://web.archive.org/web/20140409082712/http://nicolasfley.fast-page.org/?page_id=35

      Delete
  20. It would be nice to have a level shifter - I'll order that next. I only have resistors on hand so I'm using 4.7k and 10k resistors to create a voltage divider (10k from SIOC/SIOD camera pins to the Arduino, and 4.7K from the camera pins to GND). This should divide the voltage enough for high/low voltage of the digital pins to be recognized. However, the camera refuses to initialize:
    Initializing sensor...

    Then it never says anything else.

    I've ordered a 3.3V Arduino clone that should come in soon, so these problems hopefully will be gone.

    Also, I didn't quite understand your other comment - "if you read the sensor's pixel data lines directly with the Arduino pins you risk sending 5v by mistake." I'm not sure what you mean by that. My camera D0-D7 pins are connected to the Arduino, but since they Arduino pins are configured as inputs, it shouldn't make a difference right?

    ReplyDelete
    Replies
    1. The code tries to read the sensors ID registers to check if it is the right model, but it never receives answer, as the voltage divider lowers the sensors 3.3v digital one bits below the arduino's digital one threshold (it sees always zero). You can try to modify the code skipping the ID check and see what happens: in the file sensor.cpp, substitute the line
      uint16_t productID = sensor_readReg(REG_PID);
      With:
      uint16_t productID = 0x76;
      And comment the line:
      productID |= sensor_readReg(REG_VER);
      And see what happens.

      About my comment: imagine you upload a sketch that outputs 5v by mistake, with the sensor still plugged to the Arduino.

      Delete
  21. This is really frustrating. I must be doing something else wrong. Since I don't care about reading registers from the camera anyway, and just need to set them at the beginning, I think a voltage divider could work fine. I've tried 10k as well as 4.7k which I found on the Arduino site: http://playground.arduino.cc/Main/I2CBi-directionalLevelShifter

    However, I still get jumbled garbage from the camera output. I must have messed up code or something. I have low baud rate, great wiring (helped by my electrical engineering friend), I tried a new camera after adding the voltage dividers to make sure my camera didn't burn out, I get "inited OK, sensor PID"... but I only get garbage output.

    http://imgur.com/o8wefM8

    Sometimes it looks like the output gets "whiter" when I point toward a light source, or all dark/green when I put it in the dark, or red when I point the camera to my red shirt. But it's always interspersed with the garbage green lines, and out of order.

    ReplyDelete
  22. Hey David! :D I have a positive update!
    Instead of green garbled garbage, I have something now: http://imgur.com/a/tVmLe
    But it only picks up light/dark and shows blobs, and has a green tinge. I'm not in a dark room.
    It was my fault; I did not follow the wiring connections because I wanted to add all the data pins. I connected WE to an analog pin and changed the pin settings in the code. Now that I have changed them back and only plugging in the 5 data pins that your example uses, the camera is able to give me a blob.
    I've made the sensor ID model edit in sensor.cpp, and on 115200 baud.

    Now I am trying to figure out how to get actual camera feed, not just light blobs.

    ReplyDelete
    Replies
    1. Hey, seems we are on the good direction :)
      Some sensors come with the lens holder displaced, also check the focus.

      Delete
  23. Hello all,
    I am trying to capture image vidio from ov7670 (http://dx.com/p/ov7670-300kp-vga-camera-module-for-arduino-147742) using arduino mega.
    Please help me in my task.
    Thanks in advance!!!!

    ReplyDelete
    Replies
    1. Hello,
      That module doesn't have fifo, so you have to send the video lines on-the-fly to the computer through the serial port. At the moment the only code I've developed uses a module with fifo.
      You can start with this code: https://github.com/ComputerNerd/ov7670-no-ram-arduino-uno
      To make it work wirh the arduino IDE, after extracting the zip in your sketches folder:
      - rename the folder "ov7670-no-ram-arduino-uno-master" to ov7670_no_ram
      - rename the file main.c to ov7670_no_ram.ino
      - rename the file ov7670.c to ov7670.cpp

      The wiring instructions are in the README file ( Note that I haven't tested this myself!!! )

      Besides that, Arduino Mega works at 5v. You will need a voltage tlevel translator/shifter to safely connect the data lines of the sensor to the arduino. In case you only want to read data from the sensor you can try this wiring at your own risk: http://web.archive.org/web/20140409082712/http://nicolasfley.fast-page.org/?page_id=35

      Delete
  24. Thank you very much for your work. It worked for me the first time.

    ReplyDelete
  25. why have this problem
    Arduino: 1.6.7 (Windows 8.1), Board: "Arduino/Genuino Uno"

    C:\Users\user\Documents\Arduino\ov_fifo_test\ov_fifo_test.ino:92:7: warning: extra tokens at end of #else directive [enabled by default]

    #else ifdef QQQVGA

    ^

    ov_fifo_test:162: error: ISO C++ forbids declaration of 'vsyncIntFunc' with no type [-fpermissive]

    void static __inline__ vsyncIntFunc() {

    ^

    C:\Users\user\Documents\Arduino\ov_fifo_test\ov_fifo_test.ino: In function 'void setup()':

    ov_fifo_test:147: error: invalid conversion from 'int (*)()' to 'void (*)()' [-fpermissive]

    attachInterrupt(VSYNC_INT, &vsyncIntFunc, FALLING);

    ^

    In file included from sketch\ov_fifo_test.ino.cpp:1:0:

    C:\Program Files (x86)\Arduino\hardware\arduino\avr\cores\arduino/Arduino.h:142:6: error: initializing argument 2 of 'void attachInterrupt(uint8_t, void (*)(), int)' [-fpermissive]

    void attachInterrupt(uint8_t, void (*)(void), int mode);

    ^

    C:\Users\user\Documents\Arduino\ov_fifo_test\ov_fifo_test.ino: In function 'void vsyncIntFunc()':

    ov_fifo_test:162: error: new declaration 'void vsyncIntFunc()'

    void static __inline__ vsyncIntFunc() {

    ^

    ov_fifo_test:162: error: ambiguates old declaration 'int vsyncIntFunc()'

    void static __inline__ vsyncIntFunc() {

    ^

    ov_fifo_test:170: error: invalid conversion from 'int (*)()' to 'void (*)()' [-fpermissive]

    attachInterrupt(VSYNC_INT, &vsyncIntFunc, FALLING);

    ^

    In file included from sketch\ov_fifo_test.ino.cpp:1:0:

    C:\Program Files (x86)\Arduino\hardware\arduino\avr\cores\arduino/Arduino.h:142:6: error: initializing argument 2 of 'void attachInterrupt(uint8_t, void (*)(), int)' [-fpermissive]

    void attachInterrupt(uint8_t, void (*)(void), int mode);

    ^

    C:\Users\user\Documents\Arduino\ov_fifo_test\ov_fifo_test.ino: At global scope:

    C:\Users\user\Documents\Arduino\ov_fifo_test\ov_fifo_test.ino:162:19: warning: inline function 'int vsyncIntFunc()' used but never defined [enabled by default]

    void static __inline__ vsyncIntFunc() {

    ^

    exit status 1
    ISO C++ forbids declaration of 'vsyncIntFunc' with no type [-fpermissive]

    This report would have more information with
    "Show verbose output during compilation"
    enabled in File > Preferences.

    ReplyDelete
    Replies
    1. Hi!

      Trys this changing this:

      #else
      #ifdef QQQVGA
      static const uint8_t fW = 80;
      static const uint8_t fH = 60;
      static const frameFormat_t frameFormat = FF_QQQVGA;
      #endif
      #endif

      and this:

      attachInterrupt(VSYNC_INT, (void(*)())&vsyncIntFunc, FALLING);

      and tell me what happens

      Delete
    2. This comment has been removed by the author.

      Delete
  26. This comment has been removed by the author.

    ReplyDelete
  27. WHY DO NOT USE D2,D1,D0 PORT ???

    ReplyDelete
    Replies
    1. Hi, sorry for the late answer. Did you solve your problems?
      I discarded the least significant bits to reduce the amount of data to stream and get more FPS.

      Delete
  28. thank you !
    DO you have Color Tracking code??

    ReplyDelete
  29. what meaning for this code ? can you Explanation for me ?
    thank you ! David!
    void drawTracking() {
    pushStyle();
    noFill();
    strokeWeight(3);
    // rect(0, 0, 100, 100 );

    if (((tmp_x1-tmp_x0) > 3) && ((tmp_x1-tmp_x0) < G_DEF.F_W/2) && ((tmp_y1-tmp_y0) < G_DEF.F_H/2) && ((tmp_y1-tmp_y0) > 3)) {
    stroke(0);
    float minX = width-x0*G_DEF.DRAW_SCALE;
    float minY = y0*G_DEF.DRAW_SCALE;
    float wX = -(x1-x0)*G_DEF.DRAW_SCALE;
    float hY = (y1-y0)*G_DEF.DRAW_SCALE;
    float centX = minX+wX/2;
    float centY = minY+hY/2;
    rect(minX, minY, wX, hY );
    line( centX-10, centY, centX+10, centY );
    line( centX, centY-10, centX, centY+10 );
    if (bKalmanEnabled) {
    x0 = (float)filter_x0.update(tmp_x0);
    y0 = (float)filter_y0.update(tmp_y0);
    x1 = (float)filter_x1.update(tmp_x1);
    y1 = (float)filter_y1.update(tmp_y1);
    }
    else {
    x0 = tmp_x0;
    y0 = tmp_y0;
    x1 = tmp_x1;
    y1 = tmp_y1;
    }
    stroke(255,0,0);
    minX = width-x0*G_DEF.DRAW_SCALE;
    minY = y0*G_DEF.DRAW_SCALE;
    wX = -(x1-x0)*G_DEF.DRAW_SCALE;
    hY = (y1-y0)*G_DEF.DRAW_SCALE;
    centX = minX+wX/2;
    centY = minY+hY/2;

    rect(minX, minY, wX, hY );


    line( centX-10, centY, centX+10, centY );
    line( centX, centY-10, centX, centY+10 );
    stroke(0,0,255);
    line(lastCenter.x, lastCenter.y,centX, centY);
    lastCenter.x = centX;
    lastCenter.y = centY;

    }
    popStyle();
    }

    ReplyDelete
  30. This comment has been removed by the author.

    ReplyDelete
  31. Hey David,

    I used your code and worked well for me. Thank you for the detailed explanation. I am trying to connect 2 ov7670-fifo cameras to arduino mega. I needed help with it. Hoping to hear back. Thanks

    ReplyDelete
    Replies
    1. I love dirty hacks :), and this can be very dirty indeed:

      Try wiring both cameras in parallel, except for the data lines. Wire D3-D7 of first/second camera to different pins in the arduino. Then modify the code to read an image twice as wide: 160x60, and read large rows (160pix), first half row 80pix from the D3-D7 from first camera and next half row 80pix from the D3-D7 from second camera.
      Modify the all the code related to capture and streaming to match the new frame with of 160 pix.

      Cross fingers and see what happens :)

      Delete
    2. See comment below:
      http://therandomlab.blogspot.com.es/2014/09/arduvision-i-embedded-computer-vision.html?showComment=1461667687218#c7631993560235717669

      If you suceed, please report with some feedback :)

      Delete
  32. hey David

    For working with arduino MEGA2560 what file I need to change ?

    Thanks

    ReplyDelete
    Replies
    1. you would need a voltage translator to connect the 3.3v sensor to the Atmega (5v): https://www.adafruit.com/products/395

      Delete
    2. hey ; thanks for that, but I mean the files, for example IO_config.h or something like that, and and other question where I have to save these files ? in the project file of arduino ? I talk about arduino side not preocessing side



      Thaks again

      Delete
    3. In IO_config you will have to set up the secondary camera data pins as inputs. The primary is in port D:
      #define DATA_DDR DDRD
      #define DATA_PORT PORTD
      #define DATA_PINS PIND

      Choose another port in your mega with spare digital pins and add the additional definitions to config_IO:
      #define DATA_DDR2 DDRx
      #define DATA_PORT2 PORTx
      #define DATA_PINS2 PINx
      Then, in function setup_IO_ports() reset registers, register directions and set that data pins as input:
      DDRx = PORTx = 0;
      DATA_DDR2 = 0;

      In fifo.h, duplicate function fifo_readRow1ppb with name fifo_read2Rows1ppb and modify it so they capture the two camera's rows:

      static __inline__ void fifo_read2Rows1ppb(uint8_t* _rowStart, uint8_t* _rowEnd)
      {
      uint8_t* _rowStart2 = _rowEnd;
      while (_rowStart != _rowEnd) {
      SET_RCLK_H;
      *_rowStart = DATA_PINS >> 4;
      *_rowStart2 = DATA_PINS2 >> 4;
      SET_RCLK_L;
      SET_RCLK_H;
      *_rowStart++ |= DATA_PINS & 0xf0;
      *_rowStart2++ |= DATA_PINS2 & 0xf0;
      SET_RCLK_L;
      }
      }

      in ov_fifo_test change the buffer length:
      byte rowBuf[MAX_FRAME_LEN*2];

      If everything works well you can call your new function like this:

      fifo_read2Rows1ppb(rowBuf, rowBuf+fW);

      And you will have the two rows stored in the buffer, one after the other.

      Delete
    4. (i guess you are the one that wants to connect two cameras to a Mega)

      Delete
    5. haha not I'm not ;) but thanks

      Delete
    6. Hey
      Finally i'm using Arduino UNO so i dont have to change the IO_File but for work to 3.3v I put a resistors to make 5 to 3.3v but I guess that is necesary just for SDA, SCL and VSYNC ports beacuase if a make that for all of them it does not work isn't it ?

      Even when I tested the program in processing side
      there is a mistake with the size() it can not be determinated, because all those variables are nothing for processing

      Thank you

      Delete
    7. This comment has been removed by the author.

      Delete
    8. In console just "try" but is not conected what is that for ?

      Delete
    9. The variables in the sentence:
      size(G_DEF.SCR_W, G_DEF.SCR_H+G_DEF.FONT_BKG_SIZE);
      are defined in the file/tab: globalDefinitions.java

      Delete
  33. Hey Can you tell me why are you using F_W to be 80 and F_H to be 60?

    ReplyDelete
  34. Hey David,
    My project is still in the making..Will update you when that's done. In the mean time can u help me with another issue. I am trying to also connect this camera with raspberry pi board.
    No documents on it have been found. Do you think its doable?

    Thank you!

    ReplyDelete
    Replies
    1. https://www.raspberrypi.org/forums/viewtopic.php?f=44&t=73190

      "Sorry, won't work.

      Those modules output 25MB/sec with an 8 bit bus and a strobe, the Pi GPIO is NOT up to handling that."

      Use a webcam or a rPi camera:

      https://www.raspberrypi.org/help/camera-module-setup/

      Delete
  35. Hey.. I wanted to know one more thing. My OV7670 comes with HREF on pin 6 instead of WRST. So how do i use it in my code?

    ReplyDelete
    Replies
    1. I assume your module is like this:
      http://www.electrodragon.com/w/OV7670_Module
      If so, just connect the arduino pins to your module according to the labeling. Note WEN is labeled as "WR".

      Delete
    2. http://www.amazon.com/Arducam-OV7670-Megapixel-Sensor-Camera/dp/B017SHVZJM/ref=sr_1_1?ie=UTF8&qid=1464373070&sr=8-1&keywords=ov7670+fifo
      This is the camera that I am currently using!!

      Delete
    3. Just connect you module's corresponding pins to the arduino pins as in the as in the connections schematic above, and ignore the FIFO_WRST line (in your module it is already phisically tied to RCLK)

      Delete
  36. Hello,i have a OV7670FIFO camera module, i want to take photos with it, i have arduino mega 2560.
    I can't connect my arduino to the camera module.
    Can you help me to do that ?

    ReplyDelete
  37. Hello, can you help me to connect my arduino mega2560 with my camera module OV7670 FIFO ?
    My pins are ( CS RRST WRST RD WE PWDN SCL VSYNCH SCL SDA XCLK D0 D1 D2 D3 D4 D5 D6 D7 ) i want a correspondance between my pins and those posted ?

    ReplyDelete
    Replies
    1. Remember to put a voltage shifter inbetween the Mega (5v) and the sensor (3.3v)!!!

      According to this schematic: http://d1.ourdev.cn/bbs_upload782111/files_41/ourdev_651354BMLFCB.pdf

      RD = FIFO_RCLK
      CS = FIFO_OE

      The rest is obvious. Ignore XCLK and PWDN.

      Delete
  38. Hey David,

    Can you tell me what ppb stands for and why is it divivded into 8,4,2,1,0?

    ReplyDelete
    Replies
    1. (zero pixels per byte means one pixel uses more than one byte)

      Delete
  39. hello, please can you tell me how can i connect my camera module with my arduino mega 2560 ?

    ReplyDelete
    Replies
    1. http://therandomlab.blogspot.com.es/2016/06/arduvision-ii-ov7670-fifo-module-and.html

      Delete
  40. This comment has been removed by the author.

    ReplyDelete
  41. Hi David !! Thank for share your project on this Lab. This exactly project I need, but I have some problem.....
    IN MY CASE:
    + I follow your schematic and use the same version of device as your project (Arduino promini 3.3V 8Mhz and Ov7670 version 1.0)
    + I get messege:
    "_Initializing sensor...inited OK ...."
    + I have a STABLE running with baudrate setup in arduino sketch:
    //static const unsigned long _BAUDRATE = 57600;
    and in Processing sketch:
    //public final static int BAUDRATE = 115200;

    MY PROBLEM:
    1/ The FPS of streaming image I have received on the processing GUI window (at 0PPB) just about 1.1111 fps. Its look not smooth than your demo in youtube (your is 3.333 fps). How can I increase FPS ?
    2/ My image receive on GUI is too dark than your demo. In the light area, the image is not bright enough to see, just like a grey and dark, but if I turn the camera to the bright direction, I can see a little thing with higher light effect. How can I increase the brightness to get the better image ?
    _Thank so much for your support and try to solve my problem !!
    *Hope your reply soon & sorry for my bad English :d

    ReplyDelete
    Replies
    1. yo should set the same baudrate in both arduino and processing

      Delete
    2. Ah thank you for reply !
      _If I try the same baudrate for arduino & processing but the sensor is not be initialize, processing screen was BLACK and I realize that the processing baudrate must by arduino baudrate x2 => the program is run normaly and
      occur 2 problem in bottom comment :D
      The stranger phenomenon so difference with other user :|

      Delete
    3. Have you tried both at lower baudrates? 19200 or 38400

      Delete
    4. also check that the serial wires are not too long

      Delete
  42. My serial wires just about 20cm.
    Can you tell me the baudrate you have use to stream your project :D
    And I still not understand my running will work well with setup follow this:
    the processing baudrate = 2 x (arduino promini 3.3v 8mhz baudrate)
    Anyway thank for your support too much. I will learning & research more on my case and report the better result to you :D

    ReplyDelete
    Replies
    1. try 10cm and keep the wires separated from the others.
      my baudrate is 500000 :)

      Delete
    2. Okay thank you :D I'll try to fix it.
      Im come from VietNam and studying at Ho Chi Minh University of Science.
      Nice to meet you David !! :d

      Delete
    3. Nice to meet you too!
      I'm currently based in Valencia, Spain, working in R&D, and did my studies at the Polytechnic University of Valencia.

      Delete
  43. why am I having this problem ?

    Arduino: 1.6.11 (Windows 10), Board: "Arduino Pro or Pro Mini, ATmega328 (3.3V, 8 MHz)"

    C:\Users\Heaven\Documents\Arduino\sketch_aug26b\sketch_aug26b.ino: In function 'void vsyncIntFunc()':

    sketch_aug26b:165: error: ambiguating new declaration of 'void vsyncIntFunc()'

    void static __inline__ vsyncIntFunc() {

    ^

    C:\Users\Heaven\Documents\Arduino\sketch_aug26b\sketch_aug26b.ino:165:19: note: old declaration 'int vsyncIntFunc()'

    void static __inline__ vsyncIntFunc() {

    ^

    exit status 1
    ambiguating new declaration of 'void vsyncIntFunc()'

    This report would have more information with
    "Show verbose output during compilation"
    option enabled in File -> Preferences.

    ReplyDelete
    Replies
    1. I see by the name of the sketch (sketch_aug26b.ino) you are not using the original files...
      Does the original code from github (with all the files) work for you?

      Delete
  44. Hi David,
    I'm using a GCC aduino Pro mini 3.3V. I set the baud rate for both the Processing and Arduino code to 500000.

    I get:
    Initializing sensor...
    inited OK, sensor PID: 7673

    Could not find the folder ...
    ran opened the screen, but that is so black ...
    squeezed space and went through all modes and nothing

    ReplyDelete
    Replies
    1. Hi, please check the wiring, if the sensor is inited ok, it should work fine.

      Delete
  45. Hello David

    I attempted to replicate your circuit but the following error shows up: Panic! INIT sensor keeps failing.. What's the reason? The output remains black as well

    ReplyDelete
    Replies
    1. The most common problems are:
      a) bad wirings
      b) using a standard arduino (5v) instead of special 3.3v arduino. If you want to use a standard adruino use voltage level converters (see: http://therandomlab.blogspot.com.es/2016/06/arduvision-ii-ov7670-fifo-module-and.html)
      c) Too high USB speed selected in the arduino/processing codes

      Delete
    2. Swapnil Saha !!

      Did you fixed the problem ??
      I am having same issue.
      could please help with some feedbacks ?
      Please reply soon.

      Delete
    3. Hey Swapnil !
      Did you fixed the problem ?
      I am having the same issue.
      So it would be helpful if you provide some feedbacks on how you solved it .
      please reply soon.

      Delete
  46. Hey david !
    I am very thankful for your effort on providing these help for using the module. But i am having some issues on displaying the images on the screen. Both the codes on arduino IDE and processing are verified with no any errors and also i have checked through some of these baudrates; 38400, 115200, 56700 and 500000 with all different modes. But still the output on processing is black.

    When i randomly check through baudrates in serial monitor of the arduino IDE, it says;

    initializing sensor...
    retrying...
    retrying...
    retrying...
    Panic! INIT sensor keeps failing.

    and also in the processing console no any initialization messages shows up.
    only something like;

    [0] "COM5"

    shows up.

    Please reply soon!
    and again thankyou.

    ReplyDelete
    Replies
    1. Please check the wirings again and make sure you are using an 5v 8MHz arduino.

      Delete
    2. I mean 3.3v 8MHz!!! (I've repeated so many times I just wrote it wrong :b )

      Delete