Реклама ⓘ
Главная » Arduino
Призовой фонд
на апрель 2024 г.
1. 100 руб.
От пользователей

Похожие статьи:


Реклама ⓘ

Электронный барометр своими руками

В данном проекте мы рассмотрим подключения датчика давления по интерфейсу I2C к контроллеру Arduino и снятие показаний. Проще говоря мы создадим электронный барометр своими руками.

В качестве датчика давления мы будем использовать BMP085 от фирмы Bosch. Описание и документацию на датчик можно найти здесь. Даташит: BMP085.
BMP085 представляет из себя высокоточный цифровой датчик атмосферного давления с ультранизким энергопотреблением. Также, датчик позволяет измерять температуру. Интерфейс подключения: I2C. Применяется датчик в GPS-навигации, метеостанциях, приборах определения скорости подьема/спуска, в измерителях мощности воздушного потока и т.п.

Макетная плата с Arduino и BMP085

Информация, которая представлена фирмой Bosch по работе с данным датчиком очень скудная. Разобраться с BMP085 помог сайт Jeelabs

Аппаратная часть

Датчик давления BMP085 на плате

К Arduino, датчик BMP085 подключается также, как и другие I2C устройства: подключите VCC к VCC, GND к GND, SCL к аналоговому выводу 5, а SDA к аналоговому выводу 4. Поставьте подтягивающие (pull-up) резисторы (от 1к до 20к, например 4.7кОм) между SDA, SCL и VCC (на моей плате они уже присутствуют).

Напряжение питания датчика: 1.8-3.6 В. Также, датчик содержит выход EOC, который сигнализирует об окончании процесса измерения и обработки данных. Если EOC=1, то обработка завершена, если EOC=0, то в процессе. EOC подключен к аналоговому выводу 2 Arduino, но не использовался.

Программное обеспечение

К нашей радости, код от Jeenode содержит всю необходимую функциональность, единственное, что я добавил, так это возможность использования всех режимов передискретизации (oversampling). В BMP085 есть возможность задания 4 режимов передискретизации, каждый из которых затрачивает больше времени и энергии, чем предыдущий режим, но в то же время повышает точность измерения.

Итак, программа. Для начала, мы должны сделать возможность считывания всех 16-битных значений с регистров датчика:

int read_int_register(unsigned char r)
{
  unsigned char msb, lsb;
  Wire.beginTransmission(I2C_ADDRESS);
  Wire.send(r);  // регистр для чтения
  Wire.endTransmission();
 
  Wire.requestFrom(I2C_ADDRESS, 2); // считываем 2 байта
  while(!Wire.available()) {
    // ожидание
  }
  msb = Wire.receive();
  while(!Wire.available()) {
    // ожидание
  }
  lsb = Wire.receive();
  return (((int)msb<<8) | ((int)lsb));
}

Далее, нам необходима функция, которая будет записывать значение в 8-ми битный регистр:

char read_register(unsigned char r)
{
  unsigned char v;
  Wire.beginTransmission(I2C_ADDRESS);
  Wire.send(r);  // регистр для чтения
  Wire.endTransmission();
 
  Wire.requestFrom(I2C_ADDRESS, 1); // считываем байт
  while(!Wire.available()) {
    // ожидание
  }
  v = Wire.receive();
  return v;
}

Затем, нужно определить несколько глобальных переменных для чтения калибровочных данных из Eeprom датчика:

//взято с даташита BMP085
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;
void  bmp085_get_cal_data() {
  Serial.println("Reading Calibration Data");
  ac1 = read_int_register(0xAA);
  Serial.print("AC1: ");
  Serial.println(ac1,DEC);
  ac2 = read_int_register(0xAC);
  Serial.print("AC2: ");
  Serial.println(ac2,DEC);
  ac3 = read_int_register(0xAE);
  Serial.print("AC3: ");
  Serial.println(ac3,DEC);
  ac4 = read_int_register(0xB0);
  Serial.print("AC4: ");
  Serial.println(ac4,DEC);
  ac5 = read_int_register(0xB2);
  Serial.print("AC5: ");
  Serial.println(ac5,DEC);
  ac6 = read_int_register(0xB4);
  Serial.print("AC6: ");
  Serial.println(ac6,DEC);
  b1 = read_int_register(0xB6);
  Serial.print("B1: ");
  Serial.println(b1,DEC);
  b2 = read_int_register(0xB8);
  Serial.print("B2: ");
  Serial.println(b1,DEC);
  mb = read_int_register(0xBA);
  Serial.print("MB: ");
  Serial.println(mb,DEC);
  mc = read_int_register(0xBC);
  Serial.print("MC: ");
  Serial.println(mc,DEC);
  md = read_int_register(0xBE);
  Serial.print("MD: ");
  Serial.println(md,DEC);
}

Снятие показаний всех значений с Eeprom может более эффективным, чем каждый раз записывать и считывать показания с каждого регистра. Т.о. достигается хороший выигрыш по времени.
Данные raw температуры(ut) и давления(up) могут быть считаны как 16 и 24 битные значения:

unsigned int bmp085_read_ut() {
  write_register(0xf4,0x2e);
  delay(5); //дольше чем 4.5 мс
  return read_int_register(0xf6);
}
long bmp085_read_up() {
  write_register(0xf4,0x34+(oversampling_setting<<6)); 
  delay(pressure_waittime[oversampling_setting]);
 
  unsigned char msb, lsb, xlsb;
  Wire.beginTransmission(I2C_ADDRESS);
  Wire.send(0xf6);
  Wire.endTransmission();
 
  Wire.requestFrom(I2C_ADDRESS, 3);
  while(!Wire.available()) {
    // ожидание
  }
  msb = Wire.receive();
  while(!Wire.available()) {
    // ожидание
  }
  lsb |= Wire.receive();
  while(!Wire.available()) {
    // ожидание
  }
  xlsb |= Wire.receive();
  return (((long)msb<<16) | ((long)lsb<<8) | ((long)xlsb)) >>(8-oversampling_setting);
}

Алгоритм преобразования температуры и давления из raw-данных датчика в реальную температуру (градусы Цельсия) и давление (Паскаль) взят из даташита (плюс некоторые дополнения от Jeenodes):

void bmp085_read_temperature_and_pressure(int* temperature, long* pressure) {
   int  ut= bmp085_read_ut();
   long up = bmp085_read_up();
   long x1, x2, x3, b3, b5, b6, p;
   unsigned long b4, b7;
 
   //расчет температуры
   x1 = ((long)ut - ac6) * ac5 >> 15;
   x2 = ((long) mc << 11) / (x1 + md);
   b5 = x1 + x2;
   *temperature = (b5 + 8) >> 4; 
 
   //расчет давления
   b6 = b5 - 4000;
   x1 = (b2 * (b6 * b6 >> 12)) >> 11; 
   x2 = ac2 * b6 >> 11;
   x3 = x1 + x2;
   b3 = (((int32_t) ac1 * 4 + x3)<> 2;
   x1 = ac3 * b6 >> 13;
   x2 = (b1 * (b6 * b6 >> 12)) >> 16;
   x3 = ((x1 + x2) + 2) >> 2;
   b4 = (ac4 * (uint32_t) (x3 + 32768)) >> 15;
   b7 = ((uint32_t) up - b3) * (50000 >> oversampling_setting);
   p = b7 < 0x80000000 ? (b7 * 2) / b4 : (b7 / b4) * 2;
   
   x1 = (p >> 8) * (p >> 8);
   x1 = (x1 * 3038) >> 16;
   x2 = (-7357 * p) >> 16;
   *pressure = p + ((x1 + x2 + 3791) >> 4); 
}

Данные температуры и давления рассчитываются в одно и то же время (значения температуры используются для расчета давления).

Оригинал статьи

Прикрепленные файлы:

Теги:

Колтыков А.В. Опубликована: 2011 г. 0 2
Я собрал 0 0
x

Оценить статью

  • Техническая грамотность
  • Актуальность материала
  • Изложение материала
  • Полезность устройства
  • Повторяемость устройства
  • Орфография
0

Средний балл статьи: 0 Проголосовало: 0 чел.

Комментарии (9) | Я собрал (0) | Подписаться

0
Аким #
Такие статьи позволяют любителям расширять кругозор. Спасибо.
Ответить
0
FreeManGH #
Доброго времени суток!
Залил скетч и на сериал мониторе получил следующее:
Setting up BMP085
Reading Calibration Data
AC1: 7386
AC2: -1005
AC3: -14386
AC4: 31836
AC5: 24818
AC6: 20257
B1: 5498
B2: 5498
MB: -32768
MC: -11075
MD: 2432
540 98933
540 98931
540 98928
540 98938
540 98934
540 98938
541 98938
541 98945
541 98953
540 98931
В каких единицах(формате) выплевываются данные?
540 - вроде температоура, а 98933 - давление, как перевести в градусы цельсия и в мм.рт.ст?
Ответить
0
Павел #
Разделите второй столбец на 133.3
Ответить
0
Евгений #
Я так понял, датчик показывает данные в Кельвинах и Паскалях?Чтобы перевести показания в удобоваримые:
- нужно из первого столбца вычесть 273,15 и получим температуру в градусах Цельсия;
- второй столбец разделить на 133.3, чтобы перевести давление из Паскалей в мм.рт.ст.

Но у меня какой-то косяк в расчётах в приведенном скетче. Давление нормально переводится и отображается (99308 Па или 745 мм рт ст). А вот температура отображается числом около 270, если это Кельвины, то при переводе в цельсии получаем -3 градуса, хотя дома у меня около 25 градусов
В чем может быть проблема?
Ответить
0
Евгений #
Видимо, дома у вас 27 градусов. Не помню точно, вроде ардуино не дружит с плавающей точкой, поэтому 270 это 27,0 градуса.
Ответить
0
Роман #
Здравствуйте! Собрал подобный барометр - работает, всё ок, но только показания давления скачут (также как и на рисунке выше) Вопрос: Так и должно быть?
Ответить
0
Максим #
Подскажите, а как прочитать данные по высоте над уровнем моря? Этот датчик позволяет выводить данные по температуре, давлению и высоте.
Ответить
0
Андрей #
Максим, об этом сказано в даташите на bmp085. Высота рассчитывается по формуле h=4330*(1-(p/p0)^1/5.255). Где р0 - это давление над уровнем моря.
Ответить
0
Miko #
Здравствуйте! У меня датчик размещен немного на другой плате, там два питания - 5 и 3,3... это типа можно выбрать необходимо напряжение или нужно их 2 подключать?
Не работает чет у меня, пишет:

Setting up BMP085
Reading Calibration Data
и зависает в функции bmp085_get_cal_data() -> "read_int_register" на первом "ожидании"

Wire.requestFrom(I2C_ADDRESS, 2); // read a byte
while(!Wire.available()) {
// ожидание
}
Подскажите плиз, в чем может быть проблема?
Ответить
Добавить комментарий
Имя:
E-mail:
не публикуется
Текст:
Защита от спама:
В чем измеряется сила тока?
Файлы:
 
Для выбора нескольких файлов использйте CTRL

Arduino UNO
Arduino UNO
Модуль радиореле на 4 канала Катушка Тесла
вверх