Witam, w tym artykule chciałbym przedstawić w jaki sposób możemy mierzyć ciśnienie atmosferyczne za pomocą prostego układu.
Potrzebne nam będą :
– Arduino
– Czujnik ciśnienia atmosferycznego
–ATmega328P-PU
–Płyta Stykowa
–Wyświetlacz LCD 2×16
Zaczynamy od wgrania Bootloadera to naszej ATmegi.
Podłączenia ATmegi z Arduino:
Arduino pin 10 – ATmega pin 1
Arduino pin 11 – ATmega pin 17
Arduino pin 12 – ATmega pin 18
Arduino pin 13 – ATmega pin 19
GND- ATmega pin22
5V – ATmega pin 7
Otwieramy przykładowy program ArduinoISP i wysyłamy go do naszego Arduino.
Po wykonaniu tej czynności zmieniamy płytkę z naszego Arduino na Atmegę(Narzędzia -> Płytka->ATmega328P-PU) oraz zmieniamy programator(Narzędzia -> Programator->Arduino as ISP) i wypalamy Bootloader.
Następnie na ATmegę wgrywamy program który będzie nam potrzebny do obsługi czujnika BMP085 i wyświetlacza LCD 2×16.
Kod pochodzi ze strony producenta, jednak trzeba było dopisać kilka linijek w celu wyświelenia danych na wyświetlaczu.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 |
#include <Wire.h> #include <LiquidCrystal.h> #define BMP085_ADDRESS 0x77 LiquidCrystal lcd(12, 11, 5, 4, 3, 2); const unsigned char OSS = 0; 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; long b5; void setup(){ lcd.begin(16,2); lcd.setCursor(0,1); Wire.begin(); bmp085Calibration(); } void loop() { float temperature = bmp085GetTemperature(bmp085ReadUT()); float pressure = bmp085GetPressure(bmp085ReadUP()); float atm = pressure / 101325; float altitude = calcAltitude(pressure); pressure = pressure / 100; lcd.clear(); lcd.print("Temp: "); lcd.print(temperature, 2); lcd.print(" C"); lcd.setCursor(0,2); lcd.print("cisni: "); lcd.print(pressure); lcd.print("hPa"); delay(10000); } void bmp085Calibration() { 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); } float bmp085GetTemperature(unsigned int ut){ long x1, x2; x1 = (((long)ut - (long)ac6)*(long)ac5) >> 15; x2 = ((long)mc << 11)/(x1 + md); b5 = x1 + x2; float temp = ((b5 + 8)>>4); temp = temp /10; return temp; } long bmp085GetPressure(unsigned long up){ long x1, x2, x3, b3, b6, p; unsigned long b4, b7; b6 = b5 - 4000; // Calculate B3 x1 = (b2 * (b6 * b6)>>12)>>11; x2 = (ac2 * b6)>>11; x3 = x1 + x2; b3 = (((((long)ac1)*4 + x3)<<OSS) + 2)>>2; // Calculate 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)); if (b7 < 0x80000000) p = (b7<<1)/b4; else p = (b7/b4)<<1; x1 = (p>>8) * (p>>8); x1 = (x1 * 3038)>>16; x2 = (-7357 * p)>>16; p += (x1 + x2 + 3791)>>4; long temp = p; return temp; } char bmp085Read(unsigned char address) { unsigned char data; Wire.beginTransmission(BMP085_ADDRESS); Wire.write(address); Wire.endTransmission(); Wire.requestFrom(BMP085_ADDRESS, 1); while(!Wire.available()) ; return Wire.read(); } int bmp085ReadInt(unsigned char address) { unsigned char msb, lsb; Wire.beginTransmission(BMP085_ADDRESS); Wire.write(address); Wire.endTransmission(); Wire.requestFrom(BMP085_ADDRESS, 2); while(Wire.available()<2) ; msb = Wire.read(); lsb = Wire.read(); return (int) msb<<8 | lsb; } unsigned int bmp085ReadUT(){ unsigned int ut; Wire.beginTransmission(BMP085_ADDRESS); Wire.write(0xF4); Wire.write(0x2E); Wire.endTransmission(); delay(5); ut = bmp085ReadInt(0xF6); return ut; } unsigned long bmp085ReadUP(){ unsigned char msb, lsb, xlsb; unsigned long up = 0; Wire.beginTransmission(BMP085_ADDRESS); Wire.write(0xF4); Wire.write(0x34 + (OSS<<6)); Wire.endTransmission(); delay(2 + (3<<OSS)); msb = bmp085Read(0xF6); lsb = bmp085Read(0xF7); xlsb = bmp085Read(0xF8); up = (((unsigned long) msb << 16) | ((unsigned long) lsb << 8) | (unsigned long) xlsb) >> (8-OSS); return up; } void writeRegister(int deviceAddress, byte address, byte val) { Wire.beginTransmission(deviceAddress); Wire.write(address); Wire.write(val); Wire.endTransmission(); } int readRegister(int deviceAddress, byte address){ int v; Wire.beginTransmission(deviceAddress); Wire.write(address); Wire.endTransmission(); Wire.requestFrom(deviceAddress, 1); while(!Wire.available()) { } v = Wire.read(); return v; } float calcAltitude(float pressure){ float A = pressure/101325; float B = 1/5.25588; float C = pow(A,B); C = 1 - C; C = C /0.0000225577; float X = pressure / 100000; return C; } |
Po wgraniu kodu wystarczy tylko odpowiednio podłaczyć elementy pod naszą ATmegę. Gotowy ukłąd wygląda tak:
Przepraszam za jakość zdjęcia, ale na chwilę obecną nie dysponuje lepszym aparatem.
Dziękuje za uwagę :)
74zł za czujnik ????? to sie chyba mija z celem
no bez kitu :d
na ebay’u ten czujnik można dostać taniej :)
Projekt fajny i ciekawy, ale –robert– ma rację. Znalazłem ten czujnik na ebay za 1,69€ + 1€ przesyłka co daje po przeliczeniu na złotówki nie całe 12 złotych.
http://www.ebay.pl/itm/New-GY-65-BMP085-Digital-Barometric-Pressure-Sensor-Module-Board-For-Arduino-/111217757507?pt=UK_Sound_Vision_Other&hash=item19e5184d43
10zł!
Panowie, ale o co ten ból zadka ? Chłopak podał namiary na Nettigo zapewne by wziąć udział w promocji o której pisał Łukasz. Komu chce się czekać na wysyłkę z Chin niech sobie kupi czujnik w Chinach i po kłopocie. A sam artykuł całkiem ciekawy, jedyne do czego można się przyczepić to ten bootloader w tym wypadku zupełnie zbędny. Pozdrawiam.
podasz bootloadera do atmegi ?
chodzi skrypty do boards.txt ? czy pilk bootloadera?
pliki bootloadera poprosze . Te co mam coś mi nie działają
Bootloader jest na forum.
Wszystko ładnie, ale w przypadku wgrywania na “Zewnętrzną” ATmege musisz dodać kondensatory filtrujące zasilanie oraz rezystor do RESET.
Polecam lekturę: http://mirekk36.blogspot.com/2012/04/mikrokontroler-prawidowe-zasilanie.html
Przepraszam bardzo ale wpis tragiczny i propaguje BARDZO złe nawyki.
– Kondensatory filtrujące napięcie zasilania mikrokontrolera
– Rezystor na pinie reset
– Cewka na zasilaniu części analogowej (no, w tym projekcie możnaby ewentualnie ją pominąć, bo nie używamy ADC)
– 5V i masę podłączamy do KAŻDEGO pinu Vcc i GND (tak, nawet jeżeli nie używamy ADC)!!!
– na stronie Nettigo znajduje się taka uwaga: “Zasilanie 1.8 – 3.6 V. Podanie napięcia zasilającego 5V uszkodzić może czujnik!”. No ja tutaj stabilizatora na 3V3 nie widzę, ale na pewno nie byłoby przy nim kondensatorów :P
– nie dam głowy (bo nie używam tego typu wyświetlaczy), ale mocno wydaje mi się, że na jednej z nóżek powinien być potencjometr, albo chociaż rezystor…
Bez urazy, ale moim zdaniem wpis szkodliwy, bo ktoś wejdzie na tą stronę, przejrzy projekt i nie zaglądając w komentarze podłączy układ tak jak to pokazałeś, pięknie smażąc sobie moduł za 80zł. (o zasilaniu mikrokontrolera nawet nie będę już wspominał)
napięcie 5V nie uszkadza czujnika, potencjometr można ominąc gdy nie jest potrzebny, układ działa i jakoś nic się z nim nie dzieję.
“napięcie 5V nie uszkadza czujnika” – lepiej znasz budowę układu niż jego producent? imponujące. polecam lekturę noty katalogowej wykorzystanego przez Ciebie układu:
https://www.sparkfun.com/datasheets/Components/General/BST-BMP085-DS000-05.pdf
strona 7, tabela 2 “Absolute maximum ratings”, wiersz 2 “Supply voltage (on all pins) MAX: +4.25V”
przy czym jest to maksymalne napięcie, jakie można podać na dowolną nóżkę – w innym miejscu (strona 6, tabela 1, wiersz 2) znajduje się wyraźna informacja, że maksymalne dopuszczalne napięcie zasilania to 3.6V.
“układ działa i jakoś nic się z nim nie dzieję” – gratuluję, że się nic nie dzieje – masz po prostu dużo szczęścia. polecam notę katalogową mikrokontrolera ATmega328 (pozwolisz, że nie podam konkretnych stron) w której znajdują się informacje informujące o KONIECZNOŚCI stosowania filtrowania napięcia zasilania, podłączania WSZYSTKICH pinów odpowiedzialnych za zasilanie układu i podciągnięciu pinu reset do zasilania przez rezystor.
jeżeli nie chce Ci się wertować noty mikrokontrolera, to przeczytaj chociaż ten artykuł, do którego link już gdzieś tutaj w komentarzach się pojawił:
http://mikrokontrolery.blogspot.com/2011/04/minimalne-podlaczanie-pinow.html
i drobna uwaga (już poza “konkursem”) – każdy ma prawo popełniać błędy (też to często robię), ale jeżeli ktoś zwraca Ci na nie uwagę to należy umieć się do nich przyznać, a nie dalej brnąć.
jako “Uczeń Technikum Informatycznego” powinieneś być otwarty na nową wiedzę i uwagi, a nie uważać się za alfę i omegę.
toż luzuj, napisałem że u mnie nic nie powoduje napięcie 5V. Może uszkodzić a nie musi, nie wiem gdzie udałem alfe i omege ale ok.
Jest jakiś w miarę prosty sposób na bezprzewodowy odczyt temperatury? Cholernie by mi się coś takiego przydało, żeby mieć podgląd temperatury z kotłowni w salonie.
Witam,
Jak już ktoś wcześniej zauważył układ BMP085 należy zasilić 3.3V, ale również magistrala I2C również musi działać na poziomie 3.3V! Do tego celu należy użyć konwertera logicznego np. https://nettigo.pl/products/126.
Tak więc artykuł wymaga jeszcze kilku poprawek.
Pozdrawiam,
—
malebranchi
ok, dzięki
btw kiedyś również miałem chęć opisania tego układu i nawet zacząłem to robić, ale jak to zwykle bywa, zabrakło mi motywacji do dokończenia. Niemniej mały szkic popełniłem:
https://majsterkowo.pl/?p=5934&preview=true
Pozdrawiam,
—
malebranchi
DZIWIĘ SIĘ ŻE POSZŁO TO NA GŁÓWNĄ Z TYLOMA BŁĘDAMI.
Kilka komentarzy jest już na temat zasilania tego układu i mikroprocesora więc nie będę się powtarzał. Moim zdaniem moderatorzy tej strony powinni postawić jasne sprawo: albo poprawić zasilanie albo wylatuje do kosza..
Wykonałem ten projekt, ale po pierwsze użyłem bibliotek producenta do obsługi BMP085, zmodyfikowałem tylko program wyświetlający odczytane dane w konsoli do wyświetlania ich na LCD. Dodatkowo zrobiłem układ zasilania dla poziomu 5V pod ATmegę i 3.3V do czujnika. Wszystko działa luks torpeda
Prosta metoda zastosowania czujnika BMP085 w układach zasilanych 5V jest przedstawiona http://4.bp.blogspot.com/-Sh9HWlMoRig/UwjU99AvecI/AAAAAAAAFcU/5ASqxRqzORU/s1600/WxSSR_v1-aprs.png