Come configurare smartphone e PC. Portale informativo
  • casa
  • In contatto con
  • Progetti di mini stazioni meteo Arduino Pro. Modulo sensore di pressione barometrica BMP085 per arduino (o come realizzare una stazione meteorologica con le proprie mani)

Progetti di mini stazioni meteo Arduino Pro. Modulo sensore di pressione barometrica BMP085 per arduino (o come realizzare una stazione meteorologica con le proprie mani)

Come la maggior parte delle persone che lavorano, perseguire i propri progetti occupa l’unico tempo libero che ti rimane. Ecco perché non creavo nulla da molto tempo e non vedevo l’ora di fare qualcosa. Questa opportunitàè apparso, stranamente, all'università. È settembre fuori dalla finestra, quarto anno e imminenti corsi sulla progettazione di circuiti. Ci è stato detto che i corsi potevano essere svolti in due varianti: cartacea e hardware.

Per 5 anni, i corsi cartacei nella nostra università sono stati svolti secondo il principio "prendi quelli vecchi e mettili insieme". Questo approccio non mi andava bene a causa della sua routine, quindi ho scelto immediatamente i corsi sull'hardware. Come è stato proposto il cuore del corso Microcontrollore Arduino grazie alla sua facilità di apprendimento. Dopo aver determinato il tipo di corso, rimaneva un'altra domanda: cosa si dovrebbe fare esattamente. Poiché non avevo esperienza nella programmazione di microcontrollori, ho subito aperto Google e ho iniziato a studiare progetti esistenti. Ci sono molti progetti, alcuni abbastanza semplici, altri ingegnosi (scanner 3D, per esempio), ma la stragrande maggioranza non aveva applicazione pratica. E volevo solo qualcosa che non restasse sullo scaffale a raccogliere polvere. Dopo un'escursione di mezz'ora nel mondo di Arduino, mi sono interessato al tema delle stazioni meteorologiche domestiche e i progetti non mi sono sembrati molto difficili da realizzare (che è ciò che ha attirato maggiormente il nuovo arrivato).

È così che è stato scelto l'argomento del corso e col tempo non sembravano esserci problemi.

Selezione dei componenti

Osservando diversi progetti, mi sono reso conto che Nano o addirittura Pro Mini, ma ho comunque scelto Arduino Uno nella speranza che mi piacerebbe programmare per Arduino e implementare altri progetti in futuro. Non avevo mai tenuto in mano un saldatore prima, quindi per uno sviluppo più semplice ho deciso di acquistare anche Sensor Shield v4.

Più dettagli

La tassa contribuisce connessione veloce sensori, moduli, servomotori, interfacce Seriali e I2C, ed inoltre visualizza tutte le porte del controller del form factor Duemilanova/Uno (collegabile anche alla serie mega, ma con limitazioni e conseguenti conseguenze). Supporta altri scudi sopra di sé.


Ho scelto i seguenti sensori come fonti per i dati meteorologici:


Ho deciso per i sensori. Ma cosa fare con i dati provenienti dai sensori? Ho deciso di esporlo. Volevo una foto a colori, quindi ho scartato subito le soluzioni monocromatiche. Dopo diversi minuti di ricerca, è stato selezionato il display TFT da 1,8 pollici ST7735.

Più dettagli

Poiché il display utilizza un protocollo SPI a 4 fili per la comunicazione e dispone di un proprio frame buffer indirizzabile ai pixel, può essere utilizzato con qualsiasi tipo di microcontrollore. Il display da 1,8 pollici ha 128x160 pixel a colori. C'è anche uno slot per schede memoria microSD, pertanto, puoi facilmente scaricare tutti i colori immagini raster da FAT16/FAT32 file system schede microSD.

Caratteristiche:

  • Diagonale display: 1,8 pollici, risoluzione 128x160 pixel, colore a 18 bit (262.144 colori)
  • Controller con indirizzamento pixel integrato del buffer di memoria video
  • Slot microSD integrato: utilizza più di 2 linee digitali
  • Compatibile con 3,3 e 5 V
  • Dimensioni: 34 mm x 56 mm x 6,5 m


Programmazione del controller Arduino

Dopo aver deciso i componenti per la stazione meteorologica, inizieremo a programmare il controller. L'ambiente utilizzato per il firmware Arduino Sviluppo Arduino IDE. Utilizzate anche le librerie di Adafruit.

Prima di passare allo schizzo, diamo un'occhiata alle funzionalità:

  • Le letture vengono rilevate dai sensori ogni 10 secondi e sullo schermo vengono aggiornati solo gli indicatori che sono cambiati rispetto alla misurazione precedente
  • Trasferimento dati implementato tramite porta COM

Schizzo

#includere // libreria per la comunicazione con dispositivi I2C #include // Libreria principale per tutti i sensori #include // libreria per BMP180 #include // Libreria grafica principale #include // Libreria specifica dell'hardware #include // libreria per la comunicazione con dispositivi SPI #include "dht.h" // libreria per DHT #define DHT22_PIN 2 // collega il pin dati di DHT22 a 2 pin digitali #define TFT_CS 10 // collega il pin CS di TFT a 10 pin digitali #define TFT_RST 9 // collega il pin RST di TFT al pin digitale 9 // puoi anche collegarlo al reset di Arduino // in tal caso, imposta questo pin #define su 0! #define TFT_DC 8 // collega il pin DC di TFT a 8 pin digitali Adafruit_ST7735 tft = Adafruit_ST7735(TFT_CS, TFT_DC, TFT_RST); // inizializza TFT #define TFT_SCLK 13 // collega il pin SCLK di TFT a 13 pin digitali #define TFT_MOSI 11 // collega il pin MOSI di TFT a 11 pin digitali dht DHT; Adafruit_BMP085_Unified bmp = Adafruit_BMP085_Unified(10085); //inizializza BMP180 int bmpFlag = 0; struct ( uint32_t totale; uint32_t ok; uint32_t crc_error; uint32_t time_out; uint32_t connect; uint32_t ack_l; uint32_t ack_h; uint32_t sconosciuto; ) stat = ( 0,0,0,0,0,0,0,0); // struttura per lo stato del dht void setup(void) ( Serial.begin(9600); Serial.println("Meteo Test"); Serial.println(""); if(!bmp.begin()) // controlla la connessione per BMP180 ( Serial.print("Ooops, nessun BMP180 rilevato... Controlla il cablaggio o l'ADDR I2C!"); bmpFlag = 1; ) tft.initR(INITR_BLACKTAB); // Inizializza TFT e riempi con il colore nero tft.fillScreen (ST7735_BLACK); tft.setRotation(tft.getRotation() + 1); tft.setTextSize(1.5); delay(500); // ritardo per garantire che TFT sia stato inizializzato) // ultimi dati misurati float oldTemperature = 0 , oldAltitude = 0, oldPressure = 0, oldDHTHumidity = 0, oldDHTTemperature; bool wasUpdate = false; void loop(void) ( if(Serial.available() > 0) // abbiamo i dati sulla porta seriale ( Serial.read(); // legge byte dalla porta seriale e invia gli ultimi dati misurati printValue("Pressure", oldPressure , " hPa", false); printValue("Temperatura", oldTemperatura, " C", false); printValue("Altitudine", oldAltitude, " m", false); printValue("Umidità", oldDHTHUmidità, "%", false); printValue("DHT_temperature", oldDHTTemperature, " C", false); Serial.println("END_TRANSMISSION"); ) evento sensors_event_t; temperatura float, altitudine; if(bmpFlag == 0)( bmp.getEvent(&event) ; // ottieni dati da BMP180 if (event.pressione) ( bmp.getTemperature(&temperatura); float seaLevelPressure = SENSORS_PRESSURE_SEALEVELHPA; Altitudine = bmp.pressioneToAltitude(seaLevelPressure, evento.pressione, temperatura); ) else ( Serial.println("Sensore error"); ) ) uint32_t start = micros(); int chk = DHT.read22(DHT22_PIN); // ottiene dati da DHT22 uint32_t stop = micros(); stat.total++; switch (chk) // controlla lo stato di DHT22 ( caso DHTLIB_OK: stat.ok++; rottura; caso DHTLIB_ERROR_CHECKSUM: stat.crc_error++; Serial.print("Errore di checksum,\t"); rottura; caso DHTLIB_ERROR_TIMEOUT: stat.time_out++; Serial.print("Errore di timeout,\t"); rottura; caso DHTLIB_ERROR_CONNECT: stat.connect++; Serial.print("Errore di connessione,\t"); rottura; caso DHTLIB_ERROR_ACK_L: stat.ack_l++; Serial.print("Errore riconoscimento basso,\t"); rottura; caso DHTLIB_ERROR_ACK_H: stat.ack_h++; Serial.print("Errore riconoscimento alto,\t"); rottura; predefinito: stat.sconosciuto++; Serial.print("Errore sconosciuto,\t"); rottura; ) se(bmpFlag! = 0 || !event.pressione) // aggiorna i dati (tft.fillRect(0, 30, 160, 6, ST7735_BLACK); tft.setCursor(0, 30); tft.setTextColor(ST7735_RED); printValue("ERRORE INIZIALIZZAZIONE BMP", 0 , "", true); ) else ( if(event.pressione != oldPressure) ( tft.fillRect(0, 30, 160, 7, ST7735_BLACK); tft.setCursor(0, 30); tft.setTextColor(ST7735_RED) ; printValue("Pressione", evento.pressione, " hPa", true); oldPressure = evento.pressione; wasUpdate = true; ) if(temperatura!= oldTemperature) ( tft.fillRect(0, 38, 160, 7, ST7735_BLACK ); tft.setCursor(0, 38); tft.setTextColor(ST7735_WHITE); printValue("Temperatura", temperatura, " C", true); oldTemperature = temperatura; wasUpdate = true; ) if(altitudine != oldAltitude) ( tft.fillRect(0, 46, 160, 7, ST7735_BLACK); tft.setCursor(0, 46); tft.setTextColor(ST7735_BLUE); printValue("Altitudine", altitudine, " m", true); oldAltitude = altitudine; wasUpdate = true; ) ) if(DHT.humidity != oldDHTHumidity) ( tft.fillRect(0, 54, 160, 7, ST7735_BLACK); tft.setCursor(0, 54); tft.setTextColor(ST7735_GREEN); printValue("Umidità", DHT.umidità, "%", true); oldDHTHumidità = DHT.umidità; wasUpdate = vero; ) if(DHT.temperatura != oldDHTTemperatura) ( tft.fillRect(0, 80, 160, 7, ST7735_BLACK); tft.setCursor(0, 80); tft.setTextColor(ST7735_YELLOW); printValue("DHT_temperatura", DHT. temperatura, " C", true); oldDHTTemperature = DHT.temperatura; wasUpdate = true; ) if(wasUpdate) ( Serial.println("END_TRANSMISSION"); ) wasUpdate = false; ritardo(10000); ) void printValue(char* titolo, doppio valore, char* misura, bool tftPrint) ( if(tftPrint) // stampa i dati su TFT ( tft.print(titolo); tft.print(": "); tft.print( valore); tft.println(misura); ) Serial.print(titolo); // invia i dati alla porta seriale Serial.print(": "); Serial.print(valore); Serial.println(misura); )

È ora di assemblare il corpo

La condizione principale del corso era un prototipo funzionante in una forma presentabile. Pertanto, ho dovuto acquistare una custodia e, armato di una lima, inserire in qualche modo la stazione meteorologica nella custodia.

La custodia è stata acquistata da un negozio di elettronica radiofonica locale.

Telaio

(La custodia nella foto è leggermente diversa. Ho un coperchio trasparente)



Quindi, utilizzando una lima, sono stati praticati dei fori per l'uscita dei sensori e l'alimentazione. Ho deciso di spostare i sensori all'esterno, perché mentre testavo il sistema senza custodia, ho notato che la parte posteriore dello schermo diventava molto calda, influenzando la temperatura all'interno della custodia.

Alloggiamento con aperture per sensori e alimentazione



Dato che ho dovuto saldare le gambe a 2 sensori e ho bruciato la traccia su uno di essi, ho deciso di non sfidare la sorte e di non saldare i fili ai sensori (mi eserciterò su qualcos'altro), ma affinché la connessione per essere più o meno affidabile ho deciso di riavvolgere il nastro isolante.

Il sistema prima di essere “inserito” nell’alloggiamento



Dato che il case è molto più grande di quello dell'Arduino (non ce n'era uno più piccolo), ho dovuto inventare un supporto in modo che la scheda non si muovesse all'interno del case. Inoltre, dalla schiuma è stata ritagliata una figura e in essa c'era un rettangolo per lo schermo per nascondere l'interno della custodia. Non avevo la supercolla a portata di mano, quindi ho dovuto usare il nastro biadesivo.

Miracolo-yuda pesce-balena



Avvitare il coperchio, collegare l'alimentazione e attendere.

Stazione meteorologica completata nell'edificio



Dopo aver visualizzato i risultati sullo schermo, identifichiamo uno spiacevole errore nella misurazione dell'umidità: DHT22 produce diligentemente il valore 99,90% (1,00% è estremamente raro). Cominciamo a capire qual è il problema. La prima cosa che facciamo è guardare l'output dei valori sulla porta COM. Si sente bene. Dopo diverse ricariche, smontaggi e rimontaggi della custodia, mi viene in mente l'idea di cercare la risposta su Google. Come previsto, la Google russa non ha detto nulla di utile. OK. Iniziamo la ricerca in inglese e su uno dei forum incontriamo ragazzi con un problema simile. Le prime quattro pagine di discussione non danno nulla di utile, ma nella quinta pagina troviamo la risposta alla nostra domanda:
I sensori di umidità possono essere facilmente influenzati dai gas sbagliati o da un'esposizione molto prolungata a un'umidità elevata IIRC. Nella scheda tecnica c'è una procedura su come “resettare” il sensore, potresti provarla.

L'unica domanda rimasta era quando e come sono riuscito a danneggiare DHT22. Ma si stava avvicinando il momento di seguire il corso e così ho lasciato la soluzione a questo problema per dopo.

Epilogo

Il corso è stato superato. La stazione meteorologica è stata rinviata a tempo indeterminato fino alla chiusura di tutti gli sterili presso l'università. Tuttavia, siamo dovuti tornare alla stazione meteorologica prima di quanto pensassi. È successo così che a metà novembre ho cambiato posto di lavoro e nel nuovo team ho incontrato persone interessate alla piattaforma Arduino e simili. Pertanto, il mio interesse per questa piattaforma, senza avere il tempo di calmarmi, è divampato di nuovo. Ho tirato fuori la mia stazione meteorologica, l'ho collegata al computer e mi sono ricordato che avevo implementato il trasferimento dei dati da Arduino tramite la porta COM. E poi mi è venuta l'idea di scrivere un programma che riceva i dati tramite la porta COM da Arduino e li trasmetta al monitoraggio pubblico
  • Arduino
  • Aggiungere etichette

    Continuiamo a sviluppare la nostra stazione meteorologica.

    Prima di passare all’aggiornamento, voglio fare un po’ di chiarezza.

    Uno dei nostri colleghi mi ha scritto chiedendomi perché è stato introdotto il timer watchdog?

    Il timer di watchdog è attivo in caso di emergenza. Come dimostra la pratica, ENC28J60 non dura più a lungo (se la memoria non fallisce) 4 connessioni simultanee. Considerando quante connessioni di servizio si verificano costantemente per mantenere il funzionamento della rete stessa e il traffico appena lasciato creato da tutti i tipi di giocattoli domestici (ad esempio, televisori moderni, scansiona gli host disponibili sulla rete e le loro porte aperte) il design entra semplicemente in uno stato di torpore. ENC28J60 non può funzionare in modo indipendente con protocolli di rete e tutto è implementato nelle biblioteche. Forse sono proprio loro.
    Controllato tutte le librerie disponibili e diversi moduli(improvvisamente matrimonio), ma da raggiungere funzionamento stabile Non ho potuto farlo per molto tempo. Termine massimo erano circa 3-4 settimane.
    Ecco perché il “cane” gira lì e, se succede qualcosa, tira il controller. Dopodiché il problema è scomparso.
    Inoltre, non nego che possano esserci alcune sfumature o problemi nella mia rete domestica. Ma poiché ho avuto un problema, anche un'altra persona potrebbe averlo. Finora ho trovato solo questa soluzione.
    Per quanto ne so, i chip Wiznet (W5100 e versioni successive) non ce l'hanno, o semplicemente non avevano un bell'aspetto.

    Passiamo all'aggiornamento

    Ancora più importante, ci stiamo allontanando dal chip ENC28J60 e vai a W5100. Ho provato a implementare tutto sul vecchio chip, ma la memoria del microcontrollore non è sufficiente a causa delle librerie molto grandi ENC28J60. Quando si utilizza un nuovo chip, standard biblioteche dallo sviluppatore e tutte le modifiche apportate, rimane ancora di più 20% memoria libera microcontrollore ATMega328. E questi sono nuovi panini!

    In questa versione (chiamiamola la seconda) è possibile trasmettere letture dai sensori tramite comunicazone wireless utilizzando la frequenza 433 MHz. Ho preso i moduli stessi dai cinesi, i contrassegni XY-MK-5V. Vorrei sottolineare che la qualità della trasmissione è lungi dall'essere perfetta. Possibile perdita di segnale, rumore, incapacità di trasmettere simultaneamente, ecc., Ecc. Ma il loro prezzo (meno di 1 dollaro a set) compensa queste carenze. Ti svelo un segreto per cui questi moduli (i più economici) si trovano in molte stazioni meteorologiche di marca uso domestico. Wow, inaspettato?

    Cominciamo con la stazione base

    Ci stiamo trasferendo a Arduino UNO E Scudo Ethernet(prima versione) basata su chip W5100. Questo è un panino ed è inutile descriverlo. Descriverò solo gli ulteriori contatti coinvolti per i moduli XY-MK-5V.

    Il modulo trasmettitore utilizza energia 5 V, GND(dove saremmo senza madre) e D2 pin sul controller. Modifica il contatto D2 (DATI) puoi usare la funzione vw_set_tx_pin dalla libreria VW.

    A differenza dello schizzo precedente, questo ne prevede due librerie aggiuntive:

    #includere #includere

    Lo schizzo stesso

    Testo nascosto

    #includere #includere #includere #includere #includere #includere #includere #includere #define DHTTYPE DHT22 #define DHTPIN 5 DHT dht(DHTPIN, DHTTYPE); byte mac = (0x54, 0x34, 0x31, 0x31, 0x31, 0x31); char server = "narodmon.ru"; porta intera = 8283; Indirizzo IP ip(192,168,0,201); Client client Ethernet; BMP085 dps = BMP085(); lungo Temperatura = 0, Pressione = 0; float H, dP, dPt; intervallo bool = vero; EasyTransferVirtualWire ET; struct SEND_DATA_STRUCTURE( byte ID; // ID dispositivo int Temperatura; // Temperatura float Pressione; // Pressione float Umidità; // Umidità float dewPoint; // Punto di rugiada/gelo ); Trasmissione SEND_DATA_STRUCTURE; void setup() ( // Inizializza il timer Watchdog wdt_disable(); delay(8000); wdt_enable(WDTO_8S); // Inizializza la console Serial.begin(9600); // Inizializza il sensore DHT dht.begin(); / / Inizializzazione del modulo 433 MHz ET.begin(details(broadcast)); vw_set_ptt_inverted(true); vw_set_tx_pin(2); vw_setup(2000); // Avviamo la rete, se non abbiamo aspettato i dati dal server DHCP, quindi // assegnarci noi stessi un indirizzo if (Ethernet.begin(mac) == 0) Ethernet.begin(mac, ip); // Inizializzazione di 1-Wire Wire.begin(); delay(200); // Inizializzazione di BMP180 con regolazione in altezza // dps.init (MODE_STANDARD, 3200, true); // Inizializza BMP180 dps.init(); Serial.println(Ethernet.localIP()); // Invia i primi dati subito dopo l'accensione send_info (vero); ) // funzione dewPoint NOAA / / riferimento (1): http://wahiduddin.net/calc/density_algorithms.htm // riferimento (2): http://www.colorado.edu/geography/weather_station /Geog_site/about.htm double dewPoint(double centigrado, doppia umidità) ( // (1) Pressione di vapore di saturazione = ESGG(T) doppio RAPPORTO = 373,15 / (273,15 + centigrado); doppio RHS = -7.90298 * (RAPPORTO - 1); RHS += 5.02808 * log10(RAPPORTO); RHS += -1.3816e-7 * (pow(10, (11.344 * (1 - 1/RAPPORTO))) - 1) ; RHS += 8.1328e-3 * (pow(10, (-3.49149 * (RAPPORTO - 1))) - 1) ; RHS += log10(1013.246); // il fattore -3 serve per regolare le unità: pressione di vapore SVP * umidità doppia VP = pow(10, RHS - 3) * umidità; // (2) PUNTO DI RUGIADA = F(pressione di vapore) doppia T = log(VP/0,61078); // temp var return (241.88 * T) / (17.558 - T); ) void send_info(bool eth) ( bool fail = true; while(fail) ( // Proviamo a leggere i dati dal sensore di umidità DHT finché non otteniamo // un risultato. Nel 90% dei casi tutto funziona bene, ma abbiamo bisogno 100 % if((H = dht.readHumidity()) >= 0) ( // Ottiene umidità e temperatura dal sensore BMP180 dps.getPressure(&Pressure); dps.getTemperature(&Temperature); // Calcola il punto di rugiada se la temperatura esterna è superiore a 0 gradi Celsius // e si prevede un risultato superiore a 0, altrimenti output 0. Ciò è necessario // per non trarre in inganno durante la stagione invernale. // dP = Temperatura>0?((dPt=Puntorugiada(Temperatura*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); }

    Ai moduli stessi deve essere aggiunta un'antenna. Per 433 MHzÈ sufficiente un normale filo di rame lungo 17cm. Senza un'antenna, puoi dimenticarti del normale funzionamento.

    Passiamo alla parte più importante di questo aggiornamento: la stazione wireless locale

    Per implementarlo (sul ginocchio) ho utilizzato un analogo Arduino NANO(sulla base ATMega328) E TFT visualizzare su un chip ST7735S con permesso 128×160

    Testo nascosto



    Visualizzazione della piedinatura -> controller

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

    Il modulo ricevitore si collega solo come un trasmettitore DATI appuntare D7.

    Un paio di foto di come appare:

    Testo nascosto

    Schizzo del ricevitore

    Testo nascosto

    #includere #includere #includere #includere intero x, y; int w = 128, h = 160; dimensione intera; // 433 EasyTransferVirtualWire ET; struct SEND_DATA_STRUCTURE( byte ID; // ID dispositivo int Temperatura; // Temperatura float Pressione; // Pressione float Umidità; // Umidità float dewPoint; // Punto di rugiada/gelo ); Trasmissione SEND_DATA_STRUCTURE; int Log_Temperatura = -1; float Log_Pressione = -1; float Log_Umidità = -1; float Log_puntorugiada = -1; // TFT #define cs 10 #define dc 9 #define rst 8 char Temperatura, pressione, umidità, punto di rugiada; Informazioni sulla stringa; TFT Schermo TFT = TFT(cs, dc, rst); void setup())( Serial.begin(9600); // Inizializzazione del modulo 433 MHz ET.begin(details(broadcast)); vw_set_ptt_inverted(true); vw_set_rx_pin(7); vw_setup(2000); vw_rx_start(); // Inizializzazione e configurazione iniziale della visualizzazione TFTscreen.begin(); TFTscreen.setRotation(2); TFTscreen. background(0, 0, 0); // Disegno di elementi statici // 1. Vieni a trovarci TFTscreen.stroke(255, 255 , 255); TFTscreen.setTextSize(1); TFTscreen.text(" ", 10, 10); // 2. Descrizione delle letture dei sensori TFTscreen.text("mmHg", w/2+5, 80); TFTscreen .text ("%", w/2+5, 100); TFTscreen.text("C", w/2+5, 120); broadcast.Temperatura = 0; broadcast.Pressure = 0; broadcast.Humidity = 0 ; broadcast .dewPoint = 0; TFTPrint(); ) void loop())( if(ET.receiveData())( if(broadcast.ID == 1) TFTPrint(); /* Serial.println(broadcast.Temperature) ; Serial.println(broadcast.Pressure); Serial.println(broadcast.Humidity); Serial.println(broadcast.dewPoint); Serial.println(); */ ) ) void change(int size, int x, int y, bool up, bool clear = false) ( if(clear) TFTscreen.stroke(0, 0, 0); else ( cambia(dimensione, x, y, !su, true); TFTscreen.stroke((su)?0:255, 0, (su)?255:0); ) if((dimensione%2) == 0 ) dimensione++; while(dimensione > 0) ( TFTscreen.line(x, y, x+(dimensione--), y); ++x, (su)?--y:++y, --size; ) /* while( dimensione > 0) ( TFTscreen.line(x, y, (su)?x+dimensione-1:x, (su)?y:y+dimensione-1); ++x, ++y, --dimensione; ) */ ) int x_center(int w, int lunghezza, int dimensione) ( return floor((w-lunghezza*(dimensione*5)+dimensione*2)/2); ) int x_alignment_right(int w, int lunghezza, int dimensione) ( return ceil(w-length*(dimensione*5)+dimensione*2); ) void TFTPrint() ( dimensione = 3; // ================= ================================================== === =============== // Visualizza letture della temperatura // ============== =========== ========================================== ==== if(broadcast. Temperatura != Log_Temperatura) ( TFTscreen.setTextSize(size); // Sovrascrivi i dati obsoleti String info = String(Log_Temperature); info.concat(" C"); if(Log_Temperature > 0) info = "+"+info; info .toCharArray(Temperatura, info.length()+1); TFTscreen.stroke(0, 0, 0); TFTscreen.text(Temperatura, x_center(w, info.length()+1 , dimensione), 35); / / Visualizza informazioni sulle nuove letture = String(broadcast. Temperatura); info.concat("C"); if(trasmissione.Temperatura > 0) info = "+"+info; info.toCharArray(Temperatura, info.length()+1); // Cambia il colore del valore della temperatura in base alla temperatura stessa int r, g = 0, b; if(broadcast.Temperature > 0) ( r = map(broadcast.Temperature, 0, 40, 255, 150); // Rosso b = map(broadcast.Temperature, 0, 40, 30, 0); // Cambia il tonalità per una transizione più visiva fino allo zero ) else ( r = map(broadcast.Temperature, -40, 0, 0, 30); // Cambia la tonalità per una transizione più visiva fino allo zero b = map(broadcast.Temperature, - 40, 0, 150, 255); // Blu ) schermo TFT.stroke(b, g, r); // ATTENZIONE: le posizioni dei colori nella libreria sono confuse, la posizione RGB viene utilizzata da BGR! TFTscreen.text(Temperatura, x_center(w, info.length()+1, dimensione), 35); ) dimensione = 1; // ================================================ ==== ==================================== // Letture della pressione di uscita // === ====== ============================================ ========= ======================= if(broadcast.Pressure != Log_Pressure) ( TFTscreen.setTextSize(size); / / Sovrascrivi dati obsoleti info = 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 ); // Genera nuove letture info = 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); modifiche(10, 106, 85, (broadcast.Pressure > Log_Pressure)?true:false); ) else ( modifiche (10, 106, 85, vero, vero); modifiche(10, 106, 85, falso, vero); ) // ====================== ======== ========================================== =========== = // Letture dell'umidità in uscita // =============================== =========================== ======================= ================== if(broadcast.Humidity!= Log_Humidity) ( TFTscreen.setTextSize(size); // Sovrascrivi le informazioni sui dati obsoleti = String(Log_Humidity); info.toCharArray(Umidità, info.length()); Schermo TFT.stroke(0, 0, 0); TFTscreen.text(Umidità, x_alignment_right(w/2-5, info.length(), dimensione), 100); // Visualizza le informazioni sulle nuove letture = String(broadcast.Humidity); info.toCharArray(Umidità, info.length()); schermo TFT.corsa(255, 255, 255); TFTscreen.text(Umidità, x_alignment_right(w/2-5, info.length(), dimensione), 100); modifiche(10, 106, 105, (trasmissione.Umidità > Log_Umidità)?true:false); ) else ( modifiche(10, 106, 105, vero, vero); modifiche(10, 106, 105, falso, vero); ) // ================== ================================================== === ============== // Uscita delle letture del punto di rugiada/punto di gelo // ============ ========= ============================================ ====== if(broadcast.puntorugiada! = Log_dewPoint) ( TFTscreen.setTextSize(size); // Sovrascrivi i dati obsoleti 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); // Genera nuove letture info = 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); modifiche(10, 106, 125, (broadcast.dewPoint > Log_dewPoint)?true:false); ) else (changes(10, 106, 125, true, true); changes(10, 106, 125, false, true); ) // Aggiorna i valori nei log per i successivi confronto delle letture Log_Temperature = broadcast.Temperature; Log_Pressure = broadcast.Pressure; Log_Umidità = broadcast.Umidità; Log_puntorugiada = broadcast.puntorugiada; )

    Le letture sono visualizzate in modo abbastanza compatto, ma come dimostra la pratica (e il consiglio dei miei compagni) - "gusto e colore, anche la moglie non è un'amica". Ho ascoltato molti consigli e suggerimenti, ma si contraddicono a vicenda. Pertanto, fallo secondo i tuoi gusti.

    Mi è sembrato che il design sia la parte del progetto che occupa la maggior parte del tempo!

    Testo nascosto

    Alcuni dati sono fabbricati per riflettere alcuni elementi di progettazione.

    Gli artefatti sul display sono polvere e altro sporco che si è accumulato nel corso del tempo in cui il display è rimasto... da qualche parte lì,... beh, lì, non ricordo dove l'ho preso! Lasciami in pace!

    Lo schizzo ha funzioni di posizionamento. Sono piuttosto primitivi, ma ti permettono di ottenere determinati effetti.

    1. x_centro
    2. x_allineamento_destra

    Il primo centra il testo e il secondo lo allinea al lato destro della zona specificata. Tutti i calcoli vengono effettuati in relazione alle dimensioni dato testo, in base all'espressione 1 dimensione = 1PX x 1PX segmento di carattere.

    Il display visualizza anche elementi corrispondenti ad un aumento o diminuzione di un particolare valore di lettura. Sono visualizzati sotto forma di triangoli. Ma nel codice funzione i cambiamenti Esiste una visualizzazione alternativa sotto forma di triangoli ruotati di 45 gradi. Se le letture aumentano l'elemento è rosso, altrimenti blu.

    A proposito, il colore e l'ombra della temperatura principale cambiano a seconda della temperatura stessa. Una decisione piuttosto controversa, ma secondo me visivamente confortevole. Ho lottato per un po' e ho capito che i valori nella funzione colpo, oggetto Display TFT, sono elencati nell'ordine sbagliato. BGR posto RGB. Questo è un errore dello sviluppatore oppure non capisco qualcosa.

    PS: Tutto è abbastanza interessante, ma secondo me merita ulteriori sviluppi. Questo è quello che faremo tra qualche tempo.

    Un giorno, mentre passeggiavo per la città, vidi che aveva aperto un nuovo negozio di elettronica radiofonica. Quando sono entrato ho trovato un gran numero di Scudi per Arduino perché Avevo a casa un Arduino Uno e un Arduino Nano e mi è venuta subito l'idea di giocare con i trasmettitori di segnale a distanza. Ho deciso di acquistare il trasmettitore e il ricevitore più economici a 433 MHz:

    Trasmettitore di segnale.


    Ricevitore di segnale.

    Dopo aver registrato un semplice schizzo di trasmissione dati (un esempio tratto da qui), si è scoperto che i dispositivi di trasmissione possono essere abbastanza adatti per trasmettere dati semplici, come temperatura, umidità.

    Il trasmettitore ha le seguenti caratteristiche:
    1. Modello: MX-FS-03V
    2. Portata (a seconda della presenza di oggetti bloccanti): 20-200 metri
    3. Tensione operativa: 3,5 -12 V
    4. Dimensioni del modulo: 19 * 19 mm
    5. Modulazione del segnale: AM
    6. Potenza del trasmettitore: 10 mW
    7. Frequenza: 433 MHz
    8. Lunghezza richiesta dell'antenna esterna: 25 cm
    9. Facile da collegare (solo tre fili): DATI; VCC; Terra.

    Caratteristiche del modulo ricevente:
    1. Tensione operativa: CC 5 V
    2. Corrente: 4 mA
    3. Frequenza operativa: 433,92 MHz
    4. Sensibilità: - 105 dB
    5. Dimensioni del modulo: 30 * 14 * 7 mm
    6. Necessario antenna esterna: 32cm.

    Internet afferma che il raggio di trasmissione delle informazioni a 2Kb/sec può raggiungere fino a 150 m. Non l'ho controllato personalmente, ma in un bilocale è accettato ovunque.

    Hardware per stazione meteo domestica

    Dopo diversi esperimenti, ho deciso di collegare un sensore di temperatura, umidità e trasmettitore ad Arduino Nano.


    Il sensore di temperatura DS18D20 è collegato ad Arduino come segue:

    1) GND al meno del microcontrollore.
    2) DQ tramite una resistenza di pull-up a terra e al pin D2 di Arduino
    3) Vdd a +5V.

    Il modulo trasmettitore MX-FS - 03V è alimentato a 5 Volt, l'uscita dati (ADATA) è collegata al pin D13.

    Collegato ad Arduino Uno display LCD e barometro BMP085.


    Schema di collegamento ad Arduino Uno

    Il ricevitore del segnale è collegato al pin D10.

    Modulo BMP085 - sensore digitale pressione atmosferica. Il sensore consente di misurare temperatura, pressione e altitudine sul livello del mare. Interfaccia di connessione: I2C. Tensione di alimentazione del sensore 1,8-3,6 V

    Il modulo si collega ad Arduino allo stesso modo degli altri dispositivi I2C:

    • VCC-VCC (3,3 V);
    • TERRA-TERRA;
    • SCL - al pin analogico 5;
    • SDA - al pin analogico 4.
    • Molto basso costo
    • Alimentazione e I/O 3-5 V
    • Determinazione dell'umidità 20-80% con precisione del 5%.
    • Rilevamento della temperatura 0-50 gradi. con una precisione del 2%.
    • Frequenza di polling non superiore a 1 Hz (non più di una volta ogni 1 secondo)
    • Dimensioni 15,5 mm x 12 mm x 5,5 mm
    • 4 pin con spaziatura tra i pin 0,1".

    DHT ha 4 pin:

    1. Vcc (alimentazione 3-5V)
    2. Uscita dati: uscita dati
    3. Non usato
    4. Generale

    Si collega al D8 di Arduino.

    Parte software di una stazione meteorologica domestica

    Il modulo trasmittente misura e trasmette la temperatura ogni 10 minuti.

    Di seguito il programma:

    /* Sketch versione 1.0 Invia la temperatura ogni 10 minuti. */ #include #include #include #define ONE_WIRE_BUS 2 //Pin per collegare il sensore Dallas OneWire oneWire(ONE_WIRE_BUS); Sensori di temperatura Dallas (&oneWire); Indirizzo dispositivo all'interno del termometro; void setup(void) ( //Serial.begin(9600); vw_set_ptt_inverted(true); // Necessario per DR3100 vw_setup(2000); // Imposta la velocità di trasmissione (bit/s) sensori.begin(); if (! sensori .getAddress(insideThermometer, 0)); printAddress(insideThermometer); sensori.setResolution(insideThermometer, 9); ) void printTemperature(DeviceAddress deviceAddress) ( float tempC = sensori.getTempC(deviceAddress); //Serial.print("Temp C : "); //Serial.println(tempC); //Formazione dei dati per l'invio int number = tempC; char simbolo = "c"; //Simbolo di servizio per determinare che si tratta di un sensore String strMsg = "z" ; strMsg += simbolo; strMsg += " "; strMsg += numero; strMsg += " "; char msg; strMsg.toCharArray(msg, 255); vw_send((uint8_t *)msg, strlen(msg)); vw_wait_tx (); / / Attende il completamento del trasferimento delay(200); ) void loop(void) ( for (int j=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); } }

    Il dispositivo ricevente riceve i dati, misura la pressione e la temperatura nella stanza e li trasmette al display.

    #include #include LiquidCrystal lcd(12, 10, 5, 4, 3, 2); #include sensore dht11; #define DHT11PIN 8 #include #include BMP085 dps = BMP085(); lungo Temperatura = 0, Pressione = 0, Altitudine = 0; void setup() ( Serial.begin(9600); vw_set_ptt_inverted(true); // Necessario per DR3100 vw_setup(2000); // Imposta la velocità di ricezione vw_rx_start(); // Avvia il monitoraggio della trasmissione lcd.begin(16, 2) ; Wire.begin(); ritardo(1000); dps.init(); //lcd.setCursor(14,0); //lcd.write(byte(0)); //lcd.home(); ) void loop() ( uint8_t buf; // Buffer per il messaggio uint8_t buflen = VW_MAX_MESSAGE_LEN; // Lunghezza buffer if (vw_get_message(buf, &buflen)) // Se il messaggio viene ricevuto ( // Inizia l'analisi int i; // If il messaggio non è indirizzato a noi, exit if (buf != "z") ( return; ) char command = buf; // Il comando è all'indice 2 // Il parametro numerico inizia all'indice 4 i = 4; int numero = 0; // Poiché la trasmissione avviene carattere per carattere, è necessario convertire il set di caratteri in un numero while (buf[i] != " ") ( numero *= 10; numero += buf[i] - "0"; i++; ) dps.getPressure(&Pressure); dps.getAltitude (&Altitude); dps.getTemperature(&Temperature); //Serial.print(comando); Serial.print(" "); Serial.println( numero); lcd.print("T="); lcd.setCursor(2,0); lcd.print(numero); lcd.setCursor(5,0); lcd.print("P="); lcd.print(Pressione/133,3); lcd.print("mmH"); lcd.setCursor(0,1); lcd.print("T="); lcd.print(Temperatura*0.1); lcd.print("H="); lcd.print(sensore.umidità); lcd.casa(); //ritardo(2000); int chk = sensore.read(DHT11PIN); switch (chk) ( case DHTLIB_OK: //Serial.println("OK"); break; case DHTLIB_ERROR_CHECKSUM: //Serial.println("Errore checksum"); break; case DHTLIB_ERROR_TIMEOUT: //Serial.println("Timeout errore"); break; default: //Serial.println("Errore sconosciuto"); break; ) ) )

    PS In futuro ho intenzione di aggiungere quanto segue:
    - sensore di umidità al trasmettitore, rielaborare l'algoritmo di trasmissione dei dati
    - sensore per la misurazione della velocità e della direzione del vento.
    - aggiungi un altro display al dispositivo ricevente.
    - trasferire il ricevitore e il trasmettitore su un microcontrollore separato.

    Di seguito una foto di quanto accaduto:

    Elenco dei radioelementi

    Designazione Tipo Denominazione Quantità NotaNegozioIl mio blocco note
    Parte trasmittente.
    Scheda Arduino

    Arduino Nano 3.0

    1 Al blocco note
    termometro

    DS18B20

    1 Al blocco note
    Resistore

    220 Ohm

    1 Al blocco note
    Modulo trasmettitoreMX-FS-03V (433 MHz)1 Al blocco note
    Parte ricevente radio.
    Scheda Arduino

    ArduinoUno

    1 Al blocco note
    Resistenza trimmer 1 Al blocco note
    Resistore

    Come base viene preso il progetto della stazione meteorologica tratto dal libro di V. Petin "Progetti utilizzando il controller Arduino", 2a edizione (progetto 5, appendice 2). Utilizzato Arduino IDE 1.8.5 su Windows 10.
    È stato generato un errore durante l'esecuzione dello schizzo

    In Internet si possono scaricare librerie per Arduino che hanno gli stessi nomi ma contenuti diversi. Lo schizzo potrebbe non funzionare se stai utilizzando la libreria sbagliata. A quanto pare mi sono imbattuto nelle librerie sbagliate. Ho aggiunto al progetto un sensore BMP180 per misurare la pressione atmosferica e ho rielaborato lo schizzo.

    Schema di collegamento

    Scansione degli indirizzi

    Innanzitutto, collega il sensore BMP180 e l'indicatore LCD1602 ad Arduino. Compila lo schizzo dello scanner I2C ed eseguilo per determinare gli indirizzi dei dispositivi sul bus I2C.

    Ogni 5 secondi il programma esegue la scansione dei dispositivi e rilascia gli indirizzi sulla porta COM. Ho trovato due dispositivi con indirizzi 0x3F e 0x77. BMP180 per impostazione predefinita ha l'indirizzo 0x77, il che significa che l'indicatore LCD ha l'indirizzo 0x3F.
    In alcuni circuiti del libro i punti in cui i segnali SDA e SCL sono collegati alla scheda Arduino sono confusi. Dovrebbe essere: SDA - in A4, SCL - in A5. Se il modulo BMP180 ha cinque pin, al pin VIN vengono forniti +5 Volt.

    Schema elettrico

    Ora assemblare completamente il circuito. Ho utilizzato un LED RGB a catodo comune montato sulla scheda insieme a resistori da 150 ohm. Il catodo comune è collegato al pin GND, i restanti pin sono collegati secondo lo schema. Non è necessario apportare modifiche allo schizzo, poiché la luminosità dei LED cambia secondo una legge ciclica.
    Lo schema mostra il collegamento di un LED RGB con anodo comune, come nel libro.
    Se sullo schermo LCD1602 non sono visibili caratteri, ruotare il controllo della luminosità. La retroilluminazione dell'indicatore consuma molta corrente, quindi utilizzare un alimentatore con una corrente di almeno 2 A. Ho utilizzato un hub USB con un alimentatore esterno da 2 A.
    Il circuito utilizzava una campana piezoelettrica ZP-22. La resistenza collegata al campanello è di 100 ohm. La frequenza del suono può essere modificata nel programma. Ho scelto una frequenza di 1000 Hz. Se trovi un cicalino con una frequenza sonora fissa, puoi accenderlo e spegnerlo semplicemente applicando e rimuovendo la tensione, come un normale LED. All'avvio dello schizzo viene emesso un breve segnale acustico. È possibile abilitare la segnalazione periodica mentre il programma è in esecuzione rimuovendo il commento dalla riga //bzz(100); nello schizzo.
    Nel progetto ho utilizzato un sensore DHT11 sotto forma di modulo con una resistenza da 4,7 kOhm già montata. La resistenza può variare da 4,7 a 10 kOhm.
    Collegare il pin Vcc del modulo orologio DS1302 al bus +5 Volt. In questo modo ridurrai il consumo della batteria, essenzialmente funzionerà solo quando l'Arduino è spento.

    Programma (schizzo)

    La libreria bmp085 viene utilizzata per la manutenzione del BMP180. Il valore della pressione dipende dall'altitudine della zona. Per il corretto valore della pressione atmosferica è necessario selezionare l'altitudine. Per fare ciò, modifica la riga dps.init(MODE_STANDARD, 10000, true); La mia altezza è di 100 m (10000 cm). Il frammento del calcolo della pressione è tratto dall'esempio BMP085_test2.ino della libreria bmp085.

    Schizzo meteo_P

    #includere
    #includere
    #includere
    #include "DHT.h"
    #includere
    BMP085 dps = BMP085();
    lungo Pressione = 0, Altitudine = 0;
    tempo lungo senza segno1 = 0;

    #definire il PIN DHTP 10
    #define DHTTYPE 11 // 11 - DHT11, 22 - DHT22
    DHT dht(DHTPIN, TIPO DHT);

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

    int REDpin = 9;
    int PIN VERDE = 6;
    int BLUpin = 11;

    LiquidCrystal_I2C lcd(0x3f, 16, 2); // inserisci il tuo indirizzo 0x20...0xff indirizzo
    memTime lungo senza segno;
    int bzzPin = 8;

    void HumTempRead() (
    float ronzio = dht.readHumidity();
    float temp = dht.readTemperature();
    if (isnan(ronzio) || isnan(temp)) (
    Serial.println("Impossibile leggere dal sensore DHT!");
    lcd.setCursore(0, 1);
    lcd.print("H=--% T=---");
    lcd.setCursore(11, 1);
    lcd.print((carattere)223);
    lcd.setCursore(12, 1);
    lcd.print("C ");
    ) altro (
    lcd.setCursore(0, 1);
    lcd.print("H=");
    lcd.setCursore(2, 1);
    lcd.print(ronzio);
    lcd.setCursore(4, 1);
    lcd.print("% T="+");
    lcd.setCursor(9, 1);
    lcd.print(temp);
    lcd.setCursore(11, 1);
    lcd.print((carattere)223);
    lcd.setCursore(12, 1);
    lcd.print("C ") ;
    }
    }

    void setup_bzz() (
    modalità pin(bzzPin, USCITA);
    }

    void bzz(int _bzzTime) (
    tono(bzzPin, 1000, _bzzTime); // frequenza 1000 Hz
    }

    configurazione nulla() (
    Serial.begin(9600);
    Filo.begin();
    ritardo(1000);

    dps.init(MODE_STANDARD, 10000, vero); // 100 metri (altezza sul livello del mare in cm)

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

    LCD.init();
    lcd.retroilluminazione();
    lcd.casa();
    // lcd.setCursor(0, 0);

    rtc.halt(falso);
    rtc.writeProtect(falso);

    //rtc.setDOW(VENERDI); // Imposta il giorno della settimana su VENERDI imposta il giorno della settimana
    //rtc.setTime(4, 58, 0); // Imposta l'ora su 12:00:00 (formato 24 ore)
    //rtc.setDate(6, 8, 2010); // Imposta la data al 6 agosto 2010 imposta la data (giorno, mese, anno)
    }

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

    if ((millis() - memTime > 2000) o (millis()< memTime)) { // DHT11/22 1 time each 2 seconds
    HumTempRead();
    memTime = millis();
    }
    ritardo(100);

    if (((millis() - tempo1) / 1000.0) >= 1.0) (
    dps.calcTrueTemperature();
    tempo1 = milli();
    }
    dps.getPressione(&Pressione);
    Serial.print(" Pressione(Pa):");
    Serial.println(Pressione);

    lungo p2;
    intero pi greco;
    p2 = (Pressione / 133,3224); // Pa in mmHg.
    pi = tronca(p2); // scartando la parte frazionaria del numero

    lcd.setCursore(0, 0);
    lcd.print("P=");
    lcd.setCursore(2, 0);
    lcd.print(pi); // uscita bancomat. pressione sul display LCD
    lcd.setCursore(5, 0);
    lcd.print("mm");
    // ritardo(3000);
    //bzz(100); // rimuovi il commento se vuoi ascoltare i segnali
    {
    for (int valore = 0 ; valore<= 255; value += 1) {
    analogWrite(REDpin, valore);
    analogWrite(GREENpin, 255 - valore);
    analogWrite(BLUEpin, 255);
    ritardo(5);
    }

    for (int valore = 0; valore<= 255; value += 1) {
    analogWrite(REDpin, 255);
    analogWrite(GREENpin, valore);
    analogWrite(BLUEpin, 255 - valore);
    ritardo(5);
    }

    for (int valore = 0; valore<= 255; value += 1) {
    analogWrite(REDpin, 255 - valore);
    analogWrite(GREENpin, 255);
    analogWrite(pinBLU, valore);
    ritardo(5);
    }
    }
    }

    Nel Catalogo file è possibile scaricare lo schizzo e le librerie utilizzate nel progetto.

    Importa le librerie LiquidCrystal_I2C.zip, bmp085.zip, DS1302.zip e DHT.zip dall'archivio scaricato nell'IDE di Arduino. Vai al menù Schizzo Collega la libreria Aggiungi libreria .ZIP... e nella finestra seleziona l'archivio zip della libreria.
    Carica lo schizzo meteo_P. Sostituisci l'indirizzo LCD1602 nello schizzo con il valore ottenuto scansionando il bus I2C. Compila ed esegui lo schizzo.
    Se lo schizzo funziona, apri il monitor della porta e visualizza i messaggi visualizzati. Regolare l'altezza nell'istruzione dps.init(MODE_STANDARD, 10000 , true); per ottenere valori di pressione reali.
    Imposta l'orologio. Decommentare la riga //rtc.setTime(4, 58, 0); e tra parentesi indicare l'ora corrente (ore, minuti e secondi separati da virgole) e ricaricare lo schizzo nel controller. Dopo aver impostato il tempo, commenta nuovamente questa riga ed esegui nuovamente lo schizzo.
    Se l'illuminazione notturna ti infastidisce, puoi regolarla modificando la lunghezza del ritardo nei cicli for alla fine dello schizzo. Con ritardo(2); il ciclo dura 2-3 secondi, con ritardo(5); — da 4 a 5 secondi, con ritardo(30); - fino a 15-16 secondi. Le informazioni sull'indicatore verranno aggiornate con lo stesso intervallo.
    Quando si utilizza la stazione meteorologica in modo autonomo, ad es. senza collegarsi alla porta USB del computer, commentare le righe dello sketch con la dicitura Serial... per disabilitare l'output delle informazioni sul monitor della porta COM.

    PS. Nello schizzo del libro e negli esempi per la libreria DHT è indicata la linea di definizione #definire DHTTYPE DHT11. Lo schizzo si avvia, ma si blocca dopo alcune ore. L'orologio si ferma, il display non cambia. Nel monitor della porta viene visualizzato un messaggio vago, che contiene un collegamento a dht.
    In questa riga ho rimosso le lettere DHT, cioè fatto #definire DHTTYPE 11. Successivamente, lo schizzo ha iniziato a funzionare stabilmente.

    Articolo aggiornato il 25 giugno 2018

    Risorse utilizzate
    1. Petin V.A. Progetti che utilizzano il controller Arduino (Elettronica) 2a edizione, San Pietroburgo. BHV-Pietroburgo, 2015 464 pag.
    2. Petin V. A., Binyakovsky A. A. Enciclopedia pratica di Arduino. - M., DMK Press, 2017. - 152 pag.
    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. esempio BMP085_test2.ino dalla libreria 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/

    Stazione meteo fai da te.

    Era sera, non c'era niente da fare dopo il Capodanno. Come al solito, durante le vacanze invernali di Capodanno voglio occupare la testa e le mani con qualcosa di utile e creativo. Durante queste vacanze di Capodanno ho deciso di realizzare una stazione meteorologica con le mie mani. Ho iniziato a prepararmi in anticipo, ho acquistato e assemblato tutti i componenti prima del nuovo anno e ho eseguito la programmazione principale durante le vacanze.

    (ci sono un sacco di foto sotto il taglio!)

    Per prima cosa esaminerò i componenti; non fornirò link, poiché i prodotti su eBay (nel mio account personale) sono stati archiviati. Ho acquistato molti componenti tranquillamente su eBay. Ho provato per la prima volta un'asta; prima compravo sempre “compralo subito”. Cosa posso dire, se non ti affretti a fare acquisti, puoi acquistare alcuni componenti a un prezzo inferiore (la differenza a volte è doppia).

    Sensore di pressione VMR085
    Questo è il sensore principale. Quando l'ho visto su eBay, sapevo che volevo costruire una stazione meteorologica domestica.
    Il sensore è arrivato in una normale busta, ricoperta con pluriball all'interno.

    All'interno della busta c'erano il biglietto da visita del venditore e un sensore, confezionati in una busta antistatica e avvolti in un altro strato di pluriball.

    La borsa antistatica è stata sigillata in modo che l'umidità durante il volo non minacciasse il sensore

    Tiriamo fuori il sensore. Da un lato si trova una linea di contatti saldati, che sono stati inseriti nella schiuma per evitare che si pieghino. Dall'altro lato c'è il sensore stesso e i contrassegni dei contatti.




    Andrebbe tutto bene, ma i segni di contatto vengono applicati in un'immagine speculare.
    Il sensore è collegato tramite il bus I2C ed è alimentato a 3,3 V. Cioè, per il normale funzionamento sono necessari 4 fili (+, -, SDA, SCL)
    È possibile interrogare il sensore in 2 modi: tramite la libreria o utilizzando le funzioni direttamente nello schizzo.
    Programma di esempio:

    #includere

    #define BMP085_ADDRESS 0x77 // Indirizzo I2C di BMP085

    Const carattere senza segno OSS = 0; // Impostazione del sovracampionamento

    // Valori di calibrazione
    int ac1;
    int ac2;
    intero ac3;
    unsigned int ac4;
    unsigned int ac5;
    unsigned int ac6;
    intero b1;
    intero b2;
    intmb;
    int mc;
    int md;

    Breve temperatura;
    lunga pressione;

    Configurazione nulla()
    {
    Serial.begin(9600);
    Filo.begin();
    bmp085Calibrazione();
    }

    ciclo vuoto()
    {
    temperatura = bmp085GetTemperature(bmp085ReadUT());
    pressione = bmp085GetPressure(bmp085ReadUP());
    Serial.print("Temperatura: „);
    Stampa.seriale(temperatura/10.0, DEC);
    Serial.println("C");
    Serial.print("Pressione: „);
    Stampa.seriale(pressione/133.322, DEC);
    Serial.println(“mm Hg”);
    Serial.println();
    ritardo(1000);
    }

    Non valido bmp085Calibrazione()
    {
    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);
    }

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

    Ritorno ((b5 + 8)>>4);
    }

    Lungo bmp085GetPressure(unsigned long up)
    {
    lungo x1, x2, x3, b3, b6, p;
    b4, b7 lungo senza segno;
    b6 = b5 - 4000;
    // Calcola B3
    x1 = (b2 * (b6 * b6)>>12)>>11;
    x2 = (ac2 * b6)>>11;
    x3 = x1 + x2;
    b3 = ((((((lungo)ac1)*4 + x3)<>2;
    // Calcola B4
    x1 = (ac3 * b6)>>13;
    x2 = (b1 * ((b6 * b6)>>12))>>16;
    x3 = ((x1 + x2) + 2)>>2;
    b4 = (ac4 * (unsigned long)(x3 + 32768))>>15;
    b7 = ((unsigned long)(up - b3) * (50000>>OSS));
    se (b7< 0x80000000)
    p = (b7<<1)/b4;
    altro
    p = (b7/b4)<<1;
    x1 = (p>>8) * (p>>8);
    x1 = (x1 * 3038)>>16;
    x2 = (-7357 * p)>>16;
    p += (x1 + x2 + 3791)>>4;
    restituire p;
    }

    // Leggi 1 byte dal BMP085 all'"indirizzo"
    char bmp085Read(indirizzo carattere senza segno)
    {
    dati di carattere non firmati;

    Wire.write(indirizzo);
    Wire.endTransmission();
    Wire.requestFrom(BMP085_ADDRESS, 1);
    while(!Wire.disponibile())
    ;
    return Filo.read();
    }

    Int bmp085ReadInt(indirizzo carattere senza segno)
    {
    carattere senza segno msb, lsb;
    Wire.beginTransmission(BMP085_ADDRESS);
    Wire.write(indirizzo);
    Wire.endTransmission();
    Wire.requestFrom(BMP085_ADDRESS, 2);
    while(Wire.disponibile()<2)
    ;
    msb = Filo.read();
    lsb = Filo.read();
    ritorno (int) msb<<8 | lsb;
    }

    // Legge il valore della temperatura non compensato
    unsigned int bmp085ReadUT()
    {
    int senza segno;
    // Scrive 0x2E nel registro 0xF4
    // Ciò richiede una lettura della temperatura
    Wire.beginTransmission(BMP085_ADDRESS);
    Filo.scrittura(0xF4);
    Wire.write(0x2E);
    Wire.endTransmission();
    // Attendi almeno 4,5 ms
    ritardo(5);
    // Legge due byte dai registri 0xF6 e 0xF7
    ut = bmp085ReadInt(0xF6);
    ritorno;
    }

    // Legge il valore della pressione non compensata
    bmp085ReadUP() lungo senza segno
    {
    carattere senza segno msb, lsb, xlsb;
    lungo senza segno = 0;
    // Scrivi 0x34+(OSS<<6) into register 0xF4
    // Richiedi una lettura della pressione con l'impostazione del sovracampionamento
    Wire.beginTransmission(BMP085_ADDRESS);
    Filo.scrittura(0xF4);
    Wire.write(0x34 + (OSS<<6));
    Wire.endTransmission();
    // Attende la conversione, il tempo di ritardo dipende dall'OSS
    ritardo(2 + (3<// Leggi il registro 0xF6 (MSB), 0xF7 (LSB) e 0xF8 (XLSB)
    Wire.beginTransmission(BMP085_ADDRESS);
    Filo.scrittura(0xF6);
    Wire.endTransmission();
    Wire.requestFrom(BMP085_ADDRESS, 3);
    // Attendi che i dati diventino disponibili
    while(Wire.disponibile()< 3)
    ;
    msb = Filo.read();
    lsb = Filo.read();
    xlsb = Filo.read();
    su = (((unsigned long) msb<< 16) | ((unsigned long) lsb << 8) | (unsigned long) xlsb) >> (8-OSS);
    tornare su;
    }


    Inoltre, il sensore dispone di un proprio sensore termico per la compensazione della pressione e di un altimetro

    Arduino Nano v3.0
    Questo è il cuore dell'intera stazione meteorologica. In poche parole, il controller è di dimensioni miniaturizzate.
    ho comprato
    Non parlerò in dettaglio del controller, poiché questo è già stato fatto prima di me:


    Il pacchetto lightake era prefabbricato, il controller è arrivato in una confezione contenente un cavo USB e un Arduino in una busta antistatica sigillata.

    Per stimare le dimensioni, ho posizionato una moneta da 1 rublo accanto all'Arduino.

    Primo piano della scheda controller



    Il cavo USB è buono, con anello in ferrite. L'Arduino è alimentato tramite un cavo USB. L'ambiente di sviluppo può essere scaricato (pagina download). Il linguaggio è simile al "C", non ci sono stati problemi a padroneggiarlo, dato che ci programmo molto al lavoro.

    Schermo a cristalli liquidi
    Al lavoro ho trovato nei bidoni uno schermo LCD 1602 compatibile. Ho dovuto armeggiare con la connessione, poiché non sono riuscito a trovare una scheda tecnica. Di conseguenza, il display LCD ha iniziato a funzionare.

    Ma dopo un breve periodo di utilizzo, ho notato che questa schermata non mi bastava e non sarebbe stato possibile visualizzare più dati, dato che ha solo 2 righe di 16 caratteri ciascuna. All'inizio sembra che questi parametri siano sufficienti, ma quando inizi a programmare, ti rendi conto che il massimo che puoi inserire è 3-4 parametri. E se crei un menu (stavo pensando di creare un menu su questa schermata), rimangono solo 1-2 parametri rimasti nello spazio libero.
    Di conseguenza, ho iniziato a cercare un altro schermo. All'inizio ho guardato attentamente lo schermo grafico del Nokia 3310 e ho anche partecipato all'asta su eBay per acquistarlo, ma non ha funzionato (di cui sono molto felice), quindi ho dovuto rinunciare a questo schermo. Ora capisco che sarebbe troppo piccolo per i miei scopi, poiché c'è qualcosa con cui confrontarmi.
    Mentre guardavo casualmente gli scudi su Arduino, mi sono imbattuto in uno schermo grafico 12864 su un controller ST7920. Questo schermo ha le giuste dimensioni e una buona risoluzione per le mie esigenze (128x64). Cioè, puoi facilmente inserire 6-7 righe di 20 caratteri in un carattere normalmente leggibile. Poiché lo schermo è grafico, oltre al testo, la grafica può essere inserita in diversi caratteri. In breve, è proprio quello di cui avevo bisogno, era tutto presente su questo schermo, quindi non ho resistito e l'ho ordinato.
    Il pacco è arrivato velocemente ed era imballato come standard: una busta di pluriball, all'interno c'era un altro strato di pluriball e uno schermo in una busta antistatica:






    Per stimare la dimensione, ho posizionato una moneta da 1 rublo accanto al display LCD.




    Per collegare velocemente lo schermo ad Arduino, ho saldato una linea di contatti ai pin del display LCD. Il display LCD può essere collegato tramite un bus seriale o parallelo. Ho scelto la prima opzione, dato che ci sono già pochi contatti Arduino liberi.
    Collegamento (preso dal web):

    - Il pin 1 (GND) è collegato al bus comune
    - Il pin 2 (VCC) è collegato al bus di alimentazione +5 V e il consumo di corrente è relativamente ridotto e il display può essere alimentato dallo stabilizzatore Arduino integrato.
    - I pin 4, 5 e 6 si collegano alle uscite digitali di Arduino, formando l'interfaccia seriale SPI:
    pin 4 – (RS) – corrisponde alla linea CS (ad esempio 7)
    pin 5 – (RW) – corrisponde alla linea MOSI (ad esempio 8)
    pin 6 – (E) – corrisponde alla linea SCK (ad esempio 3)
    I numeri di contatto di Arduino possono essere qualsiasi cosa, l'importante è non dimenticare di indicarli correttamente nel testo del programma durante l'inizializzazione del display.
    - Il pin 15 (PSB) è collegato al bus comune.
    - I contatti 19 (A) e 20 (K) sono l'alimentazione della retroilluminazione (+5 V e GND, rispettivamente). Per regolare la luminosità della retroilluminazione, è possibile utilizzare un resistore variabile da 10 kOhm collegato tra il bus di alimentazione e GND. La tensione dal suo motore viene fornita al pin 19 del display.
    Secondo queste istruzioni, ho collegato tutto tranne la retroilluminazione. Ho usato Arduino PWM per alimentare la retroilluminazione.
    Per connettere a livello di codice l'LCD ad Arduino, viene utilizzata la libreria u8glib. Puoi scaricarlo. Se ci sono problemi con il download, posso caricare la libreria su narod.ru.
    La libreria in sé non è complicata e ti consente di visualizzare testo in diversi caratteri, tracciare una linea, disegnare forme geometriche semplici (rettangolo, cerchio) e visualizzare le tue immagini preparate in modo speciale. In linea di principio, questo strumento è sufficiente per la maggior parte dei compiti.
    Ecco il risultato di un semplice programma:

    Il programma stesso:

    #include "U8glib.h"

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

    // Subroutine per determinare la memoria libera
    int freeRam() (
    extern int __heap_start, *__brkval;
    in tv;
    return (int) &v - (__brkval == 0? (int) &__heap_start: (int) __brkval);
    }

    Impostazione vuoto(vuoto) (
    u8g.setFont(u8g_font_6x10); // carattere
    u8g.setRot180(); //Capovolgi lo schermo
    analogWrite(6, 115); // Imposta la luminosità dello schermo (anodo di retroilluminazione a 6 pin)
    }

    Ciclo vuoto(vuoto) (
    u8g.primaPagina();
    Fare(

    u8g.setPrintPos(1, 12); // posizione
    u8g.print("Ciao!!!"); // testo in uscita
    u8g.drawBox(0,22,128,9); // Dipingi il rettangolo di bianco
    u8g.setColorIndex(0); // inchiostro bianco, sfondo nero
    u8g.setPrintPos(1, 30); // posizione
    u8g.print("Parola..."); // testo in uscita

    U8g.setColorIndex(1); // inchiostro bianco, sfondo nero
    u8g.setPrintPos(1, 50); // posizione
    u8g.print("Dopo l'avvio="); // testo in uscita
    u8g.setPrintPos(85, 50); // posizione
    u8g.print(millis() / 1000); // restituisce il numero di secondi dopo l'avvio
    u8g.setPrintPos(1, 64); // posizione
    u8g.print(freeRam()); // mostra quanta memoria è occupata
    ) mentre(u8g.nextPage());

    Ritardo(200);
    }

    Orologio in tempo reale DS1307
    Un altro componente per la mia stazione meteorologica. Questo scudo implementa un orologio in tempo reale. Li ho ordinati su eBay. Il venditore ha inviato la sciarpa dell'orologio in una scatola irrealisticamente grande


    All'interno della scatola c'erano due fogli A4 pubblicitari e un fazzoletto da orologio avvolti nel cellophane


    Vorrei sottolineare che la tariffa non supera i 2 rubli. moneta e la scatola misurava 13x15x5 cm.
    La tavola era imballata in una borsa antistatica

    Scialle da vicino



    Ho dovuto armeggiare con questo modulo. Innanzitutto c'erano difficoltà di connessione. E in secondo luogo, su questa tavola non c'è quarzo. Se avessi saputo che avrei dedicato così tanto tempo al modulo, molto probabilmente lo avrei assemblato da solo, dato che Internet è piena di diagrammi. Il circuito più semplice contiene 4-5 componenti.
    Per quanto riguarda la connessione. Ho trovato una libreria che dice che l'interfaccia I2C può essere collegata non ai soliti ingressi analogici di Arduino (A4 e A5), ma a qualsiasi discreto. L'ho fatto come era scritto. All'inizio non funzionava nulla, ma dopo una lunga danza con il tamburello l'orologio si è messo in moto. Bene, ho pensato, basta, i problemi sono finiti, ma dopo aver provato a collegare lo stesso modulo ad un altro Arduino, le danze con il tamburello sono continuate. Ho passato molto tempo a cercare una soluzione a questo problema e quasi ovunque veniva segnalata o una connessione errata oppure l'assenza di resistenze di pull-up sui contatti SCL e SDA. Volevo già entrare nella scheda con un saldatore, ma su un forum mi sono imbattuto per caso in un codice in cui si diceva che SCL e SDA sarebbero collegati alle porte I2C standard di Arduino. Dopo una connessione standard, tutto ha funzionato immediatamente.
    Ora riguardo al quarzo. Non so che tipo di quarzo abbiano messo lì i cinesi, ma gli orologi con tale quarzo scappavano di 10-11 secondi al giorno. Questo errore è di 5 minuti al mese e 1 ora all'anno. Non c'è bisogno di un orologio come questo. Ho dovuto andare di nuovo online e cercare come risolvere questo bug. La prima soluzione che si presenta dice che è necessario mettere a terra il quarzo. L'ho fatto: il risultato è stato zero. Ho anche scoperto da qualche parte che devo trovare una vecchia scheda madre e rimuovere il quarzo dell'orologio da lì. L'ho fatto: c'è un risultato. Ora l'orologio non corre di 10-11 secondi, ma di 1,5 secondi al giorno. Diciamo solo che è migliorato, ma è tutt’altro che ideale. Poiché non ho più voglia di armeggiare con un saldatore, si è deciso di regolare l'orologio in modo programmatico, ovvero di regolare l'orologio sul valore richiesto una volta al giorno. Dopo 10 giorni, l'orologio si è spento di non più di un secondo. Il metodo è buono, ma solo quando il dispositivo di sincronizzazione di Arduino è collegato all'alimentazione, altrimenti l'orologio funziona a batteria e scappa comunque.
    Un piccolo programma di prova:

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

    Byte decToBcd(byte val)
    {
    ritorno ((val/10*16) + (val%10));
    }

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

    Void setDateDs1307(byte secondo, // 0-59
    byte minuto, // 0-59
    byte-ora) // 0-99
    {

    Filo.scrivi(0);
    Wire.write(decToBcd(secondo));
    Wire.write(decToBcd(minuto));
    Wire.write(decToBcd(ora));
    Wire.endTransmission();
    }

    Void getDateDs1307(byte *secondo,
    byte *minuto,
    byte *ora)
    {

    Wire.beginTransmission(DS1307_I2C_ADDRESS);
    Filo.scrivi(0);
    Wire.endTransmission();

    Wire.requestFrom(DS1307_I2C_ADDRESS, 3);

    *secondo = bcdToDec(Wire.read());
    *minuto = bcdToDec(Wire.read());
    *ora = bcdToDec(Wire.read());
    }

    Configurazione nulla()
    {
    byte secondo, minuto, ora;
    Filo.begin();
    Serial.begin(9600);

    Secondo = 45;
    minuto = 5;
    ora = 16;

    SetDateDs1307(secondo, minuto, ora);
    }

    ciclo vuoto()
    {
    byte secondo, minuto, ora;

    GetDateDs1307(&secondo, &minuto, &ora);
    Serial.print(ora, DEC);
    Serial.print(:");
    Serial.print(minuti, DEC);
    Serial.print(:");
    Serial.println(secondo, DEC);

    Ritardo(1000);
    }


    La libreria non viene utilizzata qui e le funzioni per leggere e scrivere il tempo sono troncate.

    Sensore di temperatura e umidità DHT11
    Non c'è niente da dire su questo sensore. Non lo userei nemmeno se l'umidità non fosse necessaria. Sfortunatamente non ho scattato una foto quando l'ho ricevuto, quindi non ci saranno foto. Di seguito puoi vedere le foto del sensore, dove l'ho collegato ad Arduino. Il collegamento del sensore è semplice (+, uscita digitale, -). Tipicamente i sensori sono realizzati con quattro pin. Con questo fattore di forma, il terzo pin non è collegato a nulla.
    Puoi usare la libreria per connetterti ad Arduino. Puoi scaricarlo.
    Un piccolo programma di test con visualizzazione delle informazioni sul display LCD 1602:

    // includi il codice della libreria:
    #includere
    #includere

    // Dichiara oggetti
    dht11 DHT11;
    LCD a cristalli liquidi (12, 11, 6, 5, 4, 3);

    #definire DHT11PIN 7
    int io;

    Configurazione nulla()
    {
    lcd.inizio(16, 2);
    lcd.print("Stato: „);
    io=0;
    }

    ciclo vuoto()
    {
    int chk = DHT11.read(DHT11PIN);
    lcd.setCursore(8, 0);
    interruttore (chk)
    {
    caso 0: lcd.print(“OK „); break;// lcd.setCursor(11, 0); lcd.print(millis()/2000); rottura;
    caso -1: lcd.print(“Errore di checksum”); mErr(); rottura;
    caso -2: lcd.print("Errore di timeout"); mErr(); rottura;
    predefinito: lcd.print("Errore sconosciuto"); mErr(); rottura;
    }
    ritardo(500);
    lcd.setCursore(15, 0);
    interruttore(i)
    {
    caso 0: lcd.print("^"); lcd.setCursore(15, 1); lcd.print(" ");interruzione;
    caso 1: lcd.print("v"); lcd.setCursore(15, 1); lcd.print(" ");interruzione;
    predefinito: lcd.setCursor(15, 1); lcd.print("E"); rottura;
    }
    io=io+1;
    se (i>1) i=0;
    lcd.setCursore(0, 1);
    lcd.print("H=");
    lcd.setCursore(2, 1);
    lcd.print((float)DHT11.umidità, 0);
    lcd.setCursore(4, 1);
    lcd.print("%");
    lcd.setCursore(8, 1);
    lcd.print("T=");
    lcd.setCursore(10, 1);
    lcd.print((float)DHT11.temperatura, 0);
    lcd.setCursore(12, 1);
    lcd.print("C");

    Vuoto mErr()
    {
    lcd.setCursore(2, 1);
    lcd.print("**");
    lcd.setCursore(10, 1);
    lcd.print("**");
    io=5;
    }


    Il sensore presenta alcuni svantaggi: i dati provenienti dal sensore sono solo numeri interi e la portata è debole.

    Sembra che io abbia scritto di tutti i componenti. Non resta che raccogliere tutto in un unico insieme.
    Ops, quasi dimenticavo! Per assemblare il dispositivo, è necessaria una custodia. Ho anche ordinato la custodia su Ebay. Si è scoperto che il venditore veniva dall'Inghilterra. Il pacco è arrivato velocemente, ma non ho fatto foto. Tutte le foto del caso sono qui sotto.

    Per prima cosa ho assemblato tutto sul tavolo utilizzando un cablaggio speciale. Ho scritto un programma di test e l'ho caricato sul controller.



    In effetti, il colore blu della retroilluminazione è molto più luminoso. Anche alla luminosità minima (Luminoso=5), la cornice è illuminata.

    Per assemblare tutto in modalità wireless, si è deciso di realizzare una mini scheda madre e sui connettori sono state inserite schede e schermature Arduino. Se succede qualcosa, possono essere rimossi rapidamente e facilmente. Ho anche deciso di collegare lo schermo LCD e i pulsanti di controllo ai connettori, solo per saldare il sensore di temperatura sui fili.
    Ecco come è venuta fuori la sciarpa



    Nell'ultima foto non ho completamente lavato via il flusso. Ho incollato della gomma porosa sotto gli scudi accanto ai connettori in modo che ci fosse almeno un supporto. Anche se in effetti gli scudi nei connettori sui contatti reggono bene.

    Scheda madre con Shield installati e scheda Arduino.

    Ecco come appare una connessione completa alla scheda madre


    Invece dei pulsanti, ho usato uno scudo fatto in casa saldato su una breadboard. Ho usato i pulsanti dei vecchi topi come pulsanti.
    Come puoi vedere, il numero di fili è diminuito.

    Il problema principale del posizionamento nella custodia è ritagliare una scanalatura liscia per lo schermo LCD. Non importa quanto ci provassi, non funzionava ancora perfettamente. In alcuni punti gli spazi erano poco più di 1 mm. Per far sembrare tutto in ordine, ho preso del sigillante nero per acquari e ho riempito tutte le fessure, allo stesso tempo ho attaccato lo schermo a questo sigillante. Dopo che il sigillante si è asciugato, ho tagliato l'eccesso dall'esterno. In piena luce, il sigillante è visibile, ma in luce normale tutto si fonde con il corpo.
    Ecco come appare il case dall'interno con uno schermo LCD e una scheda madre installati.

    Ecco come appare dall'esterno in piena luce (mi spiace per le impronte digitali, le ho viste mentre sistemavo le foto).

    Ho pensato a lungo a come inserire i pulsanti nella custodia e, soprattutto, quali pulsanti utilizzare...
    Nei negozi di radioelettronica piaceva il pulsante con un perno lungo e le punte che si adattavano a questo perno. Questi pulsanti vengono utilizzati per la saldatura alla scheda. Andrebbe tutto bene, ma hanno un aspetto negativo: la corsa pressante è molto piccola e rumorosa.
    Abbiamo dovuto posizionare i pulsanti in due fasi: la prima consisteva nel posizionare i pulsanti sulla lavagna, la seconda era montare questa lavagna su un'altra lavagna. E poi metti tutto questo nel corpo sulle guide.

    Ecco come appare una sciarpa con bottoni:



    Ecco come si presenta la scheda portaoggetti:


    Qui puoi vedere le guide in cui è inserita la scheda con i pulsanti. Alcuni elementi sono stati saldati per dare rigidità alla tavola.

    Ora mettiamo tutto nel corpo
    Senza collegare i pulsanti:


    Con collegamento a pulsante:

    Chiudi la custodia e accendila. Funziona tutto alla grande, i pulsanti funzionano come dovrebbero.

    Alla fine pubblico un breve video del funzionamento del dispositivo in diverse modalità:
    http://www.youtube.com/watch?v=KsiVaUWkXNA&feature=youtu.be
    Per coloro che non vedono il video qui, ecco il link

    È ora di terminare la recensione.
    Scriverò qualcosa sul programma e poi alcune brevi conclusioni. Quando ho scritto il programma, non pensavo che avrei raggiunto molto presto il limite di 30.720 byte.


    Ho dovuto ottimizzare il codice. Ho spostato molti pezzi di codice nelle subroutine. Non avrei mai pensato che un'istruzione switch...case in forma compilata occupasse più spazio di diverse istruzioni if...else. Anche la corretta dichiarazione delle variabili consente di risparmiare spazio. Se dichiari un array lungo, sebbene sia del tutto possibile ottenerlo per byte, il sovraccarico della memoria raggiunge i 500 byte, a seconda della dimensione dell'array. Quando scrivi un programma, non ci pensi, e solo dopo, quando analizzi il programma, ti accorgi di aver sbagliato alcune cose, e inizi a ottimizzare il codice. Dopo che i problemi con le dimensioni del programma sono stati risolti, ho riscontrato una limitazione della RAM. Ciò è stato espresso nel fatto che il programma ha iniziato a bloccarsi dopo il caricamento. Ho dovuto introdurre una subroutine per il calcolo della RAM libera. Di conseguenza, sono stato costretto ad abbandonare un algoritmo di previsione del tempo, poiché deve visualizzare le icone sullo schermo. L'algoritmo stesso funziona, ma è stato necessario registrare l'output delle icone. Ho ancora idee su come ottimizzare il codice, ma nel prossimo futuro lascerò il dispositivo in funzione così com'è per valutarne le prestazioni e identificare tutti i bug.

    Ora alcune conclusioni
    Aspetti negativi
    1) Prezzo. La giustificazione di questo svantaggio è che un hobby non è mai economico.

    professionisti
    1) Ottima funzionalità del dispositivo
    2) L'aumento delle funzioni è limitato solo dal controller utilizzato e dai propri desideri
    3) Piacere estetico dalla contemplazione e soddisfazione morale dal fatto di aver finalmente assemblato e completato questo dispositivo

    Ho intenzione di acquistare +85 Aggiungi ai preferiti Mi è piaciuta la recensione +137 +304

    I migliori articoli sull'argomento