我的ESP32實做書籍:我出書了 ESP32 物聯網專題
博客來網址:https://www.books.com.tw/products/0010901195
實做說明
ESP32CAM預設是透過WIFI傳遞mjpeg影像,同網域監看視訊影像很簡單,但是如果跨網域就要利用NAT的IP轉送,設定有點麻煩。
其他的方式,例如將照片上傳到Google空間,或者把照片上傳到Line等。不過都較為複雜
這次則是使用現在最流行的MQTT轉送照片,並用手機觀看,設定VGA品質每5秒一張,測試幾個小時都很正常。
本次感謝網友楊老師,主內容是他的程式,他還有寫一個車牌辨識,改天請他分享
不過要記得的是我這次用的MQTT沒有安全性,只要有人訂閱同一個Topic就可以觀看你的照片喔
一、材料準備
1.手機,安裝好MQTT APP:MQTT Dash(https://play.google.com/store/apps/details?id=net.routix.mqttdash&hl=zh_TW)
2.ESP32CAM
二、ESP32CAM燒錄以下程式
要先安裝程式庫,請利用功能表/草稿碼/匯入程式庫/管理程式庫,輸入關鍵字:PubSubClient,作者為Nick O’Leary這個
#include <esp_camera.h>
#include <WiFi.h>
#include <PubSubClient.h>
// ------ 以下修改成你自己的WiFi帳號密碼 ------
const char* ssid = "You";
const char* password = "0933932774";
// ------ 以下修改成你MQTT設定 ------
const char* mqtt_server = "mqtt.eclipseprojects.io";//免註冊MQTT伺服器
const unsigned int mqtt_port = 1883;
#define MQTT_USER "my_name" //本案例未使用
#define MQTT_PASSWORD "my_password" //本案例未使用
#define MQTT_PUBLISH_Monitor "yourTopic/esp32cam/pic" // 放置Binary JPG Image的Topoc,記得要改成自己的
// ------ OV2640相機設定 ------------
#define CAMERA_MODEL_AI_THINKER
#define PWDN_GPIO_NUM 32
#define RESET_GPIO_NUM -1
#define XCLK_GPIO_NUM 0
#define SIOD_GPIO_NUM 26
#define SIOC_GPIO_NUM 27
#define Y9_GPIO_NUM 35
#define Y8_GPIO_NUM 34
#define Y7_GPIO_NUM 39
#define Y6_GPIO_NUM 36
#define Y5_GPIO_NUM 21
#define Y4_GPIO_NUM 19
#define Y3_GPIO_NUM 18
#define Y2_GPIO_NUM 5
#define VSYNC_GPIO_NUM 25
#define HREF_GPIO_NUM 23
#define PCLK_GPIO_NUM 22
char clientId[50];
void mqtt_callback(char* topic, byte* payload, unsigned int msgLength);
WiFiClient wifiClient;
PubSubClient mqttClient(mqtt_server, mqtt_port, mqtt_callback, wifiClient);
//啟動WIFI連線
void setup_wifi() {
Serial.printf("\nConnecting to %s", ssid);
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
}
Serial.print("\nWiFi Connected. IP Address: ");
Serial.println(WiFi.localIP());
}
//MQTT callback,本案例沒使用
void mqtt_callback(char* topic, byte* payload, unsigned int msgLength) {
}
//重新連線MQTT Server
boolean mqtt_nonblock_reconnect() {
boolean doConn = false;
if (! mqttClient.connected()) {
boolean isConn = mqttClient.connect(clientId);
//boolean isConn = mqttClient.connect(clientId, MQTT_USER, MQTT_PASSWORD);
char logConnected[100];
sprintf(logConnected, "MQTT Client [%s] Connect %s !", clientId, (isConn ? "Successful" : "Failed"));
Serial.println(logConnected);
}
return doConn;
}
//MQTT傳遞照片
void MQTT_picture() {
//camera_fb_t * fb; // camera frame buffer.
camera_fb_t * fb = NULL;
fb = esp_camera_fb_get();
if (!fb) {
delay(100);
Serial.println("Camera capture failed, Reset");
ESP.restart();
}
char* logIsPublished;
if (! mqttClient.connected()) {
// client loses its connection
Serial.printf("MQTT Client [%s] Connection LOST !\n", clientId);
mqtt_nonblock_reconnect();
}
if (! mqttClient.connected())
logIsPublished = " No MQTT Connection, Photo NOT Published !";
else {
int imgSize = fb->len;
int ps = MQTT_MAX_PACKET_SIZE;
// start to publish the picture
mqttClient.beginPublish(MQTT_PUBLISH_Monitor, imgSize, false);
for (int i = 0; i < imgSize; i += ps) {
int s = (imgSize - i < s) ? (imgSize - i) : ps;
mqttClient.write((uint8_t *)(fb->buf) + i, s);
}
boolean isPublished = mqttClient.endPublish();
if (isPublished)
logIsPublished = " Publishing Photo to MQTT Successfully !";
else
logIsPublished = " Publishing Photo to MQTT Failed !";
}
Serial.println(logIsPublished);
esp_camera_fb_return(fb);//清除緩衝區
}
void setup() {
Serial.begin(115200);
//相機設定
camera_config_t config;
config.ledc_channel = LEDC_CHANNEL_0;
config.ledc_timer = LEDC_TIMER_0;
config.pin_d0 = Y2_GPIO_NUM;
config.pin_d1 = Y3_GPIO_NUM;
config.pin_d2 = Y4_GPIO_NUM;
config.pin_d3 = Y5_GPIO_NUM;
config.pin_d4 = Y6_GPIO_NUM;
config.pin_d5 = Y7_GPIO_NUM;
config.pin_d6 = Y8_GPIO_NUM;
config.pin_d7 = Y9_GPIO_NUM;
config.pin_xclk = XCLK_GPIO_NUM;
config.pin_pclk = PCLK_GPIO_NUM;
config.pin_vsync = VSYNC_GPIO_NUM;
config.pin_href = HREF_GPIO_NUM;
config.pin_sscb_sda = SIOD_GPIO_NUM;
config.pin_sscb_scl = SIOC_GPIO_NUM;
config.pin_pwdn = PWDN_GPIO_NUM;
config.pin_reset = RESET_GPIO_NUM;
config.xclk_freq_hz = 20000000;
config.pixel_format = PIXFORMAT_JPEG;
config.jpeg_quality = 10; //10-63 lower number means higher quality
config.fb_count = 2;
//設定照片品質
config.frame_size = FRAMESIZE_QVGA ;// FRAMESIZE_ + UXGA|SXGA|XGA|SVGA|VGA|CIF|QVGA|HQVGA|QQVGA
esp_err_t err = esp_camera_init(&config);
delay(500);
//啟動WIFI連線
setup_wifi();
sprintf(clientId, "ESP32CAM_%04X", random(0xffff)); // Create a random client ID
//啟動MQTT連線
mqtt_nonblock_reconnect();
}
void loop() {
mqtt_nonblock_reconnect();
MQTT_picture();//用MQTT傳照片
delay(10000);
}
燒錄完成後,如果設定沒問題,就可以從序列視窗看到傳遞成功的畫面
接下來就是設定手機的MQTT接收端
三、手機MQTT設定
安裝好APP後,先設定MQTT伺服器
1.點選右上角的 (+) 符號
2.輸入與ESP32CAM燒錄時相同的MQTT設定
Name:隨便輸入,自己記得即可
Address:輸入與ESP32CAM程式相同的伺服器,本例:mqtt.eclipseprojects.io
Port:1883
其餘保留預設,按右上角的存檔符號
3.進入剛建立好的MQTT伺服器內(本例為Esp32cam)
點選右上角的(+)服務,加入新的選項
4.選擇類型為Image
5.進入選項設定
先將選項改為第三個Image file data received as binary payload contents
Name:ESP32CAM(自己取名即可)
Topic:請輸入你自己的ESP32CAM程式內相同的Topic
完成後點右上的存檔符號
6.回到Dashboard時,就可以看到照片不斷的傳入喔
7.可以點入,看大圖
測試了一兩天都沒什麼問題,在此分享給大家,MQTT伺服器也沒關閉連線,真是佛心來著。
MQTT APP:MQTT Dash
這個APP似乎沒辦法下載了,請問有其他的替代app嗎?
謝謝~
我們有提供MQTT的網站服務 https://mqttgo.io/
歡迎使用哦!
小霸王實驗室 台灣最快的MQTT上線了
老師架的MQTT的網站服務很讚,
但是我現在是想用手機讀取mqtt的影像,
如果MQTT Dash的手機app已不支援,請問老師現在用哪一套手機app讀取影像呢?
手機使用瀏覽器開啟https://mqttgo.io/就能使用MQTT讀取影像
可以參考影片操作!
物聯網入門推薦|免跳線! ESP32-EasyCam多功能擴充板