基于嵌入式的智能臺(tái)燈系統(tǒng)
功能說明
通過微信小程序控制臺(tái)燈的亮滅及亮度。采集溫濕度傳到微信小程序上,臺(tái)燈可以顯示實(shí)時(shí)北京時(shí)間。
功能展示
01智能臺(tái)燈演示
Mqtt服務(wù)器
- http://www.yoyolife.fun/iot:Mqtt服務(wù)器,我是在這里注冊(cè)的,免費(fèi)一個(gè),之后每個(gè)2塊錢每月。主要是結(jié)構(gòu)簡單,用起來容易。
- 下位機(jī)即ESP32要選擇
mqtt地址:t.yoyolife.fun 端口:1883
地址(里邊有三個(gè)地址) - 微信小程序要選擇
mqtt:wss地址:t.yoyolife.fun/mqtt 端口:8084
地址,不可選錯(cuò)。 - 兩邊的發(fā)布和訂閱要對(duì)應(yīng)起來,一個(gè)發(fā)布一個(gè)訂閱,跟串口的Tx、Rx一樣。服務(wù)器的主題可以隨意定,意為服務(wù)器要監(jiān)聽哪個(gè)地址。
- 設(shè)備ID即是用戶名,密碼即是密碼。
- 調(diào)試軟件為mqttx,可自行下載https://mqttx.app/zh,調(diào)試下位機(jī)的時(shí)候可以連接上邊提到的微信小程序8084那個(gè)端口,即服務(wù)器地址:
wss://t.yoyolife.fun
、端口:8084
、Path:/mqtt
、用戶名即設(shè)備ID、密碼即密碼,然后訂閱ESP32發(fā)布的那個(gè)地址,或者向ESP32訂閱的那個(gè)地址發(fā)布信息。
硬件制作
采用的是ESP32+微信小程序+Mqtt協(xié)議。
硬件選型
- ESP32開發(fā)板(VSCode+PlatformIO環(huán)境)
- DHT11溫濕度傳感器
- 兩顆LED燈(模擬臺(tái)燈)
- 0.96寸OLED屏
- 杜邦線若干
硬件連接
如圖所示,需要注意的是LED串聯(lián)電阻1K到10K都可以,主要起限流作用。如果多個(gè)LED并聯(lián)顯示的話也可選擇更小的。
硬件程序
程序采用VSCode+PlatformIO環(huán)境。安裝以下庫
-
ArduinoJson
庫:解析Mqtt協(xié)議收發(fā)的json格式數(shù)據(jù)。 -
DHT sensor library
庫:用于DHT11采集溫濕度數(shù)據(jù)。 -
NTPClient
庫:獲取網(wǎng)絡(luò)NTP時(shí)間。 -
PubSubClient
庫:Mqtt通訊協(xié)議。 -
U8g2
庫:OLED顯示庫。
代碼展示
以下展示部分重要代碼,完整完成在文章末尾。
Mqtt連接
const char *ssid = "Hide_2805"; // ESP32連接的WiFi賬號(hào)
const char *password = "asdfghjkl"; // WiFi密碼
const char *mqttServer = "t.yoyolife.fun"; // 要連接到的服務(wù)器IP
const int mqttPort = 1883; // 要連接到的服務(wù)器端口號(hào)
const char *mqttUser = "75bdfb62a1c56065949702a3a6430e38"; // MQTT服務(wù)器賬號(hào)
const char *mqttPassword = "123465"; // MQTT服務(wù)器密碼
const char *mqttsub = "/iot/4432/wsy"; // MQTT訂閱主題
const char *mqttpub = "/iot/4432/waa"; // MQTT發(fā)送主題
WiFiClient espClient; // 定義wifiClient實(shí)例
PubSubClient client(espClient); // 定義PubSubClient的實(shí)例
DynamicJsonDocument Json(1024); // 定義Json實(shí)例
String Debug_Mqtt = "";
void callback(char *topic, byte *payload, unsigned int length)
{
String Str = "";
Serial.print("來自訂閱的主題:"); // 串口打印:來自訂閱的主題:
Serial.println(topic); // 串口打印訂閱的主題
Serial.print("信息:"); // 串口打?。盒畔ⅲ?/span>
for (int i = 0; i < length; i++) // 使用循環(huán)打印接收到的信息
{
Serial.print((char)payload[i]);
Str += (char)payload[i];
}
Serial.println();
Serial.println("-----------------------");
Debug_Mqtt = Str;
deserializeJson(Json, Str);
// Lamp_Duty = Json["target"].as<String>();
Lamp_Duty = Json["value"].as<unsigned char>();
if (Lamp_Duty > 100)
Lamp_Duty = 100;
Lamp_Num = Json["num"].as<bool>();
Debug = Json["debug"].as<unsigned char>();
Serial.print("value:"); // 串口打?。簛碜杂嗛喌闹黝}:
Serial.println(Lamp_Duty); // 串口打印訂閱的主題
Serial.print("num:"); // 串口打印:來自訂閱的主題:
Serial.println(Lamp_Num); // 串口打印訂閱的主題
}
void WiFi_Click(void)
{
while (WiFi.status() != WL_CONNECTED) // 若WiFi接入成功WiFi.status()會(huì)返回 WL_CONNECTED
{
Serial.println("連接wifi中"); // 串口輸出:連接wifi中
WiFi.begin(ssid, password); // 接入WiFi函數(shù)(WiFi名稱,密碼)重新連接wif
delay(2000); // 若尚未連接WiFi,則進(jìn)行重連WiFi的循環(huán)
}
Serial.println("wifi連接成功"); // 連接wifi成功之后會(huì)跳出循環(huán),串口并輸出:wifi連接成功
client.setServer(mqttServer, mqttPort); // MQTT服務(wù)器連接函數(shù)(服務(wù)器IP,端口號(hào))
client.setCallback(callback); // 設(shè)定回調(diào)方式,當(dāng)ESP32收到訂閱消息時(shí)會(huì)調(diào)用此方法
while (!client.connected()) // 是否連接上MQTT服務(wù)器
{
Serial.println("連接服務(wù)器中"); // 串口打?。哼B接服務(wù)器中
if (client.connect("ESP32Client", mqttUser, mqttPassword)) // 如果服務(wù)器連接成功
{
Serial.println("服務(wù)器連接成功"); // 串口打?。悍?wù)器連接成功
}
else
{
Serial.print("連接服務(wù)器失敗"); // 串口打印:連接服務(wù)器失敗
Serial.print(client.state()); // 重新連接函數(shù)
delay(2000);
}
}
client.subscribe(mqttsub); // 連接MQTT服務(wù)器后訂閱主題
Serial.print("已訂閱主題,等待主題消息...."); // 串口打印:已訂閱主題,等待主題消息
client.publish(mqttpub, "Hello from ESP32"); // 向服務(wù)器發(fā)送的信息(主題,內(nèi)容)
}
void Pub_Mqtt(void)
{
char payload[200];
StaticJsonDocument<200> jsonDocument; // 聲明一個(gè)Json格式變量
jsonDocument["temperature"] = Temp;
jsonDocument["humidity"] = Humi;
serializeJson(jsonDocument, payload); // 將j
Serial.println(payload);
client.publish(mqttpub, payload); // 向服務(wù)器發(fā)送的信息(主題,內(nèi)容)son轉(zhuǎn)換為字符串
}
初始化、主函數(shù)及時(shí)間片
void Time_Slice(void)
{
if (F_Time_10ms)
{
F_Time_10ms = 0;
Display();
}
if (F_Time_100ms)
{
F_Time_100ms = 0;
Log_Print();
Ctrl_Lamp();
}
if (F_Time_2s)
{
F_Time_2s = 0;
DHT11_Get();
Pub_Mqtt();
TimeClient.update();
Serial.println(TimeClient.getFormattedTime());
}
}
void setup()
{
pinMode(LED_Pin_Gnd, OUTPUT);
digitalWrite(LED_Pin_Gnd, 0);
U8g2_Init();
u8g2.setCursor(0, 8);
u8g2.print("U8g2 OK!");
u8g2.sendBuffer();
Serial.begin(115200); // 串口函數(shù),波特率設(shè)置
u8g2.setCursor(0, 8 + 12 * 1);
u8g2.print("串口 OK!");
u8g2.sendBuffer();
WiFi_Click();
u8g2.setCursor(0, 8 + 12 * 2);
u8g2.print("WiFi OK!");
u8g2.sendBuffer();
Timer0_Init();
PWM_Init();
TimeClient.begin();
TimeClient.setTimeOffset(28800); //+1地區(qū)偏移3600
u8g2.setCursor(0, 8 + 12 * 3);
u8g2.print("NTP OK!");
u8g2.sendBuffer();
DHT.begin();
u8g2.setCursor(0, 8 + 12 * 4);
u8g2.print("DHT11 OK!");
u8g2.sendBuffer();
delay(2000);
}
void loop()
{
client.loop(); // 回旋接收函數(shù) 等待服務(wù)器返回的數(shù)據(jù)
Time_Slice();
}
硬件修改代碼作為己用
用戶如需借用代碼,只需修改關(guān)鍵部分即可,例如Mqtt的Key、發(fā)布訂閱地址,WiFi的賬號(hào)密碼等。
初始化修改
#define LED_Pin 2 //系統(tǒng)LED燈 不用修改
#define DHT11_Pin 4 //DHT11連接的IO口 可修改
#define DHTTYPE DHT11 //DHT11 不用修改
#define Lamp_Pin1 12 //LED控制輸出IO 可修改
#define Lamp_Pin2 13 //LED控制輸出IO 可修改
#define LED_Pin_Gnd 14 //LED控制輸出地 可修改
const char *ssid = "Hide_2805"; // ESP32連接的WiFi賬號(hào)
const char *password = "asdfghjkl"; // WiFi密碼
const char *mqttServer = "t.yoyolife.fun"; // 要連接到的服務(wù)器IP
const int mqttPort = 1883; // 要連接到的服務(wù)器端口號(hào)
const char *mqttUser = "75bdfb62a1c56065949702a3a6430e38"; // MQTT服務(wù)器賬號(hào)
const char *mqttPassword = "123465"; // MQTT服務(wù)器密碼
const char *mqttsub = "/iot/4432/wsy"; // MQTT訂閱主題
const char *mqttpub = "/iot/4432/waa"; // MQTT發(fā)送主題
callback函數(shù)中修改地方
Lamp_Duty = Json["value"].as<unsigned char>();//接受的Json格式的鍵名稱,跟你發(fā)送的對(duì)應(yīng)起來,后邊格式也要解析成相應(yīng)格式
if (Lamp_Duty > 100) //這里可以做一些邏輯判斷等
Lamp_Duty = 100;
Lamp_Num = Json["num"].as<bool>();
Debug = Json["debug"].as<unsigned char>();
Pub_Mqtt函數(shù)中修改地方
jsonDocument["temperature"] = Temp; //要發(fā)送的Json的鍵名稱
jsonDocument["humidity"] = Humi;
serializeJson(jsonDocument, payload);
Serial.println(payload);
client.publish(mqttpub, payload); // 向服務(wù)器發(fā)送的信息(主題,內(nèi)容)son轉(zhuǎn)換為字符串
微信小程序制作
軟件采用的是微信開發(fā)者工具,下載軟件即可使用,無需復(fù)雜環(huán)境,成品直接發(fā)布就能使用,方便快捷。
軟件程序
- 引入Mqtt的js包。
- 請(qǐng)求獲取系統(tǒng)地址權(quán)限,請(qǐng)求天氣API(高德),獲取當(dāng)?shù)靥鞖狻?/li>
- 請(qǐng)求Mqtt服務(wù)器,訂閱相關(guān)地址。
- 獲取接受的數(shù)據(jù),Json解析。
- 按鍵像相關(guān)地址發(fā)布Json數(shù)據(jù)。
下邊是具體代碼。
天氣數(shù)據(jù)
getUserLocation: function () {
let that = this;
wx.getSetting({
success: (res) => {
console.log("天氣", res);
if (
res.authSetting["scope.userLocation"] != undefined &&
res.authSetting["scope.userLocation"] != true
) {
wx.showModal({
title: "請(qǐng)求授權(quán)當(dāng)前位置",
content: "需要獲取您的地理位置,請(qǐng)確認(rèn)授權(quán)",
success: function (res) {
if (res.cancel) {
wx.showToast({
title: "拒絕授權(quán)",
icon: "none",
duration: 1000,
});
} else if (res.confirm) {
wx.openSetting({
success: function (dataAu) {
if (dataAu.authSetting["scope.userLocation"] == true) {
wx.showToast({
title: "授權(quán)成功",
icon: "success",
duration: 1000,
});
//再次授權(quán),調(diào)用wx.getLocation的API
that.getLocation();
} else {
wx.showToast({
title: "授權(quán)失敗",
icon: "none",
duration: 1000,
});
}
},
});
}
},
});
} else if (res.authSetting["scope.userLocation"] == undefined) {
//調(diào)用wx.getLocation的API
that.getLocation();
} else {
//res.authSetting['scope.userLocation'] == true
//調(diào)用wx.getLocation的API
that.getLocation();
}
},
});
},
getLocation() {
let that = this;
wx.getLocation({
type: "wgs84",
success(res) {
console.log("經(jīng)緯度", res);
if (res?.errMsg === "getLocation:ok") {
/* ----------------通過經(jīng)緯度獲取地區(qū)編碼---------------- */
wx.request({
url: "https://restapi.amap.com/v3/geocode/regeo?parameters",
data: {
key: KEY, //填入自己申請(qǐng)到的Key
location: res.longitude + "," + res.latitude, //傳入經(jīng)緯度
},
header: {
"content-type": "application/json",
},
success: function (res) {
console.log("坐標(biāo)轉(zhuǎn)換和查詢天氣", res.data);
wx.setStorageSync(
"city",
res.data.regeocode.addressComponent.adcode //地區(qū)編碼
);
that.setData({
location: res.data.regeocode.addressComponent.city +
" " +
res.data.regeocode.addressComponent.district,
});
wx.request({
url: "https://restapi.amap.com/v3/weather/weatherInfo",
data: {
key: KEY, //填入自己申請(qǐng)到的Key
city: res.data.regeocode.addressComponent.adcode, //傳入地區(qū)編碼
},
header: {
"content-type": "application/json",
},
success: function (weather) {
console.log("天氣", weather.data);
that.setData({
temp: weather.data.lives[0].temperature, //溫度
weatherText: weather.data.lives[0].weather, //天氣描述 晴天 下雨天...
welcome: "今天的天氣是 " + weather.data.lives[0].weather + ",又是愛豆的一天!", //歡迎語
});
},
});
},
});
}
},
});
},
Mqtt協(xié)議
connectMqtt() {
let that = this;
const options = {
connectTimeout: 4000,
address: "t.yoyolife.fun/mqtt", //輸入的地址
port: 8084, //輸入的端口號(hào)
username: "75bdfb62a1c56065949702a3a6430e38", //輸入的用戶名
password: "123465", //輸入的密碼
};
console.log("address是:", options.address);
client = mqtt.connect(MQTTADDRESS, options); //連接
client.on("connect", (e) => {
console.log('連接成功');
})
client.on("reconnect", (error) => {
console.log("正在重連:", error);
wx.showToast({
icon: "none",
title: "正在重連",
});
});
client.on("error", (error) => {
console.log("連接失敗:", error);
wx.showToast({
icon: "none",
title: "mqtt連接失敗",
});
});
// 訂閱一個(gè)主題
let message = this.data.push;
client.subscribe(this.data.push, {
qos: 0
}, function (err) {
if (!err) {
console.log("訂閱成功", message);
wx.showToast({
icon: "none",
title: "添加成功",
});
}
});
client.on("message", (topic, message) => {
console.log("收到地址:", topic);
console.log("收到消息:", message.toString());
let getMessage = {}; //收到的消息
try {
getMessage = JSON.parse(message); //收到的消息轉(zhuǎn)換成json對(duì)象
console.log(getMessage);
that.setData({
temperature: getMessage.temperature,
humidity: getMessage.humidity,
})
} catch (error) {
console.log("JSON解析失??!");
}
})
}
修改代碼作為己用
用戶如需借用代碼,只需修改關(guān)鍵部分即可,例如Mqtt的Key、發(fā)布訂閱地址,WiFi的賬號(hào)密碼等。
程序初始化
const KEY = "1acc1391bf1593cf96f258d2f9ebe552"; //注意這里是高德地圖的KEY 不是Mqtt服務(wù)器的KEY
const app = getApp();
import mqtt from "../../utils/mqtt.min"; //加載的Mqtt協(xié)議的文件名
const MQTTADDRESS = "wxs://t.yoyolife.fun/mqtt"; //mqtt服務(wù)器地址
data中數(shù)據(jù)
welcome: "你好,這里是Shiboven。",//主頁顯示
push: "/iot/4432/waa", //訂閱地址
subscr: "/iot/4432/wsy", //發(fā)布地址
connectMqtt函數(shù)
const options = {
connectTimeout: 4000, //重連時(shí)間
address: "t.yoyolife.fun/mqtt", //Mqtt服務(wù)器地址
port: 8084, //Mqtt服務(wù)器端口號(hào)
username: "75bdfb62a1c56065949702a3a6430e38", //Mqtt用戶名
password: "123465", //Mqtt密碼
};
總結(jié)
項(xiàng)目本身功能簡單,但是包含內(nèi)容還是挺多的,擴(kuò)展的話也比較容易。文章來源:http://www.zghlxwxcb.cn/news/detail-785302.html
項(xiàng)目地址:https://download.csdn.net/download/weixin_42320020/88731183文章來源地址http://www.zghlxwxcb.cn/news/detail-785302.html
到了這里,關(guān)于基于嵌入式的智能臺(tái)燈系統(tǒng)的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!