Добрый день всем. Задам вопрос по нелюбимому многими модулю esp-32-cam. Данный модуль однако в наличии есть и с ним что то надо делать )) Допустим мы сделали фото и имеем сохраненный jpeg файл . Есть какая то стандартная возможность работы с ним? Отправка по ftp или копирование в другим именем?
Из имеющихся методов file.read(buf,len); file.write(buf,len); ничего не работает. По крайнем мере модуль сразу уходит у меня в ребут и ничего не записывается. Вернее создается максимум пустой jpeg.
по сути обнаружил единственную возможность такой работы - это копирование по частям в буфер в виде заранее созданного unsigned char PROGMEN массива, затем file.write( или ftp.write(. Но на мой взгляд это совершенно извращенный способ работы с файлами.
Может кто то просветить возможно ли как то еще записывать и изменять jpeg файлы ?
Феерично
Записать на карту памяти, а обработать потом.
Это так красиво в фильмах выглядит…
Я даже не говорю про обработать. Просто тупо скопировать например с другим именем или отправить уже готовый файл по ftp.
Где мы имеем сохраненный файл?
Работал с данными модулями в качестве функции распознавания лиц годик назад. Покупал у разных продавцов, более десятка штук точно было. Так вот, китайцы сами этот модуль сделали нелюбимым для программистов. Как раз признаки как у топикстартера. А причина банальна. Они ставили вместо нормальной внешней микросхемы ОЗУ, пустышки. Я практически на всех модулях заменил эту восьминогую микруху, которая отдельно стоит чуть дороже самого модуля включая камеру. Так что прежде чем решать что то программно, надо у железа восстановить полную функциональность.
@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;
}