这些小活动你都参加了吗?快来围观一下吧!>>
电子产品世界 » 论坛首页 » 活动中心 » 有奖活动 » 【全网首拆】M5STACK ATOM系列开发板拆解 / AtomS3R-CAM摄

共1条 1/1 1 跳转至

【全网首拆】M5STACK ATOM系列开发板拆解 / AtomS3R-CAM摄像头更换方法(提高10倍像素)

助工
2026-05-31 22:17:59     打赏


前言:由于AtomS3R-CAM 和 AtomS3R-M12 两款开发板的唯一区别就是图像传感器,而且AtomS3R-CAM只有分辨率0.3MP,因此打算更换成M12同款的OV3660(像素瞬间提高10倍)

但是发现网上并没有相关拆解方法以及内部结构图,所以只好自己试一试了...


一、硬件介绍

本次拆解的是M5STACK ATOM系列的AtomS3R-CAM开发板;

产品尺寸只有 24.0 x 24.0 x 13.5mm,重量 7.4g,非常的小巧,长宽大致不到小型面包板长度的一半;


image-20260531213207767.png


其他ATOM系列的开发板外部布局都大致相同,都可以采用以下介绍的拆卸方法;

image-20260531203422540.png

image-20260531203422540

二、拆卸方法

硬件准备:

1、一张硬卡片(银行卡、身份证等都行)

2、镊子(直尖头)




拆卸方法:

1、先将尾部后侧的贴纸撕掉;

2、用硬卡片从后侧往里卡出一个缝隙;

3、然后用镊子向箭头两侧所指的方向,往内向下撬,直到听到卡扣脱落的清脆声音;


image-20260518222230157.png

image-20260518222230157

内部卡扣结构

image-20260518221343804.png

image-20260518221343804

整体上下外壳

image-20260518221353134.png

image-20260518221353134

整体内部图,看上去布局很紧凑;

摄像头排线长度大约10mm,不过市面上的最短基本大多都在21mm;

所以要替换其他摄像头(OV3660 / OV5640)的话,还需要单独定制一个相同长度的...

(不过单独定制的价格还是挺“昂贵”的...)


image-20260518220412857.png


image-20260518220409037.png



侧面视角

image-20260518220458024.png


底部视角

image-20260518220630580.png



三、摄像头测试代码


如果更换了摄像头,以下是OV3660的功能测试代码;


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

#define USE_ATOMS3R_CAM

#define STA_MODE
// #define AP_MODE

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

WiFiServer server(80);
camera_fb_t* fb    = NULL;
uint8_t* out_jpg   = NULL;
size_t out_jpg_len = 0;

static void jpegStream(WiFiClient* client);

static camera_config_t camera_config = {
    .pin_pwdn     = PWDN_GPIO_NUM,
    .pin_reset    = RESET_GPIO_NUM,
    .pin_xclk     = XCLK_GPIO_NUM,
    .pin_sscb_sda = SIOD_GPIO_NUM,
    .pin_sscb_scl = SIOC_GPIO_NUM,
    .pin_d7       = Y9_GPIO_NUM,
    .pin_d6       = Y8_GPIO_NUM,
    .pin_d5       = Y7_GPIO_NUM,
    .pin_d4       = Y6_GPIO_NUM,
    .pin_d3       = Y5_GPIO_NUM,
    .pin_d2       = Y4_GPIO_NUM,
    .pin_d1       = Y3_GPIO_NUM,
    .pin_d0       = Y2_GPIO_NUM,

    .pin_vsync = VSYNC_GPIO_NUM,
    .pin_href  = HREF_GPIO_NUM,
    .pin_pclk  = PCLK_GPIO_NUM,

    .xclk_freq_hz = 20000000,
    .ledc_timer   = LEDC_TIMER_0,
    .ledc_channel = LEDC_CHANNEL_0,

    .pixel_format = PIXFORMAT_RGB565,
    .frame_size   = FRAMESIZE_QVGA,

    .jpeg_quality  = 12,
    .fb_count      = 2,
    .fb_location   = CAMERA_FB_IN_PSRAM,
    .grab_mode     = CAMERA_GRAB_LATEST,
    .sccb_i2c_port = 0,
};

void setup()
{
    Serial.begin(115200);
    pinMode(POWER_GPIO_NUM, OUTPUT);
    digitalWrite(POWER_GPIO_NUM, LOW);
    delay(500);
    esp_err_t err = esp_camera_init(&camera_config);
    if (err != ESP_OK) {
        Serial.println("Camera Init Fail");
        delay(1000);
        esp_restart();
    } else {
        Serial.println("Camera Init Success");
    }
    delay(100);

#ifdef STA_MODE

    WiFi.mode(WIFI_STA);
    WiFi.begin(ssid, password);
    WiFi.setSleep(false);
    Serial.println("");

    Serial.print("Connecting to ");
    Serial.println(ssid);

    // Wait for connection
    while (WiFi.status() != WL_CONNECTED) {
        delay(500);
        Serial.print(".");
    }

    Serial.println("");
    Serial.print("Connected to ");
    Serial.println(ssid);
    Serial.print("IP address: ");
    Serial.println(WiFi.localIP());
#endif

#ifdef AP_MODE
    if (!WiFi.softAP(ssid, password)) {
        log_e("Soft AP creation failed.");
        while (1);
    }

    Serial.println("AP SSID:");
    Serial.println(ssid);
    Serial.println("AP PASSWORD:");
    Serial.println(password);

    IPAddress IP = WiFi.softAPIP();
    Serial.print("AP IP address: ");
    Serial.println(IP);
#endif

    server.begin();
}

void loop()
{
    WiFiClient client = server.available();  // listen for incoming clients
    if (client) {                            // if you get a client,
        while (client.connected()) {         // loop while the client's connected
            if (client.available()) {        // if there's bytes to read from the
                jpegStream(&client);
            }
        }
        // close the connection:
        client.stop();
        Serial.println("Client Disconnected.");
    }
}

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

static void jpegStream(WiFiClient* client)
{
    Serial.println("Image stream start");
    client->println("HTTP/1.1 200 OK");
    client->printf("Content-Type: %s\r\n", _STREAM_CONTENT_TYPE);
    client->println("Content-Disposition: inline; filename=capture.jpg");
    client->println("Access-Control-Allow-Origin: *");
    client->println();
    static int64_t last_frame = 0;
    if (!last_frame) {
        last_frame = esp_timer_get_time();
    }

    for (;;) {
        fb = esp_camera_fb_get();
        if (fb) {

            frame2jpg(fb, 255, &out_jpg, &out_jpg_len);

            Serial.printf("pic size: %d\n", out_jpg_len);
            client->print(_STREAM_BOUNDARY);
            client->printf(_STREAM_PART, out_jpg_len);
            int32_t to_sends    = out_jpg_len;
            int32_t now_sends   = 0;
            uint8_t* out_buf    = out_jpg;
            uint32_t packet_len = 8 * 1024;
            while (to_sends > 0) {
                now_sends = to_sends > packet_len ? packet_len : to_sends;
                if (client->write(out_buf, now_sends) == 0) {
                    goto client_exit;
                }
                out_buf += now_sends;
                to_sends -= now_sends;
            }

            int64_t fr_end     = esp_timer_get_time();
            int64_t frame_time = fr_end - last_frame;
            last_frame         = fr_end;
            frame_time /= 1000;
            Serial.printf("MJPG: %luKB %lums (%.1ffps)\r\n", (long unsigned int)(out_jpg_len / 1024),
                          (long unsigned int)frame_time, 1000.0 / (long unsigned int)frame_time);

            if (fb) {
                esp_camera_fb_return(fb);
                fb = NULL;
            }

            if (out_jpg) {
                free(out_jpg);
                out_jpg     = NULL;
                out_jpg_len = 0;
            }
        } else {
            Serial.println("Camera capture failed");
        }
    }

client_exit:
    if (fb) {
        esp_camera_fb_return(fb);
        fb = NULL;
    }
    if (out_jpg) {
        free(out_jpg);
        out_jpg     = NULL;
        out_jpg_len = 0;
    }
    client->stop();
    Serial.printf("Image stream end\r\n");
}


四、安装方法


安装非常简单,只需上下外壳对齐卡扣后向下按压即可;


1、先将开发板放置到底部配件上;

2、再将USB口、摄像头对齐上半部分配件;

3、对齐后,向下按压即可合体;


image-20260531220002355.png













关键词: M5STACK ATOM          AtomS3R-CAM    

共1条 1/1 1 跳转至

回复

匿名不能发帖!请先 [ 登陆 注册 ]