1. 程式人生 > >智能家居入門DIY——【四、組合】

智能家居入門DIY——【四、組合】

vat -- cond 一點 ros 但是 comm end 上電

前面幾篇介紹了一些傳感器和代碼,這篇介紹一下把它們組合起來。之所以單獨列出這部分,原因在於組合更多功能的時候發現使用軟串口庫驅動ESP8266時由於內存過小導致發送失敗甚至整個系統無法工作的情況。所以,我只組合了DHT11、火焰傳感、MQ-9這幾個傳感器。今天優化了ESP8266部分的代碼之後,實際測試時還可以用起一個GP2Y10,再多就不行了,而且包括DHT11、GP2Y10都不是使用現成的庫文件,而是自己寫了一些代碼。暫時確實沒有更多精力去自己寫軟串口通訊的部分了。首先看一下DHT11的代碼:

// DHT11SimpleRead.h

#ifndef _DHT11SIMPLEREAD_h
#define _DHT11SIMPLEREAD_h #if defined(ARDUINO) && ARDUINO >= 100 #include "arduino.h" #else #include "WProgram.h" #endif class DHT11SimpleRead { public: DHT11SimpleRead(unsigned int p); bool read(); float temperature=5.0; float humidity=50.0; private
: unsigned int pin; unsigned int bits[5]; }; #endif
// 
// 
// 

#include "DHT11SimpleRead.h"

DHT11SimpleRead::DHT11SimpleRead(unsigned int p)
{
    pin = p;
}

bool DHT11SimpleRead::read()
{
    int cnt = 7;
    int idx = 0;

    //發送命令開始工作
    pinMode(pin, OUTPUT);
    digitalWrite(pin, LOW);
    delay(
20); //至少18毫秒拉低 digitalWrite(pin, HIGH); delayMicroseconds(40); //20-40微秒拉高 //轉換到主機接收 pinMode(pin, INPUT); unsigned int loopCnt = 10000; //等待80微秒左右的拉高結束 while (digitalRead(pin) == LOW) if (loopCnt-- == 0) return; loopCnt = 10000; //等待80微秒左右的拉低結束 while (digitalRead(pin) == HIGH) if (loopCnt-- == 0) return; //開始接收40位數據 for (int i = 0; i<40; i++) { loopCnt = 10000; while (digitalRead(pin) == LOW) //每一位都是從低開始,當低結束時,根據電平長短來確定是0還是1 if (loopCnt-- == 0) return; unsigned long t = micros(); //開始計時 loopCnt = 10000; while (digitalRead(pin) == HIGH) //等待新號變低的時間決定了位的高低 if (loopCnt-- == 0) return; if ((micros() - t) > 40) bits[idx] |= (1 << cnt); //一般,26-28微秒是0,29-70微秒是1 //接收滿8位開始下一字節 if (cnt == 0) { cnt = 7; idx++; } else cnt--; } //傳輸完成之後,DHT11會拉低單總線50微秒。不處理了。 //接收完成寫入數據 temperature = bits[2]; humidity= bits[0]; //進行校驗 return (unsigned int)bits[0] + bits[1] + bits[2] + bits[3] == (unsigned int)bits[4]; }

根據時序寫驅動並不是很麻煩。這樣就得到了兩個數值,今天在測試的時候發現有時讀取的值並不正確,但是剛剛上電的時候是正確的,反復檢查並優化了一些代碼之後沒有再出現這個問題,如果再出現可能就是電路設計有問題了。

然後針對ESP8266發送數據比較長進行了一點優化,當然這部分完全可以做的更好一些,但是感覺沒有什麽必要了,畢竟就是當一個玩意玩的,即使付出更多努力結果可能也只是多加一個傳感器——而我並不打算得到溫濕度、火焰、燃氣以外的數據。包括顆粒物傳感器,我也只是打算放到另一塊Arduino上,與語音識別和紅外發射放到一起做一個簡單的語音控制器來控制一些紅外遙控的設備,例如自動開關空氣凈化,語音控制電視、窗簾等。這個優化主要是針對POST部分的數據比較長,把它按行拆開透傳;也可以限定每次透傳的數據量。當然,無論如何,減少字符串占用的堆棧、盡早的回收它們是努力的方向:

bool ESP8266SoftwareSerialHTTPPOST::postString(String line)
{
    if (doATCommand("AT+CIPSEND=" + (String)(line.length()+2), ">", deffStr, 1000)) {
        if (doATCommand(line, "SEND OK", "FAIL", 1000)) {
            return true;
        }
        else {
            Serial.println("Send:err");
            Serial.println(resultLine);
        }
    }
    else {
        Serial.println("Post:ERROR" + Crlf + line + Crlf + line.length());
        Serial.println(resultLine);
    }
    return false;
}

需要註意的是,長度的計算多2字節,因為我使用的是println,而line並沒有加上\r\n。

另外,為了加速處理,除了原來對正確返回值"OK“等、超時處理之外,也對"ERROR"、"No AP"等進行了處理,這樣可以快速從對串口的等待中返回。

最後,對這些功能進行組合,得到的結果還是比較令人滿意的,它已經連續工作了12小時以上,並沒有出現什麽其他問題。

技術分享圖片

智能家居入門DIY——【四、組合】