Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

(info) Speeding up SD writing on ESP32-CAM with OV2640 camera #182

Closed
jameszah opened this issue Sep 25, 2020 · 8 comments
Closed

(info) Speeding up SD writing on ESP32-CAM with OV2640 camera #182

jameszah opened this issue Sep 25, 2020 · 8 comments

Comments

@jameszah
Copy link

Here is a bit of info on how to improve the speed of writing jpegs from the esp32-cam to an sd card.

Anyone who has tried to write photos from the esp32-cam to the sd card knows this line:

file.write(fb->buf, fb->len);

This is not a good line. It writes from the psram over the spi bus, to the sd card using either spi, or 4-bit sd_mmc or 1-bit sd_mmc, depending how you set up the sd card.

But if you replace that line with:

uint8_t framebuffer_static[32 * 1024];
memcpy(framebuffer_static, fb->buf,  fb->len);
file.write(framebuffer_static, fb->len);

it will do the operation about 5+ times faster. Here you do the memcpy to take the frame from the psram to the static ram over the spi bus, and then do the static ram to sd write. When you go from the psram directly to the sd card, the driver must grab little blocks of the data for each sd write, so the spi to the psram is constantly starting and stopping and slowing you down, while the memcpy just goes full speed for an entire 32k buffer, and then the sd write function can operate as fast as the sd will operate.

The only cost is that you have to use a block of precious static ram, plus you will have to break big frames into multiple writes of 32kb or 64kb.

Using this approach my https://github.com/jameszah/ESP32-CAM-Video-Recorder-junior
can write an avi movie on cheap class 10 (circle 10 U1) sd card at the full performance of the OV2640 camera -- 6 fps in UXGA mode, and 25 fps is SVGA mode.

@Arkanic
Copy link

Arkanic commented Apr 5, 2022

thanks, this was really helpful

@Shanjor1256
Copy link

Hello!

I am trying to implement this code into my camera code and I am getting an error where the system just resets:

rst:0x8 (TG1WDT_SYS_RESET),boot:0x13 (SPI_FAST_FLASH_BOOT)

Is there something besides replacing the file.write(fb->buf, fb->len); line with your code that I need to do?

@jameszah
Copy link
Author

That is a WatchDogTimeout -- like the sd card did not respond. Maybe a bad card, or just a bad connection, ... make sure it is formatted fat32 ... cards bigger than 4GB(?) are not normally formatted fat32. You have to open the file of course .... you could copy the code from that program mentioned above.

@Shanjor1256
Copy link

Shanjor1256 commented Feb 13, 2023

I am still working on it, I continue to get the same error whenever I start the code. I am currently working with a 32 GB card, though it is freshly formatted FAT32.

``static void save_photo(int i, camera_fb_t *fb) {
// Path where new picture will be saved in SD Card
String path = "/incident" + String(incidentNumber) + "/picture" + String(i) +".jpg";

fs::FS &fs = SD_MMC;

File file = fs.open(path.c_str(), FILE_WRITE);
uint8_t framebuffer_static[32 * 1024];
memcpy(framebuffer_static, fb->buf, fb->len);
file.write(framebuffer_static, fb->len);
file.close();
}``

When I use the file.write(fb->buf, fb->len); line I have no problems like this. Is there any possible solution besides using a new 4GB SD card?

@jameszah
Copy link
Author

Define the static frame buffer as a global -- it uses dma and needs access to the memory ... not allocated/ deallocated during that block.
If the sd works without the dma, then the sd should be fine.

@Shanjor1256
Copy link

Ok I defined the static frame buffer as a global, and I am not getting the same error anymore, but now my code is just stopping with no error message and a huge blank block being entered into my serial monitor. This stoppage seems to occur at the memcpy step. Here is the code that I use to create my photo burst, is there anything else I can try?

while (timeElapsed-timeStart < 3500) {

pictures = pictures + 1;
fb = esp_camera_fb_get();
save_photo(pictures, fb);
esp_camera_fb_return(fb);
timeElapsed = millis();

}

@jameszah
Copy link
Author

Are you sure your jpg's are less than 32kb? A memory corruption might explain the output to the serial monitor.

Are you sure that filename comes out correctly?

As an aside, it is time consuming to open and close files -- you could write the jpegs together in one file and close it at the end. Your computer will see it as an ".mjpeg" and view it, or unwrap it into the constituent jpgs.

You could post the entire program on your own github and Ill have a look.

@Shanjor1256
Copy link

I found that it works when I decrease my frame size or jpeg quality, when the frame size is XGA or lower it works, and when the jpeg quality is 20 or higher, it works (framesize UXGA). I do need to use the highest quality possible so I wonder if there is a way to make this work (I already increased the array size to 64 * 1024).

The filenames seem to work out well.

I attempted to write all the jpegs to one file and closing it at the end, but my computer is only seeing the one jpeg. I've tried changing FILE_WRITE to FILE_APPEND and that didn't work. Also I want to separate the different photo bursts into different files, do I need to clear the file with all the jpegs from one photo burst after it is over?

Also is it possible to increase the speed of the camera by removing color? I do not need color photos.

I will post my code to my github. Thank you.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants