Sensor BMP180 medida 24h y prediccion tiempo

Hola compañeros. Estoy tratando de crear un barometro mediante un sensor BMP180 y un arduino MEGA 2560. Se de la existencia de la libreria especifica para este modelo, pero tambien es posible realizarlo solo con la libreria "whire.h". He encontrado un codigo en internet, pero leyendo el datasheet del dispositivo hay cosas que no comprendo, y los resultados de presion on de una diferencia de 200mb aprox.

//Arduino 1.0+ Only
//Arduino 1.0+ Only

/*Based largely on code by  Jim Lindblom

 Get pressure, altitude, and temperature from the BMP085.
 Serial.print it out at 9600 baud to serial monitor.
 */

#include <Wire.h>

#define BMP085_ADDRESS 0x77  // I2C address of BMP085
//#define BMP085_ADDRESS 0x55  // I2C address of BMP180
const unsigned char OSS = 0;  // Oversampling Setting

// Calibration values
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 is calculated in bmp085GetTemperature(...), this variable is also used in bmp085GetPressure(...)
// so ...Temperature(...) must be called before ...Pressure(...).
long b5; 

void bmp085Calibration()
{
  ac1 = bmp085ReadInt(0xAA);
  ac2 = bmp085ReadInt(0xAB);
  ac3 = bmp085ReadInt(0xAE);
  ac4 = bmp085ReadInt(0xB0);
  ac5 = bmp085ReadInt(0xB2);
  ac6 = bmp085ReadInt(0xB4);
  b1 = bmp085ReadInt(0xB6);
  b2 = bmp085ReadInt(0xB8);
  mb = bmp085ReadInt(0xBA);
  mc = bmp085ReadInt(0xBB);
  md = bmp085ReadInt(0xBE);
}

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

  Serial.println ("Practica 32: Barometro y Termometro");
  
  Serial.print ("Inicio de Calibracion : ");
  Serial.println (millis());
  
  bmp085Calibration();
  
  Serial.print ("Fin de Calibracion : ");
  Serial.println (millis());
}

void loop()
{
  float hpa;
  float mmhg;
  float pascal = bmp085GetPressure(bmp085ReadUP()); // devuelve pascales
  float atm = pascal / 1013; // "standard atmosphere"
  float altitude = calcAltitude(pascal); //Uncompensated caculation - in Meters 

  hpa=pascal/100;
  mmhg=hpa*0.76;
  Serial.print ("Presion: ");
  Serial.print (hpa);
  Serial.println ("Hpa");

  Serial.print ("Presion: ");
  Serial.print (mmhg);
  Serial.println ("mmhg");

  Serial.print ("Presion: ");
  Serial.print (hpa);
  Serial.println ("mb");

  Serial.print ("Presion: ");
  Serial.print (atm);
  Serial.println ("atm");
  
  /*
  Serial.print("Pressure: ");
  Serial.print(pressure, 0); //whole number only.
  Serial.println(" Pa");

  Serial.print("Standard Atmosphere: ");
  Serial.println(atm, 4); //display 4 decimal places

  Serial.print("Altitude: ");
  Serial.print(altitude, 2); //display 2 decimal places
  Serial.println(" M");
  */
  Serial.println();//line break

  delay(1000); //wait a second and get values again.
}

// Stores all of the bmp085's calibration values into global variables
// Calibration values are required to calculate temp and pressure
// This function should be called at the beginning of the program

// Calculate temperature in deg C
float bmp085GetTemperature(unsigned int ut){
  long x1, x2;

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

  float temp = ((b5 + 8)>>4);
  temp = temp /10;

  return temp;
}

// Calculate pressure given up
// calibration values must be known
// b5 is also required so bmp085GetTemperature(...) must be called first.
// Value returned will be pressure in units of Pa.
long bmp085GetPressure(unsigned long up){
  long x1, x2, x3, b3, b6, p;
  unsigned long b4, b7;

  b6 = b5 - 4000;
  // Calculate B3
  x1 = (b2 * (b6 * b6)>>12)>>11;
  x2 = (ac2 * b6)>>11;
  x3 = x1 + x2;
  b3 = (((((long)ac1)*4 + x3)<<OSS) + 2)>>2;

  // Calculate 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;

  long temp = p;
  return temp;
}

// Read 1 byte from the BMP085 at '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();
}

// Read 2 bytes from the 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;
}

// Read the uncompensated temperature value
unsigned int bmp085ReadUT(){
  unsigned int ut;

  // Write 0x2E into Register 0xF4
  // This requests a temperature reading
  Wire.beginTransmission(BMP085_ADDRESS);
  Wire.write(0xF4);
  Wire.write(0x2E);
  Wire.endTransmission();

  // Wait at least 4.5ms
  delay(5);

  // Read two bytes from registers 0xF6 and 0xF7
  ut = bmp085ReadInt(0xF6);
  return ut;
}

// Read the uncompensated pressure value
unsigned long bmp085ReadUP(){

  unsigned char msb, lsb, xlsb;
  unsigned long up = 0;

  // Write 0x34+(OSS<<6) into register 0xF4
  // Request a pressure reading w/ 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<<OSS));

  // Read register 0xF6 (MSB), 0xF7 (LSB), and 0xF8 (XLSB)
  msb = bmp085Read(0xF6);
  lsb = bmp085Read(0xF7);
  xlsb = bmp085Read(0xF8);

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

  return up;
}

void writeRegister(int deviceAddress, byte address, byte val) {
  Wire.beginTransmission(deviceAddress); // start transmission to device 
  Wire.write(address);       // send register address
  Wire.write(val);         // send value to write
  Wire.endTransmission();     // end transmission
}

int readRegister(int deviceAddress, byte address){

  int v;
  Wire.beginTransmission(deviceAddress);
  Wire.write(address); // register to read
  Wire.endTransmission();

  Wire.requestFrom(deviceAddress, 1); // read a byte

  while(!Wire.available()) {
    // waiting
  }

  v = Wire.read();
  return v;
}

float calcAltitude(float pressure){

  float A = pressure/101325;
  float B = 1/5.25588;
  float C = pow(A,B);
  C = 1 - C;
  C = C /0.0000225577;

  return C;
}

Arriba hay 2 "#define" , supuestamente uno para el BMP085(0x77) y otro para el BMP180(0x55). En BMP180, en el datasheet aparece tambien que usa el 0x55, como bien indica el programa. Sin embargo, cambio esa parte del codigo y a la hora de ejecutarlo no hace absolutamente nada. Sin embargo si lo dejo con la supuesta configuracion del BMP085 si funciona, y como anteriormente he dicho, da valores con una diferencia de +200mb aproximandamente, algo mas. Las direcciones de memoria para la calibracion son correctas, tambien las he mirado en el pdf, no se que puede ser, o si es que solo funciona con 0x77. ¿Se supone que deberia usar el suyo y las medidas serian mas exactas no?

https://cdn-shop.adafruit.com/datasheets/BST-BMP180-DS000-09.pdf --> Datasheet del sensor

Haber si resuelvo esta duda, un saludo y gracias por vuestro tiempo

La dirección I2C la descubres con scanner I2C. Búscalo que esta en este blog

surbyte:
La dirección I2C la descubres con scanner I2C. Búscalo que esta en este blog

No sabia de su existencia, en efecto, me ha dado la 0x77. Por lo que ya comprendo el por que no funcionaba si no se redireccionaba a dicho dispositivo.Ahora la duda que tengo es el calculo de presion, se supone que es preciso este dispositivo, pero la diferencia de presion en mb respecto al sitio en el que me encuentro es un poco grande como mencione en el primer post. He revisado los calculos y esta todo correcto, puede ser cosa de la calibracion??

Mira la hoja de datos, ve si hay alguna calibración posible.

Por cierto olvidé pedirte que uses tags para los enlaces que has colocado en un primer posteo.
Mira en las normas como se hace.

The pressure and temperature data has to be compensated by the calibration data of the
E2PROM of the BMP180.

Eso dice la hoja de datos.

Pagina 13 habla al respecto pero yo no tocaría esos valores.

Pagina 15 tiene un diagrama de flujo de como medir los datos no compensados y como corregirlos.
Me parece que algo te falta ahi, pero veo que lo implementas aunque tal vez tengas un desbordamiento de algun tipo de variable mal definida.
Revisa los calculos parciales. Es mi mejor idea por ahora.

Otra idea. Busca la librería y toma el ejemplo que te dará valores de temperatura y presion compensados y compara con los tuyos.

He conseguido que me de valores mas normalizados (Claramente gracias a la libreria, pues no me quedaba otra), ahora lo que estoy intentando es que me de un valor cada minuto(24, simulando las horas) , y que luego compare el ultimo enviado con el primero enviado(valor 1 comparado con el 24), de esta manera se saber el cambio que ha habido, y asi decir si el tiempo ha sido bueno se ha mantenido y eso. Pero me he perdido en mitad y ya no se ni lo que hago...

/*Utilizando un sensor BMP180, diseñar un barómetro digital que exprese la presión atmosférica en hectopascales, mmHg, milibares y atmosferas.
 *Datos: (1mb=0.76mmHg, 1mb=1hPa, 1atm=1013mb).
 */

/*- (GND) to GND
 *+ (VDD) to 3.3V
 */

/*Any Arduino pins labeled:  SDA  SCL
 *Uno, Redboard, Pro:        A4   A5
 *Mega2560, Due:             20   21
 */

// Se importan las librerías
#include <SFE_BMP180.h>
#include <Wire.h>

#define TIEMPOESPERA 5000

//Se declara una instancia de la librería
SFE_BMP180 BMP180;

//Se declaran las variables. Es necesario tomar en cuenta una presión inicial
//esta será la presión que se tome en cuenta en el cálculo de la diferencia de altura
double PresionBase;

float diferencia;
//Leeremos presión y temperatura. Calcularemos la diferencia de altura
double Presion = 0;
String Altura;
float altura;
float presion_altura;
double Temperatura = 0;
float tablahora [24];
int semaforo = 0;
int tNuevo = 0, tAntiguo = 0;
float ultimaMedida;

char status;

void setup() 
{
  Serial.begin(9600);

  //Se inicia el sensor y se hace una lectura inicial
  SensorStart();
  Serial.print("Introduzca la altura sobre el nivel del mar de su localizacion: ");

  for (int i = 0; i <24; i++) 
  {
    tablahora [i] = -1;
  }
  ultimaMedida = millis();
}

void loop() 
{
  tNuevo = millis();
  while (Serial.available() >0 && semaforo == 0)
  {
    Altura= Serial.readString();
    altura=Altura.toFloat();
    
    Serial.print (altura);
    Serial.println (" Metros ");
            
    presion_altura = (1013.3/(exp(altura/(8430.153-0.095*altura))));
    
    Serial.print ("Presion actual: ");
    Serial.println (presion_altura);

    float fdifpresion = Presion - presion_altura;
    if (fdifpresion > 20) Serial.println ("Soleado muy estable");
    
    else if (fdifpresion > 10) Serial.println ("Soleado estable");
    
    else if (fdifpresion > 0) Serial.println ("Soleado");
    
    else if (fdifpresion < -5) Serial.println ("Escasa nubosidad");
    
    else if (fdifpresion > -10) Serial.println ("Nubosidad parcial");
    
    else if (fdifpresion > -15) Serial.println ("Nublado");
    
    else if (fdifpresion < -20) Serial.println ("Llovizna");
    
    else if (fdifpresion > -25) Serial.println ("Lluvia");

    else if (fdifpresion > -30) Serial.println ("Lluvia Intensa");
    
    else Serial.println ("Lluvia muy Intensa");
    
    Serial.println();//line break

    semaforo = 1;
  }

  if (semaforo == 1)
  {
    while (millis() - ultimaMedida > TIEMPOESPERA)
      {
        int i;
        for ( i = 24; i > 0; i--)
        {
          tablahora [i] = tablahora [i-1];
          tablahora [0] = Presion;
          ultimaMedida = millis();
          Serial.print ("Medida Realizada: ");
          Serial.println(i);    
          Serial.println (tablahora [0]);
          if (i == 1)
          {
            CalcularPrediccion();
            Serial.println(diferencia);
          }
        }
      }
  }
 
  //Se hace lectura del sensor
  ReadSensor();
}

void SensorStart() 
{
  //Secuencia de inicio del sensor

  if (BMP180.begin())
    Serial.println("BMP180 Inicio Completado");
  else
  {
    Serial.println("BMP180 Fallo en Inicio");
    while (1);
  }

  //Se inicia la lectura de temperatura
  status = BMP180.startTemperature();
  if (status != 0)  
  {
    delay(status);
    //Se lee una temperatura inicial
    status = BMP180.getTemperature(Temperatura);
    if (status != 0)    
    {
      //Se inicia la lectura de presiones
      status = BMP180.startPressure(3);
      if (status != 0)      
      {
        delay(status);
        //Se lee la presión inicial incidente sobre el sensor en la primera ejecución
        status = BMP180.getPressure(PresionBase, Temperatura);
      }
    }
  }
}


void ReadSensor() {
  //En este método se hacen las lecturas de presión y temperatura y se calcula la altura

  //Se inicia la lectura de temperatura
  status = BMP180.startTemperature();
  if (status != 0)
  {
    delay(status);
    //Se realiza la lectura de temperatura
    status = BMP180.getTemperature(Temperatura);
    if (status != 0)
    {
      //Se inicia la lectura de presión
      status = BMP180.startPressure(3);
      if (status != 0)
      {
        delay(status);
        //Se lleva a cabo la lectura de presión,
        //considerando la temperatura que afecta el desempeño del sensor

        status = BMP180.getPressure(Presion, Temperatura);
       }
      else Serial.println("Error en el inicio de lectura de presion");
    }
    else Serial.println("Error en la lectura de temperatura");
  }
  else Serial.println("Error en el inicio de lectura de temperatura");
}

void CalcularPrediccion ()
{
  float total = 0;
  for (int i = 0; i < 24; i++) total = total + tablahora[i];
  total = total / 24;
  diferencia = total -Presion;
}

No lo miré líneas por línea pero tu código parecía estar bien.
Estoy casi seguro que cometiste un error de tipo de variables y tienes por ahi un overflow (desbordamiento) o equivocaste un signo o una variable.

Solucionado amigo, dejo el codigo :wink:

/*- (GND) to GND
 *+ (VDD) to 3.3V
 */

/*Any Arduino pins labeled:  SDA  SCL
 *Uno, Redboard, Pro:        A4   A5
 *Mega2560, Due:             20   21
 */

// Se importan las librerías
#include <SFE_BMP180.h>
#include <Wire.h>

#define TIEMPOESPERA 3600000

//Se declara una instancia de la librería
SFE_BMP180 BMP180;

//Se declaran las variables. Es necesario tomar en cuenta una presión inicial
//esta será la presión que se tome en cuenta en el cálculo de la diferencia de altura
double PresionBase;

float diferencia;
//Leeremos presión y temperatura. Calcularemos la diferencia de altura
double Presion = 0;
String Altura;
float altura;
float presion_altura;
double Temperatura = 0;
float tablahora [24];
int semaforo = 0;
int tNuevo = 0, tAntiguo = 0;
float ultimaMedida;

char status;

void setup() 
{
  Serial.begin(9600);

  //Se inicia el sensor y se hace una lectura inicial
  SensorStart();
  Serial.print("Introduzca la altura sobre el nivel del mar de su localizacion: ");

  for (int i = 0; i <24; i++) 
  {
    tablahora [i] = 0;
  }
  ultimaMedida = millis();
}

void loop() 
{
  tNuevo = millis();
  while (Serial.available() >0 && semaforo == 0)
  {
    Altura= Serial.readString();
    altura=Altura.toFloat();
    
    Serial.print (altura);
    Serial.println (" Metros ");
            
    presion_altura = (1013.3/(exp(altura/(8430.153-0.095*altura))));
    
    Serial.print ("Presion actual: ");
    Serial.println (presion_altura);

    semaforo = 1;
  }

  if (semaforo == 1)
  {
    while (millis() - ultimaMedida > TIEMPOESPERA)
      {
        int i;
        //Se hace lectura del sensor
        ReadSensor();
        
        BMP180.getPressure(Presion, Temperatura);
        for ( i = 24; i > 0; i--)tablahora [i] = tablahora [i-1];
        tablahora [0] = Presion;
        for(int i = 0;i<24;i++)
        {
          Serial.print ("Medida Realizada: ");
          Serial.print(i);    
          Serial.print ("   -->   ");
          Serial.println (tablahora [i]);
          if (i == 23)
          {
            diferencia = tablahora[0]-tablahora[23];
            Serial.println(diferencia);
            if(diferencia < tablahora[0])
            {
              CalcularPrediccion ();
            }
          }
        }
      ultimaMedida = millis();
    }      
  }  
}

void SensorStart() 
{
  //Secuencia de inicio del sensor

  if (BMP180.begin())
    Serial.println("BMP180 Inicio Completado");
  else
  {
    Serial.println("BMP180 Fallo en Inicio");
    while (1);
  }

  //Se inicia la lectura de temperatura
  status = BMP180.startTemperature();
  if (status != 0)  
  {
    delay(status);
    //Se lee una temperatura inicial
    status = BMP180.getTemperature(Temperatura);
    if (status != 0)    
    {
      //Se inicia la lectura de presiones
      status = BMP180.startPressure(3);
      if (status != 0)      
      {
        delay(status);
        //Se lee la presión inicial incidente sobre el sensor en la primera ejecución
        status = BMP180.getPressure(PresionBase, Temperatura);
      }
    }
  }
}


void ReadSensor() {
  //En este método se hacen las lecturas de presión y temperatura y se calcula la altura

  //Se inicia la lectura de temperatura
  status = BMP180.startTemperature();
  if (status != 0)
  {
    delay(status);
    //Se realiza la lectura de temperatura
    status = BMP180.getTemperature(Temperatura);
    if (status != 0)
    {
      //Se inicia la lectura de presión
      status = BMP180.startPressure(3);
      if (status != 0)
      {
        delay(status);
        //Se lleva a cabo la lectura de presión,
        //considerando la temperatura que afecta el desempeño del sensor

        status = BMP180.getPressure(Presion, Temperatura);
       }
      else Serial.println("Error en el inicio de lectura de presion");
    }
    else Serial.println("Error en la lectura de temperatura");
  }
  else Serial.println("Error en el inicio de lectura de temperatura");
}

void CalcularPrediccion ()
{
  if(diferencia > 10) Serial.println("El tiempo mejora mucho");

  if (diferencia > 5) Serial.println("El tiempo mejora un poco");
  
  if (diferencia >= -1 && diferencia <= 1) Serial.println("El tiempo se mantiene");

  if (diferencia < -5) Serial.println("El tiempo empeora un poco");

  if (diferencia < -10) Serial.println("El tiempo empeora mucho");
}

Como encontraste las lecturas comparadas con tu medidor de presión?