J'ai utilisé OV2640 pour obtenir l'image auparavant, donc cette fois j'ai essayé d'obtenir l'image en utilisant OV7725. L'OV7725 produit des images au format bmp au lieu de jpeg, la méthode de contrôle est donc légèrement différente.
Cette fois, j'ai rendu possible la modification du registre OV7725 sur le navigateur! Dès la conclusion, je n'ai pas pu prendre une très belle photo avec 300 000 pixels. Il semble avoir les mêmes performances que l'appareil photo installé dans les premiers téléphones portables ... Si vous voulez prendre de belles photos, je pense que vous devriez utiliser une tarte aux framboises et prendre des photos avec OV5640.
J'ai utilisé ESP32-WROOM-32 pour OV2640, mais j'ai utilisé ESP32-WROVER-B avec PSRAM car OV7725 est bmp et l'utilisation de la mémoire augmente.
officiel https://github.com/espressif/esp32-camera
Peut-être avant qu'il ne soit officiellement adopté https://github.com/igrr/esp32-cam-demo
Placement des broches https://www.instructables.com/id/The-Incredible-ESP32-Wrover-From-Espressif/
Fiche technique OV7725 https://cdn.sparkfun.com/datasheets/Sensors/LightImaging/OV7725.pdf
Clonez le sous-module dans le dossier esp-idf.
git submodule add https://github.com/espressif/esp32-camera.git components/esp32-camera
mv esp-idf/components/esp32-camera/driver/private_include/sccb.h esp-idf/components/esp32-camera/driver/include/sccb.h
mv esp-idf/components/esp32-camera/driver/private_include/sensor.h esp-idf/components/esp32-camera/driver/include/sensor.h
Le serveur simple dans l'exemple d'esp-idf a été amélioré, et lorsque vous accédez à "http: //
Tous les codes sont listés ci-dessous. https://github.com/koki-iwaizumi/esp32-ov7725
La taille est VGA et le format de sortie est YUV422. Veuillez modifier les paramètres relatifs au wifi.
app_main.c
#include <string.h>
#include <esp_wifi.h>
#include <esp_event_loop.h>
#include <esp_log.h>
#include <esp_system.h>
#include <nvs_flash.h>
#include <sys/param.h>
#include <esp_http_server.h>
#include <esp_camera.h>
#include "mbedtls/base64.h"
#include "cJSON.h"
#include "sensor.h"
#include "sccb.h"
/********* io ***********/
#define CAM_PIN_PWDN 2
#define CAM_PIN_RESET 15
#define CAM_PIN_XCLK 27
#define CAM_PIN_SIOD 25
#define CAM_PIN_SIOC 23
#define CAM_PIN_VSYNC 22
#define CAM_PIN_HREF 26
#define CAM_PIN_PCLK 21
#define CAM_PIN_D9 19
#define CAM_PIN_D8 36
#define CAM_PIN_D7 18
#define CAM_PIN_D6 39
#define CAM_PIN_D5 5
#define CAM_PIN_D4 34
#define CAM_PIN_D3 32
#define CAM_PIN_D2 35
/********* wifi ***********/
#define EXAMPLE_WIFI_SSID "*"
#define EXAMPLE_WIFI_PASS "*"
static const char *TAG = "APP";
sensor_t* sensor = NULL;
static camera_config_t camera_config = {
.pin_pwdn = CAM_PIN_PWDN,
.pin_reset = CAM_PIN_RESET,
.pin_xclk = CAM_PIN_XCLK,
.pin_sscb_sda = CAM_PIN_SIOD,
.pin_sscb_scl = CAM_PIN_SIOC,
.pin_d7 = CAM_PIN_D9,
.pin_d6 = CAM_PIN_D8,
.pin_d5 = CAM_PIN_D7,
.pin_d4 = CAM_PIN_D6,
.pin_d3 = CAM_PIN_D5,
.pin_d2 = CAM_PIN_D4,
.pin_d1 = CAM_PIN_D3,
.pin_d0 = CAM_PIN_D2,
.pin_vsync = CAM_PIN_VSYNC,
.pin_href = CAM_PIN_HREF,
.pin_pclk = CAM_PIN_PCLK,
.xclk_freq_hz = 6000000,
.ledc_timer = LEDC_TIMER_0,
.ledc_channel = LEDC_CHANNEL_0,
.pixel_format = PIXFORMAT_YUV422,
.frame_size = FRAMESIZE_VGA,
.jpeg_quality = 12,
.fb_count = 1
};
esp_err_t index_get_handler(httpd_req_t *req)
{
extern const unsigned char index_start[] asm("_binary_index_html_start");
extern const unsigned char index_end[] asm("_binary_index_html_end");
const size_t index_size = (index_end - index_start);
httpd_resp_send_chunk(req, (const char *)index_start, index_size);
httpd_resp_sendstr_chunk(req, NULL);
return ESP_OK;
}
esp_err_t image_post_handler(httpd_req_t *req)
{
int content_buf_size = 10 * 1000;
char *content_buf = calloc(content_buf_size, sizeof(char));
if(content_buf == NULL){
ESP_LOGE(TAG, "Failed to allocate frame buffer - content_buf");
httpd_resp_send_500(req);
return ESP_FAIL;
}
if(httpd_req_recv(req, content_buf, req->content_len) <= 0){
ESP_LOGE(TAG, "httpd_req_recv failed");
httpd_resp_send_500(req);
return ESP_FAIL;
}
ESP_LOGE(TAG, "httpd_req_recv content=%s", content_buf);
cJSON *content_json = cJSON_Parse(content_buf);
for(int i = 0; i <= 172; i++){
char key[4];
itoa(i,key,10);
int value = strtol(cJSON_GetObjectItem(content_json, key)->valuestring, NULL, 16);
SCCB_Write(sensor->slv_addr, i, value);
}
cJSON_Delete(content_json);
free(content_buf);
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){
ESP_LOGE(TAG, "Camera capture failed");
httpd_resp_send_500(req);
return ESP_FAIL;
}
uint8_t *buf = NULL;
size_t buf_len = 0;
bool converted = frame2bmp(fb, &buf, &buf_len);
esp_camera_fb_return(fb);
if( ! converted){
ESP_LOGE(TAG, "BMP conversion failed");
httpd_resp_send_500(req);
return ESP_FAIL;
}
ESP_LOGI(TAG, "esp_get_free_heap_size (%d bytes)", esp_get_free_heap_size());
ESP_LOGI(TAG, "esp_get_minimum_free_heap_size (%d bytes)", esp_get_minimum_free_heap_size());
ESP_LOGI(TAG, "heap_caps_get_free_size(MALLOC_CAP_8BIT) (%d bytes)", heap_caps_get_free_size(MALLOC_CAP_8BIT));
ESP_LOGI(TAG, "heap_caps_get_minimum_free_size(MALLOC_CAP_8BIT) (%d bytes)", heap_caps_get_minimum_free_size(MALLOC_CAP_8BIT));
ESP_LOGI(TAG, "heap_caps_get_largest_free_block(MALLOC_CAP_8BIT) (%d bytes)", heap_caps_get_largest_free_block(MALLOC_CAP_8BIT));
int image_buf_size = 1300 * 1000;
uint8_t *image_buf = calloc(image_buf_size, sizeof(char));
if(image_buf == NULL){
free(buf);
ESP_LOGE(TAG, "Failed to allocate frame buffer - image_buf");
httpd_resp_send_500(req);
return ESP_FAIL;
}
size_t olen = 0;
int base64_err = mbedtls_base64_encode(image_buf, image_buf_size, &olen, buf, buf_len);
free(buf);
if (base64_err != 0) {
ESP_LOGE(TAG, "error base64 encoding, error %d, buff size: %d", base64_err, olen);
httpd_resp_send_500(req);
return ESP_FAIL;
}
ESP_LOGI(TAG, "esp_get_free_heap_size (%d bytes)", esp_get_free_heap_size());
ESP_LOGI(TAG, "esp_get_minimum_free_heap_size (%d bytes)", esp_get_minimum_free_heap_size());
ESP_LOGI(TAG, "heap_caps_get_free_size(MALLOC_CAP_8BIT) (%d bytes)", heap_caps_get_free_size(MALLOC_CAP_8BIT));
ESP_LOGI(TAG, "heap_caps_get_minimum_free_size(MALLOC_CAP_8BIT) (%d bytes)", heap_caps_get_minimum_free_size(MALLOC_CAP_8BIT));
ESP_LOGI(TAG, "heap_caps_get_largest_free_block(MALLOC_CAP_8BIT) (%d bytes)", heap_caps_get_largest_free_block(MALLOC_CAP_8BIT));
uint8_t *image_json = calloc(image_buf_size, sizeof(char));
if(image_json == NULL){
free(image_buf);
ESP_LOGE(TAG, "Failed to allocate frame buffer - image_json");
httpd_resp_send_500(req);
return ESP_FAIL;
}
sprintf((char *)image_json, "{\"image\":\"%s\"}", (const char *)image_buf);
free(image_buf);
ESP_LOGI(TAG, "image_json length=%d", strlen((const char*)image_json));
res = httpd_resp_set_type(req, "application/json") || httpd_resp_set_hdr(req, "Access-Control-Allow-Origin", "*") || httpd_resp_send(req, (const char *)image_json, strlen((const char*)image_json));
free(image_json);
int64_t fr_end = esp_timer_get_time();
ESP_LOGI(TAG, "BMP: %uKB %ums", (uint32_t)(buf_len/1024), (uint32_t)((fr_end - fr_start)/1000));
return res;
}
esp_err_t config_get_handler(httpd_req_t *req)
{
int data_json_size = 10 * 1000;
char *data_json = calloc(data_json_size, sizeof(char));
if(data_json == NULL){
ESP_LOGE(TAG, "Failed to allocate frame buffer - data_json");
httpd_resp_send_500(req);
return ESP_FAIL;
}
strcat(data_json, "{");
for(int i = 0; i <= 172; i++){
char data_json_buf[255] = {'\0'};
sprintf(data_json_buf, "\"%d\":\"%d\"", i, SCCB_Read(sensor->slv_addr, i));
strcat(data_json, data_json_buf);
if(i != 172) strcat(data_json, ",");
}
strcat(data_json, "}");
ESP_LOGI(TAG, "data_json=%s", data_json);
ESP_LOGI(TAG, "data_json length=%d", strlen((const char*)data_json));
esp_err_t res = httpd_resp_set_type(req, "application/json") || httpd_resp_set_hdr(req, "Access-Control-Allow-Origin", "*") || httpd_resp_send(req, (const char *)data_json, strlen((const char*)data_json));
free(data_json);
return res;
}
httpd_uri_t index_uri = {
.uri = "/",
.method = HTTP_GET,
.handler = index_get_handler,
};
httpd_uri_t image_uri = {
.uri = "/image",
.method = HTTP_POST,
.handler = image_post_handler,
};
httpd_uri_t config_uri = {
.uri = "/config",
.method = HTTP_GET,
.handler = config_get_handler,
};
httpd_handle_t start_webserver(void)
{
httpd_handle_t server = NULL;
httpd_config_t config = HTTPD_DEFAULT_CONFIG();
ESP_LOGI(TAG, "Starting server on port: '%d'", config.server_port);
if(httpd_start(&server, &config) == ESP_OK){
ESP_LOGI(TAG, "Registering URI handlers");
httpd_register_uri_handler(server, &index_uri);
httpd_register_uri_handler(server, &image_uri);
httpd_register_uri_handler(server, &config_uri);
return server;
}
ESP_LOGI(TAG, "Error starting server!");
return NULL;
}
void stop_webserver(httpd_handle_t server)
{
httpd_stop(server);
}
static esp_err_t event_handler(void *ctx, system_event_t *event)
{
httpd_handle_t *server = (httpd_handle_t *) ctx;
switch(event->event_id){
case SYSTEM_EVENT_STA_START:
ESP_LOGI(TAG, "SYSTEM_EVENT_STA_START");
ESP_ERROR_CHECK(esp_wifi_connect());
break;
case SYSTEM_EVENT_STA_GOT_IP:
ESP_LOGI(TAG, "SYSTEM_EVENT_STA_GOT_IP");
ESP_LOGI(TAG, "Got IP: '%s'", ip4addr_ntoa(&event->event_info.got_ip.ip_info.ip));
if(*server == NULL){
*server = start_webserver();
}
break;
case SYSTEM_EVENT_STA_DISCONNECTED:
ESP_LOGI(TAG, "SYSTEM_EVENT_STA_DISCONNECTED");
ESP_ERROR_CHECK(esp_wifi_connect());
if(*server){
stop_webserver(*server);
*server = NULL;
}
break;
default:
break;
}
return ESP_OK;
}
static void initialise_wifi(void *arg)
{
tcpip_adapter_init();
ESP_ERROR_CHECK(esp_event_loop_init(event_handler, arg));
wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT();
ESP_ERROR_CHECK(esp_wifi_init(&cfg));
ESP_ERROR_CHECK(esp_wifi_set_storage(WIFI_STORAGE_RAM));
wifi_config_t wifi_config = {
.sta = {
.ssid = EXAMPLE_WIFI_SSID,
.password = EXAMPLE_WIFI_PASS,
},
};
ESP_LOGI(TAG, "Setting WiFi configuration SSID %s...", wifi_config.sta.ssid);
ESP_ERROR_CHECK(esp_wifi_set_mode(WIFI_MODE_STA));
ESP_ERROR_CHECK(esp_wifi_set_config(ESP_IF_WIFI_STA, &wifi_config));
ESP_ERROR_CHECK(esp_wifi_start());
}
void app_main()
{
static httpd_handle_t server = NULL;
ESP_ERROR_CHECK(nvs_flash_init());
esp_err_t err = esp_camera_init(&camera_config);
if(err != ESP_OK){
ESP_LOGE(TAG, "Camera Init Failed");
return;
}
sensor = esp_camera_sensor_get();
initialise_wifi(&server);
}
index.html
<!doctype html>
<html lang="ja">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<link rel="stylesheet" href="https://use.fontawesome.com/releases/v5.6.4/css/all.css">
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css" integrity="sha384-ggOyR0iXCbMQv3Xipma34MD+dH/1fQ784/j6cY/iJTQUOhcWr7x9JvoRxT2MZw1T" crossorigin="anonymous">
<title>OV7725</title>
<style>
.alert{
display:none;
}
#overlay{
position: fixed;
top: 0;
z-index: 100;
width: 100%;
height:100%;
display: none;
background: rgba(0,0,0,0.6);
}
.cv-spinner{
height: 100%;
display: flex;
justify-content: center;
align-items: center;
}
.spinner{
width: 40px;
height: 40px;
border: 4px #ddd solid;
border-top: 4px #2e93e6 solid;
border-radius: 50%;
animation: sp-anime 0.8s infinite linear;
}
@keyframes sp-anime{
0% {
transform: rotate(0deg);
}
100% {
transform: rotate(359deg);
}
}
.is-hide{
display:none;
}
.ov_a{
height:600px;
overflow-y:auto;
}
</style>
</head>
<body>
<div id="overlay">
<div class="cv-spinner">
<span class="spinner"></span>
</div>
</div>
<div class="text-center mt-3 mb-3">
<h1>OV7725</h1>
</div>
<div class="container-fluid">
<div class="row">
<div class="col-lg-6 text-center mb-4">
<div class="row">
<div class="col-md-12">
<div class="alert alert-success" role="alert">success</div>
<div class="alert alert-danger" role="alert">failed</div>
</div>
<div class="col-md-12">
<img id="img" class="mw-100">
</div>
<div class="col-md-12 mt-4">
<button id="image_button" type="button" class="btn btn-success w-100">Take a Picture</button>
</div>
</div>
</div>
<div class="col-lg-6">
<div class="ov_a">
<form id="form">
<table id="table_regs" class="table table-striped">
<tr>
<th>Address(Hex)</th>
<th>Value(Hex)</th>
</tr>
</table>
</form>
</div>
</div>
</div>
</div>
<script src="https://code.jquery.com/jquery-3.3.1.slim.min.js" integrity="sha384-q8i/X+965DzO0rT7abK41JStQIAqVgRVzpbzo5smXKp4YfRvH+8abtTE1Pi6jizo" crossorigin="anonymous"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.7/umd/popper.min.js" integrity="sha384-UO2eT0CpHqdSJQ6hJty5KVphtPhzWj9WO1clHTMGa3JDZwrnQq4sF86dIHNDz0W1" crossorigin="anonymous"></script>
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/js/bootstrap.min.js" integrity="sha384-JjSmVgyd0p3pXB1rRibZUAYoIIy6OrQ6VrjIEaFf/nJGzIxFDsf4x0xIM+B07jRM" crossorigin="anonymous"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.1.1/jquery.min.js"></script>
<script type="text/javascript">
$(function(){
var parseJson = function(data) {
var returnJson = {};
for(idx = 0; idx < data.length; idx++){
returnJson[data[idx].name] = data[idx].value
}
return returnJson;
};
$(document).ready(function(){
read_config();
get_image();
});
$("#image_button").on("click", get_image);
function get_image(){
$.ajax({
url: "./image",
type: "POST",
data: JSON.stringify(parseJson($("#form").serializeArray())),
dataType: "json",
beforeSend: function() {
$(".alert").css("display", "none");
$("#overlay").fadeIn(300);
}
})
.done((data) => {
$(".alert").css("display", "none");
$(".alert-success").css("display", "block");
$("#img").attr("src", "data:image/jpeg;base64," + data["image"]);
})
.fail((data) => {
$(".alert").css("display", "none");
$(".alert-danger").css("display", "block");
console.log(data);
})
.always((data) => {
setTimeout(function(){
$("#overlay").fadeOut(300);
},500);
});
}
function read_config(){
$.ajax({
url: "./config",
type: "GET",
dataType: "json",
async: false,
})
.done((data) => {
$.each(data, function(i, item){
$("#table_regs").append('<tr><td>0x' + Number(i).toString(16) + '</td><td><div class="input-group"><div class="input-group-prepend"><span class="input-group-text" id="text1a">0x</span></div><input name="' + i + '" value="' + Number(item).toString(16) + '" type="text" class="form-control"></div></td></tr>');
});
})
}
});
</script>
</body>
</html>
Recommended Posts