{"id":17008831,"url":"https://github.com/i-e-b/espcamwifi","last_synced_at":"2026-05-02T10:37:55.067Z","repository":{"id":139825080,"uuid":"237418009","full_name":"i-e-b/EspCamWifi","owner":"i-e-b","description":"A version of the Espressive demos that builds and runs (on my machine at least)","archived":false,"fork":false,"pushed_at":"2020-02-03T17:55:05.000Z","size":5386,"stargazers_count":1,"open_issues_count":0,"forks_count":0,"subscribers_count":2,"default_branch":"master","last_synced_at":"2025-01-27T12:11:18.576Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"C","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/i-e-b.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2020-01-31T11:37:37.000Z","updated_at":"2024-07-23T11:38:49.000Z","dependencies_parsed_at":null,"dependency_job_id":"4523d91a-a2c5-4283-9039-9d41efff58df","html_url":"https://github.com/i-e-b/EspCamWifi","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/i-e-b%2FEspCamWifi","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/i-e-b%2FEspCamWifi/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/i-e-b%2FEspCamWifi/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/i-e-b%2FEspCamWifi/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/i-e-b","download_url":"https://codeload.github.com/i-e-b/EspCamWifi/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":244959053,"owners_count":20538623,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-10-14T05:29:21.235Z","updated_at":"2026-05-02T10:37:50.034Z","avatar_url":"https://github.com/i-e-b.png","language":"C","funding_links":[],"categories":[],"sub_categories":[],"readme":"# To get started\n\nYou will need to link a wifi password file like `ln -s ~/code/wifipw.h wifi/wifi_sta/main/wifipw.h` that defines `ESP_WIFI_SSID` and `ESP_WIFI_PASS`\n\n* start a shell\n* run `. ~/esp/esp-idf/export.sh`\n* cd to `/wifi/wifi_sta`\n  * `make` to build, then `make flash` to upload to Esp32 board, then `make monitor` to read serial output from board.\n\n\n# Camera unit description\n\nEnglish | [中文](https://github.com/m5stack/m5stack-cam-psram/blob/master/README_zh_CN.md)\n\n## Note\n\nNow, M5Stack has four types of camera units, there are respectively [ESP32CAM](https://docs.m5stack.com/#/en/unit/esp32cam), [M5Camera (A Model)](https://docs.m5stack.com/#/en/unit/m5camera), [M5Camera (B Model)](https://docs.m5stack.com/#/en/unit/m5camera), M5CameraX, [M5CameraF](https://docs.m5stack.com/#/en/unit/m5camera_f).\n\n\u003cimg src=\"img/camera_boards.png\"\u003e\n\nThe main differences between these cameras are **memory**, **interface**, **lens**, **optional hardware** and **camera shell**。\n\n## Firmware description\n\nThe code for this repository is for these boards, and each folder corresponds to a function.\n\n- [mpu6050](https://github.com/m5stack/m5stack-cam-psram/tree/master/mpu6050) -\u003e Gyro routine after soldering MPU6050 chip\n\n- [qr](https://github.com/m5stack/m5stack-cam-psram/tree/master/qr) -\u003e QR code recognition\n\n- [uart](https://github.com/m5stack/m5stack-cam-psram/tree/master/uart) -\u003e 与 [M5Core](https://docs.m5stack.com/#/zh_CN/core/basic) Routine for serial communication\n\n- [wifi](https://github.com/m5stack/m5stack-cam-psram/tree/master/wifi) -\u003e Routine for transferring images\n\n- [face_recognize](https://github.com/m5stack/m5stack-cam-psram/tree/master/face_recognize) -\u003e Face recognition routine\n\n**Please note that before compiling the downloaded code, you need to do the following to configure the appropriate board.**\n\nStep 1：build an ESP-IDF development environment\n\n- [https://docs.espressif.com/projects/esp-idf/en/latest/get-started/index.html](https://docs.espressif.com/projects/esp-idf/en/latest/get-started/index.html)\n\nStep 2：After setting up the ESP-IDF environment, execute `make menuconfig` in the terminal.\n\nStep 3：Configure camera model\n\n\u003cimg src=\"https://github.com/zhouyangyale/m5stack-cam-psram/blob/master/img/board.png\"\u003e\n\n\u003cimg src=\"https://github.com/zhouyangyale/m5stack-cam-psram/blob/master/img/board_.png\"\u003e\n\nStep 4：Open psram\n\n\u003cimg src=\"https://github.com/zhouyangyale/m5stack-cam-psram/blob/master/img/spi.png\"\u003e\n\n\u003cimg src=\"https://github.com/zhouyangyale/m5stack-cam-psram/blob/master/img/ignore.png\"\u003e\n\nStep 5：In the terminal Terminal, execute `make` to ensure that the compilation is correct\n\nStep 6：In the terminal Terminal, execute `make flash` to download the program.\n\nStep 7：In the terminal terminal, execute `make monitor` to open the serial port monitoring.\n\n### Comparison of different versions of cameras\n\nThe picture below is their comparison table. (Note: Because the interface has many different pins, so I have made a separate table to compare.)\n\n- If you want to **view** the detailed defference with them, please click [here](https://shimo.im/sheets/gP96C8YTdyjGgKQC).\n\n- If you want to **download** the detailed defference with them, please click [here](https://github.com/m5stack/M5-Schematic/blob/master/Units/m5camera/M5%20Camera%20Detailed%20Comparison.xlsx).\n\n\u003cimg src=\"https://m5stack.oss-cn-shenzhen.aliyuncs.com/image/m5-docs_table/camera_comparison/camera_main_comparison_en.png\"\u003e\n\n#### The picture of A model and B model\n\n\u003cimg src=\"https://m5stack.oss-cn-shenzhen.aliyuncs.com/image/m5-docs_table/camera_comparison/diff_A_B.png\"\u003e\n\n### Interface Comparison\n\n\u003cimg src=\"https://m5stack.oss-cn-shenzhen.aliyuncs.com/image/m5-docs_table/camera_comparison/CameraPinComparison_en.png\"\u003e\n\n#### Interface Difference\n\nThe following table shows interface difference between those camera boads based on the `Interface Comparison` table.\n\n\u003cimg src=\"https://m5stack.oss-cn-shenzhen.aliyuncs.com/image/m5-docs_table/camera_comparison/CameraPinDifference_en.png\"\u003e\n\n## Important to Remember\n\n- Except when using CIF or lower resolution with JPEG, the driver requires PSRAM to be installed and activated.\n- Using YUV or RGB puts a lot of strain on the chip because writing to PSRAM is not particularly fast. The result is that image data might be missing. This is particularly true if WiFi is enabled. If you need RGB data, it is recommended that JPEG is captured and then turned into RGB using `fmt2rgb888` or `fmt2bmp`/`frame2bmp`.\n- When 1 frame buffer is used, the driver will wait for the current frame to finish (VSYNC) and start I2S DMA. After the frame is acquired, I2S will be stopped and the frame buffer returned to the application. This approach gives more control over the system, but results in longer time to get the frame.\n- When 2 or more frame bufers are used, I2S is running in continuous mode and each frame is pushed to a queue that the application can access. This approach puts more strain on the CPU/Memory, but allows for double the frame rate. Please use only with JPEG.\n\n## Installation Instructions\n\n- Clone or download and extract the repository to the components folder of your ESP-IDF project\n- `Make`\n\n## API\n\n### Get img data\n\n```c\ncamera_fb_t * fb = NULL;\n// will get a img frame\nfb = esp_camera_fb_get();\n// img buf\nuint8_t *buf = fb-\u003ebuf;\n// img buf len\nunit32_t buf_len = fb-\u003elen;\n\n/* --- do some something --- */\n\n// need return img buf\nesp_camera_fb_return(fb);\n```\n\n### Set ov2640 config\n\n```c\nsensor_t *s = esp_camera_sensor_get();\ns-\u003eset_framesize(s, FRAMESIZE_VGA);\ns-\u003eset_quality(s, 10);\n...\n```\n\nDetailed view [sensor.h](components/esp32-camera/driver/include/sensor.h)\n\n## Examples\n\n### Initialization\n\n```c\n#include \"esp_camera.h\"\n\nstatic camera_config_t camera_config = {\n    .pin_reset = CAM_PIN_RESET,\n    .pin_xclk = CAM_PIN_XCLK,\n    .pin_sscb_sda = CAM_PIN_SIOD,\n    .pin_sscb_scl = CAM_PIN_SIOC,\n\n    .pin_d7 = CAM_PIN_D7,\n    .pin_d6 = CAM_PIN_D6,\n    .pin_d5 = CAM_PIN_D5,\n    .pin_d4 = CAM_PIN_D4,\n    .pin_d3 = CAM_PIN_D3,\n    .pin_d2 = CAM_PIN_D2,\n    .pin_d1 = CAM_PIN_D1,\n    .pin_d0 = CAM_PIN_D0,\n    .pin_vsync = CAM_PIN_VSYNC,\n    .pin_href = CAM_PIN_HREF,\n    .pin_pclk = CAM_PIN_PCLK,\n\n    //XCLK 20MHz or 10MHz\n    .xclk_freq_hz = 20000000,\n    .ledc_timer = LEDC_TIMER_0,\n    .ledc_channel = LEDC_CHANNEL_0,\n\n    .pixel_format = PIXFORMAT_JPEG,//YUV422,GRAYSCALE,RGB565,JPEG\n    .frame_size = FRAMESIZE_UXGA,//QQVGA-UXGA Do not use sizes above QVGA when not JPEG\n\n    .jpeg_quality = 12, //0-63 lower number means higher quality\n    .fb_count = 1 //if more than one, i2s runs in continuous mode. Use only with JPEG\n};\n\nesp_err_t camera_init(){\n    //power up the camera if PWDN pin is defined\n    if(CAM_PIN_PWDN != -1){\n        pinMode(CAM_PIN_PWDN, OUTPUT);\n        digitalWrite(CAM_PIN_PWDN, LOW);\n    }\n\n    //initialize the camera\n    esp_err_t err = esp_camera_init(\u0026camera_config);\n    if (err != ESP_OK) {\n        ESP_LOGE(TAG, \"Camera Init Failed\");\n        return err;\n    }\n\n    return ESP_OK;\n}\n\nesp_err_t camera_capture(){\n    //acquire a frame\n    camera_fb_t * fb = esp_camera_fb_get();\n    if (!fb) {\n        ESP_LOGE(TAG, \"Camera Capture Failed\");\n        return ESP_FAIL;\n    }\n    //replace this with your own function\n    process_image(fb-\u003ewidth, fb-\u003eheight, fb-\u003eformat, fb-\u003ebuf, fb-\u003elen);\n\n    //return the frame buffer back to the driver for reuse\n    esp_camera_fb_return(fb);\n    return ESP_OK;\n}\n```\n\n### JPEG HTTP Capture\n\n```c\n#include \"esp_camera.h\"\n#include \"esp_http_server.h\"\n#include \"esp_timer.h\"\n\ntypedef struct {\n        httpd_req_t *req;\n        size_t len;\n} jpg_chunking_t;\n\nstatic size_t jpg_encode_stream(void * arg, size_t index, const void* data, size_t len){\n    jpg_chunking_t *j = (jpg_chunking_t *)arg;\n    if(!index){\n        j-\u003elen = 0;\n    }\n    if(httpd_resp_send_chunk(j-\u003ereq, (const char *)data, len) != ESP_OK){\n        return 0;\n    }\n    j-\u003elen += len;\n    return len;\n}\n\nesp_err_t jpg_httpd_handler(httpd_req_t *req){\n    camera_fb_t * fb = NULL;\n    esp_err_t res = ESP_OK;\n    size_t fb_len = 0;\n    int64_t fr_start = esp_timer_get_time();\n\n    fb = esp_camera_fb_get();\n    if (!fb) {\n        ESP_LOGE(TAG, \"Camera capture failed\");\n        httpd_resp_send_500(req);\n        return ESP_FAIL;\n    }\n    res = httpd_resp_set_type(req, \"image/jpeg\");\n    if(res == ESP_OK){\n        res = httpd_resp_set_hdr(req, \"Content-Disposition\", \"inline; filename=capture.jpg\");\n    }\n\n    if(res == ESP_OK){\n        if(fb-\u003eformat == PIXFORMAT_JPEG){\n            fb_len = fb-\u003elen;\n            res = httpd_resp_send(req, (const char *)fb-\u003ebuf, fb-\u003elen);\n        } else {\n            jpg_chunking_t jchunk = {req, 0};\n            res = frame2jpg_cb(fb, 80, jpg_encode_stream, \u0026jchunk)?ESP_OK:ESP_FAIL;\n            httpd_resp_send_chunk(req, NULL, 0);\n            fb_len = jchunk.len;\n        }\n    }\n    esp_camera_fb_return(fb);\n    int64_t fr_end = esp_timer_get_time();\n    ESP_LOGI(TAG, \"JPG: %uKB %ums\", (uint32_t)(fb_len/1024), (uint32_t)((fr_end - fr_start)/1000));\n    return res;\n}\n```\n\n### JPEG HTTP Stream\n\n```c\n#include \"esp_camera.h\"\n#include \"esp_http_server.h\"\n#include \"esp_timer.h\"\n\n#define PART_BOUNDARY \"123456789000000000000987654321\"\nstatic const char* _STREAM_CONTENT_TYPE = \"multipart/x-mixed-replace;boundary=\" PART_BOUNDARY;\nstatic const char* _STREAM_BOUNDARY = \"\\r\\n--\" PART_BOUNDARY \"\\r\\n\";\nstatic const char* _STREAM_PART = \"Content-Type: image/jpeg\\r\\nContent-Length: %u\\r\\n\\r\\n\";\n\nesp_err_t jpg_stream_httpd_handler(httpd_req_t *req){\n    camera_fb_t * fb = NULL;\n    esp_err_t res = ESP_OK;\n    size_t _jpg_buf_len;\n    uint8_t * _jpg_buf;\n    char * part_buf[64];\n    static int64_t last_frame = 0;\n    if(!last_frame) {\n        last_frame = esp_timer_get_time();\n    }\n\n    res = httpd_resp_set_type(req, _STREAM_CONTENT_TYPE);\n    if(res != ESP_OK){\n        return res;\n    }\n\n    while(true){\n        fb = esp_camera_fb_get();\n        if (!fb) {\n            ESP_LOGE(TAG, \"Camera capture failed\");\n            res = ESP_FAIL;\n        } else {\n            if(fb-\u003eformat != PIXFORMAT_JPEG){\n                bool jpeg_converted = frame2jpg(fb, 80, \u0026_jpg_buf, \u0026_jpg_buf_len);\n                if(!jpeg_converted){\n                    ESP_LOGE(TAG, \"JPEG compression failed\");\n                    esp_camera_fb_return(fb);\n                    res = ESP_FAIL;\n                }\n            } else {\n                _jpg_buf_len = fb-\u003elen;\n                _jpg_buf = fb-\u003ebuf;\n            }\n        }\n        if(res == ESP_OK){\n            size_t hlen = snprintf((char *)part_buf, 64, _STREAM_PART, _jpg_buf_len);\n\n            res = httpd_resp_send_chunk(req, (const char *)part_buf, hlen);\n        }\n        if(res == ESP_OK){\n            res = httpd_resp_send_chunk(req, (const char *)_jpg_buf, _jpg_buf_len);\n        }\n        if(res == ESP_OK){\n            res = httpd_resp_send_chunk(req, _STREAM_BOUNDARY, strlen(_STREAM_BOUNDARY));\n        }\n        if(fb-\u003eformat != PIXFORMAT_JPEG){\n            free(_jpg_buf);\n        }\n        esp_camera_fb_return(fb);\n        if(res != ESP_OK){\n            break;\n        }\n        int64_t fr_end = esp_timer_get_time();\n        int64_t frame_time = fr_end - last_frame;\n        last_frame = fr_end;\n        frame_time /= 1000;\n        ESP_LOGI(TAG, \"MJPG: %uKB %ums (%.1ffps)\",\n            (uint32_t)(_jpg_buf_len/1024),\n            (uint32_t)frame_time, 1000.0 / (uint32_t)frame_time);\n    }\n\n    last_frame = 0;\n    return res;\n}\n```\n\n### BMP HTTP Capture\n\n```c\n#include \"esp_camera.h\"\n#include \"esp_http_server.h\"\n#include \"esp_timer.h\"\n\nesp_err_t bmp_httpd_handler(httpd_req_t *req){\n    camera_fb_t * fb = NULL;\n    esp_err_t res = ESP_OK;\n    int64_t fr_start = esp_timer_get_time();\n\n    fb = esp_camera_fb_get();\n    if (!fb) {\n        ESP_LOGE(TAG, \"Camera capture failed\");\n        httpd_resp_send_500(req);\n        return ESP_FAIL;\n    }\n\n    uint8_t * buf = NULL;\n    size_t buf_len = 0;\n    bool converted = frame2bmp(fb, \u0026buf, \u0026buf_len);\n    esp_camera_fb_return(fb);\n    if(!converted){\n        ESP_LOGE(TAG, \"BMP conversion failed\");\n        httpd_resp_send_500(req);\n        return ESP_FAIL;\n    }\n\n    res = httpd_resp_set_type(req, \"image/x-windows-bmp\")\n       || httpd_resp_set_hdr(req, \"Content-Disposition\", \"inline; filename=capture.bmp\")\n       || httpd_resp_send(req, (const char *)buf, buf_len);\n    free(buf);\n    int64_t fr_end = esp_timer_get_time();\n    ESP_LOGI(TAG, \"BMP: %uKB %ums\", (uint32_t)(buf_len/1024), (uint32_t)((fr_end - fr_start)/1000));\n    return res;\n}\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fi-e-b%2Fespcamwifi","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fi-e-b%2Fespcamwifi","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fi-e-b%2Fespcamwifi/lists"}