使用于23.4.15 23.11.5
目录
发送MQTT数据模板:
#include <Arduino.h>
#include <WiFi.h>
#include <PubSubClient.h>
#include <Wire.h>
#include <DHT.h>
#include "SoftwareSerial.h"
#include <ArduinoJson.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
#include "DFRobotDFPlayerMini.h"
const char *ssid = "";
const char *password = "";
const char *mqtt_server = ""; // 要连接到的服务器IP
const int mqtt_port = ; // 要连接到的服务器端口号
const char *mqtt_username = ""; // MQTT服务器账号
const char *mqtt_password = ""; // MQTT服务器密码
const char *mqtt_topic = "topic/01";
void setupWiFi();
void setupMQTT();
WiFiClient espClient;
PubSubClient client(espClient);
void setup()
{
Serial.begin(9600);
setupWiFi();
setupMQTT();
}
//----------------------------------------------------------------------------------------------
void loop()
{
// 发送JSON消息到MQTT
DynamicJsonDocument jsonDoc(128); // 动态JSON文档,可以在运行时构建
JsonObject json = jsonDoc.to<JsonObject>(); // 将文档转换为JSON对象
// 当前状态和次数
// json["peopleDetected"] = (peopleDetected > 0) ? 1 : 0;
// json["detections"] = peopleDetected;
json["smokeSensorValue"] = smokeSensorValue;
// json["HuoYan"] = HuoYan ? "0" : "1";
json["HuoYan"] = val;
json["WenDu"] = String(temperature, 0); // 格式化温度数据
json["ShiDu"] = String(humidity, 0); // 格式化湿度数据
char jsonBuffer[128];
serializeJson(json, jsonBuffer);
if (client.connected())
{
if (client.publish(mqtt_topic, jsonBuffer))
{
Serial.println("成功发布JSON消息到MQTT。");
}
else
{
Serial.println("无法发布JSON消息到MQTT。");
// 如果发布失败,尝试重新连接到MQTT代理
client.disconnect();
setupMQTT();
}
}
else
{
// 如果未连接,尝试重新连接到MQTT代理
setupMQTT();
}
delay(500);
}
//----------------------------------------------------------------------------------------------
void setupWiFi()
{
delay(10);
// Connect to Wi-Fi
Serial.println();
Serial.print("Connecting to ");
Serial.println(ssid);
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED)
{
delay(500);
Serial.print(".");
}
Serial.println();
Serial.print("Connected to ");
Serial.println(ssid);
}
void setupMQTT()
{
client.setServer(mqtt_server, mqtt_port);
// client.setCallback(callback);
// Connect to MQTT
while (!client.connected())
{
Serial.print("Connecting to MQTT...");
if (client.connect("ESP32Client", mqtt_username, mqtt_password))
{
Serial.println("connected");
// client.publish(mqtt_topic, "ESP32 connected");
}
else
{
Serial.print("failed with state ");
Serial.print(client.state());
delay(2000);
}
}
}
或者(这里以RS485检测土壤N、P、K 为例)
// TX 16
// RX 17 R485
#include <Arduino.h>
#include <Wire.h>
#include <WiFi.h>
#include <WiFiClient.h>
#include <PubSubClient.h>
#include "DHT.h"
#include <HardwareSerial.h>
#include <BH1750.h>
unsigned char item[8] = {0x01, 0x03, 0x00, 0x1E, 0x00, 0x03, 0x65, 0xCD};
String data = "{\"\":\"\"}";
#define ADDR 0b0100011
// TX 16
// RX 17 R485
int sense_Pin = 35; // 土壤传感器输入接模拟引脚 A0
const char *ssid = ""; // ESP32连接的WiFi账号
const char *password = ""; // WiFi密码
const char *mqttServer = ""; // 要连接到的服务器IP
const int mqttPort = ; // 要连接到的服务器端口号
const char *mqttUser = ""; // MQTT服务器账号
const char *mqttPassword = ""; // MQTT服务器密码
WiFiClient espClient; // 定义wifiClient实例
PubSubClient client(espClient); // 定义PubSubClient的实例
void callback(char *topic, byte *payload, unsigned int length)
{
Serial.print("来自订阅的主题:"); // 串口打印:来自订阅的主题:-
Serial.println(topic); // 串口打印订阅的主题
Serial.print("信息:"); // 串口打印:信息:
for (int i = 0; i < length; i++) // 使用循环打印接收到的信息
{
Serial.print((char)payload[i]);
}
Serial.println();
Serial.println("-----------------------");
}
void NPK()
{
String data = "";
char buff[128]; // 定义存储传感器数据的数组
String info[11];
for (int i = 0; i < 8; i++)
{ // 发送测温命令
Serial2.write(item[i]); // write输出
}
delay(100); // 等待测温数据返回
data = "";
while (Serial2.available())
{ // 从串口中读取数据
unsigned char in = (unsigned char)Serial2.read(); // read读取
// Serial.print(in, HEX);
// Serial.print(',');
data += in;
data += ',';
}
if (data.length() > 0)
{ // 先输出一下接收到的数据
// Serial.print(data.length());
// Serial.println();
// Serial.println(data);
int commaPosition = -1;
// 用字符串数组存储
for (int i = 0; i < 11; i++)
{
commaPosition = data.indexOf(',');
if (commaPosition != -1)
{
info[i] = data.substring(0, commaPosition);
data = data.substring(commaPosition + 1, data.length());
}
else
{
if (data.length() > 0)
{
info[i] = data.substring(0, commaPosition);
}
}
}
}
Serial.print("氮元素含量:");
Serial.print(info[4]);
Serial.println("mg");
Serial.print("磷元素含量:");
Serial.print(info[6]);
Serial.println("mg");
Serial.print("钾元素含量:");
Serial.print(info[8]);
Serial.println("mg");
String N = String(info[4]);
String P = String(info[6]);
String K = String(info[8]);
// 构建一个 JSON 格式的payload的字符串
String payload = "{";
payload += "\"N\":";
payload += N;
payload += ",";
payload += "\"P\":";
payload += P;
payload += ",";
payload += "\"K\":";
payload += K;
payload += "}";
// Send payload
char attributes[100];
payload.toCharArray(attributes, 100);
// boolean publish(const char* topic, const char* payload);
client.publish("topic/01", attributes);
Serial.print("[publish]-->>");
Serial.println(attributes);
}
void setup()
{
// put your setup code here, to run once:
Serial.begin(9600);
pinMode(sense_Pin, INPUT);
Serial2.begin(9600);
while (WiFi.status() != WL_CONNECTED) // 若WiFi接入成功WiFi.status()会返回 WL_CONNECTED
{
Serial.println("连接wifi中"); // 串口输出:连接wifi中
WiFi.begin(ssid, password); // 接入WiFi函数(WiFi名称,密码)重新连接wif
delay(1500); // 若尚未连接WiFi,则进行重连WiFi的循环
}
Serial.println("wifi连接成功"); // 连接wifi成功之后会跳出循环,串口并输出:wifi连接成功
client.setServer(mqttServer, mqttPort); // MQTT服务器连接函数(服务器IP,端口号)
client.setCallback(callback); // 设定回调方式,当ESP32收到订阅消息时会调用此方法
while (!client.connected()) // 是否连接上MQTT服务器
{
Serial.println("连接服务器中"); // 串口打印:连接服务器中
if (client.connect("xxx", mqttUser, mqttPassword)) // 如果服务器连接成功
{
Serial.println("服务器连接成功"); // 串口打印:服务器连接成功
}
else
{
Serial.print("连接服务器失败"); // 串口打印:连接服务器失败
Serial.print(client.state()); // 重新连接函数
delay(2000);
}
// }
client.subscribe("plant/01"); // 连接MQTT服务器后订阅主题
Serial.print("已订阅主题,等待主题消息...."); // 串口打印:已订阅主题,等待主题消息
client.publish("plant/01", "Hello from ESP32"); // 向服务器发送的信息(主题,内容)
pinMode(fire_sensor, INPUT); // 接收火焰传感器
}
}
void loop()
{
client.loop();
NPK();
delay(11000);
}
基于ESP32的模块疑难代码
舵机的多角度调节
尝试了很多代码后并不是很好用,最终用的是:
// 舵机部分
// 主要通过rotationDuration转动的毫秒数时间来表示旋转角度 ,350为大半圈
int rotationDuration = 350; // 舵机旋转的持续时间(毫秒)
int pwmChannel1 = 3; // 使用3号通道,定时器1共有16个通道
void rotateServo(int servoPin, int pwmChannel);
const int servoPin1 = 25;
bool isRunning = true; // 控制舵机是否运行
unsigned long oneDayMillis = 24 * 60 * 60 * 1000; // 1天的毫秒数
//--------------------------------------------
//setup初始化
// 舵机
ledcSetup(pwmChannel1, pwmFrequency, pwmResolution); // 设置PWM通道1
ledcAttachPin(servoPin1, pwmChannel1); // 将引脚绑定到PWM通道1
// loop
if (isRunning)
{
// rotateServo(servoPin1, pwmChannel1);
// rotateServo(servoPin2, pwmChannel2);
// rotateServo(servoPin3, pwmChannel3);
rotateServo(servoPin4, pwmChannel4);
isRunning = false;
}
//函数控制旋转方向
void rotateServo(int servoPin, int pwmChannel)
{
// 正向旋转
ledcWrite(pwmChannel, 52);
delay(rotationDuration);
// // 停止
ledcWrite(pwmChannel, 77);
delay(1000);
// 反向旋转
ledcWrite(pwmChannel, 102);
delay(rotationDuration);
// // // 停止
ledcWrite(pwmChannel, 77);
delay(rotationDuration);
}
语音控制多个舵机旋转+多环境数据模块等等等
附完整代码
#include <Arduino.h>
#include <WiFi.h>
#include <PubSubClient.h>
#include <Wire.h>
#include <DHT.h>
#include "SoftwareSerial.h"
#include <ArduinoJson.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
#include "DFRobotDFPlayerMini.h"
const char *ssid = "";
const char *password = "";
// const char *mqtt_server = "broker.emqx.io"; // 要连接到的服务器IP
// const int mqtt_port = 1883; // 要连接到的服务器端口号
// const char *mqtt_username = ""; // MQTT服务器账号
// const char *mqtt_password = ""; // MQTT服务器密码
// const char *mqtt_topic = "topic/01";
const char *mqtt_server = ""; // 要连接到的服务器IP
const int mqtt_port = ; // 要连接到的服务器端口号
const char *mqtt_username = ""; // MQTT服务器账号
const char *mqtt_password = ""; // MQTT服务器密码
const char *mqtt_topic = "";
void setupWiFi();
void setupMQTT();
// void callback(char* topic, byte* payload, unsigned int length);
// // 小一 纸张 废电池 剩菜 尘土
WiFiClient espClient;
PubSubClient client(espClient);
const int infraredPin = 12; // 红外传感器
// OLED屏幕分辨率
Adafruit_SSD1306 display = Adafruit_SSD1306(128, 64, &Wire);
// 火焰 35 用A口
int fire_sensor = 35;
// 舵机部分
int rotationDuration = 350; // 舵机旋转的持续时间(毫秒)
int pwmChannel1 = 3; // 使用3号通道,定时器1共有16个通道
int pwmChannel2 = 4; // 使用4号通道
int pwmChannel3 = 5;
int pwmChannel4 = 6;
int pwmFrequency = 50; // PWM频率为50Hz
int pwmResolution = 10; // PWM分辨率为10位,范围是0-1024
void rotateServo(int servoPin, int pwmChannel);
const int servoPin1 = 25;
const int servoPin2 = 26;
const int servoPin3 = 27;
const int servoPin4 = 14;
int peopleDetected = 0;
bool isRunning = true; // 控制舵机是否运行
// 01、 MQ-2烟雾传感器 34
const int smokeSensorPin = 34;
int smokeSensorValue = 0;
// E18-D80NK 光电传感器
const int sensorPin = 18; // 光电传感器信号引脚
unsigned long lastHighTime = 0; // 上次检测到高电平的时间
int highCount = 0; // 高电平计数
int highCount01 = 12;
int highCount02 = 5;
// int highCount03 = 20;
unsigned long oneDayMillis = 24 * 60 * 60 * 1000; // 1天的毫秒数
// 定义 DHT11 传感器的数据引脚
#define DHTPIN 4
// DHT11 传感器类型
#define DHTTYPE DHT11
// 创建 DHT11 对象
DHT dht(DHTPIN, DHTTYPE);
// 读取温度和湿度数据
float temperature;
float humidity;
SoftwareSerial mySoftwareSerial(16, 17);
DFRobotDFPlayerMini myDFPlayer;
void playAudio(int audioFile);
//-------------------------------------------------------------------------------------------
void setup()
{
// Serial.begin(115200);
Serial.begin(9600);
mySoftwareSerial.begin(9600);
myDFPlayer.begin(mySoftwareSerial);
myDFPlayer.volume(30);
// 显示屏
display.begin(SSD1306_SWITCHCAPVCC, 0x3C);
display.clearDisplay();
display.setTextSize(2);
display.setTextColor(SSD1306_WHITE);
display.setCursor(0, 0);
display.display();
pinMode(sensorPin, INPUT);
setupWiFi();
setupMQTT();
// 火焰
pinMode(fire_sensor, INPUT); // 接收火焰传感器
// 舵机
ledcSetup(pwmChannel1, pwmFrequency, pwmResolution); // 设置PWM通道1
ledcAttachPin(servoPin1, pwmChannel1); // 将引脚绑定到PWM通道1
ledcSetup(pwmChannel2, pwmFrequency, pwmResolution); // 设置PWM通道2
ledcAttachPin(servoPin2, pwmChannel2); // 将引脚绑定到PWM通道2
ledcSetup(pwmChannel3, pwmFrequency, pwmResolution); // 设置PWM通道1
ledcAttachPin(servoPin3, pwmChannel3);
ledcSetup(pwmChannel4, pwmFrequency, pwmResolution); // 设置PWM通道1
ledcAttachPin(servoPin4, pwmChannel4);
// 初始化 DHT11 传感器
dht.begin();
}
//-------------------------------------------------------------------------------------------
void loop()
{
temperature = dht.readTemperature();
humidity = dht.readHumidity();
int sensorValue = analogRead(smokeSensorPin);
float airQuality = map(sensorValue, 0, 4095, 0, 100); // 根据传感器输出值映射到0-100范围
display.clearDisplay();
display.setCursor(0, 0);
display.setTextColor(SSD1306_WHITE);
display.println("Tem:" + String(temperature));
display.println("Hum:" + String(humidity) + "%");
display.println("Air:" + String(airQuality) + "%");
display.display();
// int HuoYan = digitalRead(fire_sensor);
// if (HuoYan)
// { // 没有检测到火焰,传感器引脚输出高电平
// Serial.println("没有检测到火焰。");
// }
// else
// { // 检测到火焰,传感器引脚输出低电平
// Serial.println("检测到火焰。");
// playAudio(8);
// }
// delay(1000); // 火灭后LED多亮1秒
int val = analogRead(fire_sensor);
// data = addjson(data, json("fire", String(val)));
if (val >= 600)
{ // 没有检测到火焰,传感器引脚输出高电平
Serial.println("火焰传感器未检测到火焰");
}
else
{ // 检测到火焰,传感器引脚输出低电平
Serial.println("火焰传感器检测到火焰");
playAudio(8);
}
if (digitalRead(infraredPin) == HIGH) // 如果红外传感器检测到有人
{
Serial.println("Detect:1");
peopleDetected++;
playAudio(7);
if (isRunning)
{
rotateServo(servoPin1, pwmChannel1);
rotateServo(servoPin2, pwmChannel2);
rotateServo(servoPin3, pwmChannel3);
rotateServo(servoPin4, pwmChannel4);
isRunning = false;
}
}
else
{
Serial.println("Detect:0");
isRunning = true; // 设置为true,以允许下一次检测到人时触发旋转
}
if (Serial.available() > 0)
{
String command = Serial.readString();
int commandInt = command.toInt(); // 将字符串转换为整数
// // 小一 纸张 废电池 剩菜 尘土
if (commandInt == 1)
{
playAudio(5);
}
else if (commandInt == 2)
{
playAudio(1);
if (isRunning)
{
rotateServo(servoPin1, pwmChannel1);
isRunning = false;
}
isRunning = true;
}
else if (commandInt == 3)
{
playAudio(2);
if (isRunning)
{
rotateServo(servoPin2, pwmChannel2);
isRunning = false;
}
isRunning = true;
}
else if (commandInt == 4)
{
playAudio(3);
if (isRunning)
{
rotateServo(servoPin3, pwmChannel3);
isRunning = false;
}
isRunning = true;
}
else if (commandInt == 5)
{
playAudio(4);
if (isRunning)
{
rotateServo(servoPin4, pwmChannel4);
isRunning = false;
}
isRunning = true;
}
else
{
// 处理未知命令或错误
Serial.println("Received unknown command");
}
}
// 读取MQ-2传感器浓度值
smokeSensorValue = analogRead(smokeSensorPin);
Serial.print("Smoke Sensor Value: ");
Serial.println(smokeSensorValue);
// 光电传感器
if (digitalRead(sensorPin) == HIGH)
{
// 如果检测到高电平,增加高电平计数
highCount++;
lastHighTime = millis(); // 更新上次检测到高电平的时间
Serial.println("GuangDian: 1");
}
else
{
Serial.println("GuangDian: 0");
}
// 检查是否达到20次高电平或超过1天
if (highCount >= 20 || (millis() - lastHighTime) >= oneDayMillis)
{
Serial.println("垃圾可能已满!");
playAudio(6);
highCount = 0;
lastHighTime = millis();
}
delay(500); // 每次循环间隔0.5秒
// --------------------------------------------------------------------------------------------------
// 发送JSON消息到MQTT
DynamicJsonDocument jsonDoc(128); // 动态JSON文档,可以在运行时构建
JsonObject json = jsonDoc.to<JsonObject>(); // 将文档转换为JSON对象
// 当前状态和次数
// json["peopleDetected"] = (peopleDetected > 0) ? 1 : 0;
// json["detections"] = peopleDetected;
json["smokeSensorValue"] = smokeSensorValue;
// json["HuoYan"] = HuoYan ? "0" : "1";
json["HuoYan"] = val;
json["WenDu"] = String(temperature, 0); // 格式化温度数据
json["ShiDu"] = String(humidity, 0); // 格式化湿度数据
json["highCount"] = highCount; // 添加highCount值
json["highCount01"] = highCount01; // 添加highCount值
json["highCount02"] = highCount02; // 添加highCount值
// json["highCount03"] = highCount03; // 添加highCount值
char jsonBuffer[128];
serializeJson(json, jsonBuffer);
if (client.connected())
{
if (client.publish(mqtt_topic, jsonBuffer))
{
Serial.println("成功发布JSON消息到MQTT。");
}
else
{
Serial.println("无法发布JSON消息到MQTT。");
// 如果发布失败,尝试重新连接到MQTT代理
client.disconnect();
setupMQTT();
}
}
else
{
// 如果未连接,尝试重新连接到MQTT代理
setupMQTT();
}
delay(500);
}
//-------------------------------------------------------------------------------------------
void playAudio(int audioFile)
{
myDFPlayer.playFolder(1, audioFile);
Serial.println(audioFile);
delay(1000);
}
void rotateServo(int servoPin, int pwmChannel)
{
// 正向旋转
ledcWrite(pwmChannel, 52);
delay(rotationDuration);
// 停止
ledcWrite(pwmChannel, 77);
delay(1000);
// 反向旋转
ledcWrite(pwmChannel, 102);
delay(rotationDuration);
// 停止
ledcWrite(pwmChannel, 77);
delay(rotationDuration);
}
void setupWiFi()
{
delay(10);
// Connect to Wi-Fi
Serial.println();
Serial.print("Connecting to ");
Serial.println(ssid);
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED)
{
delay(500);
Serial.print(".");
}
Serial.println();
Serial.print("Connected to ");
Serial.println(ssid);
}
void setupMQTT()
{
client.setServer(mqtt_server, mqtt_port);
// client.setCallback(callback);
// Connect to MQTT
while (!client.connected())
{
Serial.print("Connecting to MQTT...");
if (client.connect("ESP32Client", mqtt_username, mqtt_password))
{
Serial.println("connected");
// client.publish(mqtt_topic, "ESP32 connected");
}
else
{
Serial.print("failed with state ");
Serial.print(client.state());
delay(2000);
}
}
}
// void callback(char* topic, byte* payload, unsigned int length) {
// 处理MQTT消息 回调函数
// Serial.print("Message received on topic: ");
// Serial.println(topic);
// Serial.print("Message content: ");
// for (int i = 0; i < length; i++) {
// Serial.print((char)payload[i]);
// }
// Serial.println();
// // 在这里执行您的操作,根据消息内容执行相应的逻辑
// if (strcmp(topic, "your/mqtt/topic") == 0) {
// // 处理特定主题的消息
// if (strcmp((char*)payload, "1") == 0) {
// // 执行相关操作,例如打开舵机等
// } else if (strcmp((char*)payload, "0") == 0) {
// // 执行相关操作,例如关闭舵机等
// }
// }
// }