博客 / 詳情

返回

《ESP32-S3使用指南—IDF版 V1.6》第五十六章 網絡攝像頭實驗

第五十六章 網絡攝像頭實驗

網絡攝像頭是傳統攝像機與網絡視頻技術相結合的新一代產品,除了具備一般傳統攝像機所有的圖像捕捉功能外,機內還內置了數字化壓縮控制器和基於WEB的操作系統,使得視頻數據經壓縮加密後,通過局域網,internet或無線網絡送至終端用户。而遠端用户可在PC上使用標準的網絡瀏覽器,根據網絡攝像機的IP地址,對網絡攝像機進行訪問,實時監控目標現場的情況,並可對圖像資料實時編輯和存儲,同時還可以控制攝像機的雲台和鏡頭,進行全方位地監控。本章的實驗是以網絡調試助手作為客户端,開發板作為服務器。服務器把攝像頭處理的數據使用網卡發送至服務器當中,並且在服務器實時更新圖像。

本章分為如下幾個部分:
56.1 ATK-MC5640&MC2640簡介
56.2 硬件設計
56.3 軟件設計
56.4 下載驗證

56.1 ATK-MC5640&MC2640簡介

本實驗支持正點原子5640和2640模塊,這兩個模塊的相關資料可在正點原子提供的《ATK-MC2640模塊用户手冊_V1.1》和《ATK-MC5640模塊用户手冊V1.0》用户手冊查看。

56.2 硬件設計

1.例程功能
本章實驗功能簡介:開發板主控芯片通過SCCB協議對ATK-MC5640/ ATK-MC2640模塊中的攝像頭傳感器進行配置等通訊,並通過CAMERA接口獲取ATK-MC5640/ ATK-MC2640模塊輸出的JPEG圖像數據,然後將獲取到的圖像實時的發往至正點原子自研的ATK-XCAM軟件。

2.硬件資源
1)LED燈
LED-IO1

2)XL9555
IIC_INT-IO0(需在P5連接IO0)
IIC_SDA-IO41
IIC_SCL-IO42
3)SPILCD
CS-IO21
SCK-IO12
SDA-IO11
DC-IO40(在P5端口,使用跳線帽將IO_SET和LCD_DC相連)
PWR- IO1_3(XL9555)
RST- IO1_2(XL9555)

4)CAMERA
OV_SCL-IO38
OV_SDA- IO39
VSYNC- IO47
HREF- IO48
PCLK- IO45
D0- IO4
D1- IO5
D2- IO6
D3- IO7
D4- IO15
D5- IO16
D6- IO17
D7- IO18
RESET-IO0_5(XL9555)
PWDN-IO0_4(XL9555)

3.原理圖
CAMERA接口與ESP32-S3的連接關係,如下圖所示:

圖56.2.1 CAMERA接口與ESP32-S3的連接電路圖

56.3 軟件設計

56.3.1 程序流程圖

程序流程圖能幫助我們更好的理解一個工程的功能和實現的過程,對學習和設計工程有很好的主導作用。下面看看本實驗的程序流程圖:

圖56.3.1.1 程序流程圖

56.3.2 程序解析

在本章節中,我們主要關注兩個文件:lwip_demo.c和lwip_demo.h。lwip_demo.h文件主要聲明瞭lwip_demo函數,這部分相對簡單,所以我們暫不詳細解釋。主要關注點是lwip_demo.c文件中的函數。在lwip_demo函數中,我們配置了相關的TCPClient參數,並創建了一個名為lwip_send_thread的發送數據線程。這個線程通過調用scokec函數來發送數據到服務器。接下來,我們將分別詳細解釋lwip_demo函數和lwip_send_thread任務。

/* 需要自己設置遠程IP地址 */
#define IP_ADDR   "192.168.2.245"

#define LWIP_DEMO_RX_BUFSIZE         100           /* 最大接收數據長度 */
#define LWIP_DEMO_PORT               8080             /* 連接的本地端口號 */
#define LWIP_SEND_THREAD_PRIO        10            /* 發送數據線程優先級 */
/* 接收數據緩衝區 */
uint8_t g_lwip_demo_recvbuf[LWIP_DEMO_RX_BUFSIZE]; 

/* 數據發送標誌位 */
uint8_t g_lwip_send_flag;
int g_sock = -1;
int g_lwip_connect_state = 0;
static void lwip_send_thread(void *arg);


/**
 * @brief       發送數據線程
 * @param       無
 * @retval      無
 */
void lwip_data_send(void)
{
xTaskCreate(lwip_send_thread, "lwip_send_thread", 2 * 1024, 
NULL, LWIP_SEND_THREAD_PRIO, NULL);
}

/**
 * @brief       lwip_demo實驗入口
 * @param       無
 * @retval      無
 */
void lwip_demo(void)
{
    int err;
    struct sockaddr_in atk_client_addr;
    int recv_data_len;
    char *tbuf;
    
    lwip_data_send();                                        /* 創建發送數據線程 */
    
    while (1)
    {
sock_start:
        g_lwip_connect_state = 0;
        atk_client_addr.sin_family = AF_INET;              /* 表示IPv4網絡協議 */
        atk_client_addr.sin_port = htons(LWIP_DEMO_PORT);       /* 端口號 */
        atk_client_addr.sin_addr.s_addr = inet_addr(IP_ADDR);   /* 遠程IP地址 */
        g_sock = socket(AF_INET, SOCK_STREAM, 0);/* 可靠數據流交付服務既是TCP協議 */
        memset(&(atk_client_addr.sin_zero), 0,
               sizeof(atk_client_addr.sin_zero));
        
        tbuf = malloc(200);                                     /* 申請內存 */
        sprintf((char *)tbuf, "Port:%d", LWIP_DEMO_PORT);       /* 客户端端口號 */
        lcd_show_string(5, 170, 200, 16, 16, tbuf, MAGENTA);
        
        /* 連接遠程IP地址 */
        err = connect(g_sock, (struct sockaddr *)&atk_client_addr, 
sizeof(struct sockaddr));

        if (err == -1)
        {
            lcd_show_string(5, 190, 200, 16, 16, "State:Disconnect", MAGENTA);
            g_sock = -1;
            closesocket(g_sock);
            free(tbuf);
            vTaskDelay(10);
            goto sock_start;
        }

        lcd_show_string(5,190,200,16,16,"State:Connection Successful",MAGENTA);
        g_lwip_connect_state = 1;
        
        while (1)
        {
            recv_data_len = recv(g_sock,g_lwip_demo_recvbuf,
                                 LWIP_DEMO_RX_BUFSIZE,0);
            if (recv_data_len <= 0 )
            {
                closesocket(g_sock);
                g_sock = -1;
                lcd_fill(5, 190, lcd_self.width,320, WHITE);
                lcd_show_string(5,190, 00,16,16,"State:Disconnect", MAGENTA);
                free(tbuf);
                goto sock_start;
            }

            vTaskDelay(1);
        }
    }
}

/**
 * @brief       發送數據線程函數
 * @param       pvParameters : 傳入參數(未用到)
 * @retval      無
 */
void lwip_send_thread(void *pvParameters)
{
    pvParameters = pvParameters;
    
    camera_fb_t *camera_frame = NULL;
    while (1)
    {
        if (g_lwip_connect_state == 1) /* 有數據要發送 */
        {
            camera_frame = esp_camera_fb_get();
            write(g_sock, camera_frame->buf, camera_frame->len);
            esp_camera_fb_return(camera_frame);
        }
        
        vTaskDelay(1);
    }
}

在上述源碼中,首先創建了一個用於發送ESP32-S3設備數據的任務。然後,對TCPClient進行網絡參數配置,並調用connect函數來建立與遠程服務器的連接。當連接成功時,系統將進入接收輪詢任務。如果出現斷開連接的情況,系統將嘗試重新連接服務器。在發送線程中,發送數據前會檢查連接標誌位。如果標誌位有效,則通過write函數發送攝像頭圖像數據。

56.4 下載驗證

在程序中,首先需要設置好能夠連接的網絡賬號和密碼。然後,使用筆記本電腦作為終端,確保它與ESP32-S3設備處於同一網絡段內。當ESP32-S3設備成功連接到網絡時,它的LCD顯示屏上會顯示相應的內容:

圖56.4.1 設備連接到網絡時,LCD顯示的信息
打開視頻傳輸上位機,然後配置網絡參數,如TCPServer協議、端口號等,最後點擊連接,如下圖所示。

圖56.4.1 視頻傳輸上位機顯示內容

user avatar
0 位用戶收藏了這個故事!

發佈 評論

Some HTML is okay.