ESP-32-CAM работа с jpeg файлом

Добрый день всем. Задам вопрос по нелюбимому многими модулю esp-32-cam. Данный модуль однако в наличии есть и с ним что то надо делать )) Допустим мы сделали фото и имеем сохраненный jpeg файл . Есть какая то стандартная возможность работы с ним? Отправка по ftp или копирование в другим именем?
Из имеющихся методов file.read(buf,len); file.write(buf,len); ничего не работает. По крайнем мере модуль сразу уходит у меня в ребут и ничего не записывается. Вернее создается максимум пустой jpeg.
по сути обнаружил единственную возможность такой работы - это копирование по частям в буфер в виде заранее созданного unsigned char PROGMEN массива, затем file.write( или ftp.write(. Но на мой взгляд это совершенно извращенный способ работы с файлами.
Может кто то просветить возможно ли как то еще записывать и изменять jpeg файлы ?

Феерично

Записать на карту памяти, а обработать потом.
Это так красиво в фильмах выглядит…

Я даже не говорю про обработать. Просто тупо скопировать например с другим именем или отправить уже готовый файл по ftp.

Где мы имеем сохраненный файл?

Работал с данными модулями в качестве функции распознавания лиц годик назад. Покупал у разных продавцов, более десятка штук точно было. Так вот, китайцы сами этот модуль сделали нелюбимым для программистов. Как раз признаки как у топикстартера. А причина банальна. Они ставили вместо нормальной внешней микросхемы ОЗУ, пустышки. Я практически на всех модулях заменил эту восьминогую микруху, которая отдельно стоит чуть дороже самого модуля включая камеру. Так что прежде чем решать что то программно, надо у железа восстановить полную функциональность.

1 лайк

@SAB , не было такого, чтобы ESP прошивалось нормально, а потом ррраз - и “MD5 checksum error” в завершении процесса прошивки?

На SD карте

Причем здесь прошивка вообще. Сама ESP шьется без ошибок и может даже камера всё замечательно показывать с маленьким разрешением. Но как только увеличиваешь разрешение, вот тут и вылезают глюки. Частенько контроллер просто виснет (зависит как скетч написан), и помогает только ресет физический. После установки нормальной памяти озу всё начинает работать как часики.

Как я понимаю есть какое то ограничение на размер буфера который можно копировать в новый jpeg файл. Что то вроде 100кб. Надо в общем глубже покопать. Напишу что выяснилось.

Копирование в буфер по частям это самый типичный метод работы с файлами. Только ПРОГМЕМ тут лишний, не знаю что вы имели в виду

Я про ESP32 в целом, не про CAM конкретно.

Вобщем, сам спросил, сам отвечу, чтобы поисковик запомнил.

Если загрузка на ESP32 заканчивается чем-то типа:

Writing at 0x000bd32b... (100 %)
Wrote 710864 bytes (459725 compressed) at 0x00010000 in 10.4 seconds (effective 548.3 kbit/s)...
File  md5: 0265f76f68ea8e592346a34b119aaa65
Flash md5: 8ce3512f3216afea4c40961a861c5f67
MD5 of 0xFF is 843b1e5dfe10ab4a01cd1763d7becd7a

A fatal error occurred: MD5 of file does not match data in flash!
A fatal error occurred: MD5 of file does not match data in flash!

то может помочь следующее: esptool.exe --chip esp32 --port “COM16” --baud 115200 write_flash_status --non-volatile 0

В моём случае, видимо, плата была неудачно дёрнута в процессе записи.

В общем напишу, что пока выяснилось. С массивом PROGMEN я намудрил. Дело было не в этом. Такой массив не нужен. Работает вся конструкция только до размера файла(jpeg) не более 110кб. Следующим по размеру был файл 113кб и модуль вылетел в ребут. Надо попробовать какое то копирование по частям исходя их этого размера буфера. Ниже рабочий код. Может кому то понадобится.

//Копируем в другой файл
String fname; 

String path=“/foto/picture_163.jpg”;
File file2 = SD_MMC.open(path);
File file3 = SD_MMC.open(newdir+“/new.jpg”, FILE_WRITE);
long n= file2.size();

        unsigned char *buf {new unsigned char[n]};       
        for(int i=0; i<n; i++)
        {             
          buf[i]=file2.read(); 
          //file3.write(buf[i]);//можно и так копировать побайтно. Но все равно не более 110кб
        } 
        file3.write( buf, n );             
        delete buf;

file3.close();
file2.close();

Вновь спрошу по этой теме. На самом деле размер этого самого буфера выводится при компиляции программы строкой Serial.println(ESP.getMaxAllocHeap()); Т.е. размер так называемой “кучи”-Heap с которой может работать динамическая память. В итоге выводит Max Free Heap: 113792 - т.е. те самые искомые 113кб. Пытался итерационно добавлять в создаваемый файл байты через массив указателей, затем очищать массив и в следущей итерации работать как бы с уже новым буфером. Но после первой же итерации модуль на второй вылетает в ребут.

long bufsize=100000, ost = file2.size(), tek=0, sled=0, mnog=0, i;
while(ost>0){

        if (ost>bufsize) {mnog=bufsize;}  
        else {mnog=ost;}

        tek=sled;           
        sled=tek+mnog;

        for(i=tek;i<sled;i++){
          buf[i]=file2.read();
          
        }
        file3.write( buf, mnog );             
        
        ost=ost-mnog;
        
        delete [] buf;
        buf = nullptr;

}

Почему на работает такой код ? Вроде бы я после хода цикла очищаю выделенный в динамической памяти массив.
Но имеем…

Guru Meditation Error: Core 1 panic’ed (LoadStoreError). Exception was unhandled.
Core 1 register dump:
PC : 0x400d0cb0 PS : 0x00060630 A0 : 0x80154138 A1 : 0x3ffb1df0
A2 : 0x3ffc2344 A3 : 0x40000000 A4 : 0x0001bdf3 A5 : 0x000186a0
A6 : 0x3ffe4374 A7 : 0x00030d40 A8 : 0x800d0cb0 A9 : 0x3ffb1dc0
A10 : 0x00000059 A11 : 0x00000006 A12 : 0x0000000a A13 : 0x3f4005ed
A14 : 0x00060220 A15 : 0x00000000 SAR : 0x0000000c EXCCAUSE: 0x00000003
EXCVADDR: 0x40000000 LBEG : 0x4008c6a4 LEND : 0x4008c6b7 LCOUNT : 0x00000000

ELF file SHA256: 0000000000000000

Backtrace: 0x400d0cb0:0x3ffb1df0 0x40154135:0x3ffb1e80 0x400d573e:0x3ffb1ea0 0x400d57e9:0x3ffb1ec0 0x400d5856:0x3ffb1ef0 0x400d59d6:0x3ffb1f40 0x400d0fea:0x3ffb1f90 0x400d7f9d:0x3ffb1fb0 0x4008f0c2:0x3ffb1fd0

Rebooting…

Аптамуш, он не полный. Даже не компилируется.

Очистку видно, а где выделение памяти ?

Вот же: long bufsize=100000

Так можно было ???

Да, сорри. Не добавил одну строчку.

long bufsize=100000, ost = file2.size(),tek=0,sled=0,mnog=0, i;
while(ost>0){

        if (ost>bufsize) {mnog=bufsize;}  
        else {mnog=ost;}
        
        tek=sled;           
        sled=tek+mnog;
     
       unsigned char *buf = new unsigned char[mnog];//Вот эту строчку не вставил
        for(i=tek;i<sled;i++){
          buf[i]=file2.read();
          
        }
        file3.write( buf, mnog );             
        
        ost=ost-mnog;
        
        delete [] buf;
        buf = nullptr;

}