Дачный прогноз у меня всегда начинался с носа: небо чистое вечером — утром, может, и обойдётся. Пока однажды в июле барометр на подоконнике не показал 998 гПа — на пятнадцать ниже нормы; к обеду следующего дня град побил малину на половине участка. Второй раз прибор мне помог уже по-другому: на перевале высотомер напечатал минус 240 метров при подъёме на 1800. Оба раза датчик не врал — врал я, который не разобрался, что именно он измеряет.
BMP280 — крошечный барометр на шине I2C: меряет атмосферное давление и температуру кристалла, а высоту считает арифметикой из давления. В этом уроке подключим модуль к A4/A5, разберём три метода библиотеки Adafruit_BMP280, поймаем ловушку с адресом 0x76/0x77, посчитаем высоту по формуле и соберём прогноз погоды с честной оговоркой: по одному замеру он не работает. В симуляторе у датчика два ползунка — температура и давление; скетч читает их как настоящие и печатает на LCD 16x2 и в Serial.
Для верности держите в голове масштаб задач: раз в секунду — метеостанция на подоконнике; раз в минуту — логгер на даче, где за сезон набирается полмиллиона кадров; десять раз в секунду — потолок для высотомера на дроне, дальше уже шум, а не данные. Один и тот же чип, три разных ритма — и три разных решения по питанию, журналам и осреднению.
Датчик и шина: четыре провода и один адрес
Модуль ставится на шину из урока про два провода: VCC — 5 В (на плате стоит стабилизатор), GND, SDA — A4, SCL — A5. Подтяжки распаяны на борту, отдельных резисторов не нужно. Диапазон давления — от 300 до 1100 гПа: это от минус пятисот метров до девяти километров, то есть с запасом покрывает и глубокий циклон, и крышу высотки. Разрешение — до 0,16 Па в старшем режиме: шестнадцатая доля паскаля, тысячные гПа. При опросе раз в секунду чип берёт из шины 2,7 мкА — барометр живёт от батарейки год-другой, пока вы не начнёте дёргать его чаще паспортных десяти измерений в секунду.
Не перепутайте с BME280: влажности BMP не меряет вовсе, хоть корпуса у них одинаковые. Подделки под видом BME и проверка по идентификатору чипа — тема урока про альтернативы DHT, регистры и заводскую калибровку изнутри я разбирал в уроке про температуру и давление BMP280. Здесь — практика применения.
Два вывода на краю модуля отвечают за интерфейс. CSB подтянут к питанию на плате — чип говорит по I2C; посадите его на землю, и тот же чип перейдёт на SPI с четырьмя проводами — для макетки это лишние линии без пользы. SDO выбирает адрес, о нём — следующий абзац. Температурный паспорт — от −40 до +85 °C, точность ±1 °C: для метеостанции достаточно, для термостата инкубатора — нет.
Библиотека — Adafruit_BMP280, ставится вместе с Adafruit Unified Sensor. Первая грабля ждёт ещё в setup: bmp.begin() без аргумента стучится на адрес 0x77 — а у большинства китайских модулей вывод SDO посажен на землю, и датчик живёт на 0x76. Результат везде одинаковый: begin возвращает 0, сканер при этом честно видит устройство на шине. Лечится одним словом: bmp.begin(0x76). Куда девается второй адрес: у модулей без вывода SDO он зашит жёстко, а у модулей с перемычкой SDO к VCC адрес переезжает на 0x77. Полная карта адресов и правило деления восьмибитных значений пополам — в уроке-таблице адресов.
Ритм опроса выбирайте по задаче, а не по жадности. Метеостанции хватает одного кадра в секунду: давление меняется медленно, за минуту сдвигается на доли гектопаскаля. Чаще секунды гнать его нет смысла: кристалл греется от собственной работы, и показания температуры поползут вверх. Для высотомера с быстрой реакцией есть forced-режим — одно измерение по команде; но это уже взрослые танцы, и в обычном скетче вы их не заметите.
| Единица | Где встречается | Пересчёт |
|---|---|---|
| Па (паскаль) | СИ; ровно его возвращает readPressure() | 101325 Па = 1013,25 гПа |
| гПа (гектопаскаль) | язык метеосводок и синоптиков | гПа = Па / 100 |
| мм рт. ст. | домашние барометры и бабушкины стены | гПа × 0,75 = мм рт. ст. |
| атмосфера | насос, шины, редуктор | 1 атм = 1013,25 гПа |
Высота: формула, которая врёт без калибровки
Высота у барометра — не измерение, а пересчёт: readAltitude(1013.25) подставляет давление в формулу h = 44330 × (1 − (p/p0)^0,1903) и печатает метры. Чувствительность у земли — около восьми метров на каждый гектопаскаль: проезд на лифте с третьего на первый сдвинет показания на те самые 8–9 м. Проверьте на числах: давление 1005 гПа даст 69 м, 1020 гПа — минус 56 м, а 1000 гПа — 111 м. Отсюда главная ловушка: p0 — это давление на уровне моря в момент старта. Погода гоняет давление на 20–30 гПа за сутки-двое, и если зашить константу 1013,25 в сезон циклона, прибор на равнине покажет минус сто с лишним метров. Мой перевальный минус 240 был ровно этим: p0 с заводской константой, а в горах стояло высокое солнечное давление. Правильно калибровать: встаньте на точку с известной высотой, запишите давление в p0 — и с той минуты прибор честен в пределах пары метров, пока погода не сменилась.
// BMP280: температура, давление и высота раз в секунду #include <Wire.h>#include <Adafruit_BMP280.h> Adafruit_BMP280 bmp;float p0 = 1013.25; // калибруйте по своей точке! void setup() { Serial.begin(9600); if (bmp.begin(0x76) == 0) { // 0 — датчик не ответил Serial.println("BMP280 ne nayden: proveryayte 0x76/0x77"); while (1) delay(1000); }} void loop() { float t = bmp.readTemperature(); float p = bmp.readPressure() / 100.0; // Па -> гПа float h = bmp.readAltitude(p0); Serial.print("t="); Serial.print(t, 1); Serial.print(" p="); Serial.print(p, 1); Serial.print(" mm="); Serial.print(p * 0.750062, 0); Serial.print(" h="); Serial.println(h, 1); delay(1000);}Прогноз по давлению — самое благодарное применение. Пороги у меня такие: ниже 1005 гПа — низкое, циклон, жди осадков; выше 1020 гПа — антициклон, ясно; между ними — переменная облачность. Но один замер — это не прогноз, а фотография: давление может стоять на 998 три дня без единой капли, если циклон встал стеной. Честный прогноз смотрит тренд: упало на 3 гПа за три часа — ухудшение почти наверняка, выросло на столько же — проясняется. Та же логика с трендом работает в метеостанции с DHT22, а в итоговой станции на шине барометр живёт рядом с часами и MPU6050 на одной паре A4/A5.
Тренд требует дисциплины по месту. Датчик, который вчера стоял на подоконнике, а сегодня в шкафу, покажет смену погоды, которой не было: этаж и даже расстояние до окна двигают давление на десятые доли гПа. Солнце, падающее на корпус, греет воздух внутри и занижает показания на 1–3 гПа к полудню — мой июльский «обвал» в 15 гПа был наполовину настоящим циклоном, наполовину нагретым корпусом. Держите датчик в тени, на одном месте и на одной высоте, а историю храните минимум за три часа — кольцевого массива из пары сотен ячеек для этого хватает с запасом.
И оговорка про температуру: readTemperature() показывает кристалл, а не воздух комнаты. В закрытом корпусе при опросе раз в секунду кристалл догревается на градус-другой от платы. Для температуры помещения оставьте датчику щель в корпусе и не опрашивайте чаще раза в секунду — или вешайте отдельный термометр.
Куда расти после этого урока. Первый шаг — вывести давление на индикатор из урока про TM1637: четыре цифры гПа с двоеточием выглядят как пейджер метеоролога. Второй — писать кадры на SD-карту со штампом времени: давление с метками за неделю говорит о погоде больше, чем любые пороги. Третий — высотомер на дроне: там BMP280 сажают в forced-режим и осредняют с акселерометром, но это отдельная история с фильтрами.
- readPressure() возвращает паскали: делите на 100 — получаете гектопаскали метеосводок, умножаете на 0,75 — миллиметры ртутного столба
- Адрес пишите явно: begin(0x76) для модулей с SDO на земле, begin(0x77) — на VCC; begin() без аргумента ищет 0x77
- Высота — пересчёт давления: 1 гПа ≈ 8 м у земли; калибруйте p0 по точке с известной высотой, иначе погодный ход 20–30 гПа даст минус двести метров
- Прогноз по одному замеру не работает: ниже 1005 — циклон, выше 1020 — ясно, а предсказание живёт в тренде 3 гПа за 3 часа
- readTemperature() — температура кристалла: в закрытом корпусе она на градус-другой теплее воздуха
- 1. Что возвращает bmp.readPressure()?
- 2. bmp.begin() без аргумента стучится на какой адрес?
- 3. Давление упало с 1013 до 1005 гПа. Насколько сдвинется readAltitude(1013.25)?
- 4. На улице 1002 гПа. Можно ли печатать слово про дождь по одному замеру?
- 5. Погодный ход давления за сутки — 25 гПа. Что покажет некалиброванный высотомер?
Частые вопросы по теме урока
- Что возвращает bmp.readPressure()?
- Библиотека отдаёт паскали: 100 000 вместо 1000. Делите на 100 — получаете гектопаскали для метеосводок. давление в паскалях
- bmp.begin() без аргумента стучится на какой адрес?
- Дефолт библиотеки Adafruit — 0x77. Модули с SDO на земле живут на 0x76, поэтому адрес лучше писать явно. 0x77
- Давление упало с 1013 до 1005 гПа. Насколько сдвинется readAltitude(1013.25)?
- У земли один гектопаскаль — около восьми метров: восемь гПа дают примерно 65–70 метров кажущегося спуска. примерно на 65–70 м
- На улице 1002 гПа. Можно ли печатать слово про дождь по одному замеру?
- Один замер — фотография, а не прогноз: давление может стоять на 998 трое суток без осадков. Работает тренд 3 гПа за 3 часа. нельзя: прогноз смотрит тренд, а не точку
- Погодный ход давления за сутки — 25 гПа. Что покажет некалиброванный высотомер?
- 25 гПа × 8 м = 200 м кажущегося изменения — погодный ход маскируется под движение, поэтому p0 калибруют на месте. минус двести с лишним метров