But if immediately after the capture I get the same picture buffer via serial on my pc it's all ok:
I think that the issue is the memory management in FreeRTOS task and esp32-camera library: after the picture capture, I start the WiFi connection routine, that has vTaskDelay(), and soon after I start the FTP session.
Does anyone have any helpful guidance on why and how to fix it?
My camera setup is
Code: Select all
void Camera_Setup( void )
{
// Turn-off the 'brownout detector'
WRITE_PERI_REG( RTC_CNTL_BROWN_OUT_REG, 0 );
camera_config_t config;
esp_err_t err;
pictureBuffer = NULL;
config.ledc_channel = LEDC_CHANNEL_0;
config.ledc_timer = LEDC_TIMER_0;
config.pin_d0 = Y2_GPIO_NUM;
config.pin_d1 = Y3_GPIO_NUM;
config.pin_d2 = Y4_GPIO_NUM;
config.pin_d3 = Y5_GPIO_NUM;
config.pin_d4 = Y6_GPIO_NUM;
config.pin_d5 = Y7_GPIO_NUM;
config.pin_d6 = Y8_GPIO_NUM;
config.pin_d7 = Y9_GPIO_NUM;
config.pin_xclk = XCLK_GPIO_NUM;
config.pin_pclk = PCLK_GPIO_NUM;
config.pin_vsync = VSYNC_GPIO_NUM;
config.pin_href = HREF_GPIO_NUM;
config.pin_sccb_sda = SIOD_GPIO_NUM;
config.pin_sccb_scl = SIOC_GPIO_NUM;
config.pin_pwdn = PWDN_GPIO_NUM;
config.pin_reset = RESET_GPIO_NUM;
config.xclk_freq_hz = 8000000;
config.pixel_format = PIXFORMAT_JPEG;
config.frame_size = FRAMESIZE_QVGA;
config.jpeg_quality = 10;
config.fb_location = CAMERA_FB_IN_PSRAM;
config.fb_count = 1;
config.grab_mode = CAMERA_GRAB_WHEN_EMPTY;
err = esp_camera_init( &config );
if ( err != ESP_OK )
{
ESP_LOGW( LOG_TAG_PICTURE_MANAGING, "Camera init failed with error 0x%x", err );
esp_restart();
}
else
{
ESP_LOGI( LOG_TAG_PICTURE_MANAGING, "Camera init succeeded" );
}
}
Code: Select all
#include <Arduino.h>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "freertos/timers.h"
#include "freertos/event_groups.h"
#include "ArduinoJson.h"
#include <ESP32_FTPClient.h>
#include "esp_camera.h"
#include "soc/soc.h" // Disable brownour problems
#include "soc/rtc_cntl_reg.h" // Disable brownour problems
#include "time.h"
camera_fb_t *pictureBuffer;
ulong pictureTime;
char pictureName[ 128 ];
TaskHandle_t submissionTaskHandle;
extern nodeStatus_t nodeStatus;
extern wifiCredentials_t wifiCredentials;
extern ftpCredentials_t ftpCredentials;
static boolean Ftp_Send( void )
{
uint16_t maxConnectionWaiting;
ulong timeFromPicture;
struct tm timeinfo;
ESP32_FTPClient ftp( ftpCredentials.server, ftpCredentials.port, ftpCredentials.user, ftpCredentials.pass, 5000, 2 );
maxConnectionWaiting = 0;
ftp.OpenConnection();
while ( ftp.isConnected() == false )
{
maxConnectionWaiting++;
vTaskDelay( 1000 / portTICK_PERIOD_MS );
if ( maxConnectionWaiting > FTP_CONNECTION_MAX_WAITING )
{
ESP_LOGW( LOG_TAG_PICTURE_MANAGING, "FTP connection failed!" );
return false;
}
}
timeFromPicture = millis() - pictureTime;
if ( !getLocalTime( &timeinfo ) )
{
ESP_LOGW( LOG_TAG_PICTURE_MANAGING, "Failed to obtain time for the picture name. Using local time instead" );
sprintf( pictureName, "%d.jpg", millis() );
}
else
{
timeinfo.tm_sec -= ( int )( timeFromPicture / 1000 );
sprintf( pictureName, "%d_%02d_%02d_%02d_%02d_%02d_%s.jpg", timeinfo.tm_year + 1900, timeinfo.tm_mon + 1, timeinfo.tm_mday, timeinfo.tm_hour, timeinfo.tm_min, timeinfo.tm_sec, nodeStatus.nodeId );
}
ftp.ChangeWorkDir( "images" );
ftp.InitFile( "Type I" );
ftp.NewFile( pictureName );
ftp.WriteData( pictureBuffer->buf, pictureBuffer->len );
ftp.CloseFile();
ftp.CloseConnection();
memset( pictureName, 0, sizeof( pictureName ) );
return true;
}
static boolean Wifi_Connect( void )
{
uint16_t maxConnectionTrials;
uint16_t maxConnectionWaiting;
ESP_LOGI( LOG_TAG_PICTURE_MANAGING, "Attempting WiFi connection to %s", wifiCredentials.ssid );
maxConnectionTrials = 0;
while ( maxConnectionTrials < WIFI_CONNECTION_MAX_TRIALS )
{
WiFi.begin( wifiCredentials.ssid, wifiCredentials.pass );
maxConnectionWaiting = 0;
while ( WiFi.status() != WL_CONNECTED )
{
maxConnectionWaiting++;
vTaskDelay( 1000 / portTICK_PERIOD_MS );
if ( maxConnectionWaiting > WIFI_CONNECTION_MAX_WAITING )
{
ESP_LOGW( LOG_TAG_PICTURE_MANAGING, "WiFi connection failed!" );
break;
}
}
if ( WiFi.status() == WL_CONNECTED )
{
ESP_LOGI( LOG_TAG_PICTURE_MANAGING, "Connected! My IP is %s", WiFi.localIP().toString().c_str() );
return true;
}
else
{
maxConnectionTrials++;
ESP_LOGI( LOG_TAG_PICTURE_MANAGING, "Try again in a few seconds..." );
WiFi.disconnect();
vTaskDelay( 5000 / portTICK_PERIOD_MS );
}
}
ESP_LOGW( LOG_TAG_PICTURE_MANAGING, "Somethings gone wrong in attempting WiFi connection" );
return false;
}
static void Get_Picture_Buffer( void )
{
if ( pictureBuffer == NULL )
{
ESP_LOGI( LOG_TAG_PICTURE_MANAGING, "Capturing image..." );
pictureBuffer = esp_camera_fb_get();
}
else
{
ESP_LOGW( LOG_TAG_PICTURE_MANAGING, "Picture buffer is not empty" );
}
}
static void Release_Picture_Buffer( void )
{
if ( pictureBuffer != NULL )
{
esp_camera_fb_return( pictureBuffer );
pictureBuffer = NULL;
ESP_LOGI( LOG_TAG_PICTURE_MANAGING, "Camera buffer released" );
}
else
{
ESP_LOGI( LOG_TAG_PICTURE_MANAGING, "Camera buffer NULL, nothing to release" );
}
}
static void Take_Send_Picture_Task( void *pvParameters )
{
Get_Picture_Buffer();
pictureTime = millis();
if ( !pictureBuffer )
{
ESP_LOGW( LOG_TAG_PICTURE_MANAGING, "Camera capture failed" );
}
else
{
ESP_LOGI( LOG_TAG_PICTURE_MANAGING, "Done! Size of the image %d bytes", pictureBuffer->len );
if ( pictureBuffer->format != PIXFORMAT_JPEG )
{
ESP_LOGW( LOG_TAG_PICTURE_MANAGING, "Capture Error: Non-JPEG image returned by camera module" );
}
else
{
ESP_LOGI( LOG_TAG_PICTURE_MANAGING, "Capture OK: JPEG image returned by camera module" );
if ( Wifi_Connect() == true )
{
Led_Status_Set( STATUS_LED_CONNECTED ); // This function updates the status led task
Init_Time( TIMEZONE ); // This function updates the local time
if ( Ftp_Send() == true )
{
// Other code after FTP submission
}
}
Release_Picture_Buffer();
}
}
vTaskDelete( NULL );
}
void Start_Picture_Submission( void )
{
submissionTaskHandle = NULL;
xTaskCreate( Take_Send_Picture_Task, "Take_Send_Picture_Task", TASK_TAKE_SEND_PICTURE_DEPTH, NULL, TASK_TAKE_SEND_PICTURE_PRIORITY, &submissionTaskHandle );
}