搭建arduino开发环境
这里不多说,网上有很多教程。简单说下我在搭建环境时踩的一些坑。
1.在arduino库管理器中下载esp32的库出错
解决方法:搭个梯子下载就行了
2.上传项目报错
这个问题出现的原因是板子连线有问题,在烧录的时候必须使用5V电压供电。上传后运行之前,断开GPIO0与GND的连接,并且使用3.3V电压供电,就可以跑起来了。
3.文件太大无法上传
工具-Partition Scheme-Huge APP,选这个就可以上传了
MQTT连接阿里云物联网平台
建议使用mqtt fx工具,方便模拟设备连接平台。
在设置的过程中要填一些id,密码之类的东西。
Broker Address是阿里云官方给出的,用上海这个就可以。
Broker Port填1883。
后面那三个推荐一个工具,技小新-MQTT单片机编程小工具。直接用这个工具可以计算出来。
SN/NAC随便填,product_key、device_name、device_secret这三个是物联网平台创建设备就会给出的信息复制过来就行,点生成基本信息,后面的数据就计算出来了,直接在mqtt fx中填就行了。
连接成功的话mqtt fx灯的颜色是绿色的。这样就可以模拟板子给平台上报或者订阅属性,目的是用来测试通信的。
图片数据上传
esp32cam抓拍的图片数据先保存在sd卡中,再上传。图片数据必须分包发送,要不然板子会崩溃,直接复位。data[4104]差不多是板子内存的极限了,我设置的物联网平台接收的数据格式是字符串,范围是0-2048字节,所以每次分包的大小必须在2048字节之下。但是,在上传的过程中,经过多次试验,每次数据大小只能在800字节,超过800字节就只上传最后一个包的数据,其余数据全部无法上传。
另一种方法是把jpg图片的数据大小降下来,导师说试试灰度处理。我感觉大小这方面已经是极限了,再降图片可能就无法看了。如果有更好的方法,可以私信我哦 ^ _ ^
最终完整代码
按键设置:GPIO15
#include "esp_camera.h"
#include "Arduino.h"
#include "FS.h" // SD Card ESP32
#include "SD_MMC.h" // SD Card ESP32
#include "soc/soc.h" // Disable brownour problems
#include "soc/rtc_cntl_reg.h" // Disable brownour problems
#include "driver/rtc_io.h"
#include <EEPROM.h>
#include"camera_pins.h"
#include <WiFi.h>
#include <ArduinoJson.h>
#include <aliyun_mqtt.h>
#define EEPROM_SIZE 1
int pictureNumber = 0;
String msg;
int buttonState =0;
int btnHold=0;
// 你的wifi账号密码
const char* ssid = "";
const char* password = "";
//阿里云三元组
#define PRODUCT_KEY "a1mAaYPL2Qf"
#define DEVICE_NAME "haote216"
#define DEVICE_SECRET "YgQ5MMv4wgnROBLQqInLpj6eZy0UTAkZ"
//订阅和发布时所需的主题
#define ALINK_BODY_FORMAT "{\"id\":\"1189401707\",\"version\":\"1.0.0\",\"method\":\"%s\",\"params\":%s}"
#define ALINK_TOPIC_PROP_POST "/sys/a1mAaYPL2Qf/haote216/thing/event/property/post"
#define ALINK_TOPIC_PROP_POSTRSP "/sys/a1mAaYPL2Qf/haote216/thing/event/property/post_reply"
#define ALINK_TOPIC_PROP_SET "/sys/a1mAaYPL2Qf/haote216/thing/service/property/set"
#define ALINK_METHOD_PROP_POST "thing.event.property.post"
//创建WiFiClient实例
WiFiClient espClient;
//创建MqttClient实例
PubSubClient mqttClient(espClient);
//连接Mqtt订阅属性设置Topic
void mqttCheckConnect()
{
bool connected = connectAliyunMQTT(mqttClient, PRODUCT_KEY, DEVICE_NAME, DEVICE_SECRET);
if (connected)
{
Serial.println("MQTT connect succeed!");
//订阅属性设置Topic
mqttClient.subscribe(ALINK_TOPIC_PROP_SET);
Serial.println("subscribe done");
}
}
void camera_init()
{
// Camera initOV2640 camera module
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;
if (psramFound()) {
config.frame_size = FRAMESIZE_UXGA;
config.jpeg_quality = 10;
config.fb_count = 2;
} else {
config.frame_size = FRAMESIZE_SVGA;
config.jpeg_quality = 12;
config.fb_count = 1;
}
esp_err_t err = esp_camera_init(&config);
if (err != ESP_OK) {
Serial.printf("Camera init failed with error 0x%x", err);
return;
}
}
void sd_init(void)
{
//SD card init
if (!SD_MMC.begin()) {
Serial.println("Card Mount Failed");
return;
}
uint8_t cardType = SD_MMC.cardType();
if (cardType == CARD_NONE) {
Serial.println("No SD_MMC card attached");
return;
}
}
void SPIFFS_init()
{
//初始化SPIFFS
if (!SPIFFS.begin(true)) {
Serial.println("An Error has occurred while mounting SPIFFS");}
else {
delay(500);
Serial.println("SPIFFS mounted successfully");
}
//Turn-off the 'brownout detector'
WRITE_PERI_REG(RTC_CNTL_BROWN_OUT_REG, 0);
}
void setup() {
Serial.begin(115200); //串口初始化
pinMode(KEY, INPUT); //按键初始化
WiFi.begin(ssid, password); //连接wifi
while (WiFi.status() != WL_CONNECTED) {
delay(1000);
Serial.println("Connecting to WiFi...");
}
camera_init();
sd_init();
SPIFFS_init();
Serial.print("IP Address: http://"); //打印IP地址用于服务器连接
Serial.println(WiFi.localIP());
mqttCheckConnect(); //初始化首次链接
}
void loop() {
//=====按键扫描=====
buttonState=digitalRead(KEY);
if(buttonState==LOW && btnHold ==0)
{
delay(100);
if(buttonState ==LOW)
btnHold =1;
Serial.print("按钮触发成功\n");
Serial.print( "进行拍照\n");
camera_fb_t * fb = esp_camera_fb_get();
if (!fb)
{
Serial.print( "Camera capture failed");
return;
}
else
{
EEPROM.begin(EEPROM_SIZE);
pictureNumber = EEPROM.read(0) + 1;
// Path where new picture will be saved in SD Card
String path = "/picture" + String(pictureNumber) +".jpg";
fs::FS &fs = SD_MMC;
Serial.printf("文件名字: %s\n", path.c_str());
File file = fs.open(path.c_str(), FILE_WRITE);
if(!file){
Serial.println("Failed to open file in writing mode");
}
else {
file.write(fb->buf, fb->len); // payload (image), payload length
Serial.println(fb->len);
Serial.print("抓拍成功并保存\n");
Serial.printf("保存路径: %s\n\n", path.c_str());
EEPROM.write(0, pictureNumber);
EEPROM.commit();
}
//上报属性Topic数据
//char jsonBuf[]="{\"id\":\"1189401707\",\"version\":\"1.0.0\",\"method\":\"%s\",\"params\":{\"Data\":\"12\"}}";
String a1="{\"id\":\"1189401707\",\"version\":\"1.0.0\",\"method\":\"%s\",\"params\":{\"Data\":\"";
String a2;
String a3 ="\"}}";
char data[4104];
for(int i=0;i<fb->len;i++)
{
sprintf(data, "%02X", *(fb->buf + i));
a2+=data;
if(a2.length() == 800)
{
String a4 = a1+a2;
String a = a4+a3;
char jsonBuf[a.length()+1];
for(int i=0;i<a.length();i++)
jsonBuf[i] = a[i];
jsonBuf[a.length()]='\0';
Serial.println(jsonBuf);
mqttClient.publish(ALINK_TOPIC_PROP_POST, jsonBuf);
a2="",a="",a4="";
}
}
if(a2.length() > 0)
{
String a4=a1+a2;
String a=a4+a3;
char jsonBuf[a.length()+1];
for(int i=0;i<a.length();i++)
jsonBuf[i] = a[i];
jsonBuf[a.length()]='\0';
Serial.println(jsonBuf);
mqttClient.publish(ALINK_TOPIC_PROP_POST, jsonBuf);
a2="",a="",a4="";
}
file.close();
esp_camera_fb_return(fb);
}
}
if(buttonState ==HIGH)
btnHold=0;
}