Comments (19)
I was reasonably successful!
Connected HREF to PIN 12 instead of PCLK. Sometimes it goes a little out of sync after start up but usually after resetting Arduino it is OK. I should try to do it with interrupt at some point. If the execution is really only 4 clock cycles (or not much more) then it would guarantee synchronization.
Interlace lines are very obvious. But it depends what the end goal is, it might not matter. For example last year I created a line following robot and for that double refresh rate would have helped a lot.
from liveov7670.
There is one problem. Pixel clock is already maxed out.
Pixel clock depends on XCLK and clock pre-scaler parameter. Pre-scaler value is already 0 for 10fps.
The only way to do that would be to increase XCLK. Currently XCLK is generated by digital output pin. Since Arduino runs at 16Mhz max for pin output is 8Mhz.
Maybe if there is a way to get Arduino 16Mhz clock output directly then it might be possible.
from liveov7670.
But the XCLK is first multiplied with the PLL Multiplier (REG_DBLV) before getting divided by the prescaler (2x(REG_CLKRC+1)), so setting REG_DBLV to 4 and REG_CLKRC to 1 should double the pixel clock. It's described on page 13 in the OV7670 implementation guide appnote.
from liveov7670.
I added PLL multiplier setup and was able to double pixel clock speed.
There are currently two problems.
- There isn't enough time to send data to the screen. It might be possible if the screen had parallel pixel loading instead of SPI. But it would not help with Arduino Uno/Nano since it doesn't have enough PINs. Maybe with Arduino Mega.
Yellow is pixel clock from the camera and cyan is SPI clock to the screen at 10fps:
At 20fps every other line is missed since it is still sending data to the screen:
- I tried sending only 1/3 of a line to the screen but the image was very flickery. I think the issue is that I fail to detect the first pixel reliably. Arduino runs at 16Mhz and pixel clock is at 4Mhz. This means that there are only two instructions executed during the time that pixel clock is low. I think one cycle of this loop probably is more (waiting for pixel clock to go low):
while(OV7670_PIXEL_CLOCK);
This means that detecting first pixel is very hit-and-miss.
It probably is possible to create some clever external logic that stops XCLK if pixel clock goes low then there is time for Arduino to react. But then it would actually be more sensible to use something faster than Arduino
from liveov7670.
Perhaps PCLK could be moved to GPIO1 and HREF connected to GPIO2 and start reading pixels when GPIO2 interrupts? Or if all the pixels in a row are read "blindly" then PCLK is not needed at all, only HREF..
As for TFT-speed, your SPI code (sendPixelByte) seems to max out performance (did you find the number of NOP:s experimentally?). Perhaps interlacing can be used, sending every other line switching between odd and even lines.
from liveov7670.
Using HREF instead of PCLK is good idea. I will try this tomorrow.
My impression has been that interrupts are too slow for this. If I remember correctly then when using Arduino's "attachInterrupt" it takes sixty-something cpu cycles to get to the interrupt code. Maybe if this interrupt is configured directly (without Arduino framework) it will be fast.
Yes, I removed as much NOPs as I could. Beginning of each line can be optimized (the more sparse cyan lines on the scope image). Currently it is done by the Adafruit display library methods. This could be compressed as tight as the data section.
Interlacing is also good idea. First priority is to get line data reading fixed and then interlacing shouldn't be that hard to do.
from liveov7670.
Let me know how it works out!
According to the ATmega328P datasheet it should be able to react in 4 cpu clock cycles. (see 11.7.1. Interrupt Response Time). Looking at attachInterrupt in WInterrupts.c from the Arduino core it doesn't look like it adds any significant (or any at all?) overhead.
from liveov7670.
Cool! Great work! I assume you are doing interlacing in the video?
Higher framerate also means reduced artifacts from the rolling shutter (since the time between reading out the first and the last line from the cmos i shorter) so even if you don't want/need 20fps you could do it just to get less motion distored frames. For a line follower it would be great, and you could just ignore everything except the center line and get lots of time for image processing and control.
from liveov7670.
I did some measuring.
Interrupt code is only one line that takes only one cpu cycle:
PORTD = 0b00000000; // sets pins 0..7 to LOW
With Arduino framework's "attatchInterrupt" it takes from input pin changes to output change 3.5us
3.5/0.0625 = 56 CPU cycles;
using directly this:
ISR (PCINT0_vect) {
PORTD = 0b00000000;
}
It takes ~1.2us
1.2/0.0625 = 19,2. Around 18 to 20 cycles (my measurement is not very accurate)
OV7670 has register 2A - "dummy pixel insert". A couple of dummy pixels in front of a line should compensate for the interrupt delay.
from liveov7670.
http://www.displayfuture.com/Display/datasheet/controller/ST7735.pdf
It seems that the screen (ST7735) supports 4-4-4 color mode where two pixels can be transferred with three bytes instead of four (at the cost of reduced color space):
This means that 15fps without interlacing should be possible. Maybe even in color. Currently pixel reading is slowed down by masking out raw input bits and then OR'ing them together into one byte. There is more free time during data transfer to screen. One possibility is to save raw data during read and then later clean it up.
from liveov7670.
Now the 20Hz version is using interrupt to detect new line start. It is more stable and looks better than before.
The dummy pixel setting did something (the image changed), but it didn't work as I expected. But it doesn't actually matter since it is just a couple of pixel at the edge that are lost.
from liveov7670.
Nice, good finds! Have you tried out the RGB444 mode for 15fps color too?
from liveov7670.
Not yet. I have some other stuff to do. But at some point I will try it.
from liveov7670.
Off-topic: I printed a case for my cam and added a lipo+charger and some infrared LED:s to turn it into a night vision camera for my 4.5yr old son - he loves it :) https://www.youtube.com/watch?v=J-ErxRT7Nbc
from liveov7670.
Nice! Did you design a PCB for that or wired it up manually?
from liveov7670.
I didn't have the patience to wait for a PCB so I wired it up manually :)
from liveov7670.
Looking at your conversation with YL Yang at https://youtu.be/Dp3RMb0e1eA - is the HREF usage implement already or not in this repo? And other "tweaks" in this thread?
from liveov7670.
I have an example file of the interlaced version in the repo (ExampleGrayscale20HzInterlaced.cpp). It runs at 20Hz but with only half the vertical resolution and it is in gray scale.
I haven't tried the interrupt with HREF signal since the bottleneck for Arduino is reading pixels and that already is at maximum that Arduino Uno/Nano can handle.
I haven't had time to try the last idea of reducing the color space. I am not sure it is worth the time to do it. Arduino is already very close to its limits and the benefit from doing that is probably very small.
from liveov7670.
Hey larsenglund!
There is now an easy way to get it working at 20 frames per second.
If you search "WAVGAT Nano" from aliexpress then you can find an Arduino clone that uses WAVGAT chip instead of Atmel's. It is almost fully compatible with normal Atmel based Arduino Nano. There were some minor adjustments that I had to make to the code so it would run on both. WAVGAT chip can run at 32Mhz.
Here is a demo of it working:
https://www.youtube.com/watch?v=dbMKfxACAfg
from liveov7670.
Related Issues (20)
- WAVGAT boards support? HOT 2
- Energia CC1350 Version HOT 3
- Led and button HOT 6
- No issue: This is amazing.
- Problem with installing "ArduImageCapture" Plug-In HOT 5
- How can I make VSYNC pulse when I need to capture frame? HOT 1
- TFT image Mirrored. Please Help
- CameraOV7670.h: No such file or directory HOT 3
- I have issues getting it to output a clear image HOT 2
- Camera OV7670 on SAMD51
- Camera output turned red after showing image HOT 1
- Command checksum failed HOT 1
- How to use on LCD TFT 3,5" ILI9488
- Can't compile for Nano Every HOT 1
- ov7670 library HOT 1
- Is this code compatible with the TFT ST7735S Display?
- Pin Definitions, ESP32-Applicability and Image Classification
- green square and no Vsync no matter what I do HOT 3
- Cannot upload the code. Error: ".... was not declared in this scope"
- can't compile while trying to compile to arduino uno
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from liveov7670.