Barometro Elettronico con ATmega 328
In questo articolo viene descritto come realizzare un barometro elettronico che svolge anche le funzioni di termometro, orologio e calendario, utilizzando il microcontrollore ATmega 328 e il sensore BM180 della Bosch. Il materiale necessario per realizzare il dispositivo è riportato nella seguente tabella
Componenti | Quantità |
---|---|
Microcontrollore ATmega328PU | 1 |
Sensore barometrico Bosch BM180 | 1 |
Display LCD 20×4 retroilluminato | 1 |
Integrato HCF4060 | 1 |
Integrato HCF4040 | 1 |
Quarzo da 16 Mhz | 1 |
Quarzo da 32768 Hz | 1 |
Diodi led | 3 |
Condensatori ceramici da 22 pF | 3 |
Condensatori ceramici da 10 pF | 1 |
Resistenze da 10 KΩ 1/4 W | 3 |
Resistenze da 15 KΩ 1/4 W | 1 |
Resistenze da 220 Ω 1/4 W | 3 |
Resistenze da 5Ω 1/4 W | 1 |
Resistenza da 10 MΩ (oppure 3 resistenze da 3,9MΩ + 1 resistenza da 100 KΩ | 1 |
Resistenze da 470KΩ 1/4 W | 1 |
Resistenze da 100Ω 1/4 W | 1 |
Cicalino Piezo | 1 |
Pulsanti N.A. per circuito stampato | 1 |
Guardando lo schema elettrico riportato in basso, vediamo lo stadio oscillatore composto dai due integrati HCF4060 e HCF4040 che inviano un segnale ad onda quadra alla frequenza di 1 Hz sul pin 14 del microcontrollore. Quindi ogni secondo leggeremo sul display il valore della pressione atmosferica (espressa in mbar) e della temperatura (espressa in gradi centigradi) provenienti dal sensore BM180 collegato ai pin 27 e 28. Inoltre, ogni 2,5 ore (o per un lasso di tempo che si può variare nel codice) viene fatta la misurazione tra il valore della pressione atmosferica attuale e quella precedente per monitorare se c’è stata una qualche variazione.
Se in questo lasso di tempo la pressione è rimasta stabile entrambi i led si accenderanno e sul display a destra verrà visualizzata una barra verticale. Se invece c’è stato un calo si accenderà il led rosso e sul display verrà visualizzata una freccia che punta verso il basso. Infine, si accenderà il led blu e comparirà una freccia che punta verso l’alto se c’è stato un aumento. Una cosa importante da considerare quando si utilizza questo sensore è che nel codice, nelle impostazioni di inizializzazione, va specificata l’altitudine del luogo in cui ci si trova per la corretta misura della pressione. Questo parametro può essere ricavato da qualsiasi dispositivo GPS oppure semplicemente da Google Maps, nel mio caso il valore che ho dovuto impostare è 6 metri sul livello del mare. Per quanto riguarda il funzionamento del calendario, dell’orologio e della sveglia è tutto gestito dal codice e le relative impostazioni si effettuano con soli due tasti. Nello schema non ho incluso l’alimentatore stabilizzato a 5V e rimando in un’altra sezione del sito per questo tipo di circuito.
Di seguito lo sketch completo. Da notare l’uso delle librerie < SFE_BM180> e <Wire> scaricabili a fondo pagina
#include <SFE_BMP180.h> #include <Wire.h> #include <LiquidCrystal.h> LiquidCrystal lcd(12, 11, 5, 4, 3, 13); SFE_BMP180 pressure; int ledGiu = A1; int ledSu = A2; int conta; int bottone = 7; int set = 1; int seg = 8; byte ore, minuti, secondi, o1, o2, m1, m2, s1, s2, num, funzione; float altitudine, temperatura, pressione, pressioneSLDM, PressPrev; int anno = 2016; byte giorno = 1; byte mese = 1; byte gg1, gg2, ms1, ms2; int hp = 10; byte hha, mma, hha1, hha2, mma1, mma2; byte alarm; int differenzaPressione; void diminuzione() { byte freccia[8] = { 0b01110, 0b01110, 0b01110, 0b01110, 0b01110, 0b11111, 0b01110, 0b00100 }; lcd.createChar(0, freccia); lcd.setCursor(19, 2); lcd.write(byte(0)); lcd.setCursor(19, 3); lcd.write(byte(0)); } void aumento() { byte freccia[8] = { 0b00100, 0b01110, 0b11111, 0b01110, 0b01110, 0b01110, 0b01110, 0b01110 }; lcd.createChar(0, freccia); lcd.setCursor(19, 2); lcd.write(byte(0)); lcd.setCursor(19, 3); lcd.write(byte(0)); } void stabile() { byte customChar[8] = { 0b11111, 0b11111, 0b00000, 0b11111, 0b11111, 0b00000, 0b11111, 0b11111 }; lcd.createChar(0, customChar); lcd.setCursor(19, 2); lcd.write(byte(0)); lcd.setCursor(19, 3); lcd.write(byte(0)); } void leggi_BMP180(float* altit, float* temp, float* press, float* press0) { char status; double A, T, P, p0; A = 6.0;// Altitudine della stazione di misura in metri. Può essere ricavata da un GPS status = pressure.startTemperature(); delay(status); status = pressure.getTemperature(T); status = pressure.startPressure(3); delay(status); status = pressure.getPressure(P, T); p0 = pressure.sealevel(P, A); *altit = A; *temp = T; *press = P; *press0 = p0; } void setup() { pinMode(set, INPUT); pinMode(seg, INPUT); pinMode(bottone, INPUT); pinMode(ledGiu, OUTPUT); pinMode(ledSu, OUTPUT); pinMode(hp, OUTPUT); lcd.begin(20, 4); conta = 0; secondi = 0; minuti = 25; ore = 8; funzione = 0; num = 0; hha = 7; mma = 0; alarm = 0; if (pressure.begin()) { lcd.setCursor(0, 0); lcd.print("Barometro/Termometro"); lcd.setCursor(0, 1); lcd.print("Elettronico"); lcd.setCursor(0, 2); lcd.print("By Mario de Nichilo"); leggi_BMP180(&altitudine, &temperatura, &pressione, &pressioneSLDM); PressPrev = pressione; // memorizzo la prima lettura del sensore delay(3000); lcd.clear(); } } void orologio() { if (secondi > 59) { secondi = 0; minuti = minuti + 1; } if (minuti > 59) { minuti = 0 ; ore = ore + 1; tone(10, 1887, 22); } if (ore > 23) { ore = 0; // regolazione calendario bool bisestile = (anno > 1584 && ((anno % 400 == 0) || (anno % 4 == 0 && anno % 100 != 0))); giorno++; if ((mese == 1) && (giorno > 31)) { giorno = 1; mese = 2; } if ((mese == 2) && (bisestile == true) && (giorno > 29)) { giorno = 1; mese = 3; } if ((mese == 2) && (bisestile == false) && (giorno > 28)) { giorno = 1; mese = 3; } if ((mese == 3) && (giorno > 31)) { giorno = 1; mese = 4; } if ((mese == 4) && (giorno > 30)) { giorno = 1; mese = 5; } if ((mese == 5) && (giorno > 31)) { giorno = 1; mese = 6; } if ((mese == 6) && (giorno > 30)) { giorno = 1; mese = 7; } if ((mese == 7) && (giorno > 31)) { giorno = 1; mese = 8; } if ((mese == 8) && (giorno > 31)) { giorno = 1; mese = 9; } if ((mese == 9) && (giorno > 30)) { giorno = 1; mese = 10; } if ((mese == 10) && (giorno > 31)) { giorno = 1; mese = 11; } if ((mese == 11) && (giorno > 30)) { giorno = 1; mese = 12; } if ((mese == 12) && (giorno > 31)) { giorno = 1; mese = 1; anno++; } } s2 = secondi / 10; s1 = secondi - (s2 * 10); lcd.setCursor(19, 0); lcd.print(s1); lcd.setCursor(18, 0); lcd.print(s2); lcd.setCursor(17, 0); lcd.print(":"); m2 = minuti / 10; m1 = minuti - (m2 * 10); lcd.setCursor(16, 0); lcd.print(m1); lcd.setCursor(15, 0); lcd.print(m2); lcd.setCursor(14, 0); lcd.print(":"); o2 = ore / 10; o1 = ore - (o2 * 10); lcd.setCursor(13, 0); lcd.print(o1); lcd.setCursor(12, 0); lcd.print(o2); } void misurazione() { leggi_BMP180(&altitudine, &temperatura, &pressione, &pressioneSLDM); lcd.setCursor(0, 2); lcd.print(temperatura); lcd.setCursor(8, 2); lcd.print(char(223)); lcd.setCursor(9, 2); lcd.print("C"); lcd.setCursor(0, 3); lcd.print(pressione); lcd.setCursor(8, 3); lcd.print("mBar"); } void calendario() { gg2 = giorno / 10; gg1 = giorno - (gg2 * 10); lcd.setCursor(0, 0); lcd.print(gg2); lcd.setCursor(1, 0); lcd.print(gg1); lcd.setCursor(2, 0); lcd.print("."); ms2 = mese / 10; ms1 = mese - (ms2 * 10); lcd.setCursor(3, 0); lcd.print(ms2); lcd.setCursor(4, 0); lcd.print(ms1); lcd.setCursor(5, 0); lcd.print("."); lcd.setCursor(6, 0); lcd.print(anno); } void loop() { if ((digitalRead(seg) == HIGH) && (funzione == 0)) { misurazione(); secondi = secondi + 1; orologio(); calendario(); conta = conta + 1; tone(10, 1500, 3); //1700 while ((hha == ore) && (mma == minuti) && (alarm == 1) && (digitalRead(seg) == HIGH)) { tone(10, 1887, 100); } while (digitalRead(seg) == HIGH) { // sincronia col clock esterno secondi = secondi; } } // regolazione orologio if (digitalRead(set) == HIGH) { lcd.clear(); funzione++; delay(250); if (funzione == 9) { funzione = 0; } delay(200); } // Regoloazione ore if (funzione == 1) { lcd.setCursor(0, 1); lcd.print("impostazione ore "); while ((digitalRead(bottone) == HIGH) && (funzione == 1)) { ore++; if (ore > 23) { ore = 0; } o2 = ore / 10; o1 = ore - (o2 * 10); lcd.setCursor(13, 2); lcd.print(o1); lcd.setCursor(12, 2); lcd.print(o2); delay(250); } } // Regolazione minuti if (funzione == 2) { lcd.setCursor(0, 1); lcd.print("impostazione min "); while ((digitalRead(bottone) == HIGH) && (funzione == 2)) { minuti++; if (minuti > 59) { minuti = 0; } m2 = minuti / 10; m1 = minuti - (m2 * 10); lcd.setCursor(13, 2); lcd.print(m1); lcd.setCursor(12, 2); lcd.print(m2); delay(200); } } // Regolazione calendario // Regolazione anno if (funzione == 3) { lcd.setCursor(0, 1); lcd.print("impostazione anno "); lcd.setCursor(13, 2); lcd.print(anno); while ((digitalRead(bottone) == HIGH) && (funzione == 3)) { anno++; if (anno > 2050) { anno = 2016; } lcd.setCursor(13, 2); lcd.print(anno); delay(200); } } // Regolazione mese if (funzione == 4) { lcd.setCursor(0, 1); lcd.print("impostazione mese "); ms2 = mese / 10; ms1 = mese - (ms2 * 10); lcd.setCursor(12, 2); lcd.print(ms2); lcd.setCursor(13, 2); lcd.print(ms1); while ((digitalRead(bottone) == HIGH) && (funzione == 4)) { mese++; if (mese > 12) { mese = 1; } ms2 = mese / 10; ms1 = mese - (ms2 * 10); lcd.setCursor(12, 2); lcd.print(ms2); lcd.setCursor(13, 2); lcd.print(ms1); delay(200); } } // Regolazione giorno if (funzione == 5) { lcd.setCursor(0, 1); lcd.print("impostazione giorno "); gg2 = giorno / 10; gg1 = giorno - (gg2 * 10); lcd.setCursor(13, 2); lcd.print(gg2); lcd.setCursor(14, 2); lcd.print(gg1); while ((digitalRead(bottone) == HIGH) && (funzione == 5)) { giorno++; bool bisestile = (anno > 1584 && ((anno % 400 == 0) || (anno % 4 == 0 && anno % 100 != 0))); if ((mese == 1) && (giorno > 31)) { giorno = 1; } if ((mese == 2) && (bisestile == true) && (giorno > 29)) { giorno = 1; } if ((mese == 2) && (bisestile == false) && (giorno > 28)) { giorno = 1; } if ((mese == 3) && (giorno > 31)) { giorno = 1; } if ((mese == 4) && (giorno > 30)) { giorno = 1; } if ((mese == 5) && (giorno > 31)) { giorno = 1; } if ((mese == 6) && (giorno > 30)) { giorno = 1; } if ((mese == 7) && (giorno > 31)) { giorno = 1; } if ((mese == 8) && (giorno > 31)) { giorno = 1; } if ((mese == 9) && (giorno > 30)) { giorno = 1; } if ((mese == 10) && (giorno > 31)) { giorno = 1; } if ((mese == 11) && (giorno > 30)) { giorno = 1; } if ((mese == 12) && (giorno > 31)) { giorno = 1; } gg2 = giorno / 10; gg1 = giorno - (gg2 * 10); lcd.setCursor(13, 2); lcd.print(gg2); lcd.setCursor(14, 2); lcd.print(gg1); delay(200); } } // Regolazione sveglia if (funzione == 6) { lcd.setCursor(0, 1); lcd.print("ora sveglia "); hha2 = hha / 10; hha1 = hha - (hha2 * 10); lcd.setCursor(12, 2); lcd.print(hha2); lcd.setCursor(13, 2); lcd.print(hha1); while ((digitalRead(bottone) == HIGH) && (funzione == 6)) { hha++; if (hha > 23) { hha = 0; } hha2 = hha / 10; hha1 = hha - (hha2 * 10); lcd.setCursor(12, 2); lcd.print(hha2); lcd.setCursor(13, 2); lcd.print(hha1); delay(200); } } if (funzione == 7) { lcd.setCursor(0, 1); lcd.print("min sveglia "); mma2 = mma / 10; mma1 = mma - (mma2 * 10); lcd.setCursor(12, 2); lcd.print(mma2); lcd.setCursor(13, 2); lcd.print(mma1); while ((digitalRead(bottone) == HIGH) && (funzione == 7)) { mma++; if (mma > 59) { mma = 0; } mma2 = mma / 10; mma1 = mma - (mma2 * 10); lcd.setCursor(12, 2); lcd.print(mma2); lcd.setCursor(13, 2); lcd.print(mma1); delay(200); } } // attivazione della sveglia if (funzione == 8) { lcd.setCursor(0, 1); lcd.print("attiva sveglia "); if ((digitalRead(bottone) == HIGH) && (funzione == 8)) { alarm = !alarm; delay(300); } if (alarm == 1) { lcd.setCursor(12, 2); lcd.print("ON "); } else { lcd.setCursor(12, 2); lcd.print("OFF"); } } if (conta >= 9000) { // confronto valore ogni 2,5 ore ( 9000 sec ) differenzaPressione = int(pressione) - int(PressPrev); if (differenzaPressione == 0) { lcd.setCursor(13, 3); lcd.print(pressione - PressPrev); stabile(); digitalWrite(ledSu, HIGH); digitalWrite(ledGiu, HIGH); PressPrev = pressione; conta = 0; } if ((pressione > PressPrev)) { differenzaPressione = int(pressione) - int(PressPrev); lcd.setCursor(13, 3); lcd.print(differenzaPressione); aumento(); digitalWrite(ledSu, HIGH); digitalWrite(ledGiu, LOW); PressPrev = pressione; conta = 0; } if ((pressione < PressPrev) ) { differenzaPressione = int(pressione) - int(PressPrev); lcd.setCursor(13, 3); lcd.print(differenzaPressione); digitalWrite(ledGiu, HIGH); digitalWrite(ledSu, LOW); diminuzione(); PressPrev = pressione; conta = 0; } } }
Foto del barometro in funzione
Video dimostrativo
Qui sotto è possibile scaricare i file del progetto
Libreria Sensore : BMP180_Breakout_Arduino_Library-master