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

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

// 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];
}

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

而後針對ESP8266發送數據比較長進行了一點優化,固然這部分徹底能夠作的更好一些,可是感受沒有什麼必要了,畢竟就是當一個玩意玩的,即便付出更多努力結果可能也只是多加一個傳感器——而我並不打算獲得溫溼度、火焰、燃氣之外的數據。包括顆粒物傳感器,我也只是打算放到另外一塊Arduino上,與語音識別和紅外發射放到一塊兒作一個簡單的語音控制器來控制一些紅外遙控的設備,例如自動開關空氣淨化,語音控制電視、窗簾等。這個優化主要是針對POST部分的數據比較長,把它按行拆開透傳;也能夠限定每次透傳的數據量。固然,不管如何,減小字符串佔用的堆棧、儘早的回收它們是努力的方向: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小時以上,並無出現什麼其餘問題。ui

相關文章
相關標籤/搜索