從零開始的DIY智能家居 - 基於 ESP32 的土壤濕度傳感器


前言

自從上次做了那個 甲醛傳感器水濁度傳感器 之后開始嘗到智能家居的甜頭了,這兩東西有沒有用我不知道,但是沒事的時候掏出手機瞄兩眼,看着就讓人很安心( ̄︶ ̄)↗。

於是懶惰的我開始琢磨把給植物澆水這件事情找個法子偷一下懶,也給它智能化了。這樣我就不用每天澆水,直接給水桶灌水就行。

因為土壤濕度傳感器的使用方法和水濁度傳感器差不多,我就用水濁度傳感器的代碼改了改,做了一個土壤濕度傳感器。

硬件選擇

這次開發板還是和水濁度傳感器一樣,依然還是用着安信可的 ESP32S ,別問,問就是便宜 24元

傳感器用的 DFrboot 的 土壤濕度傳感器 35元

服務器用的翼輝的 Spirit 1 ,799元,這玩意就是一次性投入上次買了之后,后面所有的設備都可以用它,作為服務器。

傳感器接線:使用 A0 控制(SVP/IO36),電源接3.3-5V都可以。
A -> A0 (SVP/IO36)
VCC -> 3.3 - 5V
GND -> GND

在這里插入圖片描述

代碼解析

獲取代碼

為了方便講解邏輯,我會打亂代碼的順序可能還會進行裁剪,要是想直接拿代碼跑的朋友可以直接去 靈感桌面的秘密寶庫 獲取代碼,或者直接 clone:

https://gitee.com/inspiration-desktop/DEV-lib-arduino.git

要是連 git 是什么都不知道,可以參考簡單無腦,上手即用 - 手把手教你使用 智能紅外溫度傳感器代碼以及依賴的 gitee 庫!
下載或者 clone代碼后這次用到的是這個三個文件夾:

在這里插入圖片描述
cjson:我移植的 cjson 庫,就是標准的 cjson 庫,放到 arduino 安裝目錄下的 libraries 文件夾里,百度一下 cjson 的函數使用就行了。

libsddc:是我移植自官方的SDDC庫和自己寫的 SDK,也是放入 libraries 文件夾里就行。里面是 SDDC 協議的處理函數,我們不用管。

demo 文件夾里面就是我們各種傳感器的 demo 代碼了:
在這里插入圖片描述
紅圈的 SEN0193_sddc_demo文件夾里面就是我們代碼,點進去就能看見 SEN0193_sddc_sdk_demo.ino 文件,雙擊文件會自動啟動 arduino-IDE 打開代碼。在工具 -> 端口 選擇對應的 COM 口然后點擊上傳就可以把代碼燒錄到板子里:
在這里插入圖片描述

具體 arduino 使用教程可以看我之前的文章 arduino開發指導手把手帶你 arduino 開發:基於ESP32S 的第一個應用-紅外測溫槍(帶引腳圖)

設備控制命令:

通過 Spirit 1 的應用程序或者嗅探器 向傳感器設備發送的命令。
傳感器本身會按周期主動上報當前土壤濕度,同時還可以通過 get 命令主動獲取當前土壤濕度:

{
    "method": "get",                      // 這個命令可以主動獲取當前土壤濕度
    "obj": ["soil_humidity"]              
}

如果默認的數據上報周期不符合需要還可以通過 set 命令來調整主動上報的間隔:

{
    "method": "set",                     // 這個命令可以調整傳感器主動上報的時間間隔,土壤濕度變化應該不會很快,可以設置慢一些 
    "periodic_time": 1000                // periodic_time是關鍵字,需要和下文的函數注冊字段一致
}

設備和協議初始化流程:

這部分基於官方 demo 寫的不需要做什么修改,主要是設備初始化,管腳配置,和協議初始化部分。

傳感器初始化部分,因為這個傳感器輸出只是普通的電壓值,用一般的 IO 口即可讀取,不需要初始化額外的串口或者 I2C,但是主動上報流程中需要加延時,為了不阻塞其他任務需要單獨創建一個線程 。

設備和協議初始化部分,代碼基本不需要改動,並且過長,這里就不放出來,有興趣的朋友可以去 靈感桌面的秘密寶庫 查看詳細代碼。

/*
 * 初始化傳感器
 */
void sensor_init()
{
    // 創建傳感器任務,周期性獲取土壤濕度傳感器的數據並發送給 EdgerOS
    xTaskCreate(periodic_sensor_task, "periodic_sensor_task", ESP_TASK_STACK_SIZE, NULL, ESP_TASK_PRIO, NULL);
}

void setup() {
    // 初始化顯示串口
    // 初始化傳感器
    sensor_init();
    // 清除一下按鍵狀態機的狀態
    // 創建按鍵掃描線程,長按 IO0 按鍵,松開后 ESP32 將會進入 SmartConfig 模式
    // 啟動 WiFi 並且連接網絡
    // 獲取並打印 IP 地址
    // sddc協議初始化
    // 獲取並打印網卡 mac 地址
    // 使用網卡 mac 地址設置設備唯一標識 UID
}

void loop() {
    // 運行 SDDC 協議循環
    // 銷毀 SDDC 協議
}

配置設備信息

這部分代碼可以配置 WiFi 名字和 WiFi 密碼,要使用的引腳,並且配置設備在 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 協議使用的端口號
#define PIN_INPUT 0                                // 選擇 IO0 進行控制
#define ESP_TASK_STACK_SIZE   4096
#define ESP_TASK_PRIO         25

static const int sensor_in = A0;                   // 數據輸入引腳

static const char* ssid = "EOS-000045";            // WiFi 名
static const char* password = "1234567890";        // WiFi 密碼

const float AirValue = 3000;                       //初始化最大干燥 (傳感器在空中的情況。這個需要根據你自己傳感器情況初始化)
const float WaterValue = 1400;                     //初始化最大濕度 (傳感器放入水中的情況。這個需要根據你自己傳感器情況初始化)
int intervals = (AirValue - WaterValue) / 3;

static  int xTicksToDelay = 10000;                 // 周期延時時間
  
OneButton button(PIN_INPUT, true);

這里填寫設備的信息,方便在 Spirit 1 上查看和尋找你需要的設備:

/*
 *  當前設備的信息定義
 */
DEV_INFO    dev_info = {
            .name     = "土壤濕度",
            .type     = "device",
            .excl     = SDDC_FALSE,
            .desc     = "ESP-32S",
            .model    = "1",
            .vendor   = "inspiration-desktop",
};

回調函數注冊

這是收到命令后回調函數注冊的位置,在這里注冊的函數才能被 SDK 正確的調用,執行正確的動作。

土壤濕度傳感器輸出 (get命令) 的土壤濕度是數字量,所以在 系統對象狀態獲取注冊 中注冊處理函數時,第二個參數需要設定為 DEV_NUM_TYPE,而 對應的處理函數是single_get_sensor。

/*
 *  系統對象狀態獲取注冊
 */
DEV_STATE_GET  dev_state_get_reg[] = {
        {"soil_humidity",   DEV_NUM_TYPE,  single_get_sensor},  // 輸出數字量,所以第二個參數為 DEV_NUM_TYPE
};

輸入(set 命令)的上報時間間隔也是數字量,所以在 數字量設備對象函數與處理方法注冊 中注冊 "periodic_time" 命令處理函數。

/* 
 *  數字量設備對象函數與處理方法注冊
 */
NUM_DEV_REGINFO num_dev[] = {
        {"periodic_time",periodic_time_set},
};

因為沒有其他輸入,所以 顯示設備對象函數與處理方法注冊IO設備對象設置函數與處理方法注冊 為空。


/*
 *  顯示設備對象函數與處理方法注冊
 */
DIS_DEV_REGINFO dis_dev[] = {
};

/*
 * IO設備對象設置函數與處理方法注冊
 */
IO_DEV_REGINFO io_dev[] = {
};

具體 SDK 的解析可以參考 同人逼死官方系列!基於sddc 協議的SDK框架 sddc_sdk_lib 解析同人逼死官方系列!從 DDC 嗅探器到 sddc_sdk_lib 的數據解析

數據獲取與發送流程

這里是我們自己編寫的處理流程 ,可以根據你的需求自己更改,收到 set 命令或者 get 命令后根據上文注冊的函數,進入對應的處理函數。

設備會監視傳感器輸出,然后根據設置的上報間隔定時上報土壤濕度數據,還可以主動發送 get 命令主動查詢傳感器當前數據:

/* 
 *  周期上報函數
 */
static void periodic_sensor_task(void *arg)
{
    while(1)
    {
    // 任務創建之后,設定延時周期
    printf("延時時間:%d",xTicksToDelay);
    delay(xTicksToDelay);
  
     // 調用主動數據上報函數
     get_sensor();
     delay(100);
    }  
   // 已停止發送數據
   Serial.printf("Soil humidity data OFF\n");
}


/* 
 *  主動數據上報函數
 */
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);
      
    // 組裝上報報文
    cJSON_AddItemToArray(value, cJSON_CreateString("soil_humidity"));
    cJSON_AddItemToObject(root, "obj", value);
      
    // 將組裝好的報文傳給上報函數
    msg = cJSON_Print(root);
    printf("定時上報: %s\n",msg);
    object_report(root);
      
    cJSON_Delete(value);
    cJSON_free(msg);
}

/* 
 *  設置周期等待時間              
 *  這是在上文注冊的 set 命令處理函數
 */
sddc_bool_t periodic_time_set(const uint64_t value)
{
    printf("修改定時時間!\n");
    xTicksToDelay = value;
    return SDDC_TRUE;
}
/* 
 *  單次獲取數據                   
 *  這是在上文注冊的 get 命令處理函數
 */
sddc_bool_t single_get_sensor(char *objvalue, int value_len)
{
    // 計算濕度百分百
    float value = 100 - (((analogRead(sensor_in))-WaterValue)/(AirValue - WaterValue))*100;
    if(value > 100)
    {
        value = 100;
    }
    snprintf(objvalue, value_len, "%f", value);
    return SDDC_TRUE;
}

代碼寫完之后燒錄進去就完事了,和之前完全一樣,點一下保存,然后上傳OK,具體可以看之前的文檔,我就懶得再寫一遍啦 (/ω\)


總結

在這里插入圖片描述

土壤濕度傳感器完美完成,接下來就是智慧澆水設備了,我馬上就能擺脫每天都要澆水的日子了!

本文僅個人學習使用,如有錯誤,歡迎指正, ( ੭ ˙ᗜ˙ )੭謝謝老板!


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM