从零开始的DIY智能家居 - 基于 ESP32 的土壤湿度传感器
文章目錄
- 前言
- 硬件選擇
- 代碼解析
- 獲取代碼
- 設(shè)備控制命令:
- 設(shè)備和協(xié)議初始化流程:
- 配置設(shè)備信息
- 回調(diào)函數(shù)注冊(cè)
- 數(shù)據(jù)獲取與發(fā)送流程
- 總結(jié)
前言
自從上次做了那個(gè) 甲醛傳感器 和 水濁度傳感器 之后開始嘗到智能家居的甜頭了,這兩東西有沒有用我不知道,但是沒事的時(shí)候掏出手機(jī)瞄兩眼,看著就讓人很安心( ̄︶ ̄)↗。
于是懶惰的我開始琢磨把給植物澆水這件事情找個(gè)法子偷一下懶,也給它智能化了。這樣我就不用每天澆水,直接給水桶灌水就行。
因?yàn)橥寥罎穸葌鞲衅鞯氖褂梅椒ê退疂岫葌鞲衅鞑畈欢?#xff0c;我就用水濁度傳感器的代碼改了改,做了一個(gè)土壤濕度傳感器。
硬件選擇
這次開發(fā)板還是和水濁度傳感器一樣,依然還是用著安信可的 ESP32S ,別問,問就是便宜 24元
傳感器用的 DFrboot 的 土壤濕度傳感器 35元
服務(wù)器用的翼輝的 Spirit 1 ,799元,這玩意就是一次性投入上次買了之后,后面所有的設(shè)備都可以用它,作為服務(wù)器。
傳感器接線:使用 A0 控制(SVP/IO36),電源接3.3-5V都可以。
A -> A0 (SVP/IO36)
VCC -> 3.3 - 5V
GND -> GND
代碼解析
獲取代碼
為了方便講解邏輯,我會(huì)打亂代碼的順序可能還會(huì)進(jìn)行裁剪,要是想直接拿代碼跑的朋友可以直接去 靈感桌面的秘密寶庫(kù) 獲取代碼,或者直接 clone:
https://gitee.com/inspiration-desktop/DEV-lib-arduino.git要是連 git 是什么都不知道,可以參考簡(jiǎn)單無腦,上手即用 - 手把手教你使用 智能紅外溫度傳感器代碼以及依賴的 gitee 庫(kù)!
下載或者 clone代碼后這次用到的是這個(gè)三個(gè)文件夾:
cjson:我移植的 cjson 庫(kù),就是標(biāo)準(zhǔn)的 cjson 庫(kù),放到 arduino 安裝目錄下的 libraries 文件夾里,百度一下 cjson 的函數(shù)使用就行了。
libsddc:是我移植自官方的SDDC庫(kù)和自己寫的 SDK,也是放入 libraries 文件夾里就行。里面是 SDDC 協(xié)議的處理函數(shù),我們不用管。
demo 文件夾里面就是我們各種傳感器的 demo 代碼了:
紅圈的 SEN0193_sddc_demo文件夾里面就是我們代碼,點(diǎn)進(jìn)去就能看見 SEN0193_sddc_sdk_demo.ino 文件,雙擊文件會(huì)自動(dòng)啟動(dòng) arduino-IDE 打開代碼。在工具 -> 端口 選擇對(duì)應(yīng)的 COM 口然后點(diǎn)擊上傳就可以把代碼燒錄到板子里:
具體 arduino 使用教程可以看我之前的文章 arduino開發(fā)指導(dǎo) 和 手把手帶你 arduino 開發(fā):基于ESP32S 的第一個(gè)應(yīng)用-紅外測(cè)溫槍(帶引腳圖)
設(shè)備控制命令:
通過 Spirit 1 的應(yīng)用程序或者嗅探器 向傳感器設(shè)備發(fā)送的命令。
傳感器本身會(huì)按周期主動(dòng)上報(bào)當(dāng)前土壤濕度,同時(shí)還可以通過 get 命令主動(dòng)獲取當(dāng)前土壤濕度:
如果默認(rèn)的數(shù)據(jù)上報(bào)周期不符合需要還可以通過 set 命令來調(diào)整主動(dòng)上報(bào)的間隔:
{"method": "set", // 這個(gè)命令可以調(diào)整傳感器主動(dòng)上報(bào)的時(shí)間間隔,土壤濕度變化應(yīng)該不會(huì)很快,可以設(shè)置慢一些 "periodic_time": 1000 // periodic_time是關(guān)鍵字,需要和下文的函數(shù)注冊(cè)字段一致 }設(shè)備和協(xié)議初始化流程:
這部分基于官方 demo 寫的不需要做什么修改,主要是設(shè)備初始化,管腳配置,和協(xié)議初始化部分。
傳感器初始化部分,因?yàn)檫@個(gè)傳感器輸出只是普通的電壓值,用一般的 IO 口即可讀取,不需要初始化額外的串口或者 I2C,但是主動(dòng)上報(bào)流程中需要加延時(shí),為了不阻塞其他任務(wù)需要單獨(dú)創(chuàng)建一個(gè)線程 。
設(shè)備和協(xié)議初始化部分,代碼基本不需要改動(dòng),并且過長(zhǎng),這里就不放出來,有興趣的朋友可以去 靈感桌面的秘密寶庫(kù) 查看詳細(xì)代碼。
/** 初始化傳感器*/ void sensor_init() {// 創(chuàng)建傳感器任務(wù),周期性獲取土壤濕度傳感器的數(shù)據(jù)并發(fā)送給 EdgerOSxTaskCreate(periodic_sensor_task, "periodic_sensor_task", ESP_TASK_STACK_SIZE, NULL, ESP_TASK_PRIO, NULL); }void setup() {// 初始化顯示串口// 初始化傳感器sensor_init();// 清除一下按鍵狀態(tài)機(jī)的狀態(tài)// 創(chuàng)建按鍵掃描線程,長(zhǎng)按 IO0 按鍵,松開后 ESP32 將會(huì)進(jìn)入 SmartConfig 模式// 啟動(dòng) WiFi 并且連接網(wǎng)絡(luò)// 獲取并打印 IP 地址// sddc協(xié)議初始化// 獲取并打印網(wǎng)卡 mac 地址// 使用網(wǎng)卡 mac 地址設(shè)置設(shè)備唯一標(biāo)識(shí) UID }void loop() {// 運(yùn)行 SDDC 協(xié)議循環(huán)// 銷毀 SDDC 協(xié)議 }配置設(shè)備信息
這部分代碼可以配置 WiFi 名字和 WiFi 密碼,要使用的引腳,并且配置設(shè)備在 Spirit 1 上顯示的信息:
#include "Arduino.h" #include <OneButton.h> #include <WiFi.h> #include <SDDC_SDK_lib.h> #include <cJSON.h> #include <Wire.h>#define SDDC_CFG_PORT 680U // SDDC 協(xié)議使用的端口號(hào) #define PIN_INPUT 0 // 選擇 IO0 進(jìn)行控制 #define ESP_TASK_STACK_SIZE 4096 #define ESP_TASK_PRIO 25static const int sensor_in = A0; // 數(shù)據(jù)輸入引腳static const char* ssid = "EOS-000045"; // WiFi 名 static const char* password = "1234567890"; // WiFi 密碼const float AirValue = 3000; //初始化最大干燥 (傳感器在空中的情況。這個(gè)需要根據(jù)你自己傳感器情況初始化) const float WaterValue = 1400; //初始化最大濕度 (傳感器放入水中的情況。這個(gè)需要根據(jù)你自己傳感器情況初始化) int intervals = (AirValue - WaterValue) / 3;static int xTicksToDelay = 10000; // 周期延時(shí)時(shí)間OneButton button(PIN_INPUT, true);這里填寫設(shè)備的信息,方便在 Spirit 1 上查看和尋找你需要的設(shè)備:
/** 當(dāng)前設(shè)備的信息定義*/ DEV_INFO dev_info = {.name = "土壤濕度",.type = "device",.excl = SDDC_FALSE,.desc = "ESP-32S",.model = "1",.vendor = "inspiration-desktop", };回調(diào)函數(shù)注冊(cè)
這是收到命令后回調(diào)函數(shù)注冊(cè)的位置,在這里注冊(cè)的函數(shù)才能被 SDK 正確的調(diào)用,執(zhí)行正確的動(dòng)作。
土壤濕度傳感器輸出 (get命令) 的土壤濕度是數(shù)字量,所以在 系統(tǒng)對(duì)象狀態(tài)獲取注冊(cè) 中注冊(cè)處理函數(shù)時(shí),第二個(gè)參數(shù)需要設(shè)定為 DEV_NUM_TYPE,而 對(duì)應(yīng)的處理函數(shù)是single_get_sensor。
/** 系統(tǒng)對(duì)象狀態(tài)獲取注冊(cè)*/ DEV_STATE_GET dev_state_get_reg[] = {{"soil_humidity", DEV_NUM_TYPE, single_get_sensor}, // 輸出數(shù)字量,所以第二個(gè)參數(shù)為 DEV_NUM_TYPE };輸入(set 命令)的上報(bào)時(shí)間間隔也是數(shù)字量,所以在 數(shù)字量設(shè)備對(duì)象函數(shù)與處理方法注冊(cè) 中注冊(cè) “periodic_time” 命令處理函數(shù)。
/* * 數(shù)字量設(shè)備對(duì)象函數(shù)與處理方法注冊(cè)*/ NUM_DEV_REGINFO num_dev[] = {{"periodic_time",periodic_time_set}, };因?yàn)闆]有其他輸入,所以 顯示設(shè)備對(duì)象函數(shù)與處理方法注冊(cè) 和 IO設(shè)備對(duì)象設(shè)置函數(shù)與處理方法注冊(cè) 為空。
/** 顯示設(shè)備對(duì)象函數(shù)與處理方法注冊(cè)*/ DIS_DEV_REGINFO dis_dev[] = { };/** IO設(shè)備對(duì)象設(shè)置函數(shù)與處理方法注冊(cè)*/ IO_DEV_REGINFO io_dev[] = { };具體 SDK 的解析可以參考 同人逼死官方系列!基于sddc 協(xié)議的SDK框架 sddc_sdk_lib 解析 和 同人逼死官方系列!從 DDC 嗅探器到 sddc_sdk_lib 的數(shù)據(jù)解析
數(shù)據(jù)獲取與發(fā)送流程
這里是我們自己編寫的處理流程 ,可以根據(jù)你的需求自己更改,收到 set 命令或者 get 命令后根據(jù)上文注冊(cè)的函數(shù),進(jìn)入對(duì)應(yīng)的處理函數(shù)。
設(shè)備會(huì)監(jiān)視傳感器輸出,然后根據(jù)設(shè)置的上報(bào)間隔定時(shí)上報(bào)土壤濕度數(shù)據(jù),還可以主動(dòng)發(fā)送 get 命令主動(dòng)查詢傳感器當(dāng)前數(shù)據(jù):
/* * 周期上報(bào)函數(shù)*/ static void periodic_sensor_task(void *arg) {while(1){// 任務(wù)創(chuàng)建之后,設(shè)定延時(shí)周期printf("延時(shí)時(shí)間:%d",xTicksToDelay);delay(xTicksToDelay);// 調(diào)用主動(dòng)數(shù)據(jù)上報(bào)函數(shù)get_sensor();delay(100);} // 已停止發(fā)送數(shù)據(jù)Serial.printf("Soil humidity data OFF\n"); }/* * 主動(dòng)數(shù)據(jù)上報(bào)函數(shù)*/ static void report_sensor_state() { int sensorValue = 0;cJSON *value;cJSON *root;char *msg;value = cJSON_CreateArray();root = cJSON_CreateObject();sddc_return_if_fail(value);sddc_return_if_fail(root);sddc_return_if_fail(value);// 組裝上報(bào)報(bào)文cJSON_AddItemToArray(value, cJSON_CreateString("soil_humidity"));cJSON_AddItemToObject(root, "obj", value);// 將組裝好的報(bào)文傳給上報(bào)函數(shù)msg = cJSON_Print(root);printf("定時(shí)上報(bào): %s\n",msg);object_report(root);cJSON_Delete(value);cJSON_free(msg); }/* * 設(shè)置周期等待時(shí)間 * 這是在上文注冊(cè)的 set 命令處理函數(shù)*/ sddc_bool_t periodic_time_set(const uint64_t value) {printf("修改定時(shí)時(shí)間!\n");xTicksToDelay = value;return SDDC_TRUE; } /* * 單次獲取數(shù)據(jù) * 這是在上文注冊(cè)的 get 命令處理函數(shù)*/ sddc_bool_t single_get_sensor(char *objvalue, int value_len) {// 計(jì)算濕度百分百float value = 100 - (((analogRead(sensor_in))-WaterValue)/(AirValue - WaterValue))*100;if(value > 100){value = 100;}snprintf(objvalue, value_len, "%f", value);return SDDC_TRUE; }代碼寫完之后燒錄進(jìn)去就完事了,和之前完全一樣,點(diǎn)一下保存,然后上傳OK,具體可以看之前的文檔,我就懶得再寫一遍啦 (/ω\)
總結(jié)
土壤濕度傳感器完美完成,接下來就是智慧澆水設(shè)備了,我馬上就能擺脫每天都要澆水的日子了!
本文僅個(gè)人學(xué)習(xí)使用,如有錯(cuò)誤,歡迎指正, ( ? ˙?˙ )?謝謝老板!
總結(jié)
以上是生活随笔為你收集整理的从零开始的DIY智能家居 - 基于 ESP32 的土壤湿度传感器的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: i 标签设置背景图片作 icon的问题
- 下一篇: 领导人要读的10本管理学书籍