Cum se configurează smartphone-uri și PC-uri. Portal de informare
  • Acasă
  • VKontakte
  • Proiecte de mini stații meteo Arduino pro. Modul senzor de presiune barometrică BMP085 pentru arduino (sau cum să faci o stație meteo cu propriile mâini)

Proiecte de mini stații meteo Arduino pro. Modul senzor de presiune barometrică BMP085 pentru arduino (sau cum să faci o stație meteo cu propriile mâini)

La fel ca majoritatea oamenilor care lucrează, urmărirea propriilor proiecte ocupă singurul timp liber care vă mai rămâne. De aceea nu am mai creat nimic de mult timp și mă simțeam mâncărime să fac ceva. Această oportunitate a apărut, destul de ciudat, la universitate. Este septembrie în afara ferestrei, anul 4 și un curs viitor despre proiectarea circuitelor. Ni s-a spus că cursurile pot fi făcute în două variante: hârtie și hardware.

Timp de 5 ani, cursurile pe hârtie la universitatea noastră s-au făcut după principiul „luați-le pe cele vechi și puneți-le împreună”. Această abordare nu mi s-a potrivit din cauza rutinei sale, așa că am ales imediat cursuri în hardware. Ca nucleul cursului a fost propus Microcontroler Arduino datorită ușurinței sale de învățare. După ce am stabilit tipul de curs, a rămas încă o întrebare: ce trebuie făcut exact. Deoarece nu aveam experiență în programarea microcontrolerelor, am deschis imediat Google și am început să studiez proiectele existente. Sunt multe proiecte, unele sunt destul de simple, altele sunt ingenioase (scanner 3D, de exemplu), dar marea majoritate nu avea aplicare practică. Și am vrut doar ceva care să nu stea pe raft și să adune praful. După o excursie de jumătate de oră în lumea Arduino, am devenit interesat de subiectul stațiilor meteo de acasă, iar proiectele nu mi s-au părut foarte greu de implementat (ceea ce l-a atras în principal pe noul venit).

Așa a fost aleasă tema pentru curs și de-a lungul timpului părea să nu existe probleme.

Selectarea componentelor

Privind prin diferite proiecte, mi-am dat seama că Nano sau chiar Pro Mini, dar totuși am ales Arduino Uno în speranța că mi-ar plăcea să programez pentru Arduino și că voi implementa mai multe proiecte în viitor. Nu mai ținusem niciodată un fier de lipit în mâini, așa că pentru o dezvoltare mai ușoară am decis să cumpăr și Sensor Shield v4.

Mai multe detalii

Taxa contribuie conexiune rapidă senzori, module, servomotoare, interfețe seriale și I2C și, de asemenea, afișează toate porturile controlerului factorului de formă Duemilanova/Uno (poate fi conectate și la seria mega, dar cu restricții și consecințele care decurg). Sprijină alte scuturi deasupra lor.


Am ales următorii senzori ca surse pentru datele meteorologice:


M-am hotarat asupra senzorilor. Dar ce să faci cu datele care vin de la senzori? Am decis să-l afișez. Am vrut o poză color, așa că am renunțat imediat la soluțiile monocrome. După câteva minute de căutare, a fost selectat afișajul TFT de 1,8 inchi ST7735.

Mai multe detalii

Deoarece afișajul folosește un protocol SPI cu 4 fire pentru comunicare și are propriul buffer de cadre adresabil în pixeli, acesta poate fi utilizat cu orice tip de microcontroler. Ecranul de 1,8 inchi are 128x160 pixeli color. Există și un slot pentru card memorie microSD, prin urmare, puteți descărca cu ușurință color imagini raster de la FAT16/FAT32 sistem de fișiere carduri microSD.

Specificatii:

  • Diagonala ecranului - 1,8 inchi, rezoluție 128x160 pixeli, culoare pe 18 biți (262.144 culori)
  • Controler cu adresare în pixeli încorporată a memoriei tampon video
  • Slot microSD încorporat - folosește mai mult de 2 linii digitale
  • Compatibil cu 3.3 și 5V
  • Dimensiuni: 34 mm x 56 mm x 6,5 m


Programare controler Arduino

După ce ne-am hotărât asupra componentelor stației meteo, vom începe programarea controlerului. Mediul folosit pentru firmware-ul Arduino Dezvoltare Arduino IDE. Folosit și bibliotecile de la Adafruit.

Înainte de a trece la schiță, să ne uităm la funcționalitate:

  • Citirile sunt luate de la senzori la fiecare 10 secunde și doar acei indicatori care s-au modificat față de măsurarea anterioară sunt actualizați pe ecran
  • Transfer de date implementat prin portul COM

Schiţa

#include // bibliotecă pentru comunicarea cu dispozitivele I2C #include // Bibliotecă de bază pentru toți senzorii #include // bibliotecă pentru BMP180 #include // Biblioteca grafică de bază #include // Bibliotecă specifică hardware-ului #include // bibliotecă pentru comunicarea cu dispozitivele SPI #include "dht.h" // bibliotecă pentru DHT #define DHT22_PIN 2 // conectați pinul de date al DHT22 la 2 pini digitali #define TFT_CS 10 // conectați pinul CS al TFT la 10 pin digital #define TFT_RST 9 // conectați pinul RST al TFT la 9 pinul digital // îl puteți conecta și la resetarea Arduino // în acest caz, setați acest #define pin la 0! #define TFT_DC 8 // conectați pinul DC al TFT la 8 pini digitali Adafruit_ST7735 tft = Adafruit_ST7735(TFT_CS, TFT_DC, TFT_RST); //inițializează TFT #define TFT_SCLK 13 // conectează pinul SCLK al TFT la 13 pin digital #define TFT_MOSI 11 // conectează pinul MOSI al TFT la 11 pin digital dht DHT; Adafruit_BMP085_Unified bmp = Adafruit_BMP085_Unified(10085); //inițializați BMP180 int bmpFlag = 0; struct ( uint32_t total; uint32_t ok; uint32_t crc_error; uint32_t time_out; uint32_t connect; uint32_t ack_l; uint32_t ack_h; uint32_t necunoscut; ) stat = ( 0,0,0,0,0,0,0,0,0,0); // structuri pentru starea dht void setup(void) ( Serial.begin(9600); Serial.println("Meteo Test"); Serial.println(""); if(!bmp.begin()) // verificați conexiunea pentru BMP180 ( Serial.print("Ooops, no BMP180 detected... Check your wiring or I2C ADDR!"); bmpFlag = 1; ) tft.initR(INITR_BLACKTAB // Initialize TFT and complete with black color tft.fillScreen); (ST7735_BLACK); tft.setRotation(tft.getRotation() + 1, tft.setTextSize(1.5); oldPressure = 0, oldDHTHumiditate = 0, oldDHTTperature; = 0 || !event.pressure) // actualizați datele ( tft.fillRect(0, 30, 160, 6, ST7735_BLACK); tft.setCursor(0, 30); tft.setTextColor(ST7735_RED); printValue("EROARE BMP INITIALIZATION", 0) , "", true ) else ( if(event.pressure != oldPressure) ( tft.fillRect(0, 30, 160, 7, ST7735_BLACK); tft.setCursor(0, 30); tft.setTextColor(ST7735_RED) ; printValue ("Presiune", event.pressure, " hPa", true); oldPressure = event.pressure = true ) if(temperature != oldTemperature) ( tft.fillRect(0, 38, 160, 7, ST7735_BLACK ); tft.setCursor (0, 38); tft.setTextColor(ST7735_WHITE); (0, 46); tft.setTextColor(ST7735_BLUE); printValue("Altitudine, "m", true); 54, 160, 7, ST7735_BLACK; tft.setCursor(0, 54);

Este timpul să asamblați corpul

Condiția principală a cursului a fost un prototip funcțional într-o formă prezentabilă. Prin urmare, a trebuit să cumpăr o carcasă și, înarmat cu un dosar, să introduc în orice fel stația meteo în carcasă.

Carcasa a fost achiziționată de la un magazin local de electronice radio.

Cadru

(Carcasa din fotografie este puțin diferită. Am un capac transparent)



Apoi, folosind un fișier, s-au făcut găuri pentru a scoate senzorii și pentru a furniza energie. Am decis să mut senzorii afară, pentru că în timp ce testam sistemul fără carcasă, am observat că spatele ecranului s-a încins foarte tare, ceea ce ar afecta temperatura din interiorul carcasei.

Carcasa cu deschideri pentru senzori si putere



Întrucât a trebuit să lipim picioarele la 2 senzori și am ars pista pe unul dintre ei, am decis să nu ispitesc soarta și să nu lipim firele la senzori (voi exersa la altceva), și pentru a face legătura. pentru a fi mai mult sau mai puțin de încredere, am decis să derulez înapoi banda electrică.

Sistemul înainte de a fi „înfundat” în carcasă



Deoarece carcasa este mult mai mare decât Arduino (nu era una mai mică), a trebuit să vin cu un suport pentru ca placa să nu se miște în interiorul carcasei. De asemenea, din spumă a fost tăiată o figură, iar în ea era un dreptunghi pentru ecran pentru a ascunde interiorul carcasei. Nu aveam superglue la îndemână, așa că a trebuit să folosesc bandă cu două fețe.

Minune-yuda pește-balenă



Înșurubați capacul, conectați alimentarea și așteptați.

Stație meteo finalizată în clădire



După afișarea rezultatelor pe ecran, identificăm o eroare neplăcută în măsurarea umidității: DHT22 produce cu sârguință cifra 99,90% (1,00% este extrem de rar). Să începem să ne dăm seama care este problema. Primul lucru pe care îl facem este să ne uităm la ieșirea valorilor către portul COM. Totul pare să fie bine. După mai multe reumpleri, demontări și remontări ale carcasei, îmi vine în minte ideea de a căuta răspunsul pe Google. După cum era de așteptat, Google rusesc nu a spus nimic util. BINE. Începem să căutăm în engleză și pe unul dintre forumuri întâlnim băieți cu o problemă similară. Primele patru pagini ale discuției nu dau nimic util, dar pe pagina a cincea găsim răspunsul la întrebarea noastră:
Senzorii de umiditate pot fi afectați cu ușurință de gazele greșite sau de expunerea foarte lungă la IIRC cu umiditate ridicată. În fișa de date există o procedură de „resetare” a senzorului, ați putea încerca.

Singura întrebare care a rămas a fost când și cum am reușit să deteriorez DHT22. Dar se apropia vremea de a urma cursurile și așa că am lăsat soluția acestei probleme pentru mai târziu.

Postfaţă

Cursul a fost promovat. Stația meteo a fost amânată pe termen nelimitat până la închiderea tuturor sterilelor din universitate. Totuși, a trebuit să ne întoarcem la stația meteo mai devreme decât credeam. S-a întâmplat că la jumătatea lunii noiembrie mi-am schimbat locul de muncă și în noua echipă am întâlnit oameni care sunt interesați de platforma Arduino și altele asemenea. Prin urmare, interesul meu pentru această platformă, fără să am timp să mă răcoresc, a aprins din nou. Mi-am scos stația meteo, am conectat-o ​​la computer și mi-am amintit că am implementat transferul de date de la Arduino prin portul COM. Și atunci mi-a venit ideea să scriu un program care să primească date prin portul COM de la Arduino și să transmită aceste date către monitorizarea publică.
  • Arduino
  • Adăugați etichete

    Continuăm să ne dezvoltăm stația meteo.

    Înainte de a trece la actualizare, vreau să clarific puțin.

    Unul dintre colegii noștri mi-a scris întrebând de ce a fost introdus cronometrul de supraveghere?

    Cronometrul de supraveghere este activat în caz de urgență. După cum arată practica, ENC28J60 nu durează mai mult (dacă memoria nu eșuează) 4 conexiuni simultane. Luând în considerare câte conexiuni de serviciu apar constant pentru a menține funcționarea rețelei în sine și pur și simplu a lăsat traficul creat de tot felul de jucării de uz casnic (de exemplu, televizoare moderne, scanați gazdele disponibile în rețea și porturile lor deschise) designul pur și simplu intră în stupoare. ENC28J60 nu poate funcționa independent cu protocoale de rețeași totul este implementat în biblioteci. Poate că sunt doar ei.
    A verificat toate bibliotecile disponibile și module diferite(deodată căsătorie), dar pentru a realiza funcționare stabilă Nu am putut să o fac multă vreme. Termen maxim a fost cam 3-4 saptamani.
    Acesta este motivul pentru care „câinele” se învârte acolo și, dacă se întâmplă ceva, trage controlerul. După aceasta problema a dispărut.
    De asemenea, nu neg că pot exista anumite nuanțe sau probleme în rețeaua mea de acasă. Dar din moment ce am avut o problemă, s-ar putea să o aibă și o altă persoană. Pana acum am gasit doar aceasta solutie.
    Din câte știu, cipurile de la Wiznet (W5100 și superioare) nu au acest lucru sau pur și simplu nu arătau suficient de bine.

    Să trecem la actualizare

    Cel mai important, ne îndepărtăm de cip ENC28J60și du-te la W5100. Am încercat să implementez totul pe vechiul cip, dar nu există suficientă memorie pentru microcontroler din cauza bibliotecilor foarte mari pt ENC28J60. Când utilizați un cip nou, standard biblioteci de la dezvoltator și toate modificările făcute, rămân și mai multe 20% memorie liberă microcontroler ATMega328. Și acestea sunt chifle noi!

    În această versiune (să o numim a doua) capacitatea de a transmite citirile de la senzori prin intermediul comunicare fără fir folosind frecventa 433 MHz. Am luat modulele în sine de la chinezi, marcaje XY-MK-5V. Aș dori să remarc că calitatea transmisiei este departe de a fi perfectă. Posibilă pierdere de semnal, zgomot, incapacitatea de a transmite simultan etc., etc. Dar prețul lor (mai puțin de 1 USD pe set) compensează aceste neajunsuri. Vă voi spune un secret pentru care aceste (cele mai ieftine) module se găsesc în multe stații meteo de marcă pentru uz casnic. Wow, neașteptat?

    Să începem cu stația de bază

    Ne mutam la Arduino UNOŞi Scut Ethernet(prima versiune) bazată pe cip W5100. Acesta este un sandviș și nu are rost să-l descriu. Voi descrie doar contactele implicate suplimentar pentru module XY-MK-5V.

    Modulul transmițător folosește energie 5V, GND(unde ar fi fără mamă) și D2 pin pe controler. Editați contactul D2 (DATE) puteți folosi funcția vw_set_tx_pin din biblioteca vw.

    Spre deosebire de schița anterioară, aceasta implică două biblioteci suplimentare:

    #include #include

    Schița în sine

    Text ascuns

    #include #include #include #include #include #include #include #include #define DHTTYPE DHT22 #define DHTPIN 5 DHT dht(DHTPIN, DHTTYPE); octet mac = (0x54, 0x34, 0x31, 0x31, 0x31, 0x31); char server = "narodmon.ru"; int port = 8283; IPAddress ip(192,168,0,201); Client EthernetClient; BMP085 dps = BMP085(); lung Temperatura = 0, Presiune = 0; float H, dP, dPt; interval bool = adevărat; EasyTransferVirtualWire ET; struct SEND_DATA_STRUCTURE( byte ID; // Device ID int Temperature; // Temperature float Presiune; // Pressure float Umiditate; // Umiditate float dewPoint; // Roua/punct de îngheț ); SEND_DATA_STRUCTURE difuzat; void setup() ( // Inițializați cronometrul Watchdog wdt_disable(); delay(8000); wdt_enable(WDTO_8S); // Inițializați consola Serial.begin(9600); // Inițializați senzorul DHT dht.begin(); / / Inițializarea modulului de 433 MHz ET.begin(details(broadcast)); vw_set_ptt_inverted(vw_set_tx_pin(2); 1-Wire Wire.begin(); // Inițializarea BMP180 cu ajustarea înălțimii // dps.init (MODE_STANDARD, 3200, true // Inițializare BMP180 dps.init(Ethernet.localIP()); // Trimite primele date imediat după pornirea dispozitivului send_info(true) // dewPoint function NOAA / / reference (1) : http://wahiduddin.net/calc/density_algorithms.htm // reference (2) : http: //www.colorado.edu/geography/weather_station/Geog_site/about.htm Punct de rouă dublu (celsius dublu, umiditate dublă) ( // (1) Presiunea vaporilor de saturație = ESGG(T) RATIO dublu = 373,15 / (273,15 + celsius) ; Acest lucru este necesar // pentru a nu induce în eroare în timpul sezonului de iarnă.<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); }

    O antenă trebuie adăugată modulelor în sine. Pentru 433 MHz Un fir de cupru lung obișnuit este suficient 17 cm. Fără antenă, puteți uita de funcționarea normală.

    Să trecem la cea mai importantă parte a acestei actualizări - stația locală wireless

    Pentru a o implementa (pe genunchi) am folosit un analog Arduino NANO(bazat pe ATMega328) Și TFT afișare pe un cip ST7735S cu permisiunea 128 x 160

    Text ascuns



    Afișaj pinout -> controler

    ============================ LED | 3,3V SCK | SCK (13) SDA | MOSI(11)A0 | DC (9) RESET | RST(8)CS | CS (10) GND | GND VCC | 5V =============================

    Modulul receptor este conectat doar la fel ca un transmițător DATE a fixa D7.

    Câteva poze cu cum arată:

    Text ascuns

    Schița receptorului

    Text ascuns

    #include #include #include #include int x, y; int w = 128, h = 160; dimensiune int; // 433 EasyTransferVirtualWire ET; struct SEND_DATA_STRUCTURE( byte ID; // Device ID int Temperature; // Temperature float Presiune; // Pressure float Umiditate; // Umiditate float dewPoint; // Roua/punct de îngheț ); SEND_DATA_STRUCTURE difuzat; Temperatură); info.concat("C"); = Log_dewPoint) ( TFTscreen.setTextSize(size); // Suprascrie datele învechite info = 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 // Iesire citiri noi = String(broadcast.dewPoint(info.toCharArray(dewPoint, info.length());); TFTscreen.stroke(255, 255, 255); Log_dewPoint)?true:false); else ( modificări (10, 106, 125, true, true); modificări (10, 106, 125, false, true); ) // Actualizați valorile în jurnalele ulterioare compararea citirilor Log_Temperature = difuzare.Temperatura;

    Citirile sunt afișate destul de compact, dar așa cum arată practica (și sfaturile camarazilor mei) - „gust și culoare, nici măcar soția nu este o prietenă”. Am ascultat o mulțime de sfaturi și sugestii, dar se contrazic. Prin urmare, fă-o după gustul tău.

    Mi s-a părut că designul este partea din proiect care ocupă cel mai mult timp!

    Text ascuns

    Unele dintre date sunt fabricate pentru a reflecta unele elemente de design.

    Artefactele de pe afișaj sunt praf și alte murdărie care s-au acumulat de-a lungul timpului în care a fost afișat... undeva acolo,... ei bine, acolo, nu-mi amintesc de unde l-am luat! Lasă-mă în pace!

    Schița are funcții de poziționare. Sunt destul de primitive, dar vă permit să obțineți anumite efecte.

    1. x_center
    2. x_alignment_right

    Primul centrează textul, iar al doilea îl aliniază în partea dreaptă a zonei specificate. Toate calculele se fac referitor la dimensiuni textul dat, pe baza expresiei 1 dimensiune = 1PX x 1PX segment de font.

    Afișajul afișează, de asemenea, elemente corespunzătoare unei creșteri sau scăderi a unei anumite valori de citire. Ele sunt afișate sub formă de triunghiuri. Dar în codul funcției schimbari Există un afișaj alternativ sub formă de triunghiuri rotite cu 45 de grade. Dacă citirile cresc, elementul este roșu, în caz contrar, albastru.

    Apropo, culoarea și nuanța temperaturii principale se schimbă în funcție de temperatura în sine. O decizie destul de controversată, dar după părerea mea, confortabilă vizual. M-am luptat cu el o vreme și mi-am dat seama că valorile din funcție accident vascular cerebral, obiect Ecran TFT, sunt listate în ordine greșită. BGR loc RGB. Aceasta este o eroare a dezvoltatorului sau nu înțeleg ceva.

    PS: Totul este destul de interesant, dar după părerea mea merită dezvoltare ulterioară. Asta vom face după ceva timp.

    Într-o zi, în timp ce mă plimbam prin oraș, am văzut un nou magazin de electronice radio care se deschisese. Cand am intrat am gasit număr mare Scuturi pentru Arduino deoarece Am avut acasă un Arduino Uno și un Arduino Nano și imediat mi-a venit ideea să mă joc cu transmițătoare de semnal la distanță. Am decis să cumpăr cel mai ieftin emițător și receptor la 433 MHz:

    Transmițător de semnal.


    Receptor de semnal.

    După ce a scris o schiță simplă a transmisiei de date (un exemplu luat de aici), s-a dovedit că dispozitivele de transmisie pot fi destul de potrivite pentru transmiterea de date simple, cum ar fi temperatura, umiditatea.

    Transmițătorul are următoarele caracteristici:
    1. Model: MX-FS - 03V
    2. Raza de actiune (in functie de prezenta obiectelor de blocare): 20-200 de metri
    3. Tensiune de operare: 3,5 -12V
    4. Dimensiuni modul: 19 * 19 mm
    5. Modulația semnalului: AM
    6. Putere emițător: 10mW
    7. Frecventa: 433 MHz
    8. Lungimea necesară a antenei externe: 25cm
    9. Ușor de conectat (doar trei fire): DATE ; VCC; Pământ.

    Caracteristicile modulului de recepție:
    1. Tensiune de funcționare: DC 5V
    2. Curent: 4mA
    3. Frecvența de funcționare: 433,92 MHz
    4. Sensibilitate: - 105dB
    5. Dimensiuni modul: 30 * 14 * 7 mm
    6. Necesar antenă externă: 32 cm.

    Internetul spune că raza de transmisie a informațiilor la 2Kb/sec poate ajunge până la 150m. Nu l-am verificat eu, dar într-un apartament cu două camere este acceptat peste tot.

    Hardware pentru stația meteo de acasă

    După mai multe experimente, am decis să conectez un senzor de temperatură, umiditate și transmițător la Arduino Nano.


    Senzorul de temperatură DS18D20 este conectat la Arduino după cum urmează:

    1) GND la minusul microcontrolerului.
    2) DQ printr-un rezistor de tragere la masă și la pinul D2 al Arduino
    3) Vdd la +5V.

    Modulul transmițător MX-FS - 03V este alimentat de 5 volți, ieșirea de date (ADATA) este conectată la pinul D13.

    Conectat la Arduino Uno Afișaj LCDși barometrul BMP085.


    Schema de conectare la Arduino Uno

    Receptorul de semnal este conectat la pinul D10.

    Modulul BMP085 - senzor digital presiunea atmosferică. Senzorul vă permite să măsurați temperatura, presiunea și altitudinea deasupra nivelului mării. Interfață de conectare: I2C. Tensiune de alimentare senzor 1,8-3,6 V

    Modulul este conectat la Arduino în același mod ca și alte dispozitive I2C:

    • VCC - VCC (3,3 V);
    • GND - GND;
    • SCL - la pinul analogic 5;
    • SDA - la pinul analogic 4.
    • Foarte cost scăzut
    • Putere și I/O 3-5 V
    • Determinarea umidității 20-80% cu o precizie de 5%.
    • Detectare temperatura 0-50 grade. cu o precizie de 2%.
    • Frecvența de interogare nu mai mult de 1 Hz (nu mai mult de o dată la fiecare secundă)
    • Dimensiuni 15,5 mm x 12 mm x 5,5 mm
    • 4 pini cu distanță de 0,1 inch

    DHT are 4 pini:

    1. Vcc (sursa de alimentare 3-5V)
    2. Data out - Ieșire date
    3. Nu este folosit
    4. General

    Se conectează la D8 din Arduino.

    Parte software a unei stații meteo de acasă

    Modulul de transmisie măsoară și transmite temperatura la fiecare 10 minute.

    Mai jos este programul:

    /* Schiță versiunea 1.0 Trimiteți temperatura la fiecare 10 minute. */ #include #include #include #define ONE_WIRE_BUS 2 //Pin pentru conectarea senzorului Dallas OneWire oneWire(ONE_WIRE_BUS); DallasSenzori de temperatură(&oneWire); DispozitivAdresa interiorTermometru; void setup(void) ( //Serial.begin(9600); vw_set_ptt_inverted(true); // Necesar pentru DR3100 vw_setup(2000); // Setați viteza de transmisie (bit/s) sensors.begin(); if (! senzori .getAddress(insideThermometer, 0)); printAddress(insideThermometer); //Serial.print; : "); //Serial.println(tempC); //Formarea datelor pentru trimiterea numărului int = tempC; simbolul char = "c"; //Simbolul serviciului pentru a determina că acesta este un senzor String strMsg = "z"; strMsg += simbol; strMsg += " "; ; 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); } }

    Dispozitivul de recepție primește date, măsoară presiunea și temperatura din cameră și le transmite pe afișaj.

    #include #include LiquidCrystal lcd(12, 10, 5, 4, 3, 2); #include senzor dht11; #define DHT11PIN 8 #include #include BMP085 dps = BMP085(); lung Temperatura = 0, Presiune = 0, Altitudine = 0; void setup() ( Serial.begin(9600); vw_set_ptt_inverted(true); // Necesar pentru DR3100 vw_setup(2000); // Setați viteza de recepție vw_rx_start(); // Începeți monitorizarea difuzării lcd.begin(16, 2) ; Wire.begin(); delay(1000); //lcd.write(0)() (uint8_t buflen; ; // Lungimea tamponului if (vw_get_message(buf, &buflen)) // Dacă mesajul este primit ( // Începeți analizarea int i; // Dacă mesajul nu ni se adresează, ieșiți dacă (buf != "z") ( return; ) char command = buf // Comanda este la indexul 2 // Parametrul numeric începe la indexul 4 i = 4 // Deoarece transmiterea este caracter cu caracter, atunci trebuie să convertiți setul; de caractere într-un număr while (buf[i] != " ") (număr *= 10; număr += buf[i] - "0"; i++; ) dps.getPressure(&Altitudine); getTemperature(&Temperatura //Serial.print(comandă);

    lcd.print("T=");
    lcd.setCursor(2,0);
    lcd.print(număr);
    lcd.setCursor(5,0);
    lcd.print("P=");

    lcd.print(Presiune/133,3);

    lcd.print("mmH");

    lcd.setCursor(0,1); lcd.print("T="); lcd.print(Temperatura*0,1); lcd.print("H="); lcd.print(senzor.umiditate);lcd.home();//întârziere(2000);
    int chk = senzor.read(DHT11PIN);
    comutați (chk) (case DHTLIB_OK: //Serial.println("OK"); pauză; caz DHTLIB_ERROR_CHECKSUM: //Serial.println("Eroare de sumă de verificare"); pauză; caz DHTLIB_ERROR_TIMEOUT: //Serial.println("Time out eroare"); break; default: //Serial.println ("Eroare necunoscută"); break; ) ) )

    P.S. Pe viitor am de gând să adaug următoarele:

    1 - senzor de umiditate la transmițător, reluați algoritmul de transmitere a datelor
    - senzor pentru măsurarea vitezei și direcției vântului.

    - adăugați un alt afișaj la dispozitivul receptor.

    1 - senzor de umiditate la transmițător, reluați algoritmul de transmitere a datelor
    - transferați receptorul și transmițătorul pe un microcontroler separat.

    Mai jos este o fotografie cu ceea ce s-a întâmplat:

    1 - senzor de umiditate la transmițător, reluați algoritmul de transmitere a datelor
    Lista radioelementelorDesemnare1 - senzor de umiditate la transmițător, reluați algoritmul de transmitere a datelor
    Tip
    comutați (chk) (case DHTLIB_OK: //Serial.println("OK"); pauză; caz DHTLIB_ERROR_CHECKSUM: //Serial.println("Eroare de sumă de verificare"); pauză; caz DHTLIB_ERROR_TIMEOUT: //Serial.println("Time out eroare"); break; default: //Serial.println ("Eroare necunoscută"); break; ) ) )

    Denumirea

    1 - senzor de umiditate la transmițător, reluați algoritmul de transmitere a datelor
    Cantitate 1 - senzor de umiditate la transmițător, reluați algoritmul de transmitere a datelor
    - transferați receptorul și transmițătorul pe un microcontroler separat.

    Ca bază se ia proiectul stației meteo din cartea lui V. Petin „Proiecte folosind controlerul Arduino”, ediția a II-a (proiectul 5, anexa 2). Folosit Arduino IDE 1.8.5 pe Windows 10.
    A fost generată o eroare la rularea schiței

    Pe Internet puteți descărca biblioteci pentru Arduino care au aceleași nume, dar conținut diferit. Schița poate să nu funcționeze dacă utilizați biblioteca greșită. Se pare că am dat peste biblioteci greșite. Am adăugat un senzor BMP180 la proiect pentru a măsura presiunea atmosferică și am reluat schița.

    Schema de conectare

    Scanarea adreselor

    Mai întâi, conectați senzorul BMP180 și indicatorul LCD1602 la Arduino. Compilați schița scanerului I2C și rulați-o pentru a determina adresele dispozitivelor de pe magistrala I2C.

    La fiecare 5 secunde, programul scanează dispozitivele și emite adrese pe portul COM. Am găsit două dispozitive cu adrese 0x3F și 0x77. BMP180 are în mod implicit adresa 0x77, ceea ce înseamnă că indicatorul LCD are adresa 0x3F.
    În unele dintre circuitele cărții, locurile în care semnalele SDA și SCL sunt conectate la placa Arduino sunt amestecate. Ar trebui să fie: SDA - la A4, SCL - la A5. Dacă modulul BMP180 are cinci pini, atunci pinul VIN este furnizat +5 volți.

    Schema de cablare

    Acum asamblați complet circuitul. Am folosit un LED RGB catod comun montat pe placă împreună cu rezistențe de 150 ohmi. Catodul comun este conectat la pinul GND, pinii rămași sunt conectați conform diagramei. Nu este nevoie să faceți modificări schiței, deoarece luminozitatea LED-urilor se modifică conform unei legi ciclice.
    Diagrama arată conectarea unui LED RGB cu un anod comun, ca în carte.
    Dacă nu sunt vizibile caractere pe ecranul LCD1602, rotiți controlul luminozității. Lumina de fundal a indicatorului consumă destul de mult curent, așa că folosește o sursă de alimentare cu un curent de minim 2 A. Am folosit un hub USB cu o sursă de alimentare externă de 2 A.
    Circuitul a folosit un sonerie piezo ZP-22. Rezistorul conectat la sonerie este de 100 ohmi. Frecvența sunetului poate fi modificată în program. Am ales o frecventa de 1000 Hz. Dacă întâlniți un sonerie cu o frecvență fixă ​​a sunetului, atunci îl puteți porni și opri pur și simplu prin aplicarea și eliminarea tensiunii, ca un LED obișnuit. Când începe schița, se aude un scurt bip. Puteți activa semnalizarea periodică în timp ce programul rulează prin decomentarea liniei //bzz(100); în schiță.
    În proiect am folosit un senzor DHT11 sub formă de modul cu o rezistență de 4,7 kOhm deja montată. Rezistența poate fi de la 4,7 la 10 kOhm.
    Conectați pinul Vcc al modulului de ceas DS1302 la magistrala de +5 volți. În acest fel, veți reduce consumul de energie a bateriei, în esență, va funcționa numai atunci când alimentarea Arduino este oprită.

    Program (schiță)

    Biblioteca bmp085 este folosită pentru deservirea BMP180. Valoarea presiunii depinde de altitudinea zonei. Pentru valoarea corectă a presiunii atmosferice, trebuie să selectați altitudinea. Pentru a face acest lucru, editați linia dps.init(MODE_STANDARD, 10000, true); Înălțimea mea este de 100 m (10000 cm). Fragmentul de calcul al presiunii este preluat din exemplul BMP085_test2.ino al bibliotecii bmp085.

    Schița meteo_P

    #include
    #include
    #include
    #include „DHT.h”
    #include
    BMP085 dps = BMP085();
    lung Presiune = 0, Altitudine = 0;
    nesemnat lung time1 = 0;

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

    int kCePin = 4; // RST DS1302
    int kIoPin = 3; // Date DS1302
    int kSclkPin = 2; //CLK DS1302
    DS1302 rtc(kCePin, kIoPin, kSclkPin);

    int REDpin = 9;
    int GREENpin = 6;
    int BLUEpin = 11;

    LiquidCrystal_I2C lcd(0x3f, 16, 2); // introduceți adresa dvs. 0x20...0xff adresa
    memTime lung nesemnat;
    int bzzPin = 8;

    void HumTempRead() (
    float hum = dht.readHumidity();
    float temp = dht.readTemperature();
    if (isnan(hum) || isnan(temp)) (
    Serial.println("Nu s-a putut citi de la senzorul DHT!");
    lcd.setCursor(0, 1);
    lcd.print("H=--% T=---");
    lcd.setCursor(11, 1);
    lcd.print((char)223);
    lcd.setCursor(12, 1);
    lcd.print("C");
    ) altfel (
    lcd.setCursor(0, 1);
    lcd.print("H=");
    lcd.setCursor(2, 1);
    lcd.print(hum);
    lcd.setCursor(4, 1);
    lcd.print("% T=+");
    lcd.setCursor(9, 1);
    lcd.print(temp);
    lcd.setCursor(11, 1);
    lcd.print((char)223);
    lcd.setCursor(12, 1);
    lcd.print("C ") ;
    }
    }

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

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

    void setup() (
    Serial.begin(9600);
    Wire.begin();
    întârziere (1000);

    dps.init(MODE_STANDARD, 10000, adevărat); // 100 de metri (înălțimea deasupra nivelului mării în cm)

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

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

    rtc.halt(fals);
    rtc.writeProtect(false);

    //rtc.setDOW(VINERI); // Setați Ziua săptămânii la VINERI setați ziua săptămânii
    //rtc.setTime(4, 58, 0); // Setați ora la 12:00:00 (format 24 de ore)
    //rtc.setDate(6, 8, 2010); // Setați data la 6 august 2010 setați data (zi, lună, an)
    }

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

    dacă ((millis() - memTime > 2000) sau (millis()< memTime)) { // DHT11/22 1 time each 2 seconds
    HumTempRead();
    memTime = milis();
    }
    întârziere (100);

    dacă (((milis() - time1) / 1000.0) >= 1.0) (
    dps.calcTrueTemperature();
    timp1 = milis();
    }
    dps.getPressure(&Presiunea);
    Serial.print(" Presiune (Pa):");
    Serial.println(Presiune);

    lung p2;
    int pi;
    p2 = (Presiune / 133,3224); // Pa în mmHg.
    pi = trunc(p2); // eliminând partea fracționară a numărului

    lcd.setCursor(0, 0);
    lcd.print("P=");
    lcd.setCursor(2, 0);
    lcd.print(pi); // ieșire atm. presiune pe LCD
    lcd.setCursor(5, 0);
    lcd.print("mm");
    // întârziere(3000);
    //bzz(100); // anulați comentariul dacă doriți să ascultați semnale
    {
    pentru (valoare int = 0; valoare<= 255; value += 1) {
    analogWrite(REDpin, valoare);
    analogWrite(GREENpin, 255 - valoare);
    analogWrite(BLUEpin, 255);
    întârziere(5);
    }

    pentru (valoare int = 0; valoare<= 255; value += 1) {
    analogWrite(REDpin, 255);
    analogWrite(GREENpin, valoare);
    analogWrite(BLUEpin, 255 - valoare);
    întârziere(5);
    }

    pentru (valoare int = 0; valoare<= 255; value += 1) {
    analogWrite(REDpin, 255 - valoare);
    analogWrite(GREENpin, 255);
    analogWrite(BLUEpin, valoare);
    întârziere(5);
    }
    }
    }

    În Catalogul de fișiere puteți descărca schița și bibliotecile care au fost utilizate în proiect.

    Importați bibliotecile LiquidCrystal_I2C.zip, bmp085.zip, DS1302.zip și DHT.zip din arhiva descărcată în Arduino IDE. Accesați meniul Schiţa Conectați biblioteca Adăugați o bibliotecă .ZIP... iar în fereastră selectați arhiva zip a bibliotecii.
    Încărcați schița meteo_P. Înlocuiți adresa LCD1602 din schiță cu valoarea obținută prin scanarea magistralei I2C. Compilați și rulați schița.
    Dacă schița funcționează, deschideți monitorul portului și vizualizați mesajele afișate. Ajustați înălțimea în instrucțiunea dps.init(MODE_STANDARD, 10000 , true); pentru a obține valori reale ale presiunii.
    Setează-ți ceasul. Decomentează linia //rtc.setTime(4, 58, 0); iar în paranteze indicați ora curentă (ora, minutele și secundele separate prin virgule) și reîncărcați schița în controler. După setarea orei, comentați din nou această linie și rulați din nou schița.
    Dacă te enervează iluminarea luminii de noapte, o poți ajusta schimbând lungimea întârzierii în buclele for de la sfârșitul schiței. Cu întârziere(2); ciclul durează 2-3 secunde, cu întârziere(5); — de la 4 la 5 secunde, cu întârziere(30); - până la 15-16 secunde. Informațiile de pe indicator vor fi actualizate la același interval.
    Când se utilizează stația meteo în mod autonom, de ex. fără a vă conecta la portul USB al computerului, comentați liniile din schiță cu cuvintele Serial ... pentru a dezactiva ieșirea informațiilor către monitorul portului COM.

    PS. În schița cărții și în exemplele pentru biblioteca DHT este indicată linia de definiție #definiți DHTTYPE DHT 11. Schița începe, dar se blochează după câteva ore. Ceasul se oprește, afișajul nu se schimbă. Pe monitorul portului apare un mesaj vag, care conține un link către dht.
    În acest rând am eliminat literele DHT, adică. a făcut #define DHTTYPE 11. După aceasta, schița a început să funcționeze stabil.

    Articol actualizat la 25 iunie 2018

    Resurse folosite
    1. Petin V.A. Proiecte care utilizează controlerul Arduino (Electronică) ediția a 2-a, Sankt Petersburg. BHV-Petersburg, 2015 464 p.
    2. Petin V. A., Binyakovsky A. A. Enciclopedia practică a Arduino. - M., DMK Press, 2017. - 152 p.
    3. http://arduinolearning.com/code/i2c-scanner.php
    4. http://arduino.ru/forum/programmirovanie/ds1302lcd1602
    5. http://robotehnika18.rf/how-to-connect-lcd-1602-to-arduino-via-i2c/
    6. exemplu BMP085_test2.ino din biblioteca bmp085.zip
    7. http://proginfo.ru/round/
    8. http://homes-smart.ru/index.php?id=14&Itemid=149&option=com_content&view=article
    9. http://iarduino.ru/lib/datasheet%20bmp180.pdf
    10. http://it-donnet.ru/hd44780_dht11_arduino/

    Stație meteo DIY.

    Era seară, nu mai era nimic de făcut după Anul Nou. Ca de obicei, în timpul sărbătorilor de iarnă de Anul Nou vreau să-mi ocup capul și mâinile cu ceva util și creativ. În aceste sărbători de Anul Nou am decis să fac o stație meteo cu propriile mele mâini. Am început pregătirile din timp, am achiziționat și asamblat toate componentele înainte de Anul Nou și am făcut programarea principală în perioada sărbătorilor.

    (Sunt o mulțime de fotografii sub tăietură!)

    În primul rând, voi trece prin componentele pe care nu le voi da link-uri, deoarece produsele de pe eBay (în contul meu personal) au fost arhivate. Am cumpărat multe componente pe îndelete de pe eBay. Am încercat o licitație pentru prima dată înainte de a cumpăra întotdeauna „cumpără-l acum”. Ce pot să spun, dacă nu te grăbești să faci cumpărături, poți cumpăra unele componente mai ieftine (diferența este uneori de două ori mai mare).

    Senzor de presiune VMR085
    Acesta este senzorul principal. Când l-am văzut pe eBay, am știut că vreau să construiesc o stație meteo acasă.
    Senzorul a sosit într-un plic obișnuit, acoperit cu folie cu bule în interior.

    În interiorul plicului se afla cartea de vizită a vânzătorului și un senzor, ambalate într-o pungă antistatică și învelită într-un alt strat de folie cu bule.

    Punga antistatică a fost sigilată astfel încât umiditatea din timpul zborului să nu amenințe senzorul

    Scoatem senzorul. Pe o parte există o linie lipită de contacte, care au fost introduse în spumă pentru a preveni îndoirea acestora. Pe de altă parte există senzorul în sine și marcajele de contact.




    Totul ar fi bine, dar marcajele de contact sunt aplicate într-o imagine în oglindă.
    Senzorul este conectat prin magistrala I2C și este alimentat de 3,3 V. Adică pentru funcționarea normală aveți nevoie de 4 fire (+, -, SDA, SCL)
    Puteți interoga senzorul în 2 moduri: fie prin bibliotecă, fie folosind funcții direct în schiță.
    Exemplu de program:

    #include

    #define BMP085_ADDRESS 0x77 // adresa I2C a BMP085

    Const unsigned char OSS = 0; // Setarea supraeșantionării

    // Valori de calibrare
    int ac1;
    int ac2;
    int ac3;
    unsigned int ac4;
    unsigned int ac5;
    unsigned int ac6;
    int b1;
    int b2;
    int mb;
    int mc;
    int md;

    Temperatura scurta;
    presiune lungă;

    Void setup()
    {
    Serial.begin(9600);
    Wire.begin();
    bmp085Calibrare();
    }

    buclă goală ()
    {
    temperatura = bmp085GetTemperature(bmp085ReadUT());
    presiune = bmp085GetPressure(bmp085ReadUP());
    Serial.print("Temperatura: „);
    Serial.print (temperatura/10,0, DEC);
    Serial.println("C");
    Serial.print("Presiune: „);
    Serial.print(presiune/133.322, DEC);
    Serial.println(“mm Hg”);
    Serial.println();
    întârziere (1000);
    }

    Void bmp085Calibrare()
    {
    ac1 = bmp085ReadInt(0xAA);
    ac2 = bmp085ReadInt(0xAC);
    ac3 = bmp085ReadInt(0xAE);
    ac4 = bmp085ReadInt(0xB0);
    ac5 = bmp085ReadInt(0xB2);
    ac6 = bmp085ReadInt(0xB4);
    b1 = bmp085ReadInt(0xB6);
    b2 = bmp085ReadInt(0xB8);
    mb = bmp085ReadInt(0xBA);
    mc = bmp085ReadInt(0xBC);
    md = bmp085ReadInt(0xBE);
    }

    Short bmp085GetTemperature (unsigned int ut)
    {
    lung x1, x2;
    x1 = (((lung)ut - (lung)ac6)*(lung)ac5) >> 15;
    x2 = ((lung)mc<< 11)/(x1 + md);
    b5 = x1 + x2;

    Întoarcere ((b5 + 8)>>4);
    }

    Long bmp085GetPressure (nesemnat de mult timp)
    {
    lung x1, x2, x3, b3, b6, p;
    nesemnat lung b4, b7;
    b6 = b5 - 4000;
    // Calculați B3
    x1 = (b2 * (b6 * b6)>>12)>>11;
    x2 = (ac2 * b6)>>11;
    x3 = x1 + x2;
    b3 = (((((lung)ac1)*4 + x3)<>2;
    // Calculați B4
    x1 = (ac3 * b6)>>13;
    x2 = (b1 * ((b6 * b6)>>12))>>16;
    x3 = ((x1 + x2) + 2)>>2;
    b4 = (ac4 * (nesigned long)(x3 + 32768))>>15;
    b7 = ((nesemnat lung)(sus - b3) * (50000>>OSS));
    dacă (b7< 0x80000000)
    p = (b7<<1)/b4;
    altfel
    p = (b7/b4)<<1;
    x1 = (p>>8) * (p>>8);
    x1 = (x1 * 3038)>>16;
    x2 = (-7357 * p)>>16;
    p += (x1 + x2 + 3791)>>4;
    întoarcere p;
    }

    // Citiți 1 octet din BMP085 la „adresă”
    char bmp085Read (adresă caracter nesemnată)
    {
    date char nesemnate;

    Wire.write(adresa);
    Wire.endTransmission();
    Wire.requestFrom(BMP085_ADDRESS, 1);
    în timp ce(!Wire.available())
    ;
    return Wire.read();
    }

    Int bmp085ReadInt (adresă caracter nesemnată)
    {
    caracter nesemnat msb, lsb;
    Wire.beginTransmission(BMP085_ADDRESS);
    Wire.write(adresa);
    Wire.endTransmission();
    Wire.requestFrom(BMP085_ADDRESS, 2);
    în timp ce(Wire.available()<2)
    ;
    msb = Wire.read();
    lsb = Wire.read();
    return (int) msb<<8 | lsb;
    }

    // Citiți valoarea temperaturii necompensate
    unsigned int bmp085ReadUT()
    {
    unsigned int ut;
    // Scrieți 0x2E în Register 0xF4
    // Aceasta solicită o citire a temperaturii
    Wire.beginTransmission(BMP085_ADDRESS);
    Wire.write(0xF4);
    Wire.write(0x2E);
    Wire.endTransmission();
    // Așteptați cel puțin 4,5 ms
    întârziere(5);
    // Citiți doi octeți din registrele 0xF6 și 0xF7
    ut = bmp085ReadInt(0xF6);
    return ut;
    }

    // Citiți valoarea presiunii necompensate
    nesemnat lung bmp085ReadUP()
    {
    caracter nesemnat msb, lsb, xlsb;
    unsigned long up = 0;
    // Scrieți 0x34+(OSS<<6) into register 0xF4
    // Solicitați o citire a presiunii cu setare de supraeșantionare
    Wire.beginTransmission(BMP085_ADDRESS);
    Wire.write(0xF4);
    Wire.write(0x34 + (OSS<<6));
    Wire.endTransmission();
    // Așteptați conversia, timpul de întârziere depinde de OSS
    întârziere (2 + (3<// Citiți registrul 0xF6 (MSB), 0xF7 (LSB) și 0xF8 (XLSB)
    Wire.beginTransmission(BMP085_ADDRESS);
    Wire.write(0xF6);
    Wire.endTransmission();
    Wire.requestFrom(BMP085_ADDRESS, 3);
    // Așteptați ca datele să devină disponibile
    în timp ce(Wire.available()< 3)
    ;
    msb = Wire.read();
    lsb = Wire.read();
    xlsb = Wire.read();
    sus = (((nesemnat lung) msb<< 16) | ((unsigned long) lsb << 8) | (unsigned long) xlsb) >> (8-OSS);
    întoarce-te sus;
    }


    În plus, senzorul are propriul său senzor termic pentru compensarea presiunii și un altimetru

    Arduino Nano v3.0
    Aceasta este inima întregii stații meteo. Mai simplu spus, controlerul are dimensiuni miniaturale.
    am cumparat
    Nu voi vorbi în detaliu despre controler, deoarece acest lucru a fost deja făcut înaintea mea:


    Pachetul lightake a fost prefabricat, controlerul a venit într-un pachet cu un cablu USB și un Arduino într-o pungă antistatică sigilată.

    Pentru a estima dimensiunea, am plasat o monedă de 1 rublă lângă Arduino.

    Placa de control de aproape



    Cablul USB este bun, cu inel de ferita. Arduino este alimentat printr-un cablu USB. Mediul de dezvoltare poate fi descărcat (pagina de descărcare). Limbajul este asemănător „C”, nu au fost probleme cu stăpânirea lui, deoarece programez mult în el la serviciu.

    Ecran LCD
    La serviciu am găsit în coșuri un ecran LCD 1602 compatibil. A trebuit să schimb conexiunea, deoarece nu am putut găsi o fișă de date pentru ea. Ca urmare, LCD-ul a început să funcționeze.

    Dar după o scurtă perioadă de utilizare, am observat că acest ecran nu mi-a fost suficient și nu ar fi posibil să afișez mai multe date, deoarece are doar 2 rânduri a câte 16 caractere fiecare. La început pare că acești parametri sunt suficienți, dar când te apuci de programare, îți dai seama că maximul pe care îl poți strânge este de 3-4 parametri. Și dacă faci un meniu (mă gândeam să fac un meniu pe acest ecran), atunci mai rămân doar 1-2 parametri spațiu liber.
    Drept urmare, am început să caut un alt ecran. La început m-am uitat cu atenție la ecranul grafic de la Nokia 3310 și am participat chiar la licitația eBay pentru a-l cumpăra, dar nu a ieșit (de care sunt foarte fericit), așa că a trebuit să renunț la acest ecran. Acum înțeleg că ar fi prea mic pentru scopurile mele, deoarece există ceva cu care să se compare.
    În timp ce mă uitam la întâmplare prin scuturi pe Arduino, am dat peste un ecran grafic 12864 pe un controler ST7920. Acest ecran are dimensiunea potrivită și rezoluție bună pentru nevoile mele (128x64). Adică, puteți plasa cu ușurință 6-7 rânduri de 20 de caractere într-un font care poate fi citit în mod normal. Deoarece ecranul este grafic, pe lângă text, graficele pot fi plasate în diferite fonturi. Pe scurt, asta este exact ceea ce aveam nevoie, totul era prezent pe acest ecran, așa că nu am putut rezista și l-am comandat.
    Coletul a sosit rapid și a fost ambalat standard: un plic de folie cu bule, în interior mai era un strat de folie cu bule și un ecran într-o pungă antistatică:






    Pentru a estima dimensiunea, am plasat o monedă de 1 rublă lângă LCD.




    Pentru a conecta rapid ecranul la Arduino, am lipit o linie de contacte la pinii LCD. LCD-ul poate fi conectat printr-o magistrală serială sau una paralelă. Am ales prima opțiune, deoarece există deja puține contacte Arduino gratuite.
    Conexiune (preluată de pe web):

    - Pinul 1 (GND) este conectat la magistrala comună
    - Pinul 2 (VCC) este conectat la magistrala de alimentare +5V, iar consumul de curent este relativ mic, iar afișajul poate fi alimentat de la stabilizatorul Arduino încorporat.
    - Pinii 4, 5 și 6 se conectează la ieșirile digitale Arduino, formând interfața serială SPI:
    pinul 4 – (RS) – corespunde liniei CS (de exemplu 7)
    pinul 5 – (RW) – corespunde liniei MOSI (de exemplu 8)
    pinul 6 – (E) – corespunde liniei SCK (de exemplu 3)
    Numerele de contact Arduino pot fi orice, principalul lucru este să nu uitați să le indicați corect în textul programului atunci când inițializați afișajul.
    - Pinul 15 (PSB) este conectat la magistrala comună.
    - Contactele 19 (A) și 20 (K) sunt sursa de alimentare cu iluminare de fundal (+5V și respectiv GND). Pentru a regla luminozitatea luminii de fundal, puteți utiliza un rezistor variabil de 10 kOhm conectat între magistrala de alimentare și GND. Tensiunea de la motorul său este furnizată pinului 19 al afișajului.
    Conform acestor instrucțiuni, am conectat totul, cu excepția luminii de fundal. Am folosit Arduino PWM pentru a alimenta lumina de fundal.
    Pentru a conecta programatic LCD-ul la Arduino, se folosește biblioteca u8glib. Îl poți descărca. Dacă există probleme la descărcare, pot încărca biblioteca pe narod.ru.
    Biblioteca în sine nu este complicată și vă permite să afișați text în diferite fonturi, să desenați o linie, să desenați forme geometrice simple (dreptunghi, cerc) și să afișați propriile imagini pregătite într-un mod special. În principiu, acest instrument este suficient pentru majoritatea sarcinilor.
    Iată rezultatul unui program simplu:

    Programul în sine:

    #include „U8glib.h”

    U8GLIB_ST7920_128X64 u8g(3, 9, 8, U8G_PIN_NONE); // SPI E = 3, RW = 9, RS = 8

    // Subrutină pentru determinarea memoriei libere
    int freeRam() (
    extern int __heap_start, *__brkval;
    int v;
    return (int) &v - (__brkval == 0? (int) &__heap_start: (int) __brkval);
    }

    Void setup(void) (
    u8g.setFont(u8g_font_6x10); // font
    u8g.setRot180(); //Întoarce ecranul
    analogWrite(6, 115); // Setați luminozitatea ecranului (anodul de iluminare de fundal la 6 pini)
    }

    Buclă goală (nulă) (
    u8g.firstPage();
    do(

    u8g.setPrintPos(1, 12); // poziție
    u8g.print("Bună ziua!!!"); // scoaterea textului
    u8g.drawBox(0,22,128,9); // Pictează dreptunghiul în alb
    u8g.setColorIndex(0); // cerneală albă, fundal negru
    u8g.setPrintPos(1, 30); // poziție
    u8g.print("Cuvânt..."); // scoaterea textului

    U8g.setColorIndex(1); // cerneală albă, fundal negru
    u8g.setPrintPos(1, 50); // poziție
    u8g.print("După pornire ="); // textul de ieșire
    u8g.setPrintPos(85, 50); // poziție
    u8g.print(millis() / 1000); // afișează numărul de secunde după pornire
    u8g.setPrintPos(1, 64); // poziție
    u8g.print(freeRam()); // arată câtă memorie este ocupată
    ) while(u8g.nextPage());

    Întârziere (200);
    }

    Ceas în timp real DS1307
    O altă componentă pentru stația mea meteo. Acest scut implementează un ceas în timp real. Le-am comandat pe eBay. Vânzătorul a trimis eșarfa ceasului într-o cutie nerealist de mare


    În interiorul cutiei erau două coli A4 cu reclamă și o batistă de ceas învelită în celofan


    Aș dori să menționez că taxa nu depășește 2 ruble. monedă, iar cutia măsura 13x15x5 cm.
    Placa a fost ambalată într-o pungă antistatică

    Şal aproape



    A trebuit să mă ocup de acest modul. În primul rând, au existat dificultăți de conectare. Și în al doilea rând, nu există cuarț pe această placă. Dacă aș fi știut că voi petrece atât de mult timp pe modul, cel mai probabil l-aș fi asamblat singur, deoarece internetul este plin de diagrame. Cel mai simplu circuit conține 4-5 componente.
    In ceea ce priveste legatura. Am găsit o bibliotecă care spunea că interfața I2C poate fi conectată nu la intrările analogice obișnuite Arduino (A4 și A5), ci la oricare dintre cele discrete. Am făcut-o așa cum a fost scris. La început nimic nu a mers, dar după un dans lung cu tamburina, ceasul a pornit. Ei bine, m-am gândit, asta e, problemele s-au terminat, dar după ce am încercat să conectez același modul la alt Arduino, dansul cu tamburina a continuat. Am petrecut mult timp căutând o soluție la această problemă și aproape peste tot a fost indicată fie o conexiune incorectă, fie absența rezistențelor pull-up pe contactele SCL și SDA. Deja voiam să intru în placă cu un fier de lipit, dar pe un forum am dat din greșeală de un cod în care se spunea că se conectează SCL și SDA la porturile standard I2C de pe Arduino. După o conexiune standard, totul a funcționat imediat.
    Acum despre cuarț. Nu știu ce fel de cuarț au pus chinezii acolo, dar ceasurile cu astfel de cuarț au fugit cu 10-11 secunde pe zi. Această eroare este de 5 minute pe lună și 1 oră pe an. Nu este nevoie de un astfel de ceas. A trebuit să intru din nou online și să caut cum să repar acest bug. Prima soluție care apare spune că trebuie să împămânți cuarțul. Am făcut-o - rezultatul a fost zero. De asemenea, am găsit undeva că trebuie să găsesc o placă de bază veche și să scot de acolo quartzul ceasului. Am făcut-o - există un rezultat. Acum ceasul fuge nu cu 10-11 secunde, ci cu 1,5 secunde pe zi. Să spunem doar că s-a îmbunătățit, dar este departe de a fi ideal. Deoarece nu mai am chef să mă joc cu un fier de lipit, s-a decis să reglez ceasul programatic, adică să reglez ceasul la valoarea necesară o dată pe zi. După 10 zile, ceasul a sunat cu cel mult o secundă. Metoda este bună, dar numai când dispozitivul de sincronizare Arduino este conectat la curent, altfel ceasul funcționează pe baterie și tot fuge.
    Un mic program de testare:

    #include „Wire.h”
    #define DS1307_I2C_ADDRESS 0x68 // SDA A4, SCL A5

    Octet decToBcd(byte val)
    {
    return ((val/10*16) + (val%10));
    }

    Byte bcdToDec(byte val)
    {
    return ((val/16*10) + (val%16));
    }

    Void setDateDs1307(octet secundă, // 0-59
    octet minut, // 0-59
    octet oră) // 0-99
    {

    Wire.write(0);
    Wire.write(decToBcd(secunda));
    Wire.write(decToBcd(minut));
    Wire.write(decToBcd(ora));
    Wire.endTransmission();
    }

    Void getDateDs1307(octet *secundă,
    octet *minut,
    octet *oră)
    {

    Wire.beginTransmission(DS1307_I2C_ADDRESS);
    Wire.write(0);
    Wire.endTransmission();

    Wire.requestFrom(DS1307_I2C_ADDRESS, 3);

    *secunda = bcdToDec(Wire.read());
    *minut = bcdToDec(Wire.read());
    *ora = bcdToDec(Wire.read());
    }

    Void setup()
    {
    octet secundă, minut, oră;
    Wire.begin();
    Serial.begin(9600);

    Al doilea = 45;
    minut = 5;
    ora = 16;

    SetDateDs1307(secundă, minut, oră);
    }

    buclă goală ()
    {
    octet secundă, minut, oră;

    GetDateDs1307(&second, &minute, &hour);
    Serial.print(oră, DEC);
    Serial.print(":");
    Serial.print(minut, DEC);
    Serial.print(":");
    Serial.println(al doilea, DEC);

    Întârziere (1000);
    }


    Biblioteca nu este folosită aici, iar funcțiile pentru timpul de citire și scriere sunt trunchiate.

    Senzor de temperatură și umiditate DHT11
    Nu este nimic de spus despre acest senzor. Nici nu l-as folosi daca nu ar fi necesara umiditatea. Din păcate, nu i-am făcut o fotografie când l-am primit, așa că nu vor fi fotografii. Fotografiile senzorului pot fi văzute mai jos, unde l-am conectat la Arduino. Conexiunea senzorului este simplă (+, ieșire digitală, -). De obicei, senzorii sunt fabricați cu patru pini. Cu acest factor de formă, al treilea pin nu este conectat la nimic.
    Puteți folosi biblioteca pentru a vă conecta la Arduino. Îl poți descărca.
    Un mic program de testare cu ieșire de informații pe afișajul LCD 1602:

    // include codul bibliotecii:
    #include
    #include

    // Declara obiecte
    dht11 DHT11;
    LiquidCrystal lcd (12, 11, 6, 5, 4, 3);

    #define DHT11PIN 7
    int i;

    Void setup()
    {
    lcd.begin(16, 2);
    lcd.print("Stare: „);
    i=0;
    }

    buclă goală ()
    {
    int chk = DHT11.read(DHT11PIN);
    lcd.setCursor(8, 0);
    comutator (chk)
    {
    cazul 0: lcd.print(“OK „); break;// lcd.setCursor(11, 0); lcd.print(millis()/2000); pauză;
    caz -1: lcd.print(„Eroare sumă de verificare”); mErr(); pauză;
    case -2: lcd.print("Eroare de expirare"); mErr(); pauză;
    implicit: lcd.print ("Eroare necunoscută"); mErr(); pauză;
    }
    întârziere (500);
    lcd.setCursor(15, 0);
    comutator(i)
    {
    cazul 0: lcd.print("^"); lcd.setCursor(15, 1); lcd.print(" ");break;
    cazul 1: lcd.print("v"); lcd.setCursor(15, 1); lcd.print(" ");break;
    implicit: lcd.setCursor(15, 1); lcd.print("E"); pauză;
    }
    i=i+1;
    dacă (i>1) i=0;
    lcd.setCursor(0, 1);
    lcd.print("H=");
    lcd.setCursor(2, 1);
    lcd.print((float)DHT11.umiditate, 0);
    lcd.setCursor(4, 1);
    lcd.print("%");
    lcd.setCursor(8, 1);
    lcd.print("T=");
    lcd.setCursor(10, 1);
    lcd.print((float)DHT11.temperature, 0);
    lcd.setCursor(12, 1);
    lcd.print("C");

    Void Err ()
    {
    lcd.setCursor(2, 1);
    lcd.print("**");
    lcd.setCursor(10, 1);
    lcd.print("**");
    i=5;
    }


    Senzorul are unele dezavantaje - datele de la senzor sunt doar în numere întregi, iar intervalul este slab.

    Se pare că am scris despre toate componentele. Tot ce rămâne este să adunăm totul într-un singur întreg.
    Hopa, aproape am uitat! Pentru a asambla dispozitivul, aveți nevoie de o husă. Am comandat și husa pe Ebay. Vânzătorul s-a dovedit a fi din Anglia. Coletul a ajuns repede, dar nu i-am făcut poze. Toate fotografiile cazului sunt mai jos.

    În primul rând, am asamblat totul pe masă folosind cablaje speciale. Am scris un program de testare și l-am încărcat în controler.



    De fapt, culoarea albastră a luminii de fundal este mult mai strălucitoare. Chiar și la luminozitate minimă (Bright=5), cadrul este iluminat.

    Pentru a asambla totul fără fir, s-a decis să se facă o mini placă de bază, iar pe conectori au fost puse plăci și scuturi Arduino. Dacă se întâmplă ceva, acestea pot fi îndepărtate rapid și ușor. De asemenea, am decis să atașez ecranul LCD și butoanele de control la conectori, doar pentru a lipi senzorul de temperatură pe fire.
    Asa a iesit esarfa



    În ultima fotografie nu am spălat complet fluxul. Am lipit cauciuc poros sub scuturi de lângă conectori, astfel încât să existe măcar puțin suport. Deși, de fapt, scuturile din conectorii de pe contacte rezistă foarte bine.

    Placa de baza cu scuturi instalate si placa Arduino.

    Așa arată o conexiune completă la placa de bază


    În loc de nasturi, am folosit un scut de casă lipit pe o placă. Am folosit ca butoane butoane de la șoareci vechi.
    După cum puteți vedea, numărul de fire a scăzut.

    Principala problemă a plasării în carcasă este decuparea unei caneluri netede pentru ecranul LCD. Indiferent cât de mult am încercat, tot nu a ieșit perfect. În unele locuri, golurile au fost puțin mai mari de 1 mm. Pentru ca totul să arate îngrijit, am luat un etanșant negru pentru acvariu și am umplut toate crăpăturile, în același timp am atașat ecranul de acest etanșant. După ce s-a uscat sigilantul, am tăiat excesul din exterior. În lumină puternică, etanșantul este vizibil, dar în lumină normală, totul se îmbină cu corpul.
    Asa arata carcasa din interior cu un ecran LCD si placa de baza instalate.

    Așa arată din exterior în lumină puternică (scuze pentru amprentele digitale, le-am văzut când sortam fotografiile).

    M-am gândit mult timp la cum să potrivesc butoanele în carcasă și, cel mai important, ce butoane să folosesc...
    In magazinele de radio-electronica le-a placut butonul cu un pin lung si varfurile care se potrivesc pe acest pin. Aceste butoane sunt folosite pentru lipirea plăcii. Totul ar fi bine, dar au un minus - cursa de apăsare este foarte mică și puternică.
    A trebuit să punem butoanele în două etape: prima a fost să plasăm butoanele pe tablă, a doua a fost să montam această placă pe o altă placă. Și apoi puneți toate acestea în corp pe ghidaje.

    Iată cum arată o eșarfă cu nasturi:



    Iată cum arată placa suport:


    Aici puteți vedea ghidajele în care este introdusă placa cu butoane. Unele elemente au fost lipite pentru a da rigiditate plăcii.

    Acum punem totul în corp
    Fără butoane de conectare:


    Cu conexiune prin buton:

    Închideți carcasa și porniți-o. Totul funcționează excelent, butoanele funcționează așa cum ar trebui.

    La final, postez un scurt videoclip cu dispozitivul care funcționează în diferite moduri:
    http://www.youtube.com/watch?v=KsiVaUWkXNA&feature=youtu.be
    Pentru cei care nu văd videoclipul aici, aici este link-ul către

    Este timpul să încheiem recenzia.
    Voi scrie puțin despre program și apoi câteva concluzii scurte. Când am scris programul, nu credeam că voi atinge foarte repede limita de 30.720 de octeți.


    A trebuit să optimizez codul. Am mutat multe bucăți de cod în subrutine. Nu m-aș fi gândit niciodată că o instrucțiune switch...case în formă compilată ocupă mai mult spațiu decât mai multe instrucțiuni if...else. Declararea corectă a variabilelor economisește și spațiu. Dacă declarați o matrice lungă, deși este foarte posibil să obțineți pe octeți, atunci depășirea memoriei ajunge la 500 de octeți, în funcție de dimensiunea matricei. Când scrii un program, nu te gândești la el și abia mai târziu, când analizezi programul, realizezi că ai greșit unele lucruri și începi să optimizezi codul. După ce s-au rezolvat problemele cu dimensiunea programului, am întâlnit o limitare a RAM. Acest lucru a fost exprimat prin faptul că programul a început să se înghețe după încărcare. A trebuit să introduc o subrutină pentru calcularea memoriei RAM liberă. Ca urmare, am fost forțat să renunț la un algoritm de prognoză meteo, deoarece trebuie să afișeze pictograme pe ecran. Algoritmul în sine funcționează, dar rezultatul pictogramelor a trebuit să fie înregistrat. Încă mai am idei despre cum să optimizez codul, dar în viitorul apropiat voi lăsa dispozitivul să funcționeze așa cum este pentru a-i evalua performanța și a identifica toate erorile.

    Acum câteva concluzii
    Contra
    1) Preț. Justificarea acestui dezavantaj este că un hobby nu este niciodată ieftin.

    Pro
    1) Funcționalitate excelentă a dispozitivului
    2) Creșterea funcțiilor este limitată doar de controlerul utilizat și de propria dorință
    3) Plăcerea estetică din contemplare și satisfacția morală din faptul că în sfârșit am asamblat și completat acest dispozitiv

    Plănuiesc să cumpăr +85 Adaugă la favorite Mi-a placut recenzia +137 +304

    Cele mai bune articole pe această temă