Arduino ve kablosuz meteoroloji istasyonu sensörleri. Arduino için BMP085 Barometrik Basınç Sensörü Modülü (veya kendi ellerinizle bir hava istasyonu nasıl yapılır)

  • 05.05.2019
Çoğu çalışan insan gibi, kendi projelerinizi yapmak kalan tek boş zamanı alır. Bu nedenle uzun süre yaratmadım ve bir şeyler yapmak için "ellerimi kaşındım". Bu fırsat üniversitede yeterince garip göründü. Pencerenin dışında 4 Eylül ve devre ile ilgili yaklaşan kurs. Kurs çalışmalarının iki farklı şekilde yapılabileceği söylendi: kağıt ve donanım.

5 yıl boyunca üniversitemizde kağıt kurslar "eskileri al ve bir araya getir" ilkesine göre yapıldı. Bu yaklaşım bana rutin olarak uymuyordu, bu yüzden hemen donanımdaki dersi seçtim. Arduino mikrodenetleyicisi, öğrenme kolaylığı nedeniyle dersin kalbi olarak önerildi. Kursun türünü belirledikten sonra, bir soru daha vardı: tam olarak ne yapılmalı. Mikrodenetleyicileri programlama konusunda tecrübem olmadığı için hemen Google'ı açtım ve mevcut projeleri incelemeye başladım. Pek çok proje var, bazıları oldukça basit, bazıları ustaca (örneğin 3B tarayıcı), ancak büyük çoğunluğunun pratik bir uygulaması yoktu. Ve tam olarak neyin rafta yatıp orada toz toplamayacağını istedim. Arduino dünyasına yarım saatlik bir geziden sonra, evdeki hava istasyonları konusuyla ilgileniyordum ve projeleri uygulamak çok zor görünmüyordu (temelde yeni başlayanlara rüşvet veriyordu).

Dönem ödevi konusu bu şekilde seçildi ve zamanla sorunlar ana hatlarıyla belirtilmemiş gibi görünüyordu.

Bileşen seçimi

Farklı projelere baktığımda Nano'nun hatta Pro Mini'nin benim için yeterli olacağını fark ettim ama yine de Arduino için programlama yapmak istediğimi ve gelecekte daha fazla projeyi hayata geçireceğimi umarak Arduino Uno'yu seçtim. Daha önce ellerimde hiç lehim havyası tutmamıştım, bu yüzden daha kolay geliştirme için Sensor Shield v4'ü de satın almaya karar verdim.

Daha fazla detay

Kart, sensörlerin, modüllerin, servo motorların, Seri ve I2C arayüzlerinin hızlı bir şekilde bağlanmasını kolaylaştırır ve ayrıca Duemilanova / Uno form faktörünün kontrolörünün tüm bağlantı noktalarını görüntüler (mega serisine de bağlanabilir, ancak kısıtlamalar ve ardından gelen sonuçlarla). Diğer kalkanları kendi başına destekler.


Meteorolojik veriler için kaynak olarak aşağıdaki sensörleri seçtim:


Sensörlere karar verdim. Ama sensörlerden gelen verilerle ne yapılmalı. Sergilemeye karar verdim. Renkli bir resim istedim, bu yüzden tek renkli çözümleri hemen attım. Birkaç dakikalık aramanın ardından 1,8 inç ST7735 TFT ekran seçildi.

Daha fazla detay

Ekran, iletişim için 4 telli bir SPI protokolü kullandığından ve kendi piksel adreslenebilir çerçeve arabelleğine sahip olduğundan, her türlü mikro denetleyici ile kullanılabilir. 1,8 inç ekran 128x160 renkli piksellere sahiptir. Ayrıca microSD hafıza kartı için bir yuva vardır, böylece bir microSD kartın FAT16 / FAT32 dosya sisteminden tam renkli bitmap'leri kolayca yükleyebilirsiniz.

Özellikler:

  • Diyagonal ekran - 1,8 inç, çözünürlük 128x160 piksel, 18 bit renk (262,144 renk)
  • Video belleği arabelleğinin yerleşik piksel adreslemesine sahip denetleyici
  • Dahili microSD yuvası - 2'den fazla dijital hat kullanır
  • 3.3 ve 5V ile uyumlu
  • Boyutlar: 34 mm x 56 mm x 6.5 m


Arduino denetleyici programlama

Hava durumu istasyonunun bileşenlerine karar verdikten sonra, kontrolörü programlamaya başlayalım. Arduino IDE, Arduino'yu flaşlamak için kullanıldı. Ayrıca Adafruit'un kütüphanelerini kullandı.

Taslağa geçmeden önce işlevselliği ele alalım:

  • Sensörlerden her 10 saniyede bir okuma alınır ve sadece önceki ölçüme göre değiştirilen göstergeler ekranda güncellenir.
  • COM bağlantı noktası üzerinden uygulanan veri aktarımı

Eskiz

#Dahil etmek // I2C cihazlarıyla iletişim için kitaplık #include // Tüm sensörler için çekirdek kitaplığı #include // BMP180 için kitaplık #include // Çekirdek grafik kitaplığı #include // Donanıma özgü kitaplık #include // SPI cihazları ile iletişim için kütüphane #include "dht.h" // DHT için kütüphane #define DHT22_PIN 2 // DHT22'nin veri pinini 2 dijital pin'e bağlayın #define TFT_CS 10 // TFT'nin CS pinini 10 dijital pin'e bağlayın #define TFT_RST 9 // TFT'nin RST pinini 9 dijital pin'e bağlayın // bunu Arduino sıfırlamasına da bağlayabilirsiniz // bu durumda bu #define pinini 0'a ayarlayın! #define TFT_DC 8 // TFT'nin DC pinini 8 dijital pin'e bağlayın Adafruit_ST7735 tft \u003d Adafruit_ST7735 (TFT_CS, TFT_DC, TFT_RST); // TFT'yi başlatın #define TFT_SCLK 13 // TFT'nin SCLK pinini 13 dijital pin'e bağlayın #define TFT_MOSI 11 // TFT'nin MOSI pinini 11 dijital pin dht DHT'ye bağlayın; Adafruit_BMP085_Unified bmp \u003d Adafruit_BMP085_Unified (10085); // BMP180 int bmpFlag \u003d 0; struct (uint32_t toplam; uint32_t ok; uint32_t crc_error; uint32_t zaman_aşımı; uint32_t bağlan; uint32_t ack_l; uint32_t ack_h; uint32_t bilinmiyor;) stat \u003d (0,0,0,0,0,0,0,0,0); // dht status void setup (void) için yapı (Serial.begin (9600); Serial.println ("Meteo Test"); Serial.println (""); if (! bmp.begin ()) // bağlantıyı kontrol et BMP180 için (Serial.print ("Hata, BMP180 algılanmadı ... Kablo bağlantılarınızı veya I2C ADDR'ınızı kontrol edin!"); bmpFlag \u003d 1;) tft.initR (INITR_BLACKTAB); // TFT'yi başlatın ve siyah renkli tft.fillScreen ile doldur (ST7735_BLACK); tft.setRotation (tft.getRotation () + 1); tft.setTextSize (1.5); delay (500); // TFT'nin başlatıldığından emin olmak için gecikme) // son ölçülen veri float oldTemperature \u003d 0 , oldAltitude \u003d 0, oldPressure \u003d 0, oldDHTHumidity \u003d 0, oldDHTTemperature; bool wasUpdate \u003d yanlış; void loop (void) (if (Serial.available ()\u003e 0) // verimiz Serial port (Serial.read (); // seri porttan baytı oku ve son ölçülen veriyi gönder printValue ("Pressure", oldPressure) , "hPa", false); printValue ("Temperature", oldTemperature, "C", false); printValue ("Rakım", oldAltitude, "m", false); printValue ("Nem", eskiDHTHumidity, "%", false); printValue ("DHT_temperature", oldDHTTemperature, "C", false); Serial.println ("END_TRANSMISSION");) sensor_event_t olayı; float sıcaklığı, altitude; if (bmpFlag \u003d\u003d 0) (bmp.getEvent (& event) ; // BMP180'den veri al if (event.pressure) (bmp.getTemperature (& temperature); float seaLevelPressure \u003d SENSORS_PRESSURE_SEALEVELHPA; altitude \u003d bmp.pressureToAltitude (seaLevelPressure, event.pressure, temperature);) else (Serial.println ("Sensör) error ");)) uint32_t start \u003d micros (); int chk \u003d DHT.read22 (DHT22_PIN); // DHT22'den veri al uint32_t stop \u003d micros (); stat.total ++; switch (chk) // durumunu kontrol et DHT22 (durum DHTLIB_OK: stat.ok ++; kırmak; durum DHTLIB_ERROR_CHECKSUM: stat.crc_error ++; Seri.print ("Sağlama toplamı hatası, \\ t"); kırmak; durum DHTLIB_ERROR_TIMEOUT: stat.time_out ++; Seri.print ("Zaman aşımı hatası, \\ t"); kırmak; durum DHTLIB_ERROR_CONNECT: stat.connect ++; Serial.print ("Bağlantı hatası, \\ t"); kırmak; durum DHTLIB_ERROR_ACK_L: stat.ack_l ++; Serial.print ("Ack Low hatası, \\ t"); kırmak; durum DHTLIB_ERROR_ACK_H: stat.ack_h ++; Serial.print ("Ack High hatası, \\ t"); kırmak; varsayılan: stat.unknown ++; Serial.print ("Bilinmeyen hata, \\ t"); kırmak; ) eğer (bmpFlag! \u003d 0 || ! event.pressure) // verileri güncelle (tft.fillRect (0, 30, 160, 6, ST7735_BLACK); tft.setCursor (0, 30); tft.setTextColor (ST7735_RED); printValue ("ERROR BMP INITIALIZATION", 0 , "", true);) else (if (event.pressure! \u003d oldPressure) (tft.fillRect (0, 30, 160, 7, ST7735_BLACK); tft.setCursor (0, 30); tft.setTextColor (ST7735_RED) ; printValue ("Pressure", event.pressure, "hPa", true); oldPressure \u003d event.pressure; wasUpdate \u003d true;) if (temperature! \u003d oldTemperature) (tft.fillRect (0, 38, 160, 7, ST7735_BLACK ); tft.setCursor (0, 38); tft.setTextColor (ST7735_WHITE); printValue ("Sıcaklık", sıcaklık, "C", doğru); oldTemperature \u003d sıcaklık; wasUpdate \u003d true;) if (altitude! \u003d oldAltitude) ( tft.fillRect (0, 46, 160, 7, ST7735_BLACK); tft.setCursor (0, 46); tft.setTextColor (ST7735_BLUE); printValue ("Rakım", rakım, "m", true); oldAltitude \u003d rakım; wasUpdate \u003d true;)) if (DHT.humidity! \u003d oldDHTHumidity) (tft.fillRect (0, 54, 160, 7, ST7735_BLACK); t ft.setCursor (0, 54); tft.setTextColor (ST7735_GREEN); printValue ("Nem", DHT.humidity, "%", true); oldDHTHumidity \u003d DHT.humidity; wasUpdate \u003d true; ) eğer (DHT.temperature! \u003d eskiDHTTemperature) (tft.fillRect (0, 80, 160, 7, ST7735_BLACK); tft.setCursor (0, 80); tft.setTextColor (ST7735_YELLOW); printValue ("DHT_temperature", DHT. sıcaklık, "C", doğru); eskiDHTTemperature \u003d DHT.temperature; wasUpdate \u003d true;) if (wasUpdate) (Serial.println ("END_TRANSMISSION");) wasUpdate \u003d false; gecikme (10000); ) void printValue (char * title, double value, char * measure, bool tftPrint) (if (tftPrint) // veriyi TFT'ye yazdır (tft.print (title); tft.print (":"); tft.print ( değer); tft.println (ölçü);) Serial.print (title); // Serial.print'e veri gönder (":"); Serial.print (değer); Serial.println (ölçü);)

Davayı bir araya getirme zamanı

Kurs çalışmasının ana koşulu, prezentabl formda çalışan bir prototipti. Bu nedenle, bir dava satın almak zorunda kaldım ve bir dosyayla donanmış olarak, hava istasyonunu herhangi bir şekilde çantaya sokmak zorunda kaldım.

Yerel bir elektronik mağazasından konut satın alındı.

Konut

(Fotoğrafta durum biraz farklı. Şeffaf kapağım var)



Ardından, bir dosya kullanarak sensörlerin çıkışını yapmak ve güç sağlamak için delikler açıldı. Sensörleri dışarı çıkarmaya karar verdim, çünkü sistemi kılıfsız test ederken ekranın arkasının çok ısındığını ve bunun kasanın içindeki sıcaklığı etkileyeceğini fark ettim.

Sensörler ve güç için delikli muhafaza



Bacakları 2 sensöre lehimlemek zorunda olduğum ve bunlardan birinin üzerindeki izi yaktığım için, kaderi kışkırtmamaya ve telleri sensörlere lehimlememeye karar verdim (başka bir şey üzerinde çalışacağım) ve bağlantının az çok güvenilir olması için geri sarmaya karar verdim elektrik bandı.

Muhafazaya "itmeden" önce sistem



Kasa Arduino'dan çok daha büyük olduğu için (daha küçük olanı yoktu), kartın kasanın içinde dolaşmaması için bir destek bulmam gerekiyordu. Ayrıca, kasanın içini gizlemek için paralondan bir figür ve içinde ekran için bir dikdörtgen kesildi. Elimde süper yapıştırıcı yoktu, bu yüzden çift taraflı bant üzerine oturmak zorunda kaldım.

Wonder Yuda balina balığı



Kapağı kapatıyoruz, güç kaynağını bağlıyoruz ve bekliyoruz.

Binadaki bitmiş hava durumu istasyonu



Sonuçları ekranda görüntüledikten sonra, nem ölçümünde hoş olmayan bir hata ortaya çıkardık: DHT22 kesinlikle% 99.90 rakamını veriyor (% 1.00 için oldukça nadirdir). Sorunun ne olduğunu anlamaya başlarız. İlk yaptığımız şey, değerlerin COM portuna çıkışına bakmaktır. İyi hissettiriyor. Kasanın birkaç kez yeniden doldurulmasından, demontajından ve montajından sonra, Google'da bir cevap aramak için düşünce aklıma geliyor. Beklendiği gibi, Rus Google etkili bir şey söylemedi. Tamam. İngilizce aramaya başladık ve forumlardan birinde benzer bir sorunu olan erkeklerle karşılaşıyoruz. Tartışmanın ilk dört sayfası pratik bir şey vermiyor, ancak beşinci sayfada sorumuzun cevabını buluyoruz:
Nem sensörleri, yanlış gazlardan veya yüksek nemli IIRC'ye çok uzun süre maruz kalmadan kolayca etkilenebilir. Veri sayfasında sensörün nasıl "sıfırlanacağı" ile ilgili bir prosedür vardır, deneyebilirsiniz.

Tek soru DHT22'ye ne zaman ve nasıl zarar vermeyi başardığımdı. Ama ders almanın zamanı gelmişti ve bu yüzden bu sorunun çözümünü daha sonraya bıraktım.

Sonsöz

Kurs başarılı oldu. Meteoroloji istasyonu, üniversitedeki tüm kuyruklar kapanana kadar süresiz olarak ertelendi. Ancak, tahmin ettiğimden daha erken meteoroloji istasyonuna dönmek zorunda kaldık. Öyle oldu ki, Kasım ayı ortasında iş yerimi değiştirdim ve yeni ekipte Arduino platformu ve benzerleriyle ilgilenen insanlarla tanıştım. Bu nedenle, bu platforma olan ilgim, soğumaya zamanım olmadığı için tekrar alevlendi. Hava istasyonumu çıkardım, bir bilgisayara bağladım ve COM portu üzerinden Arduino'dan veri aktarımı yaptığımı hatırladım. Ve sonra Arduino'dan COM portu üzerinden veri alan ve bu verileri kamusal izlemeye aktaran bir program yazma fikrini aldım.
  • Arduino
  • Etiket ekle

    Sistemin ayrı parçalarını bir Arduino UNO'da test ettim. Şunlar. ESP modülünü UNO'ya bağladım ve inceledim, bağlantısını kestim, sonra nRF24'ü bağladım vb. Sensörün pencere dışındaki son uygulaması için minyatür olanlardan Uno'ya en yakın olan Arduino Pro Mini'yi seçtim.



    Güç tüketimi açısından Arduino Pro Mini de iyi görünüyor:

    • tek başına çok "yiyen" bir USB-TTL dönüştürücü yoktur,
    • lED, 10k'lık bir direnç üzerinden bağlanır.

    Gelişmiş enerji tasarrufu için planlandı:

    • arduino Pro Mini üzerindeki LED - güç göstergesini çıkarın (kartı bozmadığım için pişman oldum)
    • veya bir Atmel ATmega328 mikroişlemci üzerinde "çıplak" bir montaj kullanın (kullanılmıyor)
    • düşük Güç Kitaplığını veya JeeLib'i kullanın.

    Düşük Güç Kitaplığını kütüphanelerden seçtim, basit ve sadece gerekli olanı içeriyor.


    Merkezi ünite için çok sayıda çevre biriminin bağlanması planlandığı için Arduino Mega kartı seçildi. Ek olarak, tamamen UNO uyumludur ve daha fazla belleğe sahiptir. İleriye baktığımda, bu seçimin tamamen haklı olduğunu söyleyeceğim.


    Arduino Mega'yı yaklaşık 8 dolara satın alabilirsiniz.

    Güç ve enerji tüketimi

    Şimdi güç ve enerji tüketimi hakkında.


    Arduino Pro Mini'nin iki çeşidi vardır:

    • 5V besleme gerilimi ve 16MHz frekans için
    • 3.3V besleme voltajı ve 8MHz frekans için.

    NRF24L01 + radyo modülü güç kaynağı için 3,3 V gerektirdiğinden ve burada performans önemli olmadığından, 8MHz ve 3.3V'de bir Arduino Pro Mini satın alın.


    Bu durumda, Arduino Pro Mini'nin besleme voltajı aralığı:

    • 3,3V model için 3,35-12V
    • 5V model için 5-12V.

    Zaten 5V Arduino Pro Mini'm vardı, bu yüzden kullandım. Arduino Pro Mini'yi yaklaşık 4 dolara satın alabilirsiniz.


    Merkezi ünite, çıkışta 12V, 450mA, 5W sağlayan küçük bir güç kaynağı ünitesi aracılığıyla 220 V'luk bir ağdan beslenecektir. 5 dolara böyle. Ayrıca 5V için ayrı bir çıkış vardır.



    Ve bu yeterli değilse, o zaman daha güçlü koyabilirsiniz. Diğer bir deyişle, merkezi ünite için güç tasarrufu yapmak pek mantıklı değil. Ancak uzak bir kablosuz sensör için enerji tasarrufu en önemli kısımdır. Ama ben de işlevselliği kaybetmek istemem.


    Bu nedenle, Arduino Pro Mini ve nRF24 radyo modülü, 4 Ni-Mh pil paketi ile çalıştırılacaktır.


    Ve Hatırla modern bir pilin maksimum kapasitesi yaklaşık 2500-2700mAh, bunların hepsi ya pazarlama hileleri (Ansmann 2850) ya da aldatma (UltraFire 3500).


    Li-Ion pilleri birkaç nedenden dolayı kullanmıyorum:

    • çok pahalı
    • ortam sıcaklığı 0 ° C'nin altına düştüğünde, lityum iyon pilin gücü% 40-50'ye düşer
    • ucuz olanlar korumasız üretilir ve güvensizdir (kısa devre veya deşarj ile patlayabilir ve yanabilir, YouTube'da bir sürü video görebilir)
    • kullanılmasalar bile yaşlanırlar (ancak bu tüm kimyasal elementler için söylenebilir), 2 yıl sonra Li-Ion pil kapasitesinin yaklaşık% 20'sini kaybeder.

    Bir prototip için, yüksek kaliteli Ni-MH AA veya AAA pillerle idare etmek oldukça mümkündür. Dahası, büyük akımlara ihtiyacımız yok. Ni-MH pillerin tek dezavantajı uzun şarj süreleridir.

    Meteoroloji istasyonunun genel şeması

    Özetleyelim. İşte nasıl çalıştığına dair genel bir taslak.



    Devam edecek.

    Etiketler: Etiket Ekle

    Meteoroloji istasyonumuzu geliştirmeye devam ediyoruz.

    Güncellemeye geçmeden önce biraz açıklığa kavuşturmak istiyorum.

    Meslektaşlarımızdan biri bana bekçi köpeğinin neden tanıtıldığını sordu.

    Bekçi köpeği zamanlayıcısı acil durumda çalışır. Pratikte görüldüğü gibi, ENC28J60 aynı anda 4 bağlantı daha fazla çekmez (bellekte başarısız olmazsa). Ağın kendisinin işleyişini sürdürmek için kaç tane servis bağlantısı olduğunu ve sadece her türden ev oyuncağının yarattığı sol trafiği (örneğin, modern TV'ler ağdaki mevcut ana bilgisayarları tarar ve onlar için bağlantı noktalarını açar) göz önüne alındığında, tasarım basitçe bir sersemlik haline gelir. ENC28J60, ağ protokolleriyle nasıl bağımsız olarak çalışılacağını bilmez ve her şey kitaplıklarda uygulanır. Belki de onların içindedir.
    Mevcut tüm kütüphaneleri ve farklı modülleri (aniden bir evlilik) kontrol ettim, ancak uzun süre istikrarlı bir çalışma yapamadım. Maksimum süre yaklaşık 3-4 haftadır.
    Bunun için "köpek" orada dönüyor ve bu durumda kontrolör çekiliyor. Bundan sonra sorun ortadan kalktı.
    Ayrıca, ev ağımda belirli nüanslar veya sorunlar olabileceğini de inkar etmiyorum. Ama bir sorunum olduğu için başka biriyle ortaya çıkabilir. Şimdiye kadar sadece böyle bir çözüm buldum.
    Bildiğim kadarıyla, Wiznet çipleri (W5100 ve üstü) buna sahip değil ya da kötü görünüyorlardı.

    Güncellemeye geçme

    En önemlisi, çipi bırakıyoruz ENC28J60ve git W5100... Her şeyi eski bir yonga üzerinde uygulamaya çalıştım, ancak çok büyük kitaplıklar nedeniyle yeterli mikro denetleyici belleği yok. ENC28J60... Yeni bir çip kullanırken standartkütüphaneler geliştiriciden ve yapılan tüm değişikliklerden, daha da fazlası var 20% ücretsiz mikro denetleyici belleği ATMega328... Ve bu, yeni çörekler!

    Bu sürüm (buna ikinci diyelim), frekansı kullanarak sensörlerden kablosuz olarak okuma iletme yeteneği ekledi. 433 MHz... Modülleri kendileri Çinlilerden aldım. XY-MK-5V... İletim kalitesinin mükemmel olmaktan uzak olduğunu belirtmek isterim. Sinyal kaybı, gürültü, aynı anda iletilememe vb. Mümkündür. Ancak fiyatları (set başına 1 dolardan az) bu dezavantajları telafi ediyor. Bu (en ucuz) modüllerin ev kullanımı için birçok markalı hava istasyonunda bulunduğunu size bir sır olarak anlatacağım. Vay canına, beklenmedik mi?

    Baz istasyonundan başlayalım

    Taşınıyoruz Arduino UNO ve Ethernet Kalkanı (ilk sürüm) çip tabanlı W5100... Bu bir sandviç ve onu tarif etmenin bir anlamı yok. Modüller için yalnızca ek olarak kullanılan kişileri açıklayacağım XY-MK-5V.

    Verici modülü güç kullanıyor 5V, GND (o zaman annesiz nerede) ve D2 denetleyicideki pin. Kişiyi değiştir D2 (VERİ) işlevi kullanabilirsiniz vw_set_tx_pin vw kütüphanesinden.

    Önceki taslaktan farklı olarak, bu iki ek kitaplık içerir:

    #Dahil etmek #Dahil etmek

    Çizimin kendisi

    Gizli metin

    #Dahil etmek #Dahil etmek #Dahil etmek #Dahil etmek #Dahil etmek #Dahil etmek #Dahil etmek #Dahil etmek #define DHTTYPE DHT22 #define DHTPIN 5 DHT dht (DHTPIN, DHTTYPE); bayt mac \u003d (0x54, 0x34, 0x31, 0x31, 0x31, 0x31); char server \u003d "narodmon.ru"; int bağlantı noktası \u003d 8283; IPAdresi ip (192,168,0,201); EthernetClient istemcisi; BMP085 dps \u003d BMP085 (); uzun Sıcaklık \u003d 0, Basınç \u003d 0; şamandıra H, dP, dPt; bool aralığı \u003d true; EasyTransferVirtualWire ET; struct SEND_DATA_STRUCTURE (bayt kimliği; // Cihaz Kimliği int Sıcaklık; // Sıcaklık şamandıra Basıncı; // Basınç şamandırası Nem; // Nem şamandıra çiy noktası; // Çiğ / donma noktası); SEND_DATA_STRUCTURE yayını; void setup () (// Watchdog zamanlayıcısını başlatın wdt_disable (); delay (8000); wdt_enable (WDTO_8S); // Konsolu başlatın Serial.begin (9600); // DHT sensörünü başlatın dht.begin (); // 433 MHz modülü ET.begin (ayrıntılar (yayın)); vw_set_ptt_inverted (true); vw_set_tx_pin (2); vw_setup (2000); // DHCP sunucusundan veri beklemediysek ağı başlatın, o zaman // kendimize bir adres atayın if (Ethernet.begin (mac) \u003d\u003d 0) Ethernet.begin (mac, ip); // 1-Wire Wire.begin (); delay (200); // BMP180'i yükseklik düzeltme ile başlat // dps.init (MODE_STANDARD, 3200, true); // BMP180 dps.init (); Serial.println (Ethernet.localIP ()); // İlk veriyi, cihazı açtıktan hemen sonra gönder send_info (true);) // dewPoint fonksiyonu NOAA / / referans (1): http://wahiduddin.net/calc/density_algorithms.htm // referans (2): http://www.colorado.edu/geography/weather_station/Geog_site/about.htm double dewPoint (çift santigrat, çift nem) (// (1) Doygunluk Buhar Basıncı \u003d ESGG (T) çift ORAN \u003d 373.15 / (273.15 + santigrat); çift \u200b\u200bRHS \u003d -7.90298 * (ORAN - 1); RHS + \u003d 5.02808 * log10 (ORAN); RHS + \u003d -1.3816e-7 * (pow (10, (11.344 * (1 - 1 / ORAN))) - 1); RHS + \u003d 8.1328e-3 * (pow (10, (-3.49149 * (ORAN - 1))) - 1); RHS + \u003d log10 (1013.246); // faktör -3 birimleri ayarlamaktır - Buhar Basıncı SVP * nem çift VP \u003d pow (10, RHS - 3) * nem; // (2) DEWPOINT \u003d F (Buhar Basıncı) double T \u003d log (VP / 0.61078); // temp var return (241.88 * T) / (17.558 - T); ) void send_info (bool eth) (bool fail \u003d true; while (fail) (// Bir sonuç alana kadar DHT nem sensöründen veri okumaya çalışırız. Vakaların% 90'ında her şey yolunda gider, ancak 100'e ihtiyacımız var % if ((H \u003d dht.readHumidity ())\u003e \u003d 0) (// BMP180 sensöründen nem ve sıcaklık alınıyor dps.getPressure (& Pressure); dps.getTemperature (& Temperature); // Sıcaklık dışarıdaysa çiğ noktasını hesapla 0 santigrat derecenin üzerinde // ve 0'ın üzerinde bir sonuç bekliyoruz, aksi takdirde 0 çıktı. Kış mevsiminde // yanılmamak için bu gereklidir. // dP \u003d Sıcaklık\u003e 0? ((dPt \u003d çiy noktası (Sıcaklık * 0.1, H))<0?0:dPt):0; dP = dewPoint(Temperature*0.1, H); // Отправляем данные в эфир 433 мГц broadcast.ID = 1; broadcast.Temperature = floor(Temperature*0.1); broadcast.Pressure = floor(Pressure/133.3*10)/10; broadcast.Humidity = floor(H*10)/10; broadcast.dewPoint = floor(dP*10)/10; ET.sendData(); delay(250); if(eth) { // Подключаемся к серверу "Народный мониторинг" if(client.connect(server, port)) { // Начинаем передачу данных // адрес_устройства_в_проекте, имя_устройства, GPS широта, GPS долгота client.print(F("#fe-31-31-0e-5a-3b#Arduino Uno#71.344699#27.200014\n")); // Температура client.print(F("#T0#")); client.print(Temperature*0.1); client.print(F("#Температура\n")); // Давление client.print("#P1#"); client.print(Pressure/133.3); client.print(F("#Давление\n")); // Влажность client.print("#H1#"); client.print(H); client.print(F("#Влажность\n")); // Точка росы\инея client.print("#T1#"); client.print(dP); client.print((dP <= 0)? F("#Точка инея\n"):F("#Точка росы\n")); //client.print(F("#Точка росы\n")); // Отправляем конец телеграммы client.print("##"); // Даем время отработать Ethernet модулю и разрываем соединение delay(250); client.stop(); } } // Останавливаем цикл, если передача завершена fail = !fail; break; } delay(250); } } void loop() { // Каждые 4 секунды сбрасываем сторожевой таймер микроконтроллера // Каждые 6 минут отправляем данные на "Народный мониторинг" // Каждые 30 секунд отсылаем данные в эфир 433 if(!(millis()%1000)) wdt_reset(); if(!(millis()%360000)) send_info(true); if(!(millis()%30000)) send_info(false); }

    Modüllere bir anten eklenmelidir. İçin 433 MHz yeterince uzun sıradan bir bakır tel 17 santimetre... Anten olmadan normal çalışmayı unutabilirsiniz.

    Bu güncellemenin en önemli kısmına geçiyoruz - yerel kablosuz istasyon

    Bunu uygulamak için (dizime) bir analog kullandım Arduino NANO (tabanda ATMega328) ve TFT çipte göster ST7735S izinle 128 x 160

    Gizli metin



    Pin çıkışı ekran -\u003e kontrolör

    \u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d LED | 3.3V SCK | SCK (13) SDA | MOSI (11) A0 | DC (9) SIFIRLA | RST (8) CS | CS (10) GND | GND VCC | 5V \u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d

    Alıcı modülü, yalnızca vericiyle aynı şekilde bağlanır. VERİ sabitlemek D7.

    Nasıl göründüğüne dair birkaç resim:

    Gizli metin

    Alıcı çizimi

    Gizli metin

    #Dahil etmek #Dahil etmek #Dahil etmek #Dahil etmek int x, y; int w \u003d 128, h \u003d 160; int boyutu; // 433 EasyTransferVirtualWire ET; struct SEND_DATA_STRUCTURE (bayt kimliği; // Cihaz Kimliği int Sıcaklık; // Sıcaklık şamandıra Basıncı; // Basınç şamandırası Nem; // Nem şamandıra çiy noktası; // Çiğ / donma noktası); SEND_DATA_STRUCTURE yayını; int Log_Temperature \u003d -1; float Log_Pressure \u003d -1; float Log_Humidity \u003d -1; float Log_dewPoint \u003d -1; // TFT #define cs 10 #define dc 9 #define ilk 8 karakter Sıcaklık, Basınç, Nem, çiy noktası; Dize bilgisi; TFT TFT ekranı \u003d TFT (cs, dc, rst); void setup () (Serial.begin (9600); // 433 MHz modülünü ET.begin (ayrıntılar (yayın)) başlatın; vw_set_ptt_inverted (true); vw_set_rx_pin (7); vw_setup (2000); vw_rx_start (); // Başlat ve ilk görüntü ayarı TFTscreen.begin (); TFTscreen.setRotation (2); TFTscreen.background (0, 0, 0); // Statik öğeler çizin // 1. Bizi ziyaret edin TFTscreen.stroke (255, 255, 255); TFTscreen.setTextSize (1); TFTscreen.text ("", 10, 10); // 2. Sensörlerden gelen okumaların açıklaması TFTscreen.text ("mmHg", w / 2 + 5, 80); TFTscreen.text ("%", w / 2 + 5, 100); TFTscreen.text ("C", w / 2 + 5, 120); yayın.Temperature \u003d 0; yayın.Basınç \u003d 0; yayın.Nem \u003d 0; yayın .dewPoint \u003d 0; TFTPrint ();) void loop () (if (ET.receiveData ()) (if (broadcast.ID \u003d\u003d 1) TFTPrint (); / * Serial.println (yayın.Temperature); Seri. println (broadcast.Pressure); Serial.println (broadcast.Humidity); Serial.println (broadcast.dewPoint); Serial.println (); * /)) void değişiklikleri (int boyut, int x , int y, bool up, bool clear \u003d false) (if (temizle) TFTscreen.stroke (0, 0, 0); else (değişiklikler (boyut, x, y,! yukarı, doğru); TFTscreen.stroke ((yukarı)? 0: 255, 0, (yukarı)? 255: 0);) if ((boyut% 2) \u003d\u003d 0 ) boyut ++; while (size\u003e 0) (TFTscreen.line (x, y, x + (size--), y); ++ x, (up)? - y: ++ y, --size;) / * while ( boyut\u003e 0) (TFTscreen.line (x, y, (yukarı)? x + boyut-1: x, (yukarı)? y: y + boyut-1); ++ x, ++ y, --size; ) * /) int x_center (int w, int length, int size) (return floor ((w-length * (size * 5) + size * 2) / 2);) int x_alignment_right (int w, int length, int size) (return ceil (w-uzunluk * (size * 5) + size * 2);) void TFTPrint () (size \u003d 3; // \u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d \u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d \u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d // Sıcaklık okumalarını görüntüleme // \u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d \u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d \u003d\u003d\u003d\u003d if (broadcast.Temperature! \u003d Log_Temperature) (TFTscreen.setTextSize (size); // Eski verileri sil String info \u003d String (Log_Temperature); info.concat ("C"); if (Log_Temperature\u003e 0) info \u003d "+" + bilgi; info.toCharArray (Sıcaklık, bilgi.uzunluk () + 1); TFTscreen.stroke (0, 0, 0); TFTscreen.text (Sıcaklık, x_center (w, bilgi.length () + 1 , boyut), 35); // Yeni okumaları görüntüle i info \u003d Dize (yayın. Sıcaklık); info.concat ("C"); eğer (yayın.Sıcaklık\u003e 0) bilgi \u003d "+" + bilgi; info.toCharArray (Sıcaklık, bilgi.uzunluk () + 1); // Sıcaklığın kendisine bağlı olarak sıcaklık değerinin rengini değiştirin int r, g \u003d 0, b; if (yayın.Sıcaklık\u003e 0) (r \u003d harita (yayın.Sıcaklık, 0, 40, 255, 150); // Kırmızı b \u003d harita (yayın.Sıcaklık, 0, 40, 30, 0); // Tonu değiştir sıfırdan daha görsel bir geçiş için) else (r \u003d map (yayın.Sıcaklık, -40, 0, 0, 30); // Sıfırdan daha görsel bir geçiş için tonu değiştirin b \u003d harita (yayın.Sıcaklık, -40, 0, 150, 255); // Mavi) TFTscreen.stroke (b, g, r); // UYARI: kitaplıkta renk konumları karıştırılır, RGB alanı BGR tarafından kullanılır! TFTscreen.text (Sıcaklık, x_center (w, info.length () + 1, size), 35); ) boyut \u003d 1; // \u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d \u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d // Basınç okumalarının göstergesi // \u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d \u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d \u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d if (broadcast.Pressure! \u003d Log_Pressure) (TFTscreen.setTextSize (size); // Eski verileri sil info \u003d String (Log_Pressure ); info.toCharArray (Pressure, info.length ()); TFTscreen.stroke (0, 0, 0); TFTscreen.text (Pressure, x_alignment_right (w / 2-5, info.length (), size), 80 ); // Yeni okumaları görüntüle info \u003d String (broadcast.Pressure); info.toCharArray (Pressure, info.length ()); TFTscreen.stroke (255, 255, 255); TFTscreen.text (Pressure, x_alignment_right (w / 2-5, info.length (), size), 80); değişiklikler (10, 106, 85, (broadcast.Pressure\u003e Log_Pressure)? True: false);) else (değişiklikler (10, 106, 85, true, doğru); değişiklikler (10, 106, 85, yanlış, doğru);) // \u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d \u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d \u003d // Nem okumalarını görüntüleyin // \u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d \u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d \u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d if (broadcast.Humidity! \u003d Log_Humidity) (TFTscreen.setTextSize (size); // Eski verileri sil info \u003d String (Log_Humidity); info.toCharArray (Nem, bilgi.uzunluk ()); TFTscreen.stroke (0, 0, 0); TFTscreen.text (Nem, x_alignment_right (w / 2-5, bilgi.length (), boyut), 100); // Yeni okumaları yazdır info \u003d String (broadcast.Humidity); info.toCharArray (Nem, bilgi.uzunluk ()); TFTscreen.stroke (255, 255, 255); TFTscreen.text (Nem, x_alignment_right (w / 2-5, bilgi.length (), boyut), 100); değişiklikler (10, 106, 105, (yayın.Nem\u003e Log_Humidity)? true: false); ) else (değişiklikler (10, 106, 105, doğru, doğru); değişiklikler (10, 106, 105, yanlış, doğru);) // \u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d \u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d \u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d // Çiy / don noktalarını görüntüleme // \u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d \u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d \u003d\u003d\u003d\u003d\u003d\u003d if (broadcast.dewPoint! \u003d Log_dewPoint) (TFTscreen.setTextSize (size); // Eski verileri sil info \u003d String (Log_dewPoint); info.toCharArray (dewPoint, info.length ()); TFTscreen.stroke (0, 0, 0); TFTscreen.text (dewPoint, x_alignment_right (w / 2-5, info.length (), size), 120); // Yeni okumaları görüntüleme info \u003d String (broadcast.dewPoint); info.toCharArray (dewPoint, info.length ()); TFTscreen.stroke (255, 255, 255); TFTscreen.text (dewPoint, x_alignment_right (w / 2-5, info.length (), size), 120); değişiklikler (10, 106, 125, (broadcast.dewPoint\u003e Log_dewPoint)? True: false);) else (değişiklikler (10, 106, 125, true, true); değişiklikler (10, 106, 125, false, true);) // Okumaların sonraki karşılaştırması için günlüklerdeki değerleri güncelleyin Log_Temperature \u003d yayın.Sıcaklık; Log_Pressure \u003d broadcast.Pressure; Log_Humidity \u003d yayın. Nemlilik; Log_dewPoint \u003d broadcast.dewPoint; )

    Göstergeler oldukça kısa bir şekilde sergileniyor, ancak uygulamanın gösterdiği gibi (ve yoldaşlarımın tavsiyesi) - "zevk ve renkte, karım bile arkadaş değil." Bir dizi tavsiye ve öneriyi dinledim, ancak birbirleriyle çelişiyorlar. Öyleyse beğeninize göre yapın.

    Bana öyle geldi ki, tasarım, projenin çoğu zaman alan kısmı!

    Gizli metin

    Verilerin bir kısmı, bazı tasarım öğelerini göstermek için üretilmiştir.

    Ekrandaki artefaktlar, ekranın içinde uzun süre biriken toz ve diğer kirlerdir ... orada bir yerde, ... peki, nereden aldığımı hatırlamıyorum! Beni yalnız bırak!

    Çizim, konumlandırma işlevlerine sahiptir. Oldukça ilkeldirler, ancak belirli etkilere ulaşabilirler.

    1. x_center
    2. x_alignment_right

    Birincisi metni ortalar ve ikincisi onu belirtilen alanın sağına hizalar. Tüm hesaplamalar, ifadeye göre belirtilen metnin boyutuna göre gerçekleştirilir. 1 boyut \u003d 1PX x 1PX yazı tipinin bölümü.

    Ekran ayrıca okumaların bu veya değerinin artması veya azalmasına karşılık gelen öğeleri de gösterir. Üçgen olarak gösterilirler. Ama fonksiyon kodunda değişiklikler45 derece döndürülmüş üçgen şeklinde alternatif bir ekran var. Okuma yükselirse, öğe kırmızı, aksi takdirde mavidir.

    Bu arada, ana sıcaklığın rengi ve gölgesi, sıcaklığın kendisine bağlı olarak değişir. Oldukça tartışmalı bir karar, ama bence görsel olarak rahat. Bir süre bunun için savaştım ve fonksiyondaki değerlerin inme, TFT görüntüleme nesneleri yanlış sırada listeleniyor. BGR bir yer RGB... Bu bir geliştiricinin hatası veya anlamadığım bir şey.

    PS: Her şey oldukça ilginç ama bence daha fazla gelişmeyi hak ediyor. Bir süre sonra ne yapacağız?

    Şehirde yürürken açılmış olan yeni bir elektronik mağazası gördüm. Girdikten sonra Arduina için çok sayıda kalkan buldum. Evde bir Arduino Uno vardı ve bir Arduino Nano hemen uzaktan sinyal vericileriyle oynama fikrini aldı. En ucuz 433 MHz verici ve alıcıyı almaya karar verdim:

    Sinyal verici.


    Sinyal alıcı.

    Veri aktarımının en basit taslağını yazdıktan sonra (buradan bir örnek alınmıştır), verici cihazların sıcaklık, nem gibi basit verileri iletmek için oldukça uygun olabileceği ortaya çıktı.

    Verici aşağıdaki özelliklere sahiptir:
    1. Model: MX -FS - 03V
    2. Etki yarıçapı (engelleyen nesnelerin varlığına bağlıdır): 20-200 metre
    3. Çalışma voltajı: 3,5 -12V
    4. Modül boyutları: 19 * 19 mm
    5. Sinyal modülasyonu: AM
    6. Verici gücü: 10mW
    7. Frekans: 433 MHz
    8. Gerekli harici anten uzunluğu: 25cm
    9. Bağlanması kolay (yalnızca üç kablo): DATA; VCC; Dünya.

    Modül özelliklerini alma:
    1. Çalışma voltajı: DC 5V
    2. Akım: 4mA
    3. Çalışma frekansı: 433.92 MHz
    4. Hassasiyet: - 105dB
    5. Modül boyutları: 30 * 14 * 7 mm
    6. Harici anten gerekli: 32 cm.

    İnternetin genişliğinde 2Kb / s'deki bilgi aktarım aralığının 150m'ye kadar ulaşabileceği söyleniyor. Kendim kontrol etmedim, ancak iki odalı bir dairede her yeri kabul ediyor.

    Ev hava istasyonu donanımı

    Bazı deneylerden sonra Arduino Nano'ya bir sıcaklık, nem sensörü ve bir verici bağlamaya karar verdim.


    DS18D20 sıcaklık sensörü arduino'ya aşağıdaki şekilde bağlanır:

    1) Mikrodenetleyicinin eksisine GND.
    2) DQ, bir çekme direnci üzerinden toprağa ve Arduino'nun D2 pinine
    3) Vdd ila + 5V.

    Verici modülü MX-FS - 03V, 5 Volt'tan güç alır, veri çıkışı (ADATA) D13 pinine bağlanır.

    Arduino Uno'ya bağlı LCD ekran ve BMP085 barometre.


    Arduino uno'ya bağlantı şeması

    Sinyal alıcı, D10 pinine bağlanır.

    BMP085 modülü, dijital bir atmosferik basınç sensörüdür. Sensör, sıcaklık, basınç ve yüksekliği ölçmenize olanak tanır. Bağlantı arayüzü: I2C. Sensör besleme voltajı 1,8-3,6 V

    Modül, Arduino'ya diğer I2C cihazlarıyla aynı şekilde bağlanır:

    • VCC - VCC (3.3V);
    • GND - GND;
    • SCL - analog pin 5'e;
    • SDA - analog pin 4'e.
    • Çok düşük maliyet
    • Güç ve G / Ç 3-5V
    • % 5 doğrulukla% 20-80 nem tayini
    • 0-50 derece sıcaklık tayini. % 2 doğrulukla
    • Örnekleme oranı 1 Hz'den fazla değil (1 saniyede bir defadan fazla değil)
    • Boyutlar 15.5mm x 12mm x 5.5mm
    • 4 pim aralığı 0,1 "

    DHT'nin 4 iğnesi vardır:

    1. Vcc (3-5V güç kaynağı)
    2. Veri çıkışı - Veri çıkışı
    3. Kullanılmamış
    4. Genel

    D8 Arduin'e bağlanır.

    Ev hava istasyonunun yazılım bölümü

    Verici modül sıcaklığı her 10 dakikada bir ölçer ve iletir.

    Program aşağıdadır:

    / * Sketch version 1.0 Sıcaklığı her 10 dakikada bir gönder. * / #include #include #include #define ONE_WIRE_BUS 2 // Dallas OneWire oneWire sensörünü bağlamak için pin (ONE_WIRE_BUS); DallasTemperature sensörleri (& oneWire); DeviceAddress insideTermometer; void setup (void) (//Serial.begin(9600); vw_set_ptt_inverted (true); // DR3100 için gereklidir vw_setup (2000); // Baud hızı (bps) sensörlerini ayarlayın.begin (); if (! sensörler .getAddress (insideThermometer, 0)); printAddress (insideThermometer); sensörler.setResolution (insideThermometer, 9);) void printTemperature (DeviceAddress deviceAddress) (float tempC \u003d sensörler.getTempC (deviceAddress); //Serial.print("Temp C : "); //Serial.println(tempC); // int numarası göndermek için veri oluşturma \u003d tempC; char symbol \u003d" c "; // Bunun bir sensör olduğunu belirlemek için hizmet sembolü String strMsg \u003d" z "; strMsg + \u003d simge; strMsg + \u003d ""; strMsg + \u003d sayı; strMsg + \u003d ""; char msg; strMsg.toCharArray (msg, 255); vw_send ((uint8_t *) msg, strlen (msg)); vw_wait_tx (); / / Transferin gecikmeyi (200) sona erdirmesini bekliyoruz;) void döngüsü (void) (for (int j \u003d 0; j<= 6; j++) { sensors.requestTemperatures(); printTemperature(insideThermometer); delay(600000); } } //Определение адреса void printAddress(DeviceAddress deviceAddress) { for (uint8_t i = 0; i < 8; i++) { if (deviceAddress[i] < 16); //Serial.print("0"); //Serial.print(deviceAddress[i], HEX); } }

    Alıcı cihaz verileri alır, odadaki basınç ve sıcaklığı ölçer ve ekrana iletir.

    #include # LiquidCrystal lcd (12, 10, 5, 4, 3, 2); #include dht11 sensörü; #define DHT11PIN 8 #include #include BMP085 dps \u003d BMP085 (); uzun Sıcaklık \u003d 0, Basınç \u003d 0, Yükseklik \u003d 0; void setup () (Serial.begin (9600); vw_set_ptt_inverted (true); // DR3100 için gereklidir vw_setup (2000); // Alma oranını ayarlayın vw_rx_start (); // Yayını izlemeye başlayın lcd.begin (16, 2); Wire.begin (); delay (1000); dps.init (); //lcd.setCursor(14,0); //lcd.write(byte(0)); //lcd.home ();) void loop () (uint8_t buf; // Mesaj için tampon uint8_t buflen \u003d VW_MAX_MESSAGE_LEN; // Tampon uzunluğu if (vw_get_message (buf, & buflen)) // Bir mesaj alınırsa (// Ayrıştırmaya başla int i; // Mesaj bize adresli değilse , exit if (buf! \u003d "z") (return;) char command \u003d buf; // Komut dizin 2'de // Sayısal parametre dizin 4'te başlar i \u003d 4; int sayı \u003d 0; // Aktarım karakter karakter olduğundan , daha sonra karakter kümesini bir sayıya dönüştürmeniz gerekir while (buf [i]! \u003d "") (sayı * \u003d 10; sayı + \u003d buf [i] - "0"; i ++;) dps.getPressure (& Pressure); dps.getAltitude (& Rakım); dps.getTemperature (& Temperature); //Serial.print(command); Serial.print (""); Serial.println (numara); lcd.print ("T \u003d"); lcd.setCursor (2.0); lcd.print (sayı); lcd.setCursor (5.0); lcd.print ("P \u003d"); lcd.print (Basınç / 133.3); lcd.print ("mmH"); lcd.setCursor (0,1); lcd.print ("T \u003d"); lcd.print (Sıcaklık * 0.1); lcd.print ("H \u003d"); lcd.print (sensor.humidity); lcd.home (); // gecikme (2000); int chk \u003d sensor.read (DHT11PIN); switch (chk) (case DHTLIB_OK: //Serial.println("OK "); break; case DHTLIB_ERROR_CHECKSUM: //Serial.println("Checksum error"); break; case DHTLIB_ERROR_TIMEOUT: //Serial.println("Zaman aşımı error "); break; default: //Serial.println("Unknown hata"); break;)))

    Not: Gelecekte aşağıdakileri eklemeyi planlıyorum:
    - vericiye nem sensörü, veri aktarım algoritmasını yeniden işleyin
    - rüzgar hızı ve yönünü ölçmek için sensör.
    - alıcı cihaza başka bir ekran ekleyin.
    - alıcı ve vericiyi ayrı bir mikro denetleyiciye aktarın.

    Aşağıda olanların bir fotoğrafını ekliyorum:

    Radyoelementlerin listesi

    Tanımlama Bir tür Mezhep numara NotPuanBenim defterim
    Gönderen kısım.
    Arduino kurulu

    Arduino Nano 3.0

    1 Not defterine
    Sıcaklık sensörü

    DS18B20

    1 Not defterine
    Direnç

    220 ohm

    1 Not defterine
    Verici modülüMX-FS-03V (433 MHz)1 Not defterine
    Radyo alma kısmı.
    Arduino kurulu

    Arduino Uno

    1 Not defterine
    Giyotin direnci 1 Not defterine
    Direnç

    V. Petin'in "Arduino denetleyicisini kullanan projeler" 2. baskısından (Ek 2 proje 5) meteoroloji istasyonu projesi esas alınmıştır. Windows 10'da Arduino IDE 1.8.5'i kullandık.
    Çizime başlarken bir hata aldım

    İnternette, aynı ada sahip ancak farklı içeriğe sahip Arduino için kitaplıkları indirebilirsiniz. Yanlış kitaplığı kullanıyorsanız çizim çalışmayabilir. Görünüşe göre yanlış kütüphanelere rastladım. Atmosferik basıncı ölçmek için projeye bir BMP180 sensörü eklendi ve taslağı yeniden tasarladı.

    Bağlantı şeması

    Adres taranıyor

    Önce BMP180 sensörünü ve LCD1602 göstergesini Arduino ya bağlayın. I2C tarayıcı taslağını derleyin ve I2C veriyolundaki cihazların adreslerini belirlemek için çalıştırın.

    Program her 5 saniyede bir cihazları tarar ve adresleri COM portuna gönderir. 0x3F ve 0x77 adreslerine sahip iki cihaz buldum. BMP180 varsayılan olarak 0x77 adresine sahiptir, bu nedenle LCD göstergesinin adresi 0x3F'dir.
    Bazı diyagramlarda kitaplar, SDA ve SCL sinyallerinin Arduino kartına bağlandığı yerlerle karıştırılır. Olmalıdır: SDA - A4, SCL - A5. BMP180'in beş pimi varsa, VIN pini +5 Volt ile sağlanır.

    Bağlantı şeması

    Şimdi devreyi tamamlayın. 150 ohm dirençlerle birlikte bir karta monte edilmiş ortak bir katot RGB LED kullandım. Ortak katot GND kontağına bağlanır, diğer pimler şemaya göre bağlanır. LED'lerin parlaklığı döngüsel bir şekilde değiştiğinden çizimde değişiklik yapmaya gerek yoktur.
    Şema, kitapta olduğu gibi bir RGB LED'in ortak bir anotla bağlantısını göstermektedir.
    LCD1602 ekranında hiçbir karakter görünmüyorsa, parlaklık kontrolünü çevirin. Gösterge arka ışığı oldukça fazla akım tüketir, bu nedenle en az 2 A akımlı bir güç kaynağı kullanın. Harici 2 A güç kaynağı olan bir USB hub kullandım.
    Devrede ZP-22 piezo çan kullandım. Zile bağlı bir direnç 100 ohm'dur. Programda ses frekansı değiştirilebilir. 1000 Hz frekans seçtim. Sabit bir ses frekansına sahip bir zil sesiyle karşılaşırsanız, normal bir LED gibi basitçe voltaj uygulayıp çıkararak onu açıp kapatabilirsiniz. Çizim başladığında kısa bir bip sesi duyulur. // bzz (100) satırının açıklamasını kaldırarak program çalışırken periyodik sinyallemeyi etkinleştirebilirsiniz; taslakta.
    Projede, halihazırda monte edilmiş 4,7 kOhm dirençli bir modül şeklinde bir DHT11 sensörü kullandım. Direnç 4,7 ila 10 kΩ arasında olabilir.
    DS1302 saat modülünün Vcc pinini +5 Volt veriyoluna bağlayın. Bu, pilin tüketimini azaltacaktır, aslında sadece Arduino kapalıyken çalışacaktır.

    Program (taslak)

    Bmp085 kitaplığı BMP180'e hizmet vermek için kullanıldı. Basınç değeri arazinin yüksekliğine bağlıdır. Atmosferik basıncın doğru değeri için yüksekliği seçmeniz gerekir. Bunu yapmak için dps.init (MODE_STANDARD, 10000, true) satırını düzenleyin; Boyum 100 m (10000 cm). Basınç hesaplamasının bir parçası, bmp085 kitaplığının BMP085_test2.ino örneğinden alınmıştır.

    Meteo_P taslağı

    #Dahil etmek
    #Dahil etmek
    #Dahil etmek
    #include "DHT.h"
    #Dahil etmek
    BMP085 dps \u003d BMP085 ();
    uzun Basınç \u003d 0, Yükseklik \u003d 0;
    işaretsiz uzun süre1 \u003d 0;

    #define DHTPIN 10
    #define DHTTYPE 11 // 11 - DHT11, 22 - DHT22
    DHT dht (DHTPIN, DHTTYPE);

    int kCePin \u003d 4; // RST DS1302
    int kIoPin \u003d 3; // Veri DS1302
    int kSclkPin \u003d 2; // CLK DS1302
    DS1302 rtc (kCePin, kIoPin, kSclkPin);

    int REDpin \u003d 9;
    int GREENpin \u003d 6;
    int MAVİpin \u003d 11;

    LiquidCrystal_I2C lcd (0x3f, 16, 2); // adresinizi girin 0x20 ... 0xff adres
    imzasız uzun memTime;
    int bzzPin \u003d 8;

    void HumTempRead () (
    float hum \u003d dht.readHumidity ();
    float temp \u003d dht.readTemperature ();
    eğer (isnan (hum) || isnan (temp)) (
    Serial.println ("DHT sensöründen okunamadı!");
    lcd.setCursor (0, 1);
    lcd.print ("H \u003d -% T \u003d ---");
    lcd.setCursor (11, 1);
    lcd.print ((karakter) 223);
    lcd.setCursor (12, 1);
    lcd.print ("C");
    ) Başka (
    lcd.setCursor (0, 1);
    lcd.print ("H \u003d");
    lcd.setCursor (2, 1);
    lcd.print (uğultu);
    lcd.setCursor (4, 1);
    lcd.print ("% T \u003d +");
    lcd.setCursor (9, 1);
    lcd.print (geçici);
    lcd.setCursor (11, 1);
    lcd.print ((karakter) 223);
    lcd.setCursor (12, 1);
    lcd.print ("C");
    }
    }

    void setup_bzz () (
    pinMode (bzzPin, OUTPUT);
    }

    void bzz (int _bzzTime) (
    ton (bzzPin, 1000, _bzzTime); // frekans 1000 Hz
    }

    geçersiz kurulum () (
    Serial.begin (9600);
    Wire.begin ();
    gecikme (1000);

    dps.init (MODE_STANDARD, 10000, doğru); // 100 metre (cm cinsinden deniz seviyesinden yükseklik)

    dht.begin ();
    setup_bzz ();
    bzz (100);

    Lcd.init ();
    lcd.backlight ();
    lcd.home ();
    // lcd.setCursor (0, 0);

    rtc.halt (yanlış);
    rtc.writeProtect (yanlış);

    //rtc.setDOW(FRIDAY); // Haftanın Gününü CUMA olarak ayarlayın haftanın gününü ayarlayın
    //rtc.setTime(4, 58, 0); // Saati 12:00:00 (24 saat biçimi) olarak ayarlayın, saati ayarlayın
    //rtc.setDate(6, 8, 2010); // Tarihi 6 Ağustos 2010 olarak ayarlayın tarihi ayarlayın (gün, ay, yıl)
    }

    lcd.setCursor (8, 0);
    lcd.print (rtc.getTimeStr ());

    eğer ((millis () - memTime\u003e 2000) veya (millis ()< memTime)) { // DHT11/22 1 time each 2 seconds
    HumTempRead ();
    memTime \u003d milis ();
    }
    gecikme (100);

    eğer (((milis () - zaman1) / 1000.0)\u003e \u003d 1.0) (
    dps.calcTrueTemperature ();
    zaman1 \u003d milis ();
    }
    dps.getPressure (& Pressure);
    Seri.print ("Basınç (Pa):");
    Serial.println (Basınç);

    uzun p2;
    int pi;
    p2 \u003d (Basınç / 133.3224); // Pa, mm Hg cinsinden
    pi \u003d kesik (p2); // sayının kesirli kısmını atın

    lcd.setCursor (0, 0);
    lcd.print ("P \u003d");
    lcd.setCursor (2, 0);
    lcd.print (pi); // çıktı atm. basınç LCD'de
    lcd.setCursor (5, 0);
    lcd.print ("mm");
    // gecikme (3000);
    // bzz (100); // sinyalleri dinlemek istiyorsanız yorum yapmayın
    {
    for (int değer \u003d 0; değer<= 255; value += 1) {
    analogWrite (REDpin, değer);
    analogWrite (YEŞİL pin, 255 - değer);
    analogWrite (MAVİ pin, 255);
    gecikme (5);
    }

    for (int değer \u003d 0; değer<= 255; value += 1) {
    analogWrite (REDpin, 255);
    analogWrite (YEŞİL pin, değer);
    analogWrite (MAVİ pin, 255 - değer);
    gecikme (5);
    }

    for (int değer \u003d 0; değer<= 255; value += 1) {
    analogWrite (REDpin, 255 - değer);
    analogWrite (YEŞİL pin, 255);
    analogWrite (MAVİ pin, değer);
    gecikme (5);
    }
    }
    }

    Dosya Kataloğunda, projede kullanılan taslak ve kitaplıkları indirebilirsiniz.

    LiquidCrystal_I2C.zip, bmp085.zip, DS1302.zip ve DHT.zip kitaplıklarını indirilen arşivden Arduino IDE'ye aktarın. Menüye git Eskiz Kitaplığı bağla .ZIP kitaplığı ekle ... ve pencerede kütüphanenin zip arşivini seçin.
    Taslağı meteo_P yükleyin. Çizimdeki LCD1602 adresini, I2C veriyolunu tarayarak elde edilen değerle değiştirin. Çizimi derleyin ve çalıştırın.
    Çizim çalışıyorsa, bağlantı noktası monitörünü açın ve görünen mesajları görüntüleyin. Dps.init deyimini (MODE_STANDARD, 10000, true) kullanarak yüksekliği ayarlayın; gerçek basınç değerlerini elde etmek için.
    Saati ayarlayın. //Rtc.setTime(4, 58, 0) satırının açıklamasını kaldırın; ve parantez içinde, geçerli saati (virgülle ayrılmış saat, dakika ve saniye) belirtin ve çizimi kontrolöre yeniden yükleyin. Zaman dolduktan sonra, bu satırı yeniden yorumlayın ve çizimi yeniden başlatın.
    Gece ışığının aydınlatması sizi rahatsız ediyorsa, taslağın sonundaki for döngülerindeki gecikmenin uzunluğunu değiştirerek bunu özelleştirebilirsiniz. Gecikmeli (2); döngü gecikmeli olarak 2-3 saniye sürer (5); - gecikmeli 4 ila 5 saniye (30); - 15-16 saniyeye kadar. Gösterge üzerindeki bilgiler aynı aralıklarla güncellenecektir.
    Meteoroloji istasyonunu bağımsız olarak kullanırken, örn. COM bağlantı noktası monitörüne bilgi çıkışını devre dışı bırakmak için bilgisayarın USB bağlantı noktasına bağlanmadan, taslakta Seri ... sözcükleriyle satırları yorumlayın.

    PS. Kitabın taslağında ve DHT kütüphanesi örneklerinde tanım satırı belirtilmiştir. #define DHTTYPE DHT 11... Çizim başlıyor ancak birkaç saat sonra çöküyor. Saat durur, ekran değişmez. Bağlantı noktası monitöründe dht bağlantısıyla birlikte belirsiz bir mesaj belirir.
    Bu satırdaki DHT harflerini kaldırdım, yani yapılmış #define DHTTYPE 11... Bundan sonra eskiz istikrarlı bir şekilde çalışmaya başladı.

    Makale 25.06.2018 tarihinde güncellenmiştir.

    Kullanılan kaynaklar
    1. Petin V.A. Arduino denetleyicisini (Elektronik) 2. baskı, St. Petersburg kullanan projeler. BHV-Petersburg, 2015 464 s.
    2. Petin V. A., Binyakovsky A. A. Arduino'nun Pratik ansiklopedisi. - M., DMK Press, 2017. - 152 s.
    3. http://arduinolearning.com/code/i2c-scanner.php
    4. http://arduino.ru/forum/programmirovanie/ds1302lcd1602
    5. http://robotekhnika18.rf/how-connect-lcd-1602-k-arduino-po-i2c/
    6. bmp085.zip kitaplığından örnek BMP085_test2.ino
    7. http://proginfo.ru/round/
    8. http://homes-smart.ru/index.php?id\u003d14&Itemid\u003d149&option\u003dcom_content&view\u003darticle
    9. http://iarduino.ru/lib/datasheet%20bmp180.pdf
    10. http://it-donnet.ru/hd44780_dht11_arduino/