該項(xiàng)目是一個(gè)無需任何互聯(lián)網(wǎng)連接即可顯示當(dāng)?shù)卮髿鈮毫Α囟葷穸群妥贤饩€指數(shù)的氣象站。
背景
之前很長一段時(shí)間,我想在不使用互聯(lián)網(wǎng)的情況下制作一個(gè)氣象站,測(cè)量周圍的天氣數(shù)據(jù)并在需要時(shí)查看數(shù)據(jù)。所以,如今我著手做了一個(gè)看起來很酷的當(dāng)?shù)貧庀笳荆梢詼y(cè)量你周圍的氣壓、溫度、濕度和當(dāng)天的紫外線指數(shù)(如果你把它放在窗戶附近)。它還有一個(gè)時(shí)鐘屏幕,用于顯示時(shí)間、日期和星期幾。
在本文中,我將向您展示如何通過這些步驟制作這個(gè)涼爽的氣象站。
第 1 步:構(gòu)建外殼
我使用Autodesk fusion 360創(chuàng)建外殼并用綠色 PLA 打印。它需要支撐,我在我的 Ender 3 上以 70mm/s 的速度以 20% 的填充量打印它。
第 2 步:BMP280
BMP280 是大氣壓力和溫度傳感器,它使用 I2C 或 SPI 協(xié)議與 Arduino 通信。這里我使用 SPI。要使用 SPI,請(qǐng)連接-
CS到D10
SDA 轉(zhuǎn) D11
SDO 到 D12
SCK 到 D13
在代碼部分,要使用這個(gè)傳感器,我們需要一個(gè)庫。首先,我將庫包含在代碼中#include 《Adafruit_BMP280.h》。你可以在本文下方找到跳轉(zhuǎn)。
然后我定義傳感器的 SPI 引腳。在 setup 函數(shù)中,我初始化 BMP 傳感器,在 loop 函數(shù)中,我使用bmp.readPressure()andbmp.readTemperature()命令讀取壓力和溫度數(shù)據(jù)。我將壓力值除以 100 以測(cè)量以 hPa 為單位的壓力。要測(cè)量我使用bmp.readAltitude(1005.47)命令的高度。在這一步,您必須根據(jù)您所在地區(qū)的平均壓力更改值。(1005.47)
第 3 步:DS3231 RTC
這個(gè)氣象站還有一個(gè)時(shí)間屏幕,可以顯示當(dāng)前時(shí)間、日期和星期的日子。為此,我使用了 DS231 RTC 模塊,它使用 I2C 協(xié)議進(jìn)行通信。所以要使用這個(gè),連接 -
SCL 到 A5
SDA 轉(zhuǎn) A4
首先,您必須使用庫示例中的DS3231_set.ino程序在 RTC 上設(shè)置時(shí)間和日期。
在主程序中,我包含庫#include 《DS3231.h》并根據(jù)庫中的指令讀取時(shí)間數(shù)據(jù)。這里我使用庫中的示例作為代碼的參考。我為一周中的每一天創(chuàng)建了一個(gè)案例來查找當(dāng)前日期。
第 4 步:DHT11
我用這個(gè)傳感器來測(cè)量濕度。為此,我將其數(shù)據(jù)連接到 Arduino D2 。在程序中,我包含 DHT 庫,#include 《DHT.h》然后在設(shè)置中初始化傳感器,在循環(huán)中,我使用dht.readHumidity()命令讀取濕度值。
第 5 步:GUVA-S12SD 紫外線傳感器
GUVA-S12SD是基于氮化鎵的肖特基型光電二極管。它具有240-370nm的典型UV檢測(cè)波長(覆蓋UVB和大部分UVA光譜)。它輸出一個(gè)校準(zhǔn)的模擬電壓,該電壓隨紫外光強(qiáng)度而變化。因此,我們可以通過 Arduino ADC 讀取模擬值。
在循環(huán)功能中,我模擬讀取傳感器值并計(jì)算紫外線指數(shù)
float sensorValue = analogRead(A0);
float sensorVoltage = sensorValue / 1024 * 5.0;
int UV_index = sensorVoltage / 0.1;
第 6 步:OLED 顯示屏
我在這個(gè)項(xiàng)目中使用 0.96“ 128*64 OLED 顯示器,它使用 I2C 協(xié)議,所以我將它連接到 Arduino,如下所示 -
SCK 到 A5
SDA 轉(zhuǎn) A4
在程序中,我首先涵蓋了Adafruit_SSD1306和Adafruit_GFX庫
#include 《Adafruit_GFX.h》
#include 《Adafruit_SSD1306.h》
然后我創(chuàng)建顯示變量并添加一些位圖來顯示一些圖像。在設(shè)置中,我初始化了顯示。然后在循環(huán)中,我使用該display.print()函數(shù)顯示每個(gè)數(shù)據(jù)。我在四個(gè)頁面上顯示數(shù)據(jù),時(shí)間、壓力、溫度和濕度以及 UV_index。每頁之間有 5 秒的延遲。
Local weather station code:
#include
#include
然后我創(chuàng)建顯示變量并添加一些位圖來顯示一些圖像。在設(shè)置中,我初始化了顯示。然后在循環(huán)中,我使用該display.print()函數(shù)顯示每個(gè)數(shù)據(jù)。我在四個(gè)頁面上顯示數(shù)據(jù),時(shí)間、壓力、溫度和濕度以及 UV_index。每頁之間有 5 秒的延遲。
Local weather station code:
#include
#include
#include
#include
#include
#include
#include
#include
#include
//#include
#define SCREEN_WIDTH 128
#define SCREEN_HEIGHT 64
#define OLED_RESET 4
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);
#define BMP_SCK (13)
#define BMP_MISO (12)
#define BMP_MOSI (11)
#define BMP_CS (10)
DS3231 clock;
bool century = false;
bool h12Flag;
bool pmFlag;
Adafruit_BMP280 bmp(BMP_CS, BMP_MOSI, BMP_MISO, BMP_SCK);
#define DHTPIN 2
#define DHTTYPE DHT11
DHT dht(DHTPIN, DHTTYPE);
const unsigned char PROGMEM frame0 [] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xFF, 0x80, 0x00, 0x00, 0x0F, 0xFF, 0xF0, 0x00, 0x00, 0x3F, 0xFF, 0xFC, 0x00, 0x00, 0x7F, 0x81, 0xFE, 0x00, 0x00, 0xFC, 0x00, 0x3F, 0x00, 0x01, 0xF0, 0x00, 0x0F, 0x80, 0x03, 0xE0, 0x18, 0x07, 0xC0, 0x07, 0x86, 0x18, 0x61, 0xE0, 0x0F, 0x02, 0x00, 0x40, 0xF0, 0x0F, 0x02, 0x00, 0x40, 0xF0, 0x1E, 0x00, 0x00, 0x00, 0x78, 0x1C, 0x40, 0x00, 0x02, 0x38, 0x3C, 0x61, 0x00, 0x06, 0x3C, 0x3C, 0x01, 0x80, 0x00, 0x3C, 0x38, 0x00, 0x80, 0x00, 0x1C, 0x38, 0x00, 0xC0, 0x00, 0x1C, 0x78, 0x00, 0xE0, 0x00, 0x1E, 0x79, 0xC0, 0xF0, 0x03, 0x9E, 0x79, 0xC0, 0x7C, 0x03, 0x9E, 0x78, 0x00, 0x7E, 0x00, 0x1E, 0x38, 0x00, 0x7E, 0x00, 0x1C, 0x38, 0xFC, 0xFF, 0x3F, 0x1C, 0x3C, 0xFC, 0x7E, 0x3F, 0x3C, 0x3C, 0xFE, 0x7E, 0x7F, 0x3C, 0x1C, 0x7E, 0x18, 0x7E, 0x38, 0x1E, 0x3F, 0x00, 0xFC, 0x78, 0x0F, 0x3F, 0xC3, 0xFC, 0xF0, 0x0F, 0x0F, 0xFF, 0xF8, 0xF0, 0x07, 0x87, 0xFF, 0xE1, 0xE0, 0x03, 0xC1, 0xFF, 0x83, 0xC0, 0x03, 0xF0, 0x3C, 0x0F, 0xC0, 0x01, 0xFC, 0x00, 0x3F, 0x80, 0x00, 0x7F, 0x81, 0xFE, 0x00, 0x00, 0x3F, 0xFF, 0xFC, 0x00, 0x00, 0x0F, 0xFF, 0xF0, 0x00, 0x00, 0x01, 0xFF, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
const unsigned char PROGMEM frame1 [] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x00, 0x7E, 0x00, 0x00, 0x00, 0x00, 0xC3, 0x00, 0x00, 0x01, 0x00, 0x9D, 0x80, 0x00, 0x03, 0x80, 0xB4, 0xE0, 0x00, 0x06, 0x80, 0xA6, 0x80, 0x00, 0x04, 0xC0, 0xA6, 0xE0, 0x00, 0x0C, 0x40, 0xA6, 0xE0, 0x00, 0x08, 0x60, 0xA6, 0x80, 0x00, 0x08, 0x20, 0xA6, 0xE0, 0x00, 0x08, 0x60, 0xA6, 0x80, 0x00, 0x0E, 0xC0, 0xA6, 0xE0, 0x00, 0x03, 0x80, 0xA6, 0x80, 0x00, 0x00, 0x10, 0xA6, 0xC0, 0x00, 0x00, 0x38, 0xA6, 0xE0, 0x00, 0x00, 0x38, 0xA6, 0x80, 0x00, 0x00, 0x6C, 0xA6, 0xE0, 0x00, 0x00, 0x44, 0xA6, 0x80, 0x00, 0x00, 0x6C, 0xA6, 0xE0, 0x00, 0x00, 0x38, 0xA6, 0x80, 0x00, 0x00, 0x00, 0xA6, 0x80, 0x00, 0x00, 0x00, 0xA4, 0xE0, 0x00, 0x00, 0x00, 0xA6, 0x80, 0x00, 0x00, 0x40, 0xA6, 0xE0, 0x00, 0x00, 0xC0, 0xA6, 0x80, 0x00, 0x01, 0xA0, 0xA6, 0xE0, 0x00, 0x01, 0x30, 0xA6, 0xE0, 0x00, 0x03, 0x10, 0xA6, 0x80, 0x00, 0x02, 0x18, 0xA6, 0xE0, 0x00, 0x06, 0x08, 0xA6, 0x80, 0x00, 0x06, 0x08, 0xA6, 0x80, 0x00, 0x02, 0x19, 0xA6, 0xC0, 0x00, 0x03, 0xF3, 0x26, 0x60, 0x00, 0x00, 0xC6, 0x26, 0x30, 0x00, 0x00, 0x0C, 0xE3, 0x10, 0x00, 0x00, 0x09, 0x80, 0x98, 0x00, 0x00, 0x19, 0x00, 0xC8, 0x00, 0x00, 0x13, 0x00, 0x6C, 0x00, 0x00, 0x12, 0x00, 0x6C, 0x00, 0x00, 0x12, 0x00, 0x6C, 0x00, 0x00, 0x12, 0x00, 0x6C, 0x00, 0x00, 0x1B, 0x00, 0x4C, 0x00, 0x00, 0x09, 0x80, 0xC8, 0x00, 0x00, 0x0C, 0xC1, 0x98, 0x00, 0x00, 0x04, 0x7F, 0x30, 0x00, 0x00, 0x06, 0x1C, 0x60, 0x00, 0x00, 0x03, 0x81, 0xC0, 0x00, 0x00, 0x00, 0xFF, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
const unsigned char PROGMEM frame2 [] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x80};
void setup() {
Serial.begin(57600);
if (!display.begin(SSD1306_SWITCHCAPVCC, 0x3C)) {
Serial.println(F("SSD1306 failed"));
}
Wire.begin();
dht.begin();
if (!bmp.begin()) {
Serial.println(F("Problem.bmp"));
while (1) delay(10);
}
display.clearDisplay();
display.setTextColor(WHITE);
display.setTextSize(1);
display.setCursor(0, 9);
display.setFont(&FreeSans9pt7b);
display.println("**** LOCAL ****");
display.setCursor(0, 38);
display.setFont(&FreeMonoBoldOblique12pt7b);
display.println("wather");
display.setCursor(27, 58);
display.println("Station");
display.display();
delay(2000);
bmp.setSampling(Adafruit_BMP280::MODE_NORMAL, /* Operating Mode. */
Adafruit_BMP280::SAMPLING_X2, /* Temp. oversampling */
Adafruit_BMP280::SAMPLING_X16, /* Pressure oversampling */
Adafruit_BMP280::FILTER_X16, /* Filtering. */
Adafruit_BMP280::STANDBY_MS_500); /* Standby time. */
}
void loop() {
//Time
display.clearDisplay();
display.setTextColor(WHITE);
display.setTextSize(1);
display.setCursor(13, 15);
display.setFont(&FreeMonoBoldOblique12pt7b);
display.print(clock.getHour(h12Flag, pmFlag));
display.setCursor(38, 15);
display.println(":");
display.setCursor(50, 15);
display.println(clock.getMinute());
display.setCursor(70, 15);
if (pmFlag) {
display.println(" PM");
} else {
display.println(" AM ");
}
display.setFont(&FreeSans9pt7b);
display.setCursor(20, 60);
display.println(clock.getDate());
display.setCursor(40, 60);
display.println("/");
display.setCursor(46, 60);
display.println(clock.getMonth(century));
display.setCursor(65, 60);
display.println("/");
display.setCursor(70, 60);
display.println("20");
display.setCursor(90, 60);
display.println(clock.getYear());
display.setCursor(30, 30);
display.setFont(&FreeSans9pt7b);
switch (clock.getDoW()) {
case 1:
display.println("Saturday");
break;
case 2:
display.println("Sunday");
break;
case 3:
display.println("Monday");
break;
case 4:
display.println("Tuesday");
break;
case 5:
display.println("Wednesday");
break;
case 6:
display.println("Thursday");
break;
case 7:
display.println("Friday");
break;
}
display.display();
delay(5000);
//P
display.clearDisplay();
display.drawBitmap(0, 0, frame0, 40, 40, 1);
display.setFont(&FreeSans9pt7b);
display.setCursor(41, 28);
display.println(bmp.readPressure() / 100);
display.setCursor(110, 28);
display.setFont();
display.println("hPa");
display.setCursor(0, 55);
display.setFont(&FreeSans9pt7b);
display.println("Altitude:");
display.setCursor(65, 62);
display.println(bmp.readAltitude(1005.47));
display.setCursor(113, 62);
display.println("m");
display.display();
delay(5000);
//T&RH
display.clearDisplay();
display.setFont(&FreeMonoBoldOblique12pt7b);
display.drawBitmap(0, 5, frame1, 40, 51, 1);
display.setCursor(35, 30);
display.print(bmp.readTemperature());
display.setFont(&FreeSans9pt7b);
display.setCursor(102, 28);
display.println(" *");
display.setCursor(110, 31);
display.println(" C");
display.setFont();
display.setCursor(66, 45);
display.println("RH :");
byte RH = dht.readHumidity();
display.setCursor(95, 45);
display.println(RH);
display.setCursor(110, 45);
display.println("%");
display.drawBitmap(0, 56, frame2, 135, 15, 1);
display.display();
delay(5000);
//UV
display.clearDisplay();
float sensorValue = analogRead(A0);
float sensorVoltage = sensorValue / 1024 * 5.0;
int UV_index = sensorVoltage / 0.1;
display.setFont(&FreeSans9pt7b);
display.setCursor(0, 15);
display.print(" UV INDEX ");
display.setCursor(58, 45);
display.println(UV_index);
display.display();
delay(5000);
}
-
氣象站
+關(guān)注
關(guān)注
1文章
761瀏覽量
15757 -
DIY設(shè)計(jì)
+關(guān)注
關(guān)注
2文章
59瀏覽量
19887 -
BMP280
+關(guān)注
關(guān)注
1文章
20瀏覽量
5784
發(fā)布評(píng)論請(qǐng)先 登錄
相關(guān)推薦
【核桃派ZeroW開發(fā)板體驗(yàn)連載】小小氣象站 03 aht10、bmp280測(cè)試
如何使用樹莓派制作小氣象站
分享一個(gè)不錯(cuò)的太陽能WiFi氣象站V2.0的項(xiàng)目
BMP280氣壓傳感器的制作
使用BMP280測(cè)量溫度、壓力和高度
![使用<b class='flag-5'>BMP280</b>測(cè)量溫度、壓力和高度](https://file.elecfans.com/web1/M00/D9/4E/pIYBAF_1ac2Ac0EEAABDkS1IP1s689.png)
使用Arduino的IoT無線氣象站
制作BMP280 ESP32天氣預(yù)報(bào)器
![<b class='flag-5'>制作</b><b class='flag-5'>BMP280</b> ESP32天氣預(yù)報(bào)器](https://file.elecfans.com/web1/M00/D9/4E/pIYBAF_1ac2Ac0EEAABDkS1IP1s689.png)
使用BMP280-DHT11的Arduino氣象站
![使用<b class='flag-5'>BMP280</b>-DHT11的Arduino<b class='flag-5'>氣象站</b>](https://file.elecfans.com/web1/M00/D9/4E/pIYBAF_1ac2Ac0EEAABDkS1IP1s689.png)
Arduino BME280氣象站儀表板
![Arduino BME<b class='flag-5'>280</b><b class='flag-5'>氣象站</b>儀表板](https://file.elecfans.com/web1/M00/D9/4E/pIYBAF_1ac2Ac0EEAABDkS1IP1s689.png)
評(píng)論