rewrite Camera initialisation

now SD mmc and camera seems working side by side
This commit is contained in:
Luc 2019-11-03 09:14:50 +01:00
parent 6d5c08be24
commit c0c294105f
7 changed files with 182 additions and 53 deletions

View File

@ -58,7 +58,7 @@ bool Commands::ESP170(const char* cmd_params, level_authenticate_type auth_type,
if (parameter == "ON") { if (parameter == "ON") {
esp3d_camera.begin(); esp3d_camera.begin();
} else { } else {
esp3d_camera.end(); esp3d_camera.stopHardware();
} }
output->printMSG ("ok"); output->printMSG ("ok");
} }

View File

@ -39,13 +39,25 @@ bool Commands::ESP172(const char* cmd_params, level_authenticate_type auth_type,
#else #else
(void)auth_type; (void)auth_type;
#endif //AUTHENTICATION_FEATURE #endif //AUTHENTICATION_FEATURE
if (!esp3d_camera.started()) {
output->printERROR("No camera initialized!", 401);
return false;
}
parameter = get_param (cmd_params, ""); parameter = get_param (cmd_params, "");
//get //get
bool plain = hastag (cmd_params, "plain"); bool plain = hastag (cmd_params, "plain");
if ((parameter.length() == 0) || plain) { if ((parameter.length() == 0) || plain) {
sensor_t * s = esp_camera_sensor_get(); sensor_t * s = esp_camera_sensor_get();
if (s == nullptr) {
if (!plain) {
output->print ("{\"status\":\"error\"}");
} else {
output->printERROR("No camera initialized!", 401);
}
return false;
}
if (!plain) { if (!plain) {
output->print ("{"); output->print ("{\"status\":\"ok\",");
} }
//framesize //framesize
if (!plain) { if (!plain) {

View File

@ -142,15 +142,15 @@
#endif //CAMERA_MODEL_M5STACK_WIDE #endif //CAMERA_MODEL_M5STACK_WIDE
#if CAMERA_DEVICE == CAMERA_MODEL_AI_THINKER #if CAMERA_DEVICE == CAMERA_MODEL_AI_THINKER
#define CAM_LED_PIN -1 #define CAM_LED_PIN -1 //used by SD so must left unset
#define CAM_PULLUP1 -1 #define CAM_PULLUP1 -1
#define CAM_PULLUP2 -1 #define CAM_PULLUP2 -1
#define PWDN_GPIO_NUM 32 #define PWDN_GPIO_NUM 32
#define RESET_GPIO_NUM -1 #define RESET_GPIO_NUM -1
#define XCLK_GPIO_NUM 0 #define XCLK_GPIO_NUM 0
#define SIOD_GPIO_NUM 26 #define SIOD_GPIO_NUM 26
#define SIOC_GPIO_NUM 27 #define SIOC_GPIO_NUM 27
#define Y9_GPIO_NUM 35 #define Y9_GPIO_NUM 35
#define Y8_GPIO_NUM 34 #define Y8_GPIO_NUM 34
#define Y7_GPIO_NUM 39 #define Y7_GPIO_NUM 39
@ -167,7 +167,7 @@
//Pins for the support of SD Card Reader //Pins for the support of SD Card Reader
//-1 means use default pins of your board defined core //-1 means use default pins of your board defined core
#define ESP_SD_CS_PIN -1 #define ESP_SD_CS_PIN -1
//These are hardcoded on ESP8266 to 12/13/14 //These are hardcoded on ESP8266 to 12/13/14
//so modifications are ignored on ESP8266 //so modifications are ignored on ESP8266
#define ESP_SD_MISO_PIN -1 #define ESP_SD_MISO_PIN -1
#define ESP_SD_MOSI_PIN -1 #define ESP_SD_MOSI_PIN -1

View File

@ -22,7 +22,7 @@
#define _VERSION_ESP3D_H #define _VERSION_ESP3D_H
//version and sources location //version and sources location
#define FW_VERSION "3.0.0.a26" #define FW_VERSION "3.0.0.a27"
#define REPOSITORY "https://github.com/luc-github/ESP3D" #define REPOSITORY "https://github.com/luc-github/ESP3D"
#endif //_VERSION_ESP3D_H #endif //_VERSION_ESP3D_H

View File

@ -28,9 +28,12 @@
#include "esp_http_server.h" #include "esp_http_server.h"
#include <esp_camera.h> #include <esp_camera.h>
#include "fd_forward.h" #include "fd_forward.h"
//#include <soc/soc.h> //not sure this one is needed
#include <soc/rtc_cntl_reg.h> #include <soc/rtc_cntl_reg.h>
#include <driver/i2c.h>
#define DEFAULT_FRAME_SIZE FRAMESIZE_SVGA #define DEFAULT_FRAME_SIZE FRAMESIZE_SVGA
#define HTTP_TASK_PRIORITY 5
#define PART_BUFFER_SIZE 64 #define PART_BUFFER_SIZE 64
#define JPEG_COMPRESSION 80 #define JPEG_COMPRESSION 80
#define MIN_WIDTH_COMPRESSION 400 #define MIN_WIDTH_COMPRESSION 400
@ -45,12 +48,17 @@ Camera esp3d_camera;
//to break the loop //to break the loop
static void disconnected_uri(httpd_handle_t hd, int sockfd) static void disconnected_uri(httpd_handle_t hd, int sockfd)
{ {
log_esp3d("Camera stream disconnected");
esp3d_camera.connect(false); esp3d_camera.connect(false);
} }
static esp_err_t stream_handler(httpd_req_t *req) static esp_err_t stream_handler(httpd_req_t *req)
{ {
log_esp3d("Camera stream reached");
if (!esp3d_camera.started()) { if (!esp3d_camera.started()) {
const char* resp = "Camera not started";
log_esp3d("Camera not started");
httpd_resp_send(req, resp, strlen(resp));
return ESP_FAIL; return ESP_FAIL;
} }
esp3d_camera.connect(true); esp3d_camera.connect(true);
@ -63,21 +71,33 @@ static esp_err_t stream_handler(httpd_req_t *req)
uint8_t * _jpg_buf = NULL; uint8_t * _jpg_buf = NULL;
char * part_buf[PART_BUFFER_SIZE]; char * part_buf[PART_BUFFER_SIZE];
dl_matrix3du_t *image_matrix = NULL; dl_matrix3du_t *image_matrix = NULL;
log_esp3d("Camera stream reached");
res = httpd_resp_set_type(req, _STREAM_CONTENT_TYPE); res = httpd_resp_set_type(req, _STREAM_CONTENT_TYPE);
if(res != ESP_OK) { if(res != ESP_OK) {
esp3d_camera.connect(false); esp3d_camera.connect(false);
const char* resp = "Stream type failed";
log_esp3d("Stream type failed");
httpd_resp_send(req, resp, strlen(resp));
return res; return res;
} }
uint8_t retry = 0;
while(true) { while(true) {
if (!esp3d_camera.isconnected()) { if (!esp3d_camera.isconnected()) {
const char* resp = "Camera is not connected";
log_esp3d("Camera is not connected");
httpd_resp_send(req, resp, strlen(resp));
return ESP_FAIL; return ESP_FAIL;
} }
log_esp3d("Camera capture ongoing"); log_esp3d("Camera capture ongoing");
fb = esp_camera_fb_get(); fb = esp_camera_fb_get();
if (!fb) { if (!fb) {
log_esp3d("Camera capture failed"); log_esp3d("Camera capture failed");
res = ESP_FAIL; if ( retry < 3) {
log_esp3d("Retry %d",retry );
retry ++;
continue;
} else {
res = ESP_FAIL;
}
} else { } else {
if(fb->width > MIN_WIDTH_COMPRESSION) { if(fb->width > MIN_WIDTH_COMPRESSION) {
if(fb->format != PIXFORMAT_JPEG) { if(fb->format != PIXFORMAT_JPEG) {
@ -164,6 +184,9 @@ int Camera::command(const char * param, const char * value)
int res = 0; int res = 0;
int val = atoi(value); int val = atoi(value);
sensor_t * s = esp_camera_sensor_get(); sensor_t * s = esp_camera_sensor_get();
if (s == nullptr) {
res = -1;
}
#if CAM_LED_PIN != -1 #if CAM_LED_PIN != -1
if (!strcmp(param, "light")) { if (!strcmp(param, "light")) {
digitalWrite(CAM_LED_PIN, val==1?HIGH:LOW); digitalWrite(CAM_LED_PIN, val==1?HIGH:LOW);
@ -233,7 +256,7 @@ bool Camera::initHardware(bool forceinit)
if (_initialised) { if (_initialised) {
return _initialised; return _initialised;
} }
stopHardware(); log_esp3d("Disable brown out");
WRITE_PERI_REG(RTC_CNTL_BROWN_OUT_REG, 0); //disable brownout detector WRITE_PERI_REG(RTC_CNTL_BROWN_OUT_REG, 0); //disable brownout detector
camera_config_t config; camera_config_t config;
config.ledc_channel = LEDC_CHANNEL_0; config.ledc_channel = LEDC_CHANNEL_0;
@ -254,19 +277,20 @@ bool Camera::initHardware(bool forceinit)
config.pin_sscb_scl = SIOC_GPIO_NUM; config.pin_sscb_scl = SIOC_GPIO_NUM;
config.pin_pwdn = PWDN_GPIO_NUM; config.pin_pwdn = PWDN_GPIO_NUM;
config.pin_reset = RESET_GPIO_NUM; config.pin_reset = RESET_GPIO_NUM;
config.xclk_freq_hz = 20000000; config.xclk_freq_hz = 10000000;
config.pixel_format = PIXFORMAT_JPEG; config.pixel_format = PIXFORMAT_JPEG;
//init with high specs to pre-allocate larger buffers config.jpeg_quality = 5;
if(psramFound()) { config.fb_count = 1;
config.frame_size = DEFAULT_FRAME_SIZE; config.frame_size = DEFAULT_FRAME_SIZE;
config.jpeg_quality = 10; if(!psramFound()) {
config.fb_count = 2; _initialised = false;
} else { log_esp3d("psram is not enabled");
config.frame_size = DEFAULT_FRAME_SIZE; return false;
config.jpeg_quality = 12;
config.fb_count = 1;
} }
if (!stopHardware()) {
log_esp3d("Stop camera failed");
}
log_esp3d("Init camera");
#if CAM_PULLUP1 != -1 #if CAM_PULLUP1 != -1
pinMode(CAM_PULLUP1, INPUT_PULLUP); pinMode(CAM_PULLUP1, INPUT_PULLUP);
#endif //CAM_PULLUP1 #endif //CAM_PULLUP1
@ -277,28 +301,28 @@ bool Camera::initHardware(bool forceinit)
pinMode(CAM_LED_PIN, OUTPUT); pinMode(CAM_LED_PIN, OUTPUT);
digitalWrite(CAM_LED_PIN, LOW); digitalWrite(CAM_LED_PIN, LOW);
#endif //CAM_LED_PIN #endif //CAM_LED_PIN
// camera init //initialize the camera
//https://github.com/espressif/esp32-camera/issues/66#issuecomment-526283681
#if CAMERA_DEVICE == CAMERA_MODEL_AI_THINKER
log_esp3d("Specific config for CAMERA_MODEL_AI_THINKER");
gpio_config_t gpio_pwr_config;
gpio_pwr_config.pin_bit_mask = (1ULL << 32);
gpio_pwr_config.mode = GPIO_MODE_OUTPUT;
gpio_pwr_config.pull_down_en = GPIO_PULLDOWN_DISABLE;
gpio_pwr_config.pull_up_en = GPIO_PULLUP_DISABLE;
gpio_pwr_config.intr_type = GPIO_INTR_DISABLE;
gpio_config(&gpio_pwr_config);
gpio_set_level(GPIO_NUM_32,0);
#endif //CAMERA_DEVICE == CAMERA_MODEL_AI_THINKER
log_esp3d("Init camera config");
esp_err_t err = esp_camera_init(&config); esp_err_t err = esp_camera_init(&config);
if (err != ESP_OK) { if (err != ESP_OK) {
log_esp3d("Camera init failed with error 0x%x", err); log_esp3d("Camera init failed with error 0x%x", err);
return false; _initialised = false;
} else {
_initialised = true;
} }
sensor_t * s = esp_camera_sensor_get();
//initial sensors are flipped vertically and colors are a bit saturated
if (s->id.PID == OV3660_PID) {
s->set_brightness(s, 1);//up the blightness just a bit
s->set_saturation(s, -2);//lower the saturation
}
s->set_framesize(s, DEFAULT_FRAME_SIZE);
#if defined(CAMERA_DEVICE_FLIP_HORIZONTALY)
s->set_hmirror(s, 1);
#endif //CAMERA_DEVICE_FLIP_HORIZONTALY
#if defined(CAMERA_DEVICE_FLIP_VERTICALY)
s->set_vflip(s, 1);
#endif //CAMERA_DEVICE_FLIP_VERTICALY
_initialised = true;
return _initialised; return _initialised;
} }
@ -306,17 +330,50 @@ bool Camera::stopHardware()
{ {
end(); end();
_initialised = false; _initialised = false;
log_esp3d("Stop cam"); log_esp3d("deinit camera");
return (esp_camera_deinit() == ESP_OK); esp_err_t err = esp_camera_deinit();
if(err == ESP_OK) {
//seems sometimes i2c install failed when doing camera init so let's remove if already installed
if(i2c_driver_delete(I2C_NUM_1)!= ESP_OK) {
log_esp3d("I2C 1 delete failed");
}
return true;
} else {
log_esp3d("Camera deinit failed with error 0x%x", err);
return false;
}
} }
//need to be call by device and by network //need to be call by device and by network
bool Camera::begin(bool forceinit) bool Camera::begin(bool forceinit)
{ {
end(); end();
log_esp3d("Begin camera");
if (!initHardware(forceinit) ) { if (!initHardware(forceinit) ) {
log_esp3d("Init hardware failed");
return false; return false;
} }
delay(1000);
log_esp3d("Init camera sensor settings");
sensor_t * s = esp_camera_sensor_get();
if (s != nullptr) {
//initial sensors are flipped vertically and colors are a bit saturated
if (s->id.PID == OV3660_PID) {
s->set_brightness(s, 1);//up the blightness just a bit
s->set_saturation(s, -2);//lower the saturation
}
s->set_framesize(s, DEFAULT_FRAME_SIZE);
#if defined(CAMERA_DEVICE_FLIP_HORIZONTALY)
s->set_hmirror(s, 1);
#endif //CAMERA_DEVICE_FLIP_HORIZONTALY
#if defined(CAMERA_DEVICE_FLIP_VERTICALY)
s->set_vflip(s, 1);
#endif //CAMERA_DEVICE_FLIP_VERTICALY
} else {
log_esp3d("Cannot access camera sensor");
}
if (NetConfig::started() && (NetConfig::getMode()!= ESP_BT)) { if (NetConfig::started() && (NetConfig::getMode()!= ESP_BT)) {
ESP3DOutput output(ESP_ALL_CLIENTS); ESP3DOutput output(ESP_ALL_CLIENTS);
httpd_config_t httpdconfig = HTTPD_DEFAULT_CONFIG(); httpd_config_t httpdconfig = HTTPD_DEFAULT_CONFIG();
@ -330,17 +387,30 @@ bool Camera::begin(bool forceinit)
_port = Settings_ESP3D::read_uint32(ESP_CAMERA_PORT); _port = Settings_ESP3D::read_uint32(ESP_CAMERA_PORT);
httpdconfig.server_port = _port; httpdconfig.server_port = _port;
httpdconfig.ctrl_port = httpdconfig.server_port +1; httpdconfig.ctrl_port = httpdconfig.server_port +1;
httpdconfig.task_priority = 1; httpdconfig.task_priority = HTTP_TASK_PRIORITY;
log_esp3d("Starting camera server");
if (httpd_start(&stream_httpd, &httpdconfig) == ESP_OK) { if (httpd_start(&stream_httpd, &httpdconfig) == ESP_OK) {
httpd_register_uri_handler(stream_httpd, &stream_uri);
String stmp = "Camera server started port " + String(httpdconfig.server_port); String stmp = "Camera server started port " + String(httpdconfig.server_port);
output.printMSG(stmp.c_str()); output.printMSG(stmp.c_str());
log_esp3d("Registering /stream");
if (httpd_register_uri_handler(stream_httpd, &stream_uri) != ESP_OK) {
log_esp3d("Registering /stream failed");
}
} else { } else {
log_esp3d("Starting camera server failed");
output.printERROR("Starting camera server failed"); output.printERROR("Starting camera server failed");
return false; return false;
} }
_started = true; _started = true;
} }
for (int j = 0; j < 5; j++) {
camera_fb_t * fb = esp_camera_fb_get(); // start the camera ... warm it up
if (fb == nullptr) {
log_esp3d("Failed to get fb");
}
esp_camera_fb_return(fb);
delay(20);
}
return _started; return _started;
} }
@ -349,22 +419,27 @@ void Camera::end()
if (_started) { if (_started) {
_started = false; _started = false;
_connected = false; _connected = false;
log_esp3d("unregister /stream");
if (ESP_OK != httpd_unregister_uri(stream_httpd, "/stream")) { if (ESP_OK != httpd_unregister_uri(stream_httpd, "/stream")) {
log_esp3d("Error unregistering /stream"); log_esp3d("Error unregistering /stream");
} }
log_esp3d("Stop httpd");
if (ESP_OK != httpd_stop(stream_httpd)) { if (ESP_OK != httpd_stop(stream_httpd)) {
log_esp3d("Error stopping stream server"); log_esp3d("Error stopping stream server");
} }
} }
} }
void Camera::handle() void Camera::handle()
{ {
//so far nothing to do //so far nothing to do
} }
uint8_t Camera::GetModel() uint8_t Camera::GetModel()
{ {
return CAMERA_DEVICE; return CAMERA_DEVICE;
} }
const char *Camera::GetModelString() const char *Camera::GetModelString()
{ {
#if defined(CUSTOM_CAMERA_NAME) #if defined(CUSTOM_CAMERA_NAME)

View File

@ -57,6 +57,12 @@ bool DevicesServices::begin()
{ {
bool res = true; bool res = true;
_started = false; _started = false;
#ifdef SD_DEVICE
if (!ESP_SD::begin()) {
log_esp3d("Error sd intialization failed");
res = false;
}
#endif //SD_DEVICE
#ifdef DISPLAY_DEVICE #ifdef DISPLAY_DEVICE
if (!esp3d_display.begin()) { if (!esp3d_display.begin()) {
log_esp3d("Error starting display device"); log_esp3d("Error starting display device");
@ -87,12 +93,6 @@ bool DevicesServices::begin()
res = false; res = false;
} }
#endif //CAMERA_DEVICE #endif //CAMERA_DEVICE
#ifdef SD_DEVICE
if (!ESP_SD::begin()) {
log_esp3d("Error sd intialization failed");
res = false;
}
#endif //SD_DEVICE
if (!res) { if (!res) {
end(); end();
} }

View File

@ -29,8 +29,14 @@ sdio_esp32.cpp - ESP3D sd support class
extern File tSDFile_handle[ESP_MAX_SD_OPENHANDLE]; extern File tSDFile_handle[ESP_MAX_SD_OPENHANDLE];
#define SDMMC_FORCE_BEGIN
uint8_t ESP_SD::getState(bool refresh) uint8_t ESP_SD::getState(bool refresh)
{ {
static bool lastinitok = false;
#ifdef SDMMC_FORCE_BEGIN
lastinitok = false;
#endif //SDMMC_LIGHT_CHECK
#if defined(ESP_SD_DETECT_PIN) && ESP_SD_DETECT_PIN != -1 #if defined(ESP_SD_DETECT_PIN) && ESP_SD_DETECT_PIN != -1
//no need to go further if SD detect is not correct //no need to go further if SD detect is not correct
if (!((digitalRead (ESP_SD_DETECT_PIN) == ESP_SD_DETECT_VALUE) ? true : false)) { if (!((digitalRead (ESP_SD_DETECT_PIN) == ESP_SD_DETECT_VALUE) ? true : false)) {
@ -46,14 +52,44 @@ uint8_t ESP_SD::getState(bool refresh)
return _state; //to avoid refresh=true + busy to reset SD and waste time return _state; //to avoid refresh=true + busy to reset SD and waste time
} }
//SD is idle or not detected, let see if still the case //SD is idle or not detected, let see if still the case
SD_MMC.end();
_state = ESP_SDCARD_NOT_PRESENT; _state = ESP_SDCARD_NOT_PRESENT;
//using default value for speed ? should be parameter
//refresh content if card was removed //refresh content if card was removed
if (SD_MMC.begin()) { if (!lastinitok) {
if ( SD_MMC.cardSize() > 0 ) { log_esp3d("last init was failed try sd_mmc begin");
//SD_MMC.end();
if (SD_MMC.begin()) {
log_esp3d("sd_mmc begin succeed");
if (SD_MMC.cardType() != CARD_NONE ) {
_state = ESP_SDCARD_IDLE;
lastinitok = true;
log_esp3d("sd_mmc card type succeed");
} else {
log_esp3d("sd_mmc card type failed");
}
} else {
log_esp3d("sd_mmc begin failed");
}
} else {
log_esp3d("last init was ok try card type");
if(SD_MMC.cardType() != CARD_NONE) {
log_esp3d("checking sd_mmc card type succeed");
_state = ESP_SDCARD_IDLE; _state = ESP_SDCARD_IDLE;
} else {
lastinitok = false;
log_esp3d("Soft sd check failed");
//SD_MMC.end();
if (SD_MMC.begin()) {
log_esp3d("new sd_mmc begin succeed");
if ( SD_MMC.cardType() != CARD_NONE ) {
_state = ESP_SDCARD_IDLE;
lastinitok = true;
log_esp3d("new sd_mmc card type succeed");
} else {
log_esp3d("new sd_mmc card type failed");
}
} else {
log_esp3d("new sd_mmc begin failed");
}
} }
} }
return _state; return _state;
@ -61,8 +97,14 @@ uint8_t ESP_SD::getState(bool refresh)
bool ESP_SD::begin() bool ESP_SD::begin()
{ {
log_esp3d("Begin SDIO");
_started = true; _started = true;
#ifdef SDMMC_FORCE_BEGIN
_state = ESP_SDCARD_NOT_PRESENT; _state = ESP_SDCARD_NOT_PRESENT;
#else
_state = getState(true);
#endif //SDMMC_FORCE_BEGIN
return _started; return _started;
} }