// BAROMARE - versao 1.1.0 // Um datalogger para Arduino com o sensor de pressão/temperatura BMP085 da BOSCH. // Data logging shield: Adafruit // BMP085 breakout board: SparkFun // Esse programa é uma versão a baseada e atualizada nos esquetes #include #include #include "RTClib.h" #define BMP085_ADDRESS 0x77 // endereço I2C do BMP085 const unsigned char OSS = 0; // Oversampling Setting // Valores de calibração 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 é calculada na função bmp085GetTemperature - está variável é também usada na função bmp085GetPressure. Assim a função bmp085GetTemperature deve ser chamada antes da bmp085GetPressure */ long b5; short temperatura; long pressao; float temp; // LOG_INTERVAL - intervalo de tempo (milisegundos) entre leituras // use 10*LOG_INTERVAL para gravar um dado a cada 10 leituras #define LOG_INTERVAL 60000 //neste caso estamos usando 60.000 ms = 60 s = 1 min #define SYNC_INTERVAL 1000 // mills between calls to flush() - to write data to the card uint32_t syncTime = 0; // time of last sync() #define ECHO_TO_SERIAL 1 // echo data para a porta serial. #define WAIT_TO_START 0 // espera pela entrada serial em setup() #define aref_voltage 5.0 // we tie 5.0V to ARef and measure it with a multimeter! RTC_DS1307 RTC; // define o Real Time Clock object // para o data logging shield, usamos o pino digita 10 para o SD cs line const int chipSelect = 10; // the logging file File logfile; void error(char *str) { Serial.print("erro: "); Serial.println(str); while(1); } void setup() { Serial.begin(9600); Wire.begin(); bmp085Calibration(); Serial.println("Temperatura(C), Pressao(Pa)"); Serial.println(); #if WAIT_TO_START Serial.println("Tecle qualquer caracter para iniciar"); while (!Serial.available()); #endif //WAIT_TO_START // inicialize o cartão SD. Serial.print("Inicializando o cartão SD..."); // make sure that the default chip select pin is set to // output, even if you don't use it: pinMode(10, OUTPUT); // veja se o cartão está presente e pode ser inicializado: if (!SD.begin(chipSelect)) { error("Falha no cartão, ou cartão ausente"); } Serial.println("cartão inicializado."); // cria um novo arquivo char filename[] = "baro00.CSV"; for (uint8_t i = 0; i < 100; i++) { filename[6] = i/10 + '0'; filename[7] = i%10 + '0'; if (! SD.exists(filename)) { // only open a new file if it doesn't exist logfile = SD.open(filename, FILE_WRITE); break; // interrompe o loop! } } if (! logfile) { error("não foi possível criar o arquivo"); } Serial.print("Logging to: "); Serial.println(filename); // conecte-se ao RTC Wire.begin(); if (!RTC.begin()) { logfile.println("falha no RTC"); #if ECHO_TO_SERIAL Serial.println("falha no RTC"); #endif //ECHO_TO_SERIAL } } void loop(void) { DateTime now; // Espere pelo tempo estipulado entre duas leituras. delay((LOG_INTERVAL -1) - (millis() % LOG_INTERVAL)); // log milisegundos desde o início. uint32_t m = millis(); //logfile.print(m); // milisegundos passados desde o início. //logfile.print(", "); #if ECHO_TO_SERIAL // Serial.print(m); // milisegundos passados desde o início. // Serial.print(", "); #endif // fetch the time now = RTC.now(); // log time logfile.print('"'); logfile.print(now.year(), DEC); logfile.print("/"); logfile.print(now.month(), DEC); logfile.print("/"); logfile.print(now.day(), DEC); logfile.print(" "); logfile.print(now.hour(), DEC); logfile.print(":"); logfile.print(now.minute(), DEC); logfile.print(":"); logfile.print(now.second(), DEC); logfile.print('"'); #if ECHO_TO_SERIAL Serial.print('"'); Serial.print(now.year(), DEC); Serial.print("/"); Serial.print(now.month(), DEC); Serial.print("/"); Serial.print(now.day(), DEC); Serial.print(" "); Serial.print(now.hour(), DEC); Serial.print(":"); Serial.print(now.minute(), DEC); Serial.print(":"); Serial.print(now.second(), DEC); Serial.print('"'); #endif //ECHO_TO_SERIAL temperatura = bmp085GetTemperature(bmp085ReadUT()); pressao = bmp085GetPressure(bmp085ReadUP()); temp = float(temperatura)/10.00; logfile.print(", "); logfile.print(temp, 2); logfile.print(", "); logfile.println(pressao, DEC); #if ECHO_TO_SERIAL Serial.print(", "); Serial.print(temp, 2); Serial.print(", "); Serial.println(pressao, DEC); #endif //ECHO_TO_SERIAL // Now we write data to disk! Don't sync too often - requires 2048 bytes of I/O to SD card // which uses a bunch of power and takes time if ((millis() - syncTime) < SYNC_INTERVAL) return; syncTime = millis(); logfile.flush(); } // Armazena todos os dados de calibração do BMP085 em variaveis globais. // Esses valores de calibração são necessários pra calcular temperatura (tem) e pressão. // Essa função deve ser chamada no início do programa. 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); } // Dado ut, calcula a temperatura. // O valor retornado estará em unidade de 0.1 graus C 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); } // Dado up, calcula a pressão. // valores de calibração devem ser conhecidos. // b5 é também necessária de forma que a função bmp085GetTemperature(...) dev ser calculada primeiro. // O valor retornado é a pressão em unidades Pa. long bmp085GetPressure(unsigned long up) { long x1, x2, x3, b3, b6, p; unsigned long b4, b7; b6 = b5 - 4000; // Calcula B3 x1 = (b2 * (b6 * b6)>>12)>>11; x2 = (ac2 * b6)>>11; x3 = x1 + x2; b3 = (((((long)ac1)*4 + x3)<>2; // Calcula 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; } // Lê 1 byte do BMP085 em '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(); } // Lê 2 bytes do BMP085 // First byte will be from 'address' // Second byte will be from '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; } // Lê o valor da temperatura não compensada. unsigned int bmp085ReadUT() { unsigned int ut; // Escreve 0x2E no Registro 0xF4; // Solicita uma leitura de temperatura. Wire.beginTransmission(BMP085_ADDRESS); Wire.write(0xF4); Wire.write(0x2E); Wire.endTransmission(); // Espere no mínimo 4.5ms. delay(5); // Lê dois bytes dos registros 0xF6 e 0xF7. ut = bmp085ReadInt(0xF6); return ut; } // Lê o valor da pressão não compensada. unsigned long bmp085ReadUP() { unsigned char msb, lsb, xlsb; unsigned long up = 0; // Escreve 0x34+(OSS<<6) no registro 0xF4; // Requisita uma leitura de pressão com oversampling setting Wire.beginTransmission(BMP085_ADDRESS); Wire.write(0xF4); Wire.write(0x34 + (OSS<<6)); Wire.endTransmission(); // Wait for conversion, delay time dependent on OSS delay(2 + (3<> (8-OSS); return up; }