BMP085 не показывает температуру/давление
- Войдите на сайт для отправки комментариев
Втр, 09/12/2014 - 09:46
Господа, я снова со своей метеостанцией пришел. Ввожу в курс темы. В спойлере можно не читать :) Суть проблемы: с BMP085 нет ни температуры ни давления.
В прошлый раз я её таки дописал, поставил на окошко и забыл. Но тут пришел северный пушной зверек и с бп станции вместо 5В прошло >20В. Ардуина, дисплей, DHT11 погорели. Попечалился... но заменил ардуину, убрал ДНТ, поменял дисплей (он через перехолник I2C), включил и не увидел температуры и давления с BMP085. Думал датчику пипец, но нет. Взял другой - тоже самое. На другой станции оба датчика работают. Далее что-то наковырял и все заработало - и давление и температура показываются, но не устраивал дисплей (1602 вместо 2402) . Забросил это дело и то, что наковырял потерял. Зашиваю то, что было до сгорания и вижу опять, что нет ни температуры ни давления с BMP085. Если быть точнее, то давление переодически меняется в пределах от -8 до -10.
Ниже код скетча. Ссылка ведет на полный архив прошивки. Подскажите, пожалуйста в чем проблема.
#include <Wire.h> // Common library #include "DHT.h" // DHT11 & DHT22 Library #include "af_BMP085.h" // Simple library for BMP085 #include <EtherCard.h> // ENC28J60 Library #include <LiquidCrystal_I2C.h> // Display with PFC8574 // BMP085: SDA->A4 / SCL->A5 // DHT11: DATA->A0 // DHT22: DATA->A1 // JACK: DATA->D4 // DISPLAY-I2C: SDA->A4 SCL->A5 BACKLIGHT->D5 // ENC28J60: SCK->D13 MOSI->D12 MISO->D11 INT->D2 RST->RST CS->D10 // ISP: SCK->D13 MOSI->D12 MISO->D11 RST->RST // DIODE GREEN: + -> D8 // DIODE ORANGE: + -> D7 // BUZZER: SIGNAL -> D9 // ANEMOMETER -> D3 (INT1) #define DHT_S1_PIN A1 // DHT22 / AM2302 #define DHT_S2_PIN A0 // DHT11 //#define WIND_PIN 3 // Anemometer uint8_t wind[8] = {B11000,B00011,B00100,B11000,B00011,B00100,B11000}; //ветер uint8_t home[8] = {B00100,B01010,B11111,B10001,B10101,B10001,B11111}; //домик uint8_t sun[8] = {B00100,B10101,B01110,B11011,B01110,B10101,B00100}; //солнышко uint8_t mmhg[8] = {B01110,B01110,B01110,B01110,B11111,B01110,B00100}; //давление uint8_t temp_w_cel[8] = {B00011,B00011,B01100,B10010,B10000,B10010,B01100}; //ц с градусом uint8_t hum[8] = {B00000,B00100,B01010,B01010,B10001,B11111,B01110}; //влажность uint8_t humidity = 0, temp_dht = 0, humidity2 = 0, temp_dht2 = 0, temp = 0, temp_bmp = 0; //short int humidity = 0, temp_dht = 0, humidity2 = 0, temp_dht2 = 0, temp = 0;//temp_bmp = 0, static uint8_t mymac[6] = { 0x11,0x11,0x11,0x11,0x11,0x11 }; LiquidCrystal_I2C lcd(0x20,4,5,6,0,1,2,3,7, NEGATIVE); //const char website[12] = "narodmon.ru"; static byte hisip[] = { 94, 19, 113, 221 }; static byte dnsip[] = {8, 8, 8, 8}; #define STATIC 1 #if STATIC static byte myip[] = { 10,1,1,62 }; static byte gwip[] = { 10,1,1,10 }; #endif int8_t pressure_mm = 0; //int32_t pressure_pa = 0, pressure_mm = 0; volatile byte half_revolutions = 0; byte Ethernet::buffer[550]; float avgwspeed = 0; //unsigned int avgrpm=0; float wspeed=0; Adafruit_BMP085 bmp; dht dht_s1, dht_s2; Stash stash; void(* resetFunc) (void) = 0; unsigned long DisplayTime; unsigned long lDisplayTime; unsigned long NMTime; unsigned long lNMTime; unsigned long AnemoTime; unsigned long lAnemoTime; unsigned long ResetTime; unsigned long lResetTime; void setup() { // LCD // pinMode(5, INPUT); // set pin to input // digitalWrite(5, HIGH); // turn on pullup resistors lcd.home(); lcd.begin(16,2); lcd.createChar(0, wind); lcd.createChar(1, home); lcd.createChar(2, sun); lcd.createChar(3, mmhg); lcd.createChar(4, temp_w_cel); lcd.createChar(5, hum); lcd.setCursor(0,0); lcd.print("[Online........."); lcd.setCursor(0,1); lcd.print("Meteostation v3]"); delay(3000); lcd.clear(); // ETHERNET if (ether.begin(sizeof Ethernet::buffer, mymac, 10) == 0) { lcd.setCursor(0,0); lcd.print("ETH ERR"); } else { lcd.setCursor(0,0); lcd.print("ETH OK"); }; #if STATIC ether.staticSetup(myip, gwip); #else if (!ether.dhcpSetup()) #endif ether.dhcpSetup(); if (!ether.dhcpSetup()) { lcd.setCursor(8,0); lcd.print("DHCP ERR"); } else { lcd.setCursor(8,0); lcd.print("DHCP OK"); } ether.copyIp(ether.dnsip, dnsip); ether.copyIp(ether.hisip, hisip); /* if (!ether.dnsLookup(website)){ lcd.setCursor(17,0); lcd.print("DNS ERR"); } else { lcd.setCursor(17,0); lcd.print("DNS OK"); }*/ while (ether.clientWaitingGw()) { ether.packetLoop(ether.packetReceive()); lcd.setCursor(0,1); lcd.print("GW OK"); } delay(4000); lcd.clear(); // BMP085 bmp.begin(); // Narodmon.ru Update nm_upd(); // Display Update DisplayTotal(); // 600000 - 10 min // 60000 - min // 1000 - sec // 100 - millisec // 10 - microsec // 1 sec = 1000ms = 1000000uS attachInterrupt(1, rpm_fun, FALLING); DisplayTime = millis(); // считываем время, прошедшее с момента запуска программы NMTime = millis(); AnemoTime = millis(); ResetTime = millis(); lDisplayTime = DisplayTime; lNMTime = NMTime; lAnemoTime = AnemoTime; lResetTime = ResetTime; } void loop() { DisplayTime = millis(); // считываем время, прошедшее с момента запуска программы if(DisplayTime >= (lDisplayTime + 60000)){ // сравниваем текущий таймер с переменной lDisplayTime + 60 секунд DisplayTotal(); // Обновляем дисплей lDisplayTime = DisplayTime; // в lDisplayTime записываем новое значение } NMTime = millis(); // считываем время, прошедшее с момента запуска программы if(NMTime >= (lNMTime + 300000)){ // сравниваем текущий таймер с переменной lNMTime + 300 секунд nm_upd(); // Отправка данных на народный мониторинг lNMTime = NMTime; // в lNMTime записываем новое значение } AnemoTime = millis(); // считываем время, прошедшее с момента запуска программы if(AnemoTime >= (lAnemoTime + 60000)){ // сравниваем текущий таймер с переменной lAnemoTime + 60 секунд anemometer(); // Обсчет анемометра lAnemoTime = AnemoTime; // в lAnemoTime записываем новое значение } ResetTime = millis(); // считываем время, прошедшее с момента запуска программы if(ResetTime >= (lResetTime + 86400000)){ // сравниваем текущий таймер с переменной lResetTime + сутки resetFunc(); // сброс lResetTime = ResetTime; // в lAnemoTime записываем новое значение } // Ethernet ping answer ether.packetLoop(ether.packetReceive()); } // Narodmon.ru Update void nm_upd(){ lcd.clear(); lcd.setCursor(0,0); lcd.print("..Now.updating.."); lcd.setCursor(0,1); lcd.print("..narodmon.ru..."); MS_BMP085(); MS_DHT11(); MS_DHT22(); byte sd = stash.create(); stash.println("ID=111111111111"); stash.println("&11111111111100="); stash.println(temp_dht); stash.println("&11111111111101="); stash.println(humidity); stash.println("&11111111111102="); stash.println(pressure_mm); anemometer(); stash.println("&11111111111106="); stash.println(avgwspeed); // stash.println(temp_bmp); stash.println("&11111111111104="); stash.println(temp_dht2); stash.println("&11111111111105="); stash.println(humidity2); stash.save(); Stash::prepare(PSTR("POST http://narodmon.ru/post.php HTTP/1.0" "\r\n" "Host: narodmon.ru" "\r\n" "Content-Length: $D" "\r\n" "\r\n" "$H"), stash.size(), sd); ether.tcpSend(); stash.cleanup(); delay(1500); lcd.clear(); DisplayTotal(); } // Main display view void DisplayTotal() { MS_SensUpdate(); lcd.clear(); lcd.setCursor(0,0); lcd.write(byte(1));//home lcd.setCursor(2,0); if (temp_dht <= -1) { lcd.print("-"); } else if (temp_dht >= 1) { lcd.print("+"); }; lcd.setCursor(3,0); lcd.print(temp_dht); lcd.setCursor(5,0); lcd.write(byte(4));//cel lcd.setCursor(7,0); lcd.write(byte(5));//hum lcd.print(humidity); lcd.setCursor(11,0); lcd.write(byte(0));//wind // lcd.print("W"); lcd.print(avgwspeed); lcd.setCursor(0,1); lcd.write(byte(2));//sun lcd.setCursor(2,1); if ( temp_dht2 >= 1 ) { lcd.print("+"); } else if (temp_dht2 <= -1) { lcd.print("-"); }; lcd.setCursor(3,1); lcd.print(temp_dht2); lcd.setCursor(5,1); lcd.write(byte(4));//cel lcd.setCursor(7,1); lcd.write(byte(5));//hum lcd.print(humidity2); lcd.setCursor(11,1); lcd.write(byte(3));//mmhg lcd.print(pressure_mm); /* [0][1][2][3][4][5 ][6][7][8][9][10][11][12][13][14][15] [S][ ][+][2][3][c*][ ][3][2][%][ ][W ][2 ][3 ][m] [s ] [H][ ][+][2][3][c*][ ][4][5][%][ ][p ][7 ][4 ][5 ][ ] Total: 16x02 */ } // Sensors // Update all sensors one time void MS_SensUpdate() { MS_BMP085(); MS_DHT22(); MS_DHT11(); } // Update only BMP085 void MS_BMP085() { temp_bmp = bmp.readTemperature(); pressure_mm = (bmp.readPressure()/133.3); } // Update only DHT22 void MS_DHT22() { if (dht_s1.read22(DHT_S1_PIN) == DHTLIB_OK) { humidity = dht_s1.humidity; temp_dht = dht_s1.temperature; temp = temp_dht; } else { temp = temp_dht; } } // Update only DHT11 void MS_DHT11() { if (dht_s2.read11(DHT_S2_PIN) == DHTLIB_OK) { humidity2 = dht_s2.humidity; temp_dht2 = dht_s2.temperature; temp = temp_dht2; } else { temp = temp_dht2; } } void rpm_fun() { half_revolutions++; } void anemometer(){ float tavgwspeed = 0; short int taws = 0; detachInterrupt(1); wspeed = half_revolutions * 0.60288; // метров в минуту wspeed = wspeed / 60; // метров в секунду if (taws == 10){ avgwspeed = tavgwspeed / 10; // средняя скорость tavgwspeed = 0; taws = 0; } else if (taws <= 9) { tavgwspeed = tavgwspeed + wspeed; // накапливание taws++; } else if (taws >= 11) { taws = 0; } half_revolutions = 0; attachInterrupt(1, rpm_fun, FALLING); }
https://www.dropbox.com/s/s9xtv3ugwcsjt6x/INT_MLS_XWS_ETHERCARD.zip?dl=0
Хрень какая-то получилась, а редактировать нельзя :(
Столько кода написано, а смысл всех этих заворотов в чем?
В том что я ни разу не программист. Все составлено из кусков примеров, по сути. И оптимизировать смысла не вижу.
Смысл в собирании данных и отправке на народный мониторинг (хотя теперь уже будет отслыаться на другой сайт, но это не важно).
По идее программа должна строиться так:
Загловочные файлы
Объявление переменных для датчиков и шин
Объявление глобальных переменных
setup() {
Запуск датчиков и прочих устройств
Рисование статических надписей на дисплее
Определение прерываний
}
void() {
Опрос датчиков
Обработка полученных данных
Вывод результатов на экран
Отправка данных
}
Interrupt () {
Выставление флагов
Накопление суммы
}
Прерывание должно быть резким как выстрел. Все расчеты надо выполнять в loop, а у тебя там много медленных операций, да и передергивание прерываний, на которых теряются сигналы.
По уму тебе надо в прерывании только импульсы считать, а скорость периодически в loop считать.
На дисплей надо писать так, чтобы лишний раз не переписывать статические надписи.
MS_SensUpdate у тебя вообще вызывается всего один раз. Смысла выносить в отдельную функцию нет никакого.
И у тебя дисплей сначала используется (75), а потом запускается (76).
pressure_mm у тебя объявлено как целое (44), а записывается в него дробное (291). С temp_bmp такая же песня.
Проверяй типы переменных.
MS_SensUpdate был задумкой но остался и пусть пока будет. 75-76 поменял. Анемометр убрал совсем. Давление дробное изпользовать не буду - исправил.
Давление и температура с бмп - не появились.
Ни разу не вижу исправлений.
В библиотеке adafruit такое объявление:
long - это целое. Либо преобразуй при выводе, либо делай преобразование при вычислении.
Датчик сам вообще живой? Попробуй залить I2cScanner и посмотри какие устрйоства на шине отзываются. По идее должен быть один из 0x20-0x27 (дисплей) и 0x77 (датчик). Ну и SDA и SCL проверь.
то-то мне и казалось что лонг не звучит %) исправил на флоат - не взлетело все равно.
Я в первом посте написал, что датчик рабочий (проверено на другом девайсе) и вся конструкция работала, пока я не зашил этот скетч (но этот же скетч, что самое странное, исправно работал почти месяцдо сгорания прошлой ардуины) .
Я тебе не просто так про i2cscanner написал.
Так и не смог придумать, зачем это надо. Датчик рабочий, адрес дисплея (работающего) известен...
Снова ерунда. После сканера зашил предыдущую прошивку (где исправлял флоат) и всё заработало. Показывает и температуру и давление О_о
Однако поторопился делиться радостью. Дисплей теперь как-то медленно-плавно перерисовывается и при этом по углам фиолетовые буквы вместо белых (он у меня синий фон белые буквы). Во время экспериментов я наблюдал такое действие при очень быстрой выдаче данных на дисплей (без И2Ц), но тут надписи меняются с указанными в коде задержками.
Ну это уже напругу на дисплее смотри и код отлаживай.
Здравствуйте всем! С наступившым 2015годом!
Небольшое продолжение темы:
Просидел несколько вечеров, молясь на BMP180. Перебрал все существующие библиотеки и примеры.
Наиболее правдиво работают от Адафруит. Но выяснилась интересная зависимость....
Высота над уровнем моря напрямую зависит от температуры. Вроде все совпадает. Давление, температура, а вот
высота нет. У меня по данным гугли 53м., а датчик показывает 70--72м. Напрашивается вопрос, кому верить. Как Гугл измеряет высоту места? Кому верить то????
Кому верить то????
Осталось найти двух владельцев более менее профессиональных GPS приемников, и поинтересоваться высотой у них...
Высота вычисляется из давления на уровне 0. Оно либо задается, либо используется захардкоженное значение.
Решил все же проверить - включил Навител. И о....!!!!! Высота 68.1м. Через 20мин. 63.2м. Этому уже можно верить.
#include <Wire.h>
#include <Adafruit_BMP085.h>
/***************************************************
This is an example for the BMP085 Barometric Pressure & Temp Sensor
Designed specifically to work with the Adafruit BMP085 Breakout
----> https://www.adafruit.com/products/391
These displays use I2C to communicate, 2 pins are required to
interface
Adafruit invests time and resources providing this open source code,
please support Adafruit and open-source hardware by purchasing
products from Adafruit!
Written by Limor Fried/Ladyada for Adafruit Industries.
BSD license, all text above must be included in any redistribution
****************************************************/
// Connect VCC of the BMP085 sensor to 3.3V (NOT 5.0V!)
// Connect GND to Ground
// Connect SCL to i2c clock - on '168/'328 Arduino Uno/Duemilanove/etc thats Analog 5
// Connect SDA to i2c data - on '168/'328 Arduino Uno/Duemilanove/etc thats Analog 4
// EOC is not used, it signifies an end of conversion
// XCLR is a reset pin, also not used here
Adafruit_BMP085 bmp;
void setup() {
Serial.begin(9600);
if (!bmp.begin()) {
Serial.println("Could not find a valid BMP085 sensor, check wiring!");
while (1) {}
}
}
void loop() {
Serial.print("Temperature = ");
Serial.print(bmp.readTemperature());
Serial.println(" *C");
Serial.print("Pressure = ");
Serial.print(bmp.readPressure());
Serial.println(" Pa");
// Calculate altitude assuming 'standard' barometric
// pressure of 1013.25 millibar = 101325 Pascal
Serial.print("Altitude = ");
Serial.print(bmp.readAltitude());
Serial.println(" meters");
// you can get a more precise measurement of altitude
// if you know the current sea level pressure which will
// vary with weather and such. If it is 1015 millibars
// that is equal to 101500 Pascals.
Serial.print("Real altitude = ");
Serial.print(bmp.readAltitude()); // Вот здесь я убрал значение.
//Serial.print(bmp.readAltitude(101500)); // Оригинальная строка. (Для чего у автора 101500, не знаю)
Serial.println(" meters");
Serial.println();
delay(5000); //Тут я увеличил задержку, что бы часто не обновлялся порт, а то не удобно.
}
Это от Адафруит. У меня пашет. Правда скетч для BMP085, а у меня BMP185, но особой разницы не вижу.
Спасибо всем за участие.
Следующие испытания - магнитный компас.
Вычисление высоты по давлению можно проводить только если откалибровать значения при текущем давлении. Без этого можно узнать только относительное смещение по высоте..
Датчик откалиброван уже Бошевцами. Иначе и не работал бы. Одно не понятно. Как математику пишут в библиотеках?! От Адафруит написана правильно, а вот остальные, что пробовал не работают!!! В даташите формулы удобоваримые, а библиотеках...... Как посмотришь, аж плохо становится. Вот такие выражения-для меня полный лес. Со временем конечно станет понятно, и можно будет самому править библиотеки, но пока..... Никак не пойму, что за двойные угловые скобки???!!!!
X1 = ((int32_t)ac3 * B6) >> 13;
X2 = ((int32_t)b1 * ((B6 * B6) >> 12)) >> 16;
X3 = ((X1 + X2) + 2) >> 2;
B4 = ((uint32_t)ac4 * (uint32_t)(X3 + 32768)) >> 15;
B7 = ((uint32_t)UP - B3) * (uint32_t)( 50000UL >> oversampling );
откалибровано там давление, а не высота
Ясное дело. Он по температуре и давлению высоту определяет.