2022-12-01|閱讀時間 ‧ 約 12 分鐘

ESP32-CAM 拍照上傳 XAMPP

ESP32 CAM 運行畫面
ESP32 CAM 運行畫面
Server 端上檔案 有 index.php
ESP32 CAM 拍照 上傳 pict.jpg 檔

XAMPP 伺服器架設

S1. 下載與安裝
S2. 啟動XAMPP、Apache、Mysql
S3. Mysql安全性設定
shell : --user=root password "1234"
phpmyadmin(config.inc.php)
S4. Apache設定 網站根目錄
http.conf : documentroot
S5. PHP環境設定
php.ini :
短標籤 : short_open_tag = On
參數為全域變數 : register_globals = off
錯誤訊息 : display_errors = On
錯誤等級 : error_reporting = E_ALL & ~E_NOTICE
時區 : date.timezone = Asia / Taipei

ESP32-CAM CODE

#include <WiFi.h>
#include "esp_camera.h"
#define SERVER      "192.168.137.1"  // 請改成你的網站伺服器位址或域名
#define UPLOAD_URL  "/esp32cam/index.php" //此處為後端 接收圖檔的php程式
#define PORT        80

const char* ssid = "Wi-Fi網路名稱";
const char* password = "網路密碼";

WiFiClient client;

const int timerInterval = 10000;    // 上傳影像的間隔毫秒數
unsigned long previousMillis = 0;

bool initCamera() {
 // 設定攝像頭的接腳和影像格式與尺寸
 static camera_config_t camera_config = {
   .pin_pwdn       = 32,  // 斷電腳
   .pin_reset      = -1,  // 重置腳
   .pin_xclk       = 0,   // 外部時脈腳
   .pin_sscb_sda   = 26,  // I2C資料腳
   .pin_sscb_scl   = 27,  // I2C時脈腳
   .pin_d7         = 35,  // 資料腳
   .pin_d6         = 34,
   .pin_d5         = 39,
   .pin_d4         = 36,
   .pin_d3         = 21,
   .pin_d2         = 19,
   .pin_d1         = 18,
   .pin_d0         = 5,
   .pin_vsync      = 25,   // 垂直同步腳
   .pin_href       = 23,   // 水平同步腳
   .pin_pclk       = 22,   // 像素時脈腳
   .xclk_freq_hz   = 20000000,       // 設定外部時脈:20MHz
   .ledc_timer     = LEDC_TIMER_0,   // 指定產生XCLK時脈的計時器
   .ledc_channel   = LEDC_CHANNEL_0, // 指定產生XCLM時脈的通道
   .pixel_format   = PIXFORMAT_JPEG, // 設定影像格式:JPEG
   .frame_size     = FRAMESIZE_SVGA, // 設定影像大小:SVGA
   .jpeg_quality   = 10,  // 設定JPEG影像畫質,有效值介於0-63,數字越低畫質越高。
   .fb_count       = 1    // 影像緩衝記憶區數量
 };

 // 初始化攝像頭
 esp_err_t err = esp_camera_init(&camera_config);
 if (err != ESP_OK) {
   Serial.printf("攝像頭出錯了,錯誤碼:0x%x", err);
   return false;
 }

 return true;
}

void postImage() {
 camera_fb_t *fb = NULL;    // 宣告儲存影像結構資料的變數
 fb = esp_camera_fb_get();  // 拍照

 if(!fb) {
   Serial.println("無法取得影像資料…");
   delay(1000);
   ESP.restart();  // 重新啟動
 }

 Serial.printf("連接伺服器:%s\n", SERVER);

 if (client.connect(SERVER, PORT)) {
   Serial.println("開始上傳影像…");     

   String boundBegin = "--ESP32CAM\r\n";
   boundBegin += "Content-Disposition: form-data; name=\"filename\"; filename=\"pict.jpg\"\r\n";
   boundBegin += "Content-Type: image/jpeg\r\n";
   boundBegin += "\r\n";

   String boundEnd = "\r\n--ESP32CAM--\r\n";

   uint32_t imgSize = fb->len;  // 取得影像檔的大小
   uint32_t payloadSize = boundBegin.length() + imgSize + boundEnd.length();

   String httpMsg = String("POST ") + UPLOAD_URL + " HTTP/1.1\r\n";
   httpMsg += String("Host: ") + SERVER + "\r\n";
   httpMsg += "User-Agent: Arduino/ESP32CAM\r\n";
   httpMsg += "Content-Length: " + String(payloadSize) + "\r\n";
   httpMsg += "Content-Type: multipart/form-data; boundary=ESP32CAM\r\n";
   httpMsg += "\r\n";
   httpMsg += boundBegin;

   // 送出HTTP標頭訊息
   client.print(httpMsg.c_str());

   // 上傳檔案
   uint8_t *buf = fb->buf;

   for (uint32_t i=0; i<imgSize; i+=1024) {
     if (i+1024 < imgSize) {
       client.write(buf, 1024);
       buf += 1024;
     } else if (imgSize%1024>0) {
       uint32_t remainder = imgSize%1024;
       client.write(buf, remainder);
     }
   }

   client.print(boundEnd.c_str());

   esp_camera_fb_return(fb);

   // 等待伺服器的回應(10秒)
   long timout = 10000L + millis();

   while (timout > millis()) {
     Serial.print(".");
     delay(100);

     if (client.available()){
       // 讀取伺服器的回應
       Serial.println("\n伺服器回應:");
       String line = client.readStringUntil('\r');
       Serial.println(line);
       break;
     }
   }

   Serial.println("關閉連線");
 } else {
   Serial.printf("無法連接伺服器:%s\n", SERVER);
 }

 client.stop();  // 關閉用戶端
}

void setup() {
 Serial.begin(115200);

 WiFi.mode(WIFI_STA);
 WiFi.begin(ssid, password);
 Serial.println("\n\n連接Wi-Fi");
 while (WiFi.status() != WL_CONNECTED) {
   delay(500);
   Serial.print(".");
 }
 Serial.print("\nIP位址:");
 Serial.println(WiFi.localIP());

 bool cameraReady = initCamera();
 if (!cameraReady) {
   Serial.println("攝像頭出錯了…");
   delay(1000);
   ESP.restart();  // 重新啟動ESP32
 }

 postImage();   // 上傳影像
}

void loop() {
 unsigned long currentMillis = millis();
 if (currentMillis - previousMillis >= timerInterval) {
   postImage();  // 上傳影像
   previousMillis = currentMillis;
 }
}

Server 端 php code

<?php
# 檢查檔案是否上傳成功
if ($_FILES['filename']['error'] === UPLOAD_ERR_OK){
  echo '檔案名稱: ' . $_FILES['filename']['name'] . '<br/>';
  echo '檔案類型: ' . $_FILES['filename']['type'] . '<br/>';
  echo '檔案大小: ' . ($_FILES['filename']['size'] / 1024) . ' KB<br/>';
  echo '暫存名稱: ' . $_FILES['filename']['tmp_name'] . '<br/>';

  # 檢查檔案是否已經存在
  if (file_exists('./' . $_FILES['filename']['name'])){
    echo '檔案已存在。<br/>';
  } else {
    $file = $_FILES['filename']['tmp_name'];
    $dest = './' . $_FILES['filename']['name'];

    # 將檔案移至指定位置
    move_uploaded_file($file, $dest);
  }
} else {
  echo '錯誤代碼:' . $_FILES['filename']['error'] . '<br/>';
}
?>
分享至
成為作者繼續創作的動力吧!
社會觀察者、社會企業家、教育創新者、遊戲人、媒體人、廚師,小人物與您分享眼見耳聞的生活大小事。 Anything will understand slightly a spot, life more color spots
從 Google News 追蹤更多 vocus 的最新精選內容從 Google News 追蹤更多 vocus 的最新精選內容

發表回應

成為會員 後即可發表留言