Arduino BMP085 Барометрический датчик пустой последовательный монитор

Я новичок в Arduino и микроконтроллерах. Я использую датчик барометрического давления BMP085. Я выполнил все необходимые подключения к плате arduino uno и дважды проверил их. Я хочу получить показания с датчика и отобразить их на моем последовательном мониторе arduino. Код, который я использую, компилируется и загружается без ошибок, но когда я открываю свой последовательный монитор, он пустой. Я пробовал использовать датчик влажности/температуры до этого, и этот датчик возвращает значения на последовательный монитор. Барометрический датчик новый, и я использовал его впервые.

Вот мой набросок. Я взял его отсюда. https://www.sparkfun.com/tutorials/253

Любая помощь будет высоко оценена.

код

#include <Wire.h>

#define BMP085_ADDRESS 0x77  // I2C-адрес BMP085

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;

// b5 вычисляется в bmp085GetTemperature(...), эта переменная также используется в bmp085GetPressure(...)
// поэтому ...Temperature(...) необходимо вызвать перед ...Pressure(...).
long b5; 

short temperature;
long pressure;

// Используйте их для преобразования высоты
const float p0 = 101325;     // Давление на уровне моря (Па)
float altitude;

void setup()
{
  Serial.begin(9600);
  Wire.begin();
  bmp085Calibration();
}

void loop()
{
  temperature = bmp085GetTemperature(bmp085ReadUT());
  pressure = bmp085GetPressure(bmp085ReadUP());
  altitude = (float)44330 * (1 - pow(((float) pressure/p0), 0.190295));

  Serial.print("Temperature: ");
  Serial.print(temperature, DEC);
  Serial.println(" *0.1 deg C");
  Serial.print("Pressure: ");
  Serial.print(pressure, DEC);
  Serial.println(" Pa");
  Serial.print("Altitude: ");
  Serial.print(altitude, 2);
  Serial.println(" m");
  Serial.println();

  delay(1000);
}

// Сохраняет все значения калибровки bmp085 в глобальные переменные
// Значения калибровки необходимы для расчета температуры и давления
// Эту функцию следует вызывать в начале программы
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);
}

// Рассчитать температуру по заданному ut.
// Возвращаемое значение будет в единицах 0,1 градуса по Цельсию
short bmp085GetTemperature(unsigned int ut)
{
  long x1, x2;

  x1 = (((long)ut - (long)ac6)*(long)ac5) >> 15;
  x2 = ((long)mc << 11)/(x1 + md);
  b5 = x1 + x2;

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

// Рассчитать отданное давление
// значения калибровки должны быть известны
// b5 также требуется, поэтому bmp085GetTemperature(...) должен быть вызван первым.
// Возвращаемое значение будет представлять собой давление в единицах Па.
long bmp085GetPressure(unsigned long up)
{
  long x1, x2, x3, b3, b6, p;
  unsigned long b4, b7;

  b6 = b5 - 4000;
  // Рассчитать B3
  x1 = (b2 * (b6 * b6)>>12)>>11;
  x2 = (ac2 * b6)>>11;
  x3 = x1 + x2;
  b3 = (((((long)ac1)*4 + x3)<<OSS) + 2)>>2;

  // Рассчитать 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;

  return p;
}

// Считать 1 байт из BMP085 по адресу 'address'
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();
}

// Считываем 2 байта из BMP085
// Первый байт будет из 'address'
// Второй байт будет из 'address'+1
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;

  // Записать 0x2E в регистр 0xF4
  // Это запрашивает показания температуры
  Wire.beginTransmission(BMP085_ADDRESS);
  Wire.write(0xF4);
  Wire.write(0x2E);
  Wire.endTransmission();

  // Подождите не менее 4,5 мс
  delay(5);

  // Считываем два байта из регистров 0xF6 и 0xF7
  ut = bmp085ReadInt(0xF6);
  return ut;
}

// Считать некомпенсированное значение давления
unsigned long bmp085ReadUP()
{
  unsigned char msb, lsb, xlsb;
  unsigned long up = 0;

  // Записать 0x34+(OSS<<6) в регистр 0xF4
  // Запрос показаний давления с настройкой избыточной выборки
  Wire.beginTransmission(BMP085_ADDRESS);
  Wire.write(0xF4);
  Wire.write(0x34 + (OSS<<6));
  Wire.endTransmission();

  // Ожидание преобразования, время задержки зависит от OSS
  delay(2 + (3<<OSS));

  // Прочитать регистр 0xF6 (MSB), 0xF7 (LSB) и 0xF8 (XLSB)
  Wire.beginTransmission(BMP085_ADDRESS);
  Wire.write(0xF6);
  Wire.endTransmission();
  Wire.requestFrom(BMP085_ADDRESS, 3);

  // Подождите, пока данные станут доступны
  while(Wire.available() < 3)
    ;
  msb = Wire.read();
  lsb = Wire.read();
  xlsb = Wire.read();

  up = (((unsigned long) msb << 16) | ((unsigned long) lsb << 8) | (unsigned long) xlsb) >> (8-OSS);

  return up;
}

проводки: https://i.sstatic.net/oRX0V.jpg

, 👍0

Обсуждение

Покажите нам свой код и схему подключения. То, что ваш код компилируется и вы дважды проверили подключение, не означает, что ошибок в кодировке быть не может., @chrisl

На этой веб-странице есть несколько фрагментов кода, поэтому, пожалуйста, скопируйте и вставьте код, который вы пытаетесь использовать, в свой вопрос., @jose can u c

Самая простая причина: вы настроили последовательный монитор на скорость передачи данных 9600 бод? Можете также добавить Serial.println("SKETCH STARTING"); после вызова Serial.begin(), чтобы проверить загрузку скетча?, @Maximilian Gerhardt

Может ли быть, что мой датчик неисправен? Если да, то как проверить его исправность? Я взял весь ino-файл из руководства и прочитал о том, что делает каждый раздел кода. На сайте не было никаких библиотек, поэтому все математические вычисления являются частью кода., @Hououin Kyoma

Скорость передачи данных — 9600 бод. Я только что проверил., @Hououin Kyoma

@MaximilianGerhardt Я добавил Serial.println("SKETCH STARTING");, как вы и указали. Скетч загрузился. На мониторе появилось сообщение "Sketch starting". После этого всё пусто., @Hououin Kyoma

Функции чтения блокируют программу до получения данных. Проверьте, можете ли вы связаться с датчиком по I2C/Wire, используя скетч сканера I2C [https://playground.arduino.cc/Main/I2cScanner]. Если устройство не отображается, значит, подключение или датчик неисправны. Если датчик найден, проверьте, соответствует ли найденный адрес используемому вами., @chrisl

Также следует показать проводку, создав схему (например, с помощью инструмента в этом редакторе вопросов) или, если вам так удобнее, с помощью чего-то вроде Fritzing. На ваших низкокачественных изображениях очень сложно разглядеть саму проводку., @chrisl

@chrisl Вот схема. https://learn.adafruit.com/assets/484 . Я попытался связаться с датчиком, запустив скетч, ссылку на который вы привели выше, но устройство не обнаружилось. Плата не может связаться с датчиком., @Hououin Kyoma

Тогда, как написал artag, вы могли сжечь датчик, в зависимости от того, какая у вас версия., @chrisl

У меня версия 3,3 В. Я в курсе, поэтому и подключил к выводу 3,3 В. Возможно ли, что я спалил датчик? Есть ли верный способ проверить это?, @Hououin Kyoma

Важно не только напряжение питания. UNO выдаёт 5 В как на SDA, так и на SCL, что может сжечь аппаратную часть I2C платы. Единственный способ убедиться в этом — проверить второй модуль, который всё ещё в порядке. На этот раз обязательно используйте преобразователь уровня., @chrisl


1 ответ


Лучший ответ:

1

Существует несколько версий плат коммутации для BMP085. Само устройство представляет собой 3v3. Некоторые платы коммутации оснащены регулятором, поэтому вы можете подавать 5 В. Некоторые также выполняют сдвиг уровня, поэтому вы можете управлять линиями I2C при 5 В и корректно работать с уровнями датчика 3v3.

Непонятно, какой у вас тип, но, похоже, вы питаете его от 3v3 на ардуино. Фото другой стороны платы датчика помогло бы.

Если датчик имеет регулятор, то его питание от 3v3 немного снизит его (регулятору нужны некоторые накладные расходы). Это может означать, что датчик работает при слишком низком напряжении.

Если на плате нет регулятора, то правильно будет запитать ее от 3v3. Однако линии I2C также нуждаются в преобразовании. Вы будете подавать 5 В на вход 3v3, что может повредить его. Вы также будете получать уровни 3v3 от датчика на 5 В arduino, что, вероятно, будет работать, но может и нет.

В идеале, поставьте между ними переключатели уровня. Они должны быть двунаправленными, как эти: https://www.adafruit.com/product/757

В некоторых случаях можно обойтись только резисторами, но на двунаправленной шине I2C это не так просто. SPI проще, так как контакты однонаправленные.

,

мой датчик http://2.bp.blogspot.com/-rYK6t2jDt_0/VxX02W1VNzI/AAAAAAAABCk/7W83W7ufzo8Kj97Ay0ioVDxBJE3vmqiNwCK4B/s1600/BMP085.jpg Возможно ли, что я спалил датчик? Я подключил его к контакту 3,3 В на плате Uno. Я немного почитал и обнаружил, что датчик оснащён стабилизатором напряжения 3,3 В. Попробую подключить его к выводу 5 В., @Hououin Kyoma

Это возможно, но это будет зависеть от того, имеются ли также преобразователи уровней для защиты управляющих контактов 3v3 от контактов 5v Arduino., @artag

Adafruit сообщает: V1 разъема использует только напряжение питания 3,3 В и логический уровень. V2 выхода использует напряжение питания 3,3–5 В и логический уровень для более гибкого использования., @artag