Skip to content

ESP32 ESP-WHO IDF with Arduino component can't build software #5276

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

Closed
RickvF opened this issue Jun 10, 2021 · 22 comments
Closed

ESP32 ESP-WHO IDF with Arduino component can't build software #5276

RickvF opened this issue Jun 10, 2021 · 22 comments
Labels
Status: Stale Issue is stale stage (outdated/stuck)

Comments

@RickvF
Copy link

RickvF commented Jun 10, 2021

Hardware:

Board: ESP-EYE DevKit for AIoT Developers
IDE name: ESP-IDF, ESP-WHO, Arduino Esp32 component
Upload Speed: 115200
Computer OS: Windows 10 (Virtual box with Ubuntu 20.04.2.0 Desktop AMD64)

Description:

I have an ESP-EYE DevKit for AIoT Developers and wanted to develop my own program for it based on the examples/esp32/camera/CameraWebServer example as was available in the Arduino IDE. I developed the program with the Arduino IDE. The program includes HardwareSerial in order to communicate via the DOUT and DIN pin to another ESP-32. Also, I made some extensions to the webserver to support multiple web pages. Most of the source code is below.

This all is working pretty well via the Arduino IDE on Windows 10. However, when I connect with some browsers to the webserver running on my ESP-EYE, the Camera and options bar cannot be displayed due to an HTTP header issue (Header field are too long for the server to interpret). This HTTP header issue can be solved by changing the header length in the sdkconfig file (Max HTTP Request Header Length and Max HTTP URI Length). When I tried to do this in my Arduino installation (on various locations over the file system within Windows 10), did not improve anything.

So I got the suggestion to try to build the environment of ESP-IDF in Ubuntu. For this, I created a virtual box with Ubuntu 20.04.2.0-desktop-amd64 version.

Next, I followed this tutorial: https://gist.github.com/abobija/2721427f18d78e439fa9875cac960ffa. With this, I was able to run the Hello World example on my ESP-EYE.
Then I followed this tutorial to include the Arduino component: https://github.com/espressif/arduino-esp32/blob/master/docs/esp-idf_component.md. I also managed to run the hello world example.

In order to run the CameraWebServer example, instead of the ESP-IDF from the tutorial, I learned I needed the ESP-WHO environment, with the camera_web_server example as base.
So followed all those steps:

The steps to build esp-who SDK on Ubuntu are as follows:

Step 1. Install Prerequisites :
sudo apt-get install git wget libncurses-dev flex bison gperf python python-pip python-setuptools python-serial 
python-click python-cryptography python-future python-pyparsing python-pyelftools cmake ninja-build ccache libffi-dev libssl-dev

Step 2. Get ESP-WHO:
mkdir esp-who
cd ~/esp-who
git clone --recursive https://github.com/espressif/esp-who.git
cd esp-who
git submodule update -f --init --recursive  
git pull

Step 3. Set up the esp-idf environment variables under esp-who:
cd ~/esp-who/esp-idf
pwd
export IDF_PATH=~/esp-who/esp-idf

Step 4. Set up the tools 
cd ~/esp-who/esp-idf
./install.sh
. ./export.sh

Step 5. Start a Project:
cd ..
cd ~/esp-who/examples/single_chip/camera_web_server
idf.py build
idf.py flash monitor

Afterwards, I was able to successfully run the camera_web_server example on my ESP-EYE.

Again I followed this tutorial: https://github.com/espressif/arduino-esp32/blob/master/docs/esp-idf_component.md to include the Arduino component to the camera_web_server example folder, and I modified the program files in the camera_web_server example folder to my developed program.

Files I had in the camera_web_server/main folder after copying my own program to it:

  • app_httpd.cpp
  • main.cpp
  • camera_index.h
  • camera_pins.h
  • communication.h
  • pages.h
  • include (this was a folder)
  • www (this was a folder)
  • CMakeLists.txt (with modified COMPONENT_SRCS to: COMPONENT_SRCS "main.cpp")
  • component.mk
  • Kconfig.projbuild

Run make menuconfig and modified the HTTP request and HTTP URi Header length. Set in the Arduino configuration the flash size to Hugh App.

When I then run idf.py build this results in the error:

../main/main.cpp:2:10: fatal error: WiFi.h: No such file or directory
 #include "WiFi.h"
          ^~~~~~~~
compilation terminated.
[693/821] Building C object esp-idf/es...sp_littlefs.dir/src/littlefs/lfs.c.obj

ninja: build stopped: subcommand failed.
ninja failed with exit code 1

When I then run make flash monitor instead of idf.py build this results in the following error:

In file included from /home/rick/esp-who/esp-who/examples/single_chip/camera_web_server/components/arduino/cores/esp32/esp32-hal.h:74,
                 from /home/rick/esp-who/esp-who/examples/single_chip/camera_web_server/components/arduino/cores/esp32/esp32-hal-ledc.c:15:
/home/rick/esp-who/esp-who/examples/single_chip/camera_web_server/components/arduino/cores/esp32/esp32-hal-gpio.h:28:10: fatal error: soc/soc_caps.h: No such file or directory
 #include "soc/soc_caps.h"
          ^~~~~~~~~~~~~~~~
compilation terminated.
make[1]: *** [/home/rick/esp-who/esp-who/esp-idf/make/component_wrapper.mk:292: cores/esp32/esp32-hal-ledc.o] Error 1
make: *** [/home/rick/esp-who/esp-who/esp-idf/make/project.mk:590: component-arduino-build] Error 2

I have no clue anymore which steps to take in order to solve one of the two error messages, all in order to solve my initial issue:
That I need to increase the numbers for Max HTTP Request Header Length and Max HTTP URI Length.

Does some has an idea to help me out and to solve the bug I am facing?
Thanks already for all your ideas and suggestions.

Main.cpp

#include "esp_camera.h"
#include <WiFi.h>
#include <HardwareSerial.h>

#define CAMERA_MODEL_ESP_EYE

#include "camera_pins.h"
#include "communication.h"

#define LED 21

HardwareSerial Myserial(1);
bool sentIP = true;

const char* ssid = "";
const char* password = "";

String message = "";
String tempMessage = ""; 

long previousMillis = 0;
long interval = 30000;

void startCameraServer();

void printIP(){
  String ip = "/IP: " + WiFi.localIP().toString();
  char ipaddres[20];
  ip.toCharArray(ipaddres,20);
  for(int i=0; i<20; i++){
    Myserial.write(ipaddres[i]); //send the IP to the main controller, so it can be sent to the application
    Serial.write(ipaddres[i]);
  }
}

void setup() {
  Serial.begin(250000);
  Serial.setDebugOutput(false);
  Serial.println();

  //LED to show no WiFi yet
  pinMode(LED, OUTPUT);
  delay(500);
  digitalWrite(LED, HIGH);

  Myserial.begin(250000, SERIAL_8N1, 12, 2); //12 = DOUT = RX,  19 = CS = RX, ------------   2= DIN= TX, 0 = CLK = TX
  //use write() and read()

  camera_config_t config;
  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_sscb_sda = SIOD_GPIO_NUM;
  config.pin_sscb_scl = SIOC_GPIO_NUM;
  config.pin_pwdn = PWDN_GPIO_NUM;
  config.pin_reset = RESET_GPIO_NUM;
  config.xclk_freq_hz = 20000000;
  config.pixel_format = PIXFORMAT_JPEG;
  //init with high specs to pre-allocate larger buffers
  if(psramFound()){
    config.frame_size = FRAMESIZE_UXGA;
    config.jpeg_quality = 10;
    config.fb_count = 2;
  } else {
    config.frame_size = FRAMESIZE_SVGA;
    config.jpeg_quality = 12;
    config.fb_count = 1;
  }

#if defined(CAMERA_MODEL_ESP_EYE)
  pinMode(13, INPUT_PULLUP);
  pinMode(14, INPUT_PULLUP);
#endif

  // camera init
  esp_err_t err = esp_camera_init(&config);
  if (err != ESP_OK) {
//    Serial.printf("Camera init failed with error 0x%x", err);
    return;
  }

  sensor_t * s = esp_camera_sensor_get();
  s->set_vflip(s, 1);
  s->set_hmirror(s, 1);
  
  //initial sensors are flipped vertically and colors are a bit saturated
  if (s->id.PID == OV3660_PID) {
    s->set_vflip(s, 1);//flip it back
    s->set_brightness(s, 1);//up the blightness just a bit
    s->set_saturation(s, -2);//lower the saturation
  }
  //drop down frame size for higher initial frame rate
  s->set_framesize(s, FRAMESIZE_QVGA);

  WiFi.begin(ssid, password);

  while (WiFi.status() != WL_CONNECTED) {
    digitalWrite(LED, HIGH);
    delay(500);
    Serial.print(".");
  }
  Serial.println("");
  Serial.println("WiFi connected");

  startCameraServer();

  Serial.print("Camera Ready! Use 'http://");
  Serial.print(WiFi.localIP());
  Serial.println("' to connect");  
  digitalWrite(LED, LOW);
  printIP();
}

void loop() {
  unsigned long currentMillis = millis();
  if((sentIP) && (currentMillis - previousMillis > interval)) {
    previousMillis = currentMillis;  
    printIP();    
  }
  // put your main code here, to run repeatedly:  
  while (Myserial.available() > 0) {
    char input = (char)Myserial.read();
    if(input == '/'){
      tempMessage = "";
      message = "";
    }
    tempMessage += input;
    yield();
  } 

  if(tempMessage.indexOf("/IP: STOP") >= 0){
    sentIP = false;
  } else {
    message = tempMessage;
  }
  delay(500);
}

app_httpd.cpp

// Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#include "esp_http_server.h"
#include "esp_timer.h"
#include "esp_camera.h"
#include "img_converters.h"
#include "camera_index.h"
#include "Arduino.h"

#include "fb_gfx.h"
#include "fd_forward.h"
#include "fr_forward.h"

#include "pages.h"
#include "communication.h"

#define ENROLL_CONFIRM_TIMES 5
#define FACE_ID_SAVE_NUMBER 7

#define FACE_COLOR_WHITE  0x00FFFFFF
#define FACE_COLOR_BLACK  0x00000000
#define FACE_COLOR_RED    0x000000FF
#define FACE_COLOR_GREEN  0x0000FF00
#define FACE_COLOR_BLUE   0x00FF0000
#define FACE_COLOR_YELLOW (FACE_COLOR_RED | FACE_COLOR_GREEN)
#define FACE_COLOR_CYAN   (FACE_COLOR_BLUE | FACE_COLOR_GREEN)
#define FACE_COLOR_PURPLE (FACE_COLOR_BLUE | FACE_COLOR_RED)

typedef struct {
        size_t size; //number of values used for filtering
        size_t index; //current value index
        size_t count; //value count
        int sum;
        int * values; //array to be filled with values
} ra_filter_t;

typedef struct {
        httpd_req_t *req;
        size_t len;
} jpg_chunking_t;

#define PART_BOUNDARY "123456789000000000000987654321"
static const char* _STREAM_CONTENT_TYPE = "multipart/x-mixed-replace;boundary=" PART_BOUNDARY;
static const char* _STREAM_BOUNDARY = "\r\n--" PART_BOUNDARY "\r\n";
static const char* _STREAM_PART = "Content-Type: image/jpeg\r\nContent-Length: %u\r\n\r\n";

static ra_filter_t ra_filter;
httpd_handle_t stream_httpd = NULL;
httpd_handle_t camera_httpd = NULL;

static mtmn_config_t mtmn_config = {0};
static int8_t detection_enabled = 0;
static int8_t recognition_enabled = 0;
static int8_t is_enrolling = 0;
static face_id_list id_list = {0};

String requestHeader;
String tempHeader;

//#undef CONFIG_HTTPD_MAX_REQ_HDR_LEN
//#define CONFIG_HTTPD_MAX_REQ_HDR_LEN 2048
//#undef HTTPD_MAX_REQ_HDR_LEN
//#define HTTPD_MAX_REQ_HDR_LEN 4096

static ra_filter_t * ra_filter_init(ra_filter_t * filter, size_t sample_size){
    memset(filter, 0, sizeof(ra_filter_t));

    filter->values = (int *)malloc(sample_size * sizeof(int));
    if(!filter->values){
        return NULL;
    }
    memset(filter->values, 0, sample_size * sizeof(int));

    filter->size = sample_size;
    return filter;
}

static int ra_filter_run(ra_filter_t * filter, int value){
    if(!filter->values){
        return value;
    }
    filter->sum -= filter->values[filter->index];
    filter->values[filter->index] = value;
    filter->sum += filter->values[filter->index];
    filter->index++;
    filter->index = filter->index % filter->size;
    if (filter->count < filter->size) {
        filter->count++;
    }
    return filter->sum / filter->count;
}

static void rgb_print(dl_matrix3du_t *image_matrix, uint32_t color, const char * str){
    fb_data_t fb;
    fb.width = image_matrix->w;
    fb.height = image_matrix->h;
    fb.data = image_matrix->item;
    fb.bytes_per_pixel = 3;
    fb.format = FB_BGR888;
    fb_gfx_print(&fb, (fb.width - (strlen(str) * 14)) / 2, 10, color, str);
}

static int rgb_printf(dl_matrix3du_t *image_matrix, uint32_t color, const char *format, ...){
    char loc_buf[64];
    char * temp = loc_buf;
    int len;
    va_list arg;
    va_list copy;
    va_start(arg, format);
    va_copy(copy, arg);
    len = vsnprintf(loc_buf, sizeof(loc_buf), format, arg);
    va_end(copy);
    if(len >= sizeof(loc_buf)){
        temp = (char*)malloc(len+1);
        if(temp == NULL) {
            return 0;
        }
    }
    vsnprintf(temp, len+1, format, arg);
    va_end(arg);
    rgb_print(image_matrix, color, temp);
    if(len > 64){
        free(temp);
    }
    return len;
}

static void draw_face_boxes(dl_matrix3du_t *image_matrix, box_array_t *boxes, int face_id){
    int x, y, w, h, i;
    uint32_t color = FACE_COLOR_YELLOW;
    if(face_id < 0){
        color = FACE_COLOR_RED;
    } else if(face_id > 0){
        color = FACE_COLOR_GREEN;
    }
    fb_data_t fb;
    fb.width = image_matrix->w;
    fb.height = image_matrix->h;
    fb.data = image_matrix->item;
    fb.bytes_per_pixel = 3;
    fb.format = FB_BGR888;
    for (i = 0; i < boxes->len; i++){
        // rectangle box
        x = (int)boxes->box[i].box_p[0];
        y = (int)boxes->box[i].box_p[1];
        w = (int)boxes->box[i].box_p[2] - x + 1;
        h = (int)boxes->box[i].box_p[3] - y + 1;
        fb_gfx_drawFastHLine(&fb, x, y, w, color);
        fb_gfx_drawFastHLine(&fb, x, y+h-1, w, color);
        fb_gfx_drawFastVLine(&fb, x, y, h, color);
        fb_gfx_drawFastVLine(&fb, x+w-1, y, h, color);
#if 0
        // landmark
        int x0, y0, j;
        for (j = 0; j < 10; j+=2) {
            x0 = (int)boxes->landmark[i].landmark_p[j];
            y0 = (int)boxes->landmark[i].landmark_p[j+1];
            fb_gfx_fillRect(&fb, x0, y0, 3, 3, color);
        }
#endif
    }
}

static int run_face_recognition(dl_matrix3du_t *image_matrix, box_array_t *net_boxes){
    dl_matrix3du_t *aligned_face = NULL;
    int matched_id = 0;

    aligned_face = dl_matrix3du_alloc(1, FACE_WIDTH, FACE_HEIGHT, 3);
    if(!aligned_face){
//        Serial.println("Could not allocate face recognition buffer");
        return matched_id;
    }
    if (align_face(net_boxes, image_matrix, aligned_face) == ESP_OK){
        if (is_enrolling == 1){
            int8_t left_sample_face = enroll_face(&id_list, aligned_face);

            if(left_sample_face == (ENROLL_CONFIRM_TIMES - 1)){
//                Serial.printf("Enrolling Face ID: %d\n", id_list.tail);
            }
//            Serial.printf("Enrolling Face ID: %d sample %d\n", id_list.tail, ENROLL_CONFIRM_TIMES - left_sample_face);
            rgb_printf(image_matrix, FACE_COLOR_CYAN, "ID[%u] Sample[%u]", id_list.tail, ENROLL_CONFIRM_TIMES - left_sample_face);
            if (left_sample_face == 0){
                is_enrolling = 0;
//                Serial.printf("Enrolled Face ID: %d\n", id_list.tail);
            }
        } else {
            matched_id = recognize_face(&id_list, aligned_face);
            if (matched_id >= 0) {
//                Serial.printf("Match Face ID: %u\n", matched_id);
                rgb_printf(image_matrix, FACE_COLOR_GREEN, "Hello Subject %u", matched_id);
            } else {
//                Serial.println("No Match Found");
                rgb_print(image_matrix, FACE_COLOR_RED, "Intruder Alert!");
                matched_id = -1;
            }
        }
    } else {
//        Serial.println("Face Not Aligned");
        //rgb_print(image_matrix, FACE_COLOR_YELLOW, "Human Detected");
    }

    dl_matrix3du_free(aligned_face);
    return matched_id;
}

static size_t jpg_encode_stream(void * arg, size_t index, const void* data, size_t len){
    jpg_chunking_t *j = (jpg_chunking_t *)arg;
    if(!index){
        j->len = 0;
    }
    if(httpd_resp_send_chunk(j->req, (const char *)data, len) != ESP_OK){
        return 0;
    }
    j->len += len;
    return len;
}

static esp_err_t capture_handler(httpd_req_t *req){
    camera_fb_t * fb = NULL;
    esp_err_t res = ESP_OK;
    int64_t fr_start = esp_timer_get_time();

    fb = esp_camera_fb_get();
    if (!fb) {
//        Serial.println("Camera capture failed");
        httpd_resp_send_500(req);
        return ESP_FAIL;
    }

    httpd_resp_set_type(req, "image/jpeg");
    httpd_resp_set_hdr(req, "Content-Disposition", "inline; filename=capture.jpg");
    httpd_resp_set_hdr(req, "Access-Control-Allow-Origin", "*");

    size_t out_len, out_width, out_height;
    uint8_t * out_buf;
    bool s;
    bool detected = false;
    int face_id = 0;
    if(!detection_enabled || fb->width > 400){
        size_t fb_len = 0;
        if(fb->format == PIXFORMAT_JPEG){
            fb_len = fb->len;
            res = httpd_resp_send(req, (const char *)fb->buf, fb->len);
        } else {
            jpg_chunking_t jchunk = {req, 0};
            res = frame2jpg_cb(fb, 80, jpg_encode_stream, &jchunk)?ESP_OK:ESP_FAIL;
            httpd_resp_send_chunk(req, NULL, 0);
            fb_len = jchunk.len;
        }
        esp_camera_fb_return(fb);
        int64_t fr_end = esp_timer_get_time();
//        Serial.printf("JPG: %uB %ums\n", (uint32_t)(fb_len), (uint32_t)((fr_end - fr_start)/1000));
        return res;
    }

    dl_matrix3du_t *image_matrix = dl_matrix3du_alloc(1, fb->width, fb->height, 3);
    if (!image_matrix) {
        esp_camera_fb_return(fb);
//        Serial.println("dl_matrix3du_alloc failed");
        httpd_resp_send_500(req);
        return ESP_FAIL;
    }

    out_buf = image_matrix->item;
    out_len = fb->width * fb->height * 3;
    out_width = fb->width;
    out_height = fb->height;

    s = fmt2rgb888(fb->buf, fb->len, fb->format, out_buf);
    esp_camera_fb_return(fb);
    if(!s){
        dl_matrix3du_free(image_matrix);
//        Serial.println("to rgb888 failed");
        httpd_resp_send_500(req);
        return ESP_FAIL;
    }

    box_array_t *net_boxes = face_detect(image_matrix, &mtmn_config);

    if (net_boxes){
        detected = true;
        if(recognition_enabled){
            face_id = run_face_recognition(image_matrix, net_boxes);
        }
        draw_face_boxes(image_matrix, net_boxes, face_id);
        free(net_boxes->score);
        free(net_boxes->box);
        free(net_boxes->landmark);
        free(net_boxes);
    }

    jpg_chunking_t jchunk = {req, 0};
    s = fmt2jpg_cb(out_buf, out_len, out_width, out_height, PIXFORMAT_RGB888, 90, jpg_encode_stream, &jchunk);
    dl_matrix3du_free(image_matrix);
    if(!s){
//        Serial.println("JPEG compression failed");
        return ESP_FAIL;
    }

    int64_t fr_end = esp_timer_get_time();
//    Serial.printf("FACE: %uB %ums %s%d\n", (uint32_t)(jchunk.len), (uint32_t)((fr_end - fr_start)/1000), detected?"DETECTED ":"", face_id);
    return res;
}

static esp_err_t stream_handler(httpd_req_t *req){
    camera_fb_t * fb = NULL;
    esp_err_t res = ESP_OK;
    size_t _jpg_buf_len = 0;
    uint8_t * _jpg_buf = NULL;
    char * part_buf[64];
    dl_matrix3du_t *image_matrix = NULL;
    bool detected = false;
    int face_id = 0;
    int64_t fr_start = 0;
    int64_t fr_ready = 0;
    int64_t fr_face = 0;
    int64_t fr_recognize = 0;
    int64_t fr_encode = 0;

    static int64_t last_frame = 0;
    if(!last_frame) {
        last_frame = esp_timer_get_time();
    }

    res = httpd_resp_set_type(req, _STREAM_CONTENT_TYPE);
    if(res != ESP_OK){
        return res;
    }

    httpd_resp_set_hdr(req, "Access-Control-Allow-Origin", "*");

    while(true){
        detected = false;
        face_id = 0;
        fb = esp_camera_fb_get();
        if (!fb) {
//            Serial.println("Camera capture failed");
            res = ESP_FAIL;
        } else {
            fr_start = esp_timer_get_time();
            fr_ready = fr_start;
            fr_face = fr_start;
            fr_encode = fr_start;
            fr_recognize = fr_start;
            if(!detection_enabled || fb->width > 400){
                if(fb->format != PIXFORMAT_JPEG){
                    bool jpeg_converted = frame2jpg(fb, 80, &_jpg_buf, &_jpg_buf_len);
                    esp_camera_fb_return(fb);
                    fb = NULL;
                    if(!jpeg_converted){
//                        Serial.println("JPEG compression failed");
                        res = ESP_FAIL;
                    }
                } else {
                    _jpg_buf_len = fb->len;
                    _jpg_buf = fb->buf;
                }
            } else {

                image_matrix = dl_matrix3du_alloc(1, fb->width, fb->height, 3);

                if (!image_matrix) {
//                    Serial.println("dl_matrix3du_alloc failed");
                    res = ESP_FAIL;
                } else {
                    if(!fmt2rgb888(fb->buf, fb->len, fb->format, image_matrix->item)){
//                        Serial.println("fmt2rgb888 failed");
                        res = ESP_FAIL;
                    } else {
                        fr_ready = esp_timer_get_time();
                        box_array_t *net_boxes = NULL;
                        if(detection_enabled){
                            net_boxes = face_detect(image_matrix, &mtmn_config);
                        }
                        fr_face = esp_timer_get_time();
                        fr_recognize = fr_face;
                        if (net_boxes || fb->format != PIXFORMAT_JPEG){
                            if(net_boxes){
                                detected = true;
                                if(recognition_enabled){
                                    face_id = run_face_recognition(image_matrix, net_boxes);
                                }
                                fr_recognize = esp_timer_get_time();
                                draw_face_boxes(image_matrix, net_boxes, face_id);
                                free(net_boxes->score);
                                free(net_boxes->box);
                                free(net_boxes->landmark);
                                free(net_boxes);
                            }
                            if(!fmt2jpg(image_matrix->item, fb->width*fb->height*3, fb->width, fb->height, PIXFORMAT_RGB888, 90, &_jpg_buf, &_jpg_buf_len)){
//                                Serial.println("fmt2jpg failed");
                                res = ESP_FAIL;
                            }
                            esp_camera_fb_return(fb);
                            fb = NULL;
                        } else {
                            _jpg_buf = fb->buf;
                            _jpg_buf_len = fb->len;
                        }
                        fr_encode = esp_timer_get_time();
                    }
                    dl_matrix3du_free(image_matrix);
                }
            }
        }
        if(res == ESP_OK){
            size_t hlen = snprintf((char *)part_buf, 64, _STREAM_PART, _jpg_buf_len);
            res = httpd_resp_send_chunk(req, (const char *)part_buf, hlen);
        }
        if(res == ESP_OK){
            res = httpd_resp_send_chunk(req, (const char *)_jpg_buf, _jpg_buf_len);
        }
        if(res == ESP_OK){
            res = httpd_resp_send_chunk(req, _STREAM_BOUNDARY, strlen(_STREAM_BOUNDARY));
        }
        if(fb){
            esp_camera_fb_return(fb);
            fb = NULL;
            _jpg_buf = NULL;
        } else if(_jpg_buf){
            free(_jpg_buf);
            _jpg_buf = NULL;
        }
        if(res != ESP_OK){
            break;
        }
        int64_t fr_end = esp_timer_get_time();

        int64_t ready_time = (fr_ready - fr_start)/1000;
        int64_t face_time = (fr_face - fr_ready)/1000;
        int64_t recognize_time = (fr_recognize - fr_face)/1000;
        int64_t encode_time = (fr_encode - fr_recognize)/1000;
        int64_t process_time = (fr_encode - fr_start)/1000;
        
        int64_t frame_time = fr_end - last_frame;
        last_frame = fr_end;
        frame_time /= 1000;
        uint32_t avg_frame_time = ra_filter_run(&ra_filter, frame_time);
//        Serial.printf("MJPG: %uB %ums (%.1ffps), AVG: %ums (%.1ffps), %u+%u+%u+%u=%u %s%d\n",
//            (uint32_t)(_jpg_buf_len),
//            (uint32_t)frame_time, 1000.0 / (uint32_t)frame_time,
//            avg_frame_time, 1000.0 / avg_frame_time,
//            (uint32_t)ready_time, (uint32_t)face_time, (uint32_t)recognize_time, (uint32_t)encode_time, (uint32_t)process_time,
//            (detected)?"DETECTED ":"", face_id
//        );
    }

    last_frame = 0;
    return res;
}

static esp_err_t cmd_handler(httpd_req_t *req){
    char*  buf;
    size_t buf_len;
    char variable[32] = {0,};
    char value[32] = {0,};

    buf_len = httpd_req_get_url_query_len(req) + 1;
    if (buf_len > 1) {
        buf = (char*)malloc(buf_len);
        if(!buf){
            httpd_resp_send_500(req);
            return ESP_FAIL;
        }
        if (httpd_req_get_url_query_str(req, buf, buf_len) == ESP_OK) {
            if (httpd_query_key_value(buf, "var", variable, sizeof(variable)) == ESP_OK &&
                httpd_query_key_value(buf, "val", value, sizeof(value)) == ESP_OK) {
            } else {
                free(buf);
                httpd_resp_send_404(req);
                return ESP_FAIL;
            }
        } else {
            free(buf);
            httpd_resp_send_404(req);
            return ESP_FAIL;
        }
        free(buf);
    } else {
        httpd_resp_send_404(req);
        return ESP_FAIL;
    }

    int val = atoi(value);
    sensor_t * s = esp_camera_sensor_get();
    int res = 0;

    if(!strcmp(variable, "framesize")) {
        if(s->pixformat == PIXFORMAT_JPEG) res = s->set_framesize(s, (framesize_t)val);
    }
    else if(!strcmp(variable, "quality")) res = s->set_quality(s, val);
    else if(!strcmp(variable, "contrast")) res = s->set_contrast(s, val);
    else if(!strcmp(variable, "brightness")) res = s->set_brightness(s, val);
    else if(!strcmp(variable, "saturation")) res = s->set_saturation(s, val);
    else if(!strcmp(variable, "gainceiling")) res = s->set_gainceiling(s, (gainceiling_t)val);
    else if(!strcmp(variable, "colorbar")) res = s->set_colorbar(s, val);
    else if(!strcmp(variable, "awb")) res = s->set_whitebal(s, val);
    else if(!strcmp(variable, "agc")) res = s->set_gain_ctrl(s, val);
    else if(!strcmp(variable, "aec")) res = s->set_exposure_ctrl(s, val);
    else if(!strcmp(variable, "hmirror")) res = s->set_hmirror(s, val);
    else if(!strcmp(variable, "vflip")) res = s->set_vflip(s, val);
    else if(!strcmp(variable, "awb_gain")) res = s->set_awb_gain(s, val);
    else if(!strcmp(variable, "agc_gain")) res = s->set_agc_gain(s, val);
    else if(!strcmp(variable, "aec_value")) res = s->set_aec_value(s, val);
    else if(!strcmp(variable, "aec2")) res = s->set_aec2(s, val);
    else if(!strcmp(variable, "dcw")) res = s->set_dcw(s, val);
    else if(!strcmp(variable, "bpc")) res = s->set_bpc(s, val);
    else if(!strcmp(variable, "wpc")) res = s->set_wpc(s, val);
    else if(!strcmp(variable, "raw_gma")) res = s->set_raw_gma(s, val);
    else if(!strcmp(variable, "lenc")) res = s->set_lenc(s, val);
    else if(!strcmp(variable, "special_effect")) res = s->set_special_effect(s, val);
    else if(!strcmp(variable, "wb_mode")) res = s->set_wb_mode(s, val);
    else if(!strcmp(variable, "ae_level")) res = s->set_ae_level(s, val);
    else if(!strcmp(variable, "face_detect")) {
        detection_enabled = val;
        if(!detection_enabled) {
            recognition_enabled = 0;
        }
    }
    else if(!strcmp(variable, "face_enroll")) is_enrolling = val;
    else if(!strcmp(variable, "face_recognize")) {
        recognition_enabled = val;
        if(recognition_enabled){
            detection_enabled = val;
        }
    }
    else {
        res = -1;
    }

    if(res){
        return httpd_resp_send_500(req);
    }

    httpd_resp_set_hdr(req, "Access-Control-Allow-Origin", "*");
    return httpd_resp_send(req, NULL, 0);
}

static esp_err_t status_handler(httpd_req_t *req){
    static char json_response[1024];

    sensor_t * s = esp_camera_sensor_get();
    char * p = json_response;
    *p++ = '{';

    p+=sprintf(p, "\"framesize\":%u,", s->status.framesize);
    p+=sprintf(p, "\"quality\":%u,", s->status.quality);
    p+=sprintf(p, "\"brightness\":%d,", s->status.brightness);
    p+=sprintf(p, "\"contrast\":%d,", s->status.contrast);
    p+=sprintf(p, "\"saturation\":%d,", s->status.saturation);
    p+=sprintf(p, "\"sharpness\":%d,", s->status.sharpness);
    p+=sprintf(p, "\"special_effect\":%u,", s->status.special_effect);
    p+=sprintf(p, "\"wb_mode\":%u,", s->status.wb_mode);
    p+=sprintf(p, "\"awb\":%u,", s->status.awb);
    p+=sprintf(p, "\"awb_gain\":%u,", s->status.awb_gain);
    p+=sprintf(p, "\"aec\":%u,", s->status.aec);
    p+=sprintf(p, "\"aec2\":%u,", s->status.aec2);
    p+=sprintf(p, "\"ae_level\":%d,", s->status.ae_level);
    p+=sprintf(p, "\"aec_value\":%u,", s->status.aec_value);
    p+=sprintf(p, "\"agc\":%u,", s->status.agc);
    p+=sprintf(p, "\"agc_gain\":%u,", s->status.agc_gain);
    p+=sprintf(p, "\"gainceiling\":%u,", s->status.gainceiling);
    p+=sprintf(p, "\"bpc\":%u,", s->status.bpc);
    p+=sprintf(p, "\"wpc\":%u,", s->status.wpc);
    p+=sprintf(p, "\"raw_gma\":%u,", s->status.raw_gma);
    p+=sprintf(p, "\"lenc\":%u,", s->status.lenc);
    p+=sprintf(p, "\"vflip\":%u,", s->status.vflip);
    p+=sprintf(p, "\"hmirror\":%u,", s->status.hmirror);
    p+=sprintf(p, "\"dcw\":%u,", s->status.dcw);
    p+=sprintf(p, "\"colorbar\":%u,", s->status.colorbar);
    p+=sprintf(p, "\"face_detect\":%u,", detection_enabled);
    p+=sprintf(p, "\"face_enroll\":%u,", is_enrolling);
    p+=sprintf(p, "\"face_recognize\":%u", recognition_enabled);
    *p++ = '}';
    *p++ = 0;
    httpd_resp_set_type(req, "application/json");
    httpd_resp_set_hdr(req, "Access-Control-Allow-Origin", "*");
    return httpd_resp_send(req, json_response, strlen(json_response));
}

//static esp_err_t index_handler(httpd_req_t *req){
//    httpd_resp_set_type(req, "text/html");
//    httpd_resp_set_hdr(req, "Content-Encoding", "gzip");
//    sensor_t * s = esp_camera_sensor_get();
//    if (s->id.PID == OV3660_PID) {
//        return httpd_resp_send(req, (const char *)index_ov3660_html_gz, index_ov3660_html_gz_len);
//    }
//    return httpd_resp_send(req, (const char *)index_ov2640_html_gz, index_ov2640_html_gz_len);
//}

static esp_err_t main_page_handler(httpd_req_t *req){
    Serial.println(req->uri);
    tempHeader = req->uri;

    Serial.println(message);
    if(message.length() > 0){
      requestHeader = message;
    }

    if(tempHeader.indexOf("/accept") >= 0){
      requestHeader = "/accept";       
      Myserial.write("/accept"); //sent accept to main esp
      
      httpd_resp_set_type(req, "text/html");
      httpd_resp_set_hdr(req, "Content-Encoding", "gzip");
      sensor_t * s = esp_camera_sensor_get();
      if (s->id.PID == OV3660_PID) {
          return httpd_resp_send(req, (const char *)index_ov3660_html_gz, index_ov3660_html_gz_len);
      }
      return httpd_resp_send(req, (const char *)index_ov2640_html_gz, index_ov2640_html_gz_len);      
    } else if(tempHeader.indexOf("/decline") >= 0){
      requestHeader = "/decline";          
      Myserial.write("/decline"); //sent decline to main esp

      httpd_resp_set_type(req, "text/html");
      return httpd_resp_send(req, decline_page, sizeof(decline_page)); 
    } else if(tempHeader.indexOf("/RESET") >= 0){
      requestHeader = "/";    

      httpd_resp_set_type(req, "text/html");
      return httpd_resp_send(req, nocall_page, sizeof(nocall_page)); 
    } else if(requestHeader.indexOf("/decline") >= 0){
      httpd_resp_set_type(req, "text/html");
      return httpd_resp_send(req, decline_page, sizeof(decline_page)); 
    } else if(requestHeader.indexOf("/accept") >= 0){
      httpd_resp_set_type(req, "text/html");
      httpd_resp_set_hdr(req, "Content-Encoding", "gzip");
      sensor_t * s = esp_camera_sensor_get();
      if (s->id.PID == OV3660_PID) {
          return httpd_resp_send(req, (const char *)index_ov3660_html_gz, index_ov3660_html_gz_len);
      }
      return httpd_resp_send(req, (const char *)index_ov2640_html_gz, index_ov2640_html_gz_len); 
    } else if(requestHeader.indexOf("/calling") >=0){
//      this->callWaiting = true;
      httpd_resp_set_type(req, "text/html");
      return httpd_resp_send(req, main_page, sizeof(main_page)); 
    } else {
      httpd_resp_set_type(req, "text/html");
      return httpd_resp_send(req, nocall_page, sizeof(nocall_page)); 
    }
}

void startCameraServer(){
    httpd_config_t config = HTTPD_DEFAULT_CONFIG();
    config.max_resp_headers = 50;

    Serial.println(CONFIG_HTTPD_MAX_REQ_HDR_LEN);
    Serial.println(HTTPD_MAX_REQ_HDR_LEN);
    Serial.println(CONFIG_HTTPD_MAX_URI_LEN);
    Serial.println(HTTPD_MAX_URI_LEN);
    Serial.println(config.max_resp_headers);
    Serial.println(config.max_uri_handlers);

    httpd_uri_t index_uri = {
        .uri       = "/",
        .method    = HTTP_GET,
        .handler   = main_page_handler,
        .user_ctx  = NULL
    };

    httpd_uri_t status_uri = {
        .uri       = "/status",
        .method    = HTTP_GET,
        .handler   = status_handler,
        .user_ctx  = NULL
    };

    httpd_uri_t cmd_uri = {
        .uri       = "/control",
        .method    = HTTP_GET,
        .handler   = cmd_handler,
        .user_ctx  = NULL
    };

    httpd_uri_t capture_uri = {
        .uri       = "/capture",
        .method    = HTTP_GET,
        .handler   = capture_handler,
        .user_ctx  = NULL
    };

   httpd_uri_t stream_uri = {
        .uri       = "/stream",
        .method    = HTTP_GET,
        .handler   = stream_handler,
        .user_ctx  = NULL
    };

    httpd_uri_t accept_uri = {
        .uri       = "/accept",
        .method    = HTTP_GET,
        .handler   = main_page_handler,
        .user_ctx  = NULL
    };

    httpd_uri_t decline_uri = {
        .uri       = "/decline",
        .method    = HTTP_GET,
        .handler   = main_page_handler,
        .user_ctx  = NULL
    };

    httpd_uri_t calling_uri = {
        .uri       = "/calling",
        .method    = HTTP_GET,
        .handler   = main_page_handler,
        .user_ctx  = NULL
    };


    ra_filter_init(&ra_filter, 20);
    
    mtmn_config.type = FAST;
    mtmn_config.min_face = 80;
    mtmn_config.pyramid = 0.707;
    mtmn_config.pyramid_times = 4;
    mtmn_config.p_threshold.score = 0.6;
    mtmn_config.p_threshold.nms = 0.7;
    mtmn_config.p_threshold.candidate_number = 20;
    mtmn_config.r_threshold.score = 0.7;
    mtmn_config.r_threshold.nms = 0.7;
    mtmn_config.r_threshold.candidate_number = 10;
    mtmn_config.o_threshold.score = 0.7;
    mtmn_config.o_threshold.nms = 0.7;
    mtmn_config.o_threshold.candidate_number = 1;
    
    face_id_init(&id_list, FACE_ID_SAVE_NUMBER, ENROLL_CONFIRM_TIMES);
    
//    Serial.printf("Starting web server on port: '%d'\n", config.server_port);
    if (httpd_start(&camera_httpd, &config) == ESP_OK) {
        httpd_register_uri_handler(camera_httpd, &index_uri);
        httpd_register_uri_handler(camera_httpd, &cmd_uri);
        httpd_register_uri_handler(camera_httpd, &status_uri);
        httpd_register_uri_handler(camera_httpd, &capture_uri);
        httpd_register_uri_handler(camera_httpd, &accept_uri);
        httpd_register_uri_handler(camera_httpd, &decline_uri);
        httpd_register_uri_handler(camera_httpd, &calling_uri);
    }

    config.server_port += 1;
    config.ctrl_port += 1;
//    Serial.printf("Starting stream server on port: '%d'\n", config.server_port);
    if (httpd_start(&stream_httpd, &config) == ESP_OK) {
        httpd_register_uri_handler(stream_httpd, &stream_uri);
    }
}

communication.h

#ifndef Communication_h
#define Communication_h

#include <HardwareSerial.h>

extern String message;
extern HardwareSerial Myserial;

#endif
@me-no-dev
Copy link
Member

What IDF version are you using?
Do not mix make menuconfig with idf.py build! Use idf.py menuconfig instead.

@RickvF
Copy link
Author

RickvF commented Jun 15, 2021

@me-no-dev I just used the master branch of https://github.com/espressif/esp-idf

As shown for the examples with the esp-who in combination with the esp32-arduino component I executed both the idf.py build and menu flash monitor commands and got different results.

But are you suggesting the esp-who with esp32-arduino component should work and I should follow the idf.py menuconfig, idf.py build and idf.py flash monitor commands?

@lbernstone
Copy link
Contributor

lbernstone commented Jun 15, 2021

Does esp-who compile on its own with esp-idf master? These components may not compile on every version of esp-idf. You typically need to match the version of arduino-esp32 with a specific version of idf (https://github.com/espressif/arduino-esp32/blob/master/tools/sdk/esp32/include/config/sdkconfig.h#L661). Currently, arduino-esp32 master compiles on esp-idf master. Earlier versions of arduino are unlikely to work with idf master. If you then want to put esp-who into the mix, you need to be sure it compiles separately on the version of esp-idf you are using.

@RickvF
Copy link
Author

RickvF commented Jun 15, 2021

Does esp-who compile on its own with esp-idf master? These components may not compile on every version of esp-idf. You typically need to match the version of arduino-esp32 with a specific version of idf (https://github.com/espressif/arduino-esp32/blob/master/tools/sdk/esp32/include/config/sdkconfig.h#L661). Currently, arduino-esp32 master compiles on esp-idf master. Earlier versions of arduino are unlikely to work with idf master. If you then want to put esp-who into the mix, you need to be sure it compiles separately on the version of esp-idf you are using.

For the ESP-who I used following tutorial provided by Espressif. The ESP-IDF was part of the ESP-WHO folder after cloning. I did not do anything extra to get the ESP-IDF. As seen also here the master branch is used for ESP-WHO

he steps to build esp-who SDK on Ubuntu are as follows:

Step 1. Install Prerequisites :
sudo apt-get install git wget libncurses-dev flex bison gperf python python-pip python-setuptools python-serial
python-click python-cryptography python-future python-pyparsing python-pyelftools cmake ninja-build ccache libffi-dev libssl-dev

Step 2. Get ESP-WHO:
mkdir esp-who
cd ~/esp-who
git clone --recursive https://github.com/espressif/esp-who.git
cd esp-who
git submodule update -f --init --recursive
git pull

Step 3. Set up the esp-idf environment variables under esp-who:
cd /esp-who/esp-idf
pwd
export IDF_PATH=
/esp-who/esp-idf

Step 4. Set up the tools
cd ~/esp-who/esp-idf
./install.sh
. ./export.sh

Step 5. Start a Project:
cd ..
cd ~/esp-who/examples/single_chip/camera_web_server
idf.py build
idf.py flash monitor

@lbernstone
Copy link
Contributor

esp-who expects idf4.0. arduino-esp32 expects idf4.4(ish). It will not be possible to integrate this without a significant effort on your part. It might be possible to get this working with the 4.0 release container at https://hub.docker.com/r/lbernstone/esp32-arduino-lib-builder.

@RickvF
Copy link
Author

RickvF commented Jun 15, 2021

Thanks for the tips.
For my understanding, this will allow me to modify the HTTP headers correctly and then use the Arduino IDE to create the rest of the project, flash it and so on? So I don't need the esp-idf anymore

@RickvF
Copy link
Author

RickvF commented Jun 15, 2021

And when I want to use the ESP-IDF I have to come up with a different solution for the setup and loop function of my main file and a different solution of the HardwareSerial I am currently using?

@lbernstone
Copy link
Contributor

the docker container includes the esp-idf at a specific point in time (in this case idf4.0 about 8 months ago) along with the arduino that compiled then. You can clone esp-who into the container and build your project there, or else build the arduino libraries there and copy them out into your normal environment. I can provide no guarantees that any of this will work, since you are trying to mix and match pieces. I don't know where your HTTP header issues are coming from. If that is your actual problem, it would probably be more direct to solve that problem, instead of going down a very long rabbit hole.

@RickvF
Copy link
Author

RickvF commented Jun 15, 2021

That is indeed the initial issue I am trying to solve, which took me already a long road down the rabbit hole. But I will try every possible solution.

@me-no-dev
Copy link
Member

generally you do not need the full esp-who. All you need is esp-face :) https://github.com/espressif/esp-dl

ESP-IDF master should compile fine with arduino master, esp32-camera master and esp-dl master.

@RickvF
Copy link
Author

RickvF commented Jun 16, 2021

That sounds as an easier solution.

So I have to install the ESP-IDF and add in the components folder of the ESP-IDF installation the following components:

Then I can take the hello world example and edit it with my sketch based on the examples/esp32/camera/CameraWebServer from the Arduino IDE?

@RickvF
Copy link
Author

RickvF commented Jun 16, 2021

It is still missing some files which are not part of the esp-dl

../main/app_httpd.cpp:22:10: fatal error: fb_gfx.h: No such file or directory
#include "fb_gfx.h"
^~~~~~~~~~
compilation terminated.
ninja: build stopped: subcommand failed.
ninja failed with exit code 1

@me-no-dev
Copy link
Member

ahh :) fb_gfx component you need to copy from ESP-WHO. It is used to draw the frames around faces

@RickvF
Copy link
Author

RickvF commented Jun 17, 2021

Thanks for your help! That got me further. idf.py build went successful.

Only got a problem with idf.py flash monitor:
Also I don't get an IP address from the WiFi connection

rote 826272 bytes (515767 compressed) at 0x00010000 in 12.5 seconds (effective 527.5 kbit/s)...
Hash of data verified.
Compressed 3072 bytes to 103...
Writing at 0x00008000... (100 %)
Wrote 3072 bytes (103 compressed) at 0x00008000 in 0.1 seconds (effective 467.8 kbit/s)...
Hash of data verified.

Leaving...
Hard resetting via RTS pin...
Executing action: monitor
Serial port /dev/ttyUSB0
Connecting....
Detecting chip type... ESP32
Running idf_monitor in directory /home/rick/Desktop/hello_world
Executing "/home/rick/.espressif/python_env/idf4.4_py3.8_env/bin/python /home/rick/esp/esp-idf/tools/idf_monitor.py -p /dev/ttyUSB0 -b 250000 --toolchain-prefix xtensa-esp32-elf- --target esp32 --revision 0 /home/rick/Desktop/hello_world/build/hello-world.elf -m '/home/rick/.espressif/python_env/idf4.4_py3.8_env/bin/python' '/home/rick/esp/esp-idf/tools/idf.py'"...
--- idf_monitor on /dev/ttyUSB0 250000 ---
--- Quit: Ctrl+] | Menu: Ctrl+T | Help: Ctrl+T followed by Ctrl+H ---
f~�f~��x��~x���怘�怘���~�f�f�~f������f�f`ff�������`�~�x�`�~f�����`�f����`f�ff��f��ff��f��f`�����f�f`���f�f`���ff�������~ff�`f���~x��x��~������x怘�f~�f~��x��~x���怘�怘���~�f�f�~f������f�f`ff�������`�~f�x�ff�f`�f�f`�����f����`f�������xf�~��f��~���f�ff~fxff�������fx�~���fx�~��`�fx�~�����fx�~����`�fx�~��~�fx�~�������`fx�`�������������x��x�~�������x��xx�xx�x���f���~`�������x������f������xx�������~f�����x�����怘�����x����f����x~��怘�f��`��f��������>8��>�>��8��>88��8��8�8>8����8�8�8>�����88>8>8��������8��>�>�>�>����>>�8>�8>�>8�>8��>8888888��>�>��8������8�>�>�����8>>��8>�>8�>��>88888888��>�>��8�>>8�����>>�>�>�>888�8>>�8>�8>�>8�>8��>8>8�8��>�>�����>�>�>888�>>8�����>����8>��>����������������������>��>88�88888��>���������88�����>>�>�8>�8>�>8�>8��>88�8>���������88�8�>�>���88888�8�8�8>�>8>�8>�>8�>8��88�8�8888��>�>������88�8�88��>��>88�>8��8�8>�88�>>�8>�8>�>8�>8��>88�8���>�>��8>�>��888�8��>������>���������>�>8>��8�>8��>88��8��>�>��8���>��>�>�>��>��>�>8>�8>�>8�>8��>88�8�8��>���8�>88����88888888�������888888888���8�8��>���888���>>�8>�8>�>8�>8��>88�88888��>�>��888>���88888888888�>��>8��888888�888�8888�8888888>888�8>�8>�8�>8��>88�8>8��>�>������������88��������������������88888�����>8���������888�8���>�����������������>����88>8��>�>�����>�>�>888�>>8�����>>�>��>888�88>��>�>>��>�>�>8�>�����>�>�>�>8�8>�8>�>8���88�8�����>����8�����>�>�88�8�����888�888�8�����8��>888�8��>8���8�88>�88>88>8>888>��>>�>�8������������������������������������8888��>8���>>8�8�8�8888>��>�8>�8>�>�>8�����������������������������������8���88��>>8��������>8�>��>88>8����8�>���������������������������������������>�>8�>��>88>8�����8�>����8�����>�>�8>�����888����8�88�����8����������������������������������������������������������������������������������������������������������������������������������������������������������8�>�>>�8>�>8�>8��>8���������������������������888���8>>�8>�8>�>8�>��>888888���������8888���8�>�>�8���������������888���>8�������8�����8��>���>�>8>�8>�>8�8��>8�8�8>������������������������������������������������������������������������������������������������������������������������88�>�>�������8888���>8�8>��8���8>8�8���>�>8�>8�������������������>����������������>�������������888�8�>���������������������������������������������������������������������8������������������������������������88>�>88��8>�8>8�>8�88�8��8>�>��>8�>8����������������������������>�������������������������������>�8������>����8>���8>8�����8��8>��>�>8�>8��>8�8�8888��>������8���������8�>>�8��>���>>�>>�>�8�8�>��>88��>888������>��>888��>��88�8�>�>>�>8>�8>�8�>8��>88�8�8888���������8888���>�>�8������>��8>���88��>�>��>8�>8��>8888������������������������������
I (540) gpio: GPIO[5]| InputEn: 1| OutputEn: 0| OpenDrain: 0| Pullup: 1| Pulldown: 0| Intr:2 
I (540) cam_hal: cam init ok
I (540) sccb: pin_sda 18 pin_scl 23
I (550) camera: Detected camera at address=0x30
I (560) camera: Camera PID=0x26 VER=0x42 MIDL=0x7f MIDH=0xa2
I (640) camera: Detected OV2640 camera
I (640) cam_hal: buffer_size: 32768, half_buffer_size: 4096, node_buffer_size: 2048, node_cnt: 16, total_cnt: 23

E (640) cam_hal: cam_dma_config(266): frame buffer malloc failed
E (640) cam_hal: cam_config(346): cam_dma_config failed
E (640) camera: Camera config failed with error 0xffffffff

@me-no-dev
Copy link
Member

E (537) spi_flash: Detected size(4096k) smaller than the size in the binary image header(8192k). Probe failed.

You have selected 8MB flash but have 4MB on the module

@RickvF
Copy link
Author

RickvF commented Jun 18, 2021

Feeling a bit stupid right now......... found it and fixed it. Camera is working.
Next step adding the mic.

Thanks for the help!

@RickvF
Copy link
Author

RickvF commented Jun 21, 2021

Got only one error left which appears after a while.

W (303806) httpd_txrx: httpd_sock_err: error in send : 11
W (303806) httpd_uri: httpd)uri: uri hadnler execution failed
W (304806) httpd_txrx: httpd_sock_err: error in send : 11
E (304806) example: httpd_resp_send_chunk(): #5 error
W (304806) httpd_uri: httpd_uri: uri handler execution failed
W (304816) httpd_uri: httpd_uri: URI '/favicon.ico'not found
W (304816) httpd_txrx: httpd_resp_send_error: 404 Not Found - This URI does not exist

But in all my webpage I even didn't specify favicon.ico. Also in the example webservers I didn't saw the use of a favicon.

@lbernstone
Copy link
Contributor

that request comes from the web browser. It wants to decorate the tab. You can provide one as a static file if you really want.

@sansillusion
Copy link

You may be interested in serving the icon inline im your main html to prevent multiple requests.

Found some details here about it:
https://davidwalsh.name/blank-favicon

@lbernstone
Copy link
Contributor

That's an interesting idea, but if you are serving more than one page, you would need to embed it in every page (or use a template).

@stale
Copy link

stale bot commented Aug 21, 2021

[STALE_SET] This issue has been automatically marked as stale because it has not had recent activity. It will be closed in 14 days if no further activity occurs. Thank you for your contributions.

@stale stale bot added the Status: Stale Issue is stale stage (outdated/stuck) label Aug 21, 2021
@stale
Copy link

stale bot commented Sep 19, 2021

[STALE_DEL] This stale issue has been automatically closed. Thank you for your contributions.

@stale stale bot closed this as completed Sep 19, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Status: Stale Issue is stale stage (outdated/stuck)
Projects
None yet
Development

No branches or pull requests

4 participants