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/>';
}
?>