步驟1:所需的組件
以下組件列表用于構(gòu)建天氣和空氣質(zhì)量監(jiān)視器。您也可以使用功能相同的組件。
ESP8266 D1 Mini
鋰電池USB充電模塊
3.3V輸出DC-to-DC模塊
5V輸出DC-to-DC模塊
小型開(kāi)關(guān)x 2
HDC1080濕度傳感器
BMP180溫度和氣壓傳感器
CCS811 TVOC傳感器
SenseAir S8 CO2傳感器
PM2。 5/PM10紅外傳感器
電路板,自動(dòng)換線工具和電線
步驟2:構(gòu)建電源電路
1。將鋰電池,電池充電器,3.3V和5V DC-DC轉(zhuǎn)換器連接在一起。您可能想在鋰電池與3.3V和5V DC-DC電源轉(zhuǎn)換器之間添加一個(gè)ON/OFF開(kāi)關(guān)。
2。測(cè)試鋰電池是否可以充電。
3。確認(rèn)可以獲得穩(wěn)定的3.3V和5V電源。
步驟3:為各種用途分配ESP8266 D1迷你引腳
首先,創(chuàng)建您的設(shè)計(jì)。為各種目的分配ESP8266 D1迷你引腳。 D1 Mini的針腳數(shù)量有限,我們需要仔細(xì)進(jìn)行分配。那些可以保存大頭針的應(yīng)該被保存。例如,某些傳感器只會(huì)通過(guò)TTL發(fā)送數(shù)據(jù),而不會(huì)接收數(shù)據(jù),因此我們不需要將接收引腳連接到D1 Mini。
以下是我的引腳分配:
/* PIN Assignment
A0 - Not Used
D0 - TFT CS
D1 - I2C CLK
D2 - I2C SDA
D3 - TFT C/D
D4 - PM2.5 CS
D5 - TFT SCK
D6 - S8 SenseAir TX+RX tied
D7 - TFT SDI(MOSI)
D8 - Not Used
TX - Debug Console
RX - PM2.5 Tx
*/
步驟4:通過(guò)SPI總線將D1 Mini與240x320 TFT相連
連接D1帶有SPI總線的240x320 TFT微型。使用以下引腳:
D0 - TFT CS
D3 - TFT C/D
D5 - TFT SCK
D7 - TFT SDI(MOSI)
請(qǐng)注意,MISO引腳未接線。原因是我們使用的TFT庫(kù)不會(huì)從TFT獲取任何數(shù)據(jù)。因此,我們可以節(jié)省1針用于其他用途。 UTFT ESP8266庫(kù)用于在SPI模式下驅(qū)動(dòng)支持ILI9341的TFT。如果您的TFT使用其他芯片組,則可能需要使用其他TFT庫(kù)。關(guān)鍵是您需要選擇一個(gè)支持SPI總線的TFT。否則,D1 Mini將沒(méi)有足夠的引腳與之連接。
要與TFT一起成功運(yùn)行,關(guān)鍵是要以正確的格式正確聲明UTFT對(duì)象。這是我們使用的方法:
// TFT Display
#include
#include
// UTFT::UTFT(byte model, int RS=SDI(MOSI), int WR=SCK, int CS=CS, int RST=NOTINUSE, int SER=DC)
UTFT myGLCD ( ILI9341_S5P, D7, D5, D0, NOTINUSE, D3); //ILI9341 in SPI
步驟5:將濕度傳感器連接到I2C總線
ESP8266 D1 Mini支持IIC總線。引腳D1用于時(shí)鐘(SCL或CLK),引腳D2用于數(shù)據(jù)(SDA)。 IIC總線可以同時(shí)支持位于不同地址的多個(gè)設(shè)備。您可以將傳感器連接到3.3V電源以及D1 Mini的SCL和SDA酒吧。
HDC1080用于感測(cè)濕度。我們使用 ClosedCube庫(kù)。
temperature[idx] = hdc1080.readTemperature();
if ( temperature[idx] 》 80.0) //Abnormal Reading, reset the chip
hdc1080.reset();
Serial.print(“HDC_Temp = ”); Serial.print(temperature[idx]); Serial.print(“ ”);
//-------------------------------
humidity[idx] = hdc1080.readHumidity();
Serial.print(“HDC_Humidity = ”); Serial.print(humidity[idx]); Serial.print(“ ”);
步驟6:將溫度和氣壓傳感器連接至IIC總線
ESP8266 D1 Mini支持IIC總線。引腳D1用于時(shí)鐘(SCL或SCK),引腳D2用于數(shù)據(jù)(SDA)。 IIC總線可以同時(shí)支持位于不同地址的多個(gè)設(shè)備。您可以將傳感器與3.3V電源以及D1 Mini的SCL和SDA酒吧相連。
BMP180用于感測(cè)溫度和氣壓。我們使用 Sparkfun庫(kù)。
if ((status = bmp180.startTemperature()) != 0) {
delay(status);
if (bmp180.getTemperature(T) != 0) {
temperature[idx] = T; // Over-ride the inaccurate temperature from HDC1080
if ((status = bmp180.startPressure(3)) != 0) {
delay(status);
if (bmp180.getPressure(P, T) != 0)
pressure[idx] = P;
}
}
}
Serial.print(“bmp180Temp = ”); Serial.print(temperature[idx]); Serial.print(“ ”);
Serial.print(“PRS = ”); Serial.print(pressure[idx]); Serial.print(“ ”);
步驟7:將TVOC傳感器連接到IIC總線
ESP8266 D1 Mini支持IIC總線。引腳D1用于時(shí)鐘(SCL或SCK),引腳D2用于數(shù)據(jù)(SDA)。 IIC總線可以同時(shí)支持位于不同地址的多個(gè)設(shè)備。您可以將傳感器與3.3V電源以及D1 Mini的SCL和SDA酒吧相連。
我們使用的TVOC傳感器是CCS811, Adafruit庫(kù)可以讀取數(shù)據(jù)。
但是,我們需要注意CCS811的自校準(zhǔn)過(guò)程,以便快速獲取數(shù)據(jù)。添加了一個(gè)額外的例程以將BASELINE數(shù)據(jù)記錄在ESP8266的EEPROM中。 CCS811會(huì)自動(dòng)連續(xù)調(diào)整BASELINE。我們定期將BASELINE記錄到EEPROM。在下一次系統(tǒng)啟動(dòng)時(shí),我們?cè)贑CS811預(yù)熱后讀入最后記錄的BASELINE。詳細(xì)邏輯可從CCS811數(shù)據(jù)表中獲得。
示例代碼如下:
setup(){
// Sensor Initilization
hdc1080.begin(0x40);
hdc1080.reset();
bmp180.begin();
ccs811.begin();
S8Serial.begin(9600);
S8_begin(&S8Serial);
//==== CCS811 BASELINE MANAGEMENT ====
EEPROM.begin(512);
copyCurrentTime(&curr_epoch, &curr_remain_millis); // Get the current time in Epoch
if (startup_epoch == 0) // initialize startup_epoch = curr_epoch;
if (last_eeprom_write_epoch == 0) // initialize
last_eeprom_write_epoch = curr_epoch;
// Read all the BASELINE records and pick the best one to use
score = 0; best_score = 0; lowest_score = 4294967295; //2^32-1
for (int j = 0; j 《 BASELINEREC_MAX; j++) { // Check all records in the EEPROM
// Read the BASELINE record
int baselinerec_addr_read = sizeof(uint16_t) + sizeof(struct baselinerec) * j;
for (int i = 0; i 《 sizeof(struct baselinerec); i++)
* ((uint8_t*)&_baselinerec_read + i) = (uint8_t)EEPROM.read(baselinerec_addr_read + i);
// Calculate the score of each record
if (_baselinerec_read.signature != 0xABAB) // record not initialized
score = 0;
else if ( (curr_epoch - _baselinerec_read.epoch) 》 28 * 24 * 3600) // record too old
score = 0;
else if ( _baselinerec_read.uptime 《 4 * 3600) // record was obtained over a too short period
score = 0;
else // score formula can be customized
score = _baselinerec_read.uptime + ((28 * 24 * 3600 - (curr_epoch - _baselinerec_read.epoch)) / 2);
Serial.print(“j=”); Serial.print(j);
Serial.print(“ signature=”); Serial.print(_baselinerec_read.signature);
Serial.print(“ epoch=”); Serial.print(_baselinerec_read.epoch);
Serial.print(“ uptime=”); Serial.print(_baselinerec_read.uptime);
Serial.print(“ avg_tvoc=”); Serial.print(_baselinerec_read.avg_tvoc);
Serial.print(“ score=”); Serial.println(score);
delay(100); // prevent D1 Mini software reset due to too much I/O
// Select the one with the highest score for read
if (score 》 best_score) {
best_score = score;
baseline_idx_read = j;
}
// Select the one with the highest score for write
if (score 《 lowest_score) {
lowest_score = score;
baseline_idx_write = j;
}
}
Serial.print(“baseline_idx_read=”); Serial.print(baseline_idx_read);
show_text(“baseline_idx_read=%.0f”, (float)baseline_idx_read, GEN_COLOR, CHART_LEFT, CHART_TOP + 96, 0);
Serial.print(“ baseline_idx_write=”); Serial.println(baseline_idx_write);
show_text(“baseline_idx_write=%.0f”, (float)baseline_idx_write, GEN_COLOR, CHART_LEFT, CHART_TOP + 112, 0);
// Read in the best record
if (best_score != 0) {
int baselinerec_addr_read = sizeof(uint16_t) + sizeof(struct baselinerec) * baseline_idx_read;
for (int i = 0; i 《 sizeof(struct baselinerec); i++)
* ((uint8_t*)&_baselinerec_read + i) = (uint8_t)EEPROM.read(baselinerec_addr_read + i);
}
// update the eeprom baseline index to record where is the current record
if (eeprom_baseline_idx_updated == false) {
EEPROM.write(0, baseline_idx_write 》》 8);
EEPROM.write(1, (baseline_idx_write 《《 8) 》》 8);
eeprom_baseline_idx_updated = true;
}
EEPROM.commit();
}
//The code below should be put in the loop() part of the sketch to write the lastly recorded BASELINE to CCS811
//and record the tunned BASELINE periodically.
//==== CCS811 BASELINE MANAGEMENT ====
// Get curr_epoch & uptiime for the operation below
copyCurrentTime(&curr_epoch, &curr_remain_millis);
uptime = curr_epoch - startup_epoch;
// write the best BASELINE to CCS811 after uptime 》 X minutes
if (ccs811_baseline_updated == false && best_score != 0 && uptime 》= 600) {
ccs811.writeBaseline(_baselinerec_read.baseline);
ccs811_baseline_updated = true;
}
// write to EEPROM periodically - Y minutes
uint8_t baseline[2];
ccs811.readBaseline(baseline);
if ( curr_epoch - last_eeprom_write_epoch 》= 900) {
_baselinerec_write.epoch = curr_epoch;
_baselinerec_write.baseline[0] = baseline[0];
_baselinerec_write.baseline[1] = baseline[1];
_baselinerec_write.uptime = uptime;
int baselinerec_addr_write = sizeof(uint16_t) + sizeof(struct baselinerec) * baseline_idx_write;
for (int i = 0; i 《 sizeof(struct baselinerec); i++)
EEPROM.write(baselinerec_addr_write + i, *((uint8_t*)&_baselinerec_write + i));
EEPROM.commit();
last_eeprom_write_epoch = curr_epoch;
}
步驟8:連接PM2.5/PM 10 TTL RX接口的傳感器
我們使用的傳感器來(lái)自中國(guó)制造商(六度空氣)。它通過(guò)TTL接口提供數(shù)據(jù)。每秒生成PM2.5和PM10讀數(shù)。無(wú)需將命令發(fā)送到傳感器即可觸發(fā)輸出。因此,只需將傳感器上的TX引腳和D1 Mini上的RX引腳連接在一起。
請(qǐng)注意,D1 Mini依靠其TX和RX引腳來(lái)更新草圖。將RX引腳與傳感器連接會(huì)影響草圖下載。因此,在草圖下載過(guò)程中實(shí)現(xiàn)了一個(gè)斷開(kāi)RX連接的開(kāi)關(guān)。不使用傳感器時(shí),小風(fēng)扇會(huì)消耗功率。傳感器處有一個(gè)啟用(CS)引腳,用于打開(kāi)/關(guān)閉風(fēng)扇和數(shù)據(jù)輸出。使能(CS)引腳連接到D1 Mini的D4。
以下是從傳感器獲取數(shù)據(jù)的代碼:
//--------------------------
// PM2.5
//Serial.println(“PM Begin ”);
digitalWrite(PM25_CS, HIGH);
delay(9000); //64 byte buffer only; 7 byte per sample; 64/7=9 max if 1 sec per sample.
while (Serial.available() 》 0) {
do {
incomingByte = Serial.read();
//Serial.print(incomingByte, HEX);
} while (incomingByte != 0xAA);
if (incomingByte == 0xAA) {
Serial.readBytes(buf, 6);
if (buf[5] == 0xFF && (buf[0] + buf[1] + buf[2] + buf[3]) == buf[4]) { //0xFF = term char; checksum
PM2_5Value = ((buf[0] 《《 8) + buf[1]) / 10.0;
PM10Value = ((buf[2] 《《 8) + buf[3]) / 10.0;
}
}
}
//Serial.println(“PM End”);
digitalWrite(PM25_CS, LOW);
pm25[idx] = (float)PM2_5Value;
pm10[idx] = (float)PM10Value;
Serial.print(“PM2.5 = ”); Serial.print(pm25[idx]); Serial.print(“ ”);
Serial.print(“PM10 = ”); Serial.println(pm10[idx]);
步驟9:將CO2傳感器連接到軟件序列
SensorAir S8通過(guò)TTL接口輸出CO2濃度。由于D1 Mini的RX引腳用于PM2.5/PM 10傳感器,因此我們需要使用CO2傳感器的軟件串行。
D1 Mini沒(méi)有太多的引腳。我們幾乎用完了別針。幸運(yùn)的是,我們可以將CO2傳感器的TX和RX引腳連接在一起,并通過(guò)單工模式與之通信。 AirSense S8的數(shù)據(jù)表中沒(méi)有對(duì)此進(jìn)行記錄,但是可以使用!因此,與CO2傳感器通信僅在D1 Mini上消耗了一個(gè)引腳。
到目前為止,我們還沒(méi)有看到來(lái)自Internet的用于SensorAir S8的Arduino庫(kù)。因此,為此目的創(chuàng)建了軟件串行功能。首先,我們需要為ABC周期初始化SensorAir S8。然后,我們可以自動(dòng)從傳感器讀取CO2值。
初始化代碼:
void S8_begin(SoftwareSerialx *ss) {
//byte ch, cmd[] = {0xFE, 0x6, 0x0, 0x1F, 0x0, 0xB4, 0xAC, 0x74}; // Set ABC Period to be 180 hours
//byte ch, cmd[] = {0xFE, 0x6, 0x0, 0x1F, 0x0, 0x30, 0xAC, 0x17}; // Set ABC Period to be 48 hours
byte ch, cmd[] = {0xFE, 0x6, 0x0, 0x1F, 0x0, 0x18, 0xAC, 0x09}; // Set ABC Period to be 24 hours
ss-》enableTx(true);
for (int i = 0; i 《 8; i++)
ss-》write(cmd[i]);
ss-》enableTx(false);
delay(250);
if (ss-》available()) {
Serial.print(“SenseAir Response:”);
while (ss-》available()) {
ch = (byte) ss-》read();
Serial.print(ch 《 0x01 ? “ 0” : “ ”);
Serial.print(ch, HEX);
}
Serial.println();
}
}
讀取代碼:
int S8_getCO2(SoftwareSerialx *ss, uint16_t*S8_CO2, uint16_t*S8_meterstatus) {
int i;
//byte ch, cmd[] = {0xFE, 0x4, 0x0, 0x03, 0x0, 0x1, 0xD5, 0xC5}; //Get CO2 Only
byte ch, cmd[] = {0xFE, 0x4, 0x0, 0x0, 0x0, 0x4, 0xE5, 0xC6}; //Get MeterStatus and CO2
byte result[20];
ss-》enableTx(true);
for (int i = 0; i 《 8; i++)
ss-》write(cmd[i]);
ss-》enableTx(false);
delay(250);
while (!ss-》available()) // wait until data is available
delay(100);
while ( ss-》available()) {
if ( (ch = ss-》read()) == 0xFE) // wait until the header is available
i = 0;
result[i] = ch;
i++;
}
*S8_CO2 = result[9] * 256 + result[10];
*S8_meterstatus = result[3] * 256 + result[4];
return *S8_meterstatus;
}
步驟10:將草圖下載到D1 Mini
將草圖下載到D1 Mini并完成。下載草圖時(shí),請(qǐng)記住要斷開(kāi)PM2.5/PM10傳感器的連接。
步驟11:給電池充電并打開(kāi)
它將首先連接到WiFi,然后發(fā)送NTP數(shù)據(jù)包并獲得Internet時(shí)間。然后,掃描其EEPROM以獲取CCS811的最佳BASELINE設(shè)置。
步驟12:讓它自己運(yùn)行。..
讓它自己運(yùn)行一段時(shí)間。您將看到測(cè)量的圖表和實(shí)時(shí)指標(biāo)!!!
責(zé)任編輯:wv
-
監(jiān)視器
+關(guān)注
關(guān)注
1文章
780瀏覽量
33104 -
ESP8266
+關(guān)注
關(guān)注
50文章
962瀏覽量
44852
發(fā)布評(píng)論請(qǐng)先 登錄
相關(guān)推薦
評(píng)論