SPI TFT + OV7670 camera project on teensy 4

Status
Not open for further replies.

cyrille

Well-known member
Hello,

I am working on a project with both a 320*240 SPI touch screen and an OV7670 camera.

Using the arduino libraries, I can make things work...
BUT, the imx seems to have HW assist for both SPI and CCIR656 compatible cameras. Is there any library or anything available to use the HW assist to DMA the screen data out in a (semi) continuous way (so that I can tell the HW: send new framebuffer, and have it being sent using DMA or something like this in parallel with the rest of my processing.
Simillary, I need/want to aquire the camera data in a HW way without having to do it in FW and get an interrupt/message/flag set once a new frame is available.

Thanks,
Cyrille
 
I've not messed with CurtE's lib ILI9341_t3n, but i believe it has a way to use DMA to get crazy fast updates. Have a look at the demosauce example that comes with the ILI9341_t3n lib. It shows very fast screens updates. @bitbank also did some lib optimizations that get high performance.

some more info here
https://forum.pjrc.com/threads/31719-Cheap-Video-with-Teensy-3-1-and-5-OV7670-camera-chip


If you do get vid working, would you mind sharing some example code? I've been wanting to get a camera working as well, but have not had the time to tinker.
 
You did not say which 320x240 display, nor which Teensy... but assuming you have a teensy with enough memory (t3.5/3.6, T4, T4.1)

As mentioned, for my ili9341_t3n library (https://github.com/KurtE/ILI9341_t3n) has DMA support.
Also our ST7735_t3/ST7789 library also has the same support, This is included with Teensyduino.

With these you can say: tft.useFrameBuffer(true);
And all writes you do go to the screen buffer.

You can do a direct update of the screen from frame buffer without using DMA by: tft.updateScreen();

You can use DMA by doing tft.updateScreenAsync();
And later test for the update completed or wait for the completion.

If you are using a processor with enough memory (T4.x) you can setup to do a sort of double buffer. There is a real basic example of this that I recently added to the ILI9341_t3n library, which sets the frame buffer to one buffer, starts the DMA operation, then tell system to use 2nd buffer and updates it and waits for the first DMA to complete before restarting the DMA operation, which starts from the 2nd buffer, which you then switch back to first...

Note: the above is not continuous. You can also setup to do continuous updates tft.updateScreenAsync(true);
which will continuously update screen. Note: you do run into issues where you are updating the memory potentially at same time as the DMA is writing out to screen... So can get partial updates if your code is not careful. You do have options to get an interrupt function called as each frame completes and also the ability on the half frame, such that you can setup your code to update the half the screen you know that part of the screen is not updating. I think there is an example showing that as well.

Also I earlier mentioned in another thread, it would probably be possible to do a combination of the two, where the DMA chain could contain two frames, so you know which frame is active and update the other... But so far I have not done this as no one sounded like they had a usage need for it.
 
Hello,

Thanks a lot for the info. I will definitely go that route. I will most likely use the updateScreen version as I will not write at anytime in the screen.

I am using a Teensy 4.0 and a ILI9341 screen. Sorry, I should have specified it at the start!

Cyrille
 
Hello,

After some issues with my board (teensy4.0) (I fired it I guess and had to replace it)... I am back in business trying to implement my project, but I am having issues.

I am trying to use one of the demo programs to test it... but it does not work with the ILI9341_t3n library.
It does however work with the Adafruit_ILI9341.h library.

Here is the beginning of my code for reference.

Thanks for your help,
Cyrille


#define TFT_CS 10 // TFT CS pin is connected to arduino pin 8
#define TFT_RST 8 // TFT RST pin is connected to arduino pin 9
#define TFT_DC 9 // TFT DC pin is connected to arduino pin 10
// initialize ILI9341 TFT library

#if 1
#include "ILI9341_t3n.h"
ILI9341_t3n tft = ILI9341_t3n(TFT_CS, TFT_DC, TFT_RST);
#else
#include <Adafruit_GFX.h>
#include <Adafruit_ILI9341.h>
Adafruit_ILI9341 tft = Adafruit_ILI9341(TFT_CS, TFT_DC, TFT_RST);
#endif

void setup() {
Serial.begin(9600);
Serial.println("ILI9341 Test!");

tft.begin();

pinMode(14, OUTPUT); analogWrite(14, 200); // LED backlight...

// read diagnostics (optional but can help debug problems)
uint8_t x = tft.readcommand8(ILI9341_RDMODE);
Serial.print("Display Power Mode: 0x"); Serial.println(x, HEX);
x = tft.readcommand8(ILI9341_RDMADCTL);
Serial.print("MADCTL Mode: 0x"); Serial.println(x, HEX);
x = tft.readcommand8(ILI9341_RDPIXFMT);
Serial.print("Pixel Format: 0x"); Serial.println(x, HEX);
x = tft.readcommand8(ILI9341_RDIMGFMT);
Serial.print("Image Format: 0x"); Serial.println(x, HEX);
x = tft.readcommand8(ILI9341_RDSELFDIAG);
Serial.print("Self Diagnostic: 0x"); Serial.println(x, HEX);

Serial.println(F("Benchmark Time (microseconds)"));

Serial.print(F("Screen fill "));
Serial.println(testFillScreen());
delay(500);
 
Last edited:
Sorry, it is unclear to me, what the issue is?
but it does not work with the ILI9341_t3n library.
Does not give me enough information to give any suggestions.

Does not compile? If so what are the compile errors.
Screen is blank?
Garbage on the screen?

It simply does not print out the registers?
 
Hello,

Yes, sorry, I should have been more descriptive, I apologize.
Blank screen is what I am getting...

But, the good news is that I seem to have found the issue. SPI Clock speed. I dropped it to 20000000 from 30Mhz and it now seems to work...

My next step is to try to turn on framebuffer and async SPI sending... but I am betting blocked there also.
I added this after the tft.begin();
tft.useFrameBuffer(true);
tft.updateScreenAsync(true);

But this does not seem to work. I end up with what seems like a blank screen with every other line slightly darker.
I hope that this is enough description to figure out what is wrong.
I wish I could tell more, but I don't know what information is relevant there.
I tried reducing the clock rate, but it did not help.

edit: removing the call to tft.updateScreenAsync(true); and adding calls to tft.updateScreen(); tft.updateScreenAsync(false); or on a regular basis does however work.
So the library is drawing on the framebuffer, but the continious async update does not seem to work.

Cyrille
 
Last edited:
I dropped it to 20000000 from 30Mhz and it now seems to work...

Any chance you can share the photo or a link to the specific ILI9341 display you're using?

Most of them work up to 30 MHz and much faster. Would be really helpful to know which models out there need to run slower.
 
Hello,

No problem, it is a module that I got from aliexpress:
https://fr.aliexpress.com/item/33040270372.html?spm=a2g0s.9042311.0.0.4d836c37psGsuk

Could the speed issue be due to the long connectors that I am using? VS a direct connection or a connection through a shield?

I was able to make some more progresses.
I can get it to work with tft.updateScreenAsync(true); BUT, I had to move the call a little bit lower in my code.
As if I needed to start performing some operation, or as if they was some timing/delay needed before I could call it.

Also, in the demo, the first part of the demo (what is in the setup call) did work. But the code in the "loop" function did not.
I found that by commenting out tft.setRotation(rotation); it was back to working. This seems as if a call to tft.setRotation is not compatible with async update. Am I missing something? I will be trying to stop the update annd wait for completion, change the rotation and turn it back on to test...

IMG_1824.jpg

Cyrille
 
Last edited:
Status
Not open for further replies.
Back
Top