Hello,
I am trying to read the OV7670 camera frames under IRQ.
The reason why I want to do it under IRQ is because frames can come as slow as 3fps, and I do not want to have to put a 1/3 of a second delay in my main loop (where I have other things to do, such as handle pen events)...
And of course, the OV7670 sends data when IT wants, not when you want it...
Anyhow, I first made a "normal", non IRQ version to make sure that I had everything OK, and then tried to move it under IRQ.
Using the "normal" version, I checked that the frame reading takes around 500micro seconds (1/2 milli second), so that it should be perfectly OK under IRQ. And that I had a limited number of IRQ per seconds (frames, tops at around 15fps)..
So, the "under IRQ" charge should be less than 0.5*15=7.5ms/s ... No problems... In theory...
BUT, then I did move the code under IRQ, suddenly, everything seems to slow down to a crawl... and the code tells me that it takes 100ms to read a frame!!!!
Note: the camera is configured at 160*120 pixels
Any clue as to what might be going wrong?
In parallel to this, I have a screen display, using the teensy tft library with the screen updated asynchronously using a framebuffer...
I have no clue if it makes any difference... The picture shows the system with the LCD displaying a starfield and the camera on the top right. The camera itself on the left and the teensy at the top...
Thanks,
Cyrille
Here is how I init the interrupt:
I am trying to read the OV7670 camera frames under IRQ.
The reason why I want to do it under IRQ is because frames can come as slow as 3fps, and I do not want to have to put a 1/3 of a second delay in my main loop (where I have other things to do, such as handle pen events)...
And of course, the OV7670 sends data when IT wants, not when you want it...
Anyhow, I first made a "normal", non IRQ version to make sure that I had everything OK, and then tried to move it under IRQ.
Using the "normal" version, I checked that the frame reading takes around 500micro seconds (1/2 milli second), so that it should be perfectly OK under IRQ. And that I had a limited number of IRQ per seconds (frames, tops at around 15fps)..
So, the "under IRQ" charge should be less than 0.5*15=7.5ms/s ... No problems... In theory...
BUT, then I did move the code under IRQ, suddenly, everything seems to slow down to a crawl... and the code tells me that it takes 100ms to read a frame!!!!
Note: the camera is configured at 160*120 pixels
Any clue as to what might be going wrong?
In parallel to this, I have a screen display, using the teensy tft library with the screen updated asynchronously using a framebuffer...
I have no clue if it makes any difference... The picture shows the system with the LCD displaying a starfield and the camera on the top right. The camera itself on the left and the teensy at the top...
Thanks,
Cyrille
Here is how I init the interrupt:
Code:
attachInterrupt(digitalPinToInterrupt(PinCamVsync), cameraSubRead, RISING);
static uint32_t readtime= 0; // incremements the time spend reading the camera...
// Here is the camera frame reading code, which works both under IRQ or not... But reports around 0.5ms execution time
// when not in IRQ and 100ms under irq!!!
// Read a uint8_t of the pixel data
static inline uint8_t cameraReadPixel()
{
uint8_t b = 0;
if (digitalReadFast(PinCamD7)) b |= 0x80;
if (digitalReadFast(PinCamD6)) b |= 0x40;
if (digitalReadFast(PinCamD5)) b |= 0x20;
if (digitalReadFast(PinCamD4)) b |= 0x10;
if (digitalReadFast(PinCamD3)) b |= 0x08;
if (digitalReadFast(PinCamD2)) b |= 0x04;
if (digitalReadFast(PinCamD1)) b |= 0x02;
if (digitalReadFast(PinCamD0)) b |= 0x01;
return b;
}
static void cameraSubRead()
{
int i= 0;
#ifdef dointerrupt
camCount++;
#endif;
uint32_t t1= micros();
while (digitalReadFast(PinCamVsync))
{
while (digitalReadFast(PinCamVsync) && !digitalReadFast(PinCamHref)); // Wait for a line to start
if (!digitalReadFast(PinCamVsync)) break; // Line didn't start, but frame ended
while (digitalReadFast(PinCamHref)) // Wait for a line to end
{
while (!digitalReadFast(PinCamPpclk)); // Wait for clock to go high
uint8_t hByte = cameraReadPixel();
while (digitalReadFast(PinCamPpclk)); // Wait for clock to go back low
while (!digitalReadFast(PinCamPpclk)); // Wait for clock to go high
cameraImage[i++] = (hByte << 8) | cameraReadPixel();
while (digitalReadFast(PinCamPpclk)); // Wait for clock to go back low
}
}
readtime+= micros()-t1;
}
// And my "gather data loop", which has both an IRQ and non IRQ version. it displays the stats....
int cameraReadCalls= 0;
// Acquire and display RGB565 image from the camera. Gets called by the main loop
bool cameraRead()
{
#ifndef dointerrupt
uint32_t t1= millis();
while (digitalReadFast(PinCamVsync)); // Wait for the old frame to end
while (! digitalReadFast(PinCamVsync)); // Wait for a new frame to start
uint32_t t2= millis();
noInterrupts();
cameraSubRead();
interrupts();
uint32_t t3= millis();
Serial.print(t2-t1); Serial.println(" camera wait time");
Serial.print(t3-t2); Serial.println(" camera read time");
#else
uint32_t t3= millis();
#endif
Serial.print(camIrqCount); Serial.println(" camera irq");
Serial.print(camCount); Serial.println(" frame count");
Serial.print(camCount/(float(t3)/1000)); Serial.println(" frame /s");
Serial.print(readtime/camCount); Serial.println(" micros / frame");
bool r= cameraNewFrame; cameraNewFrame= false; return r;
}
Last edited by a moderator: