Subversion Repositories Projects

Rev

Rev 2198 | Go to most recent revision | Blame | Last modification | View Log | RSS feed

/*
bmp085 lib 0x01

copyright (c) Davide Gironi, 2012

Released under GPLv3.
Please refer to LICENSE file for licensing information.
*/


//############################################################################
//# HISTORY  bmp085.c
//#
//# 19.09.2015 cebra
//# - add: Library für BMP085/BMP180 Luftdrucksensor, GY-87 Sensorboard
//#
//############################################################################









#ifdef USE_KOMPASS

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
#include <avr/io.h>
#include <util/delay.h>

#include "bmp085.h"

//path to i2c fleury lib
#include BMP085_I2CFLEURYPATH

/*
 * i2c write
 */

void bmp085_writemem(uint8_t reg, uint8_t value) {
        i2c_start_wait(BMP085_ADDR | I2C_WRITE);
        i2c_write(reg);
        i2c_write(value);
        i2c_stop();
}

/*
 * i2c read
 */

void bmp085_readmem(uint8_t reg, uint8_t buff[], uint8_t bytes) {
        uint8_t i =0;
        i2c_start_wait(BMP085_ADDR | I2C_WRITE);
        i2c_write(reg);
        i2c_rep_start(BMP085_ADDR | I2C_READ);
        for(i=0; i<bytes; i++) {
                if(i==bytes-1)
                        buff[i] = i2c_readNak();
                else
                        buff[i] = i2c_readAck();
        }
        i2c_stop();
}


#if BMP085_FILTERPRESSURE == 1
#define BMP085_AVARAGECOEF 21
static long k[BMP085_AVARAGECOEF];
long bmp085_avaragefilter(long input) {
        uint8_t i=0;
        long sum=0;
        for (i=0; i<BMP085_AVARAGECOEF; i++) {
                k[i] = k[i+1];
        }
        k[BMP085_AVARAGECOEF-1] = input;
        for (i=0; i<BMP085_AVARAGECOEF; i++) {
                sum += k[i];
        }
        return (sum /BMP085_AVARAGECOEF) ;
}
#endif

/*
 * read calibration registers
 */

void bmp085_getcalibration() {
        uint8_t buff[2];
        memset(buff, 0, sizeof(buff));

        bmp085_readmem(BMP085_REGAC1, buff, 2);
        bmp085_regac1 = ((int)buff[0] <<8 | ((int)buff[1]));
        bmp085_readmem(BMP085_REGAC2, buff, 2);
        bmp085_regac2 = ((int)buff[0] <<8 | ((int)buff[1]));
        bmp085_readmem(BMP085_REGAC3, buff, 2);
        bmp085_regac3 = ((int)buff[0] <<8 | ((int)buff[1]));
        bmp085_readmem(BMP085_REGAC4, buff, 2);
        bmp085_regac4 = ((unsigned int)buff[0] <<8 | ((unsigned int)buff[1]));
        bmp085_readmem(BMP085_REGAC5, buff, 2);
        bmp085_regac5 = ((unsigned int)buff[0] <<8 | ((unsigned int)buff[1]));
        bmp085_readmem(BMP085_REGAC6, buff, 2);
        bmp085_regac6 = ((unsigned int)buff[0] <<8 | ((unsigned int)buff[1]));
        bmp085_readmem(BMP085_REGB1, buff, 2);
        bmp085_regb1 = ((int)buff[0] <<8 | ((int)buff[1]));
        bmp085_readmem(BMP085_REGB2, buff, 2);
        bmp085_regb2 = ((int)buff[0] <<8 | ((int)buff[1]));
        bmp085_readmem(BMP085_REGMB, buff, 2);
        bmp085_regmb = ((int)buff[0] <<8 | ((int)buff[1]));
        bmp085_readmem(BMP085_REGMC, buff, 2);
        bmp085_regmc = ((int)buff[0] <<8 | ((int)buff[1]));
        bmp085_readmem(BMP085_REGMD, buff, 2);
        bmp085_regmd = ((int)buff[0] <<8 | ((int)buff[1]));
}

/*
 * get raw temperature as read by registers, and do some calculation to convert it
 */

void bmp085_getrawtemperature() {
        uint8_t buff[2];
        memset(buff, 0, sizeof(buff));
        long ut,x1,x2;

        //read raw temperature
        bmp085_writemem(BMP085_REGCONTROL, BMP085_REGREADTEMPERATURE);
        _delay_ms(5); // min. 4.5ms read Temp delay
        bmp085_readmem(BMP085_REGCONTROLOUTPUT, buff, 2);
        ut = ((long)buff[0] << 8 | ((long)buff[1])); //uncompensated temperature value

        //calculate raw temperature
        x1 = ((long)ut - bmp085_regac6) * bmp085_regac5 >> 15;
        x2 = ((long)bmp085_regmc << 11) / (x1 + bmp085_regmd);
        bmp085_rawtemperature = x1 + x2;
}

/*
 * get raw pressure as read by registers, and do some calculation to convert it
 */

void bmp085_getrawpressure() {
        uint8_t buff[3];
        memset(buff, 0, sizeof(buff));
        long up,x1,x2,x3,b3,b6,p;
        unsigned long b4,b7;

        #if BMP085_AUTOUPDATETEMP == 1
        bmp085_getrawtemperature();
        #endif

        //read raw pressure
        bmp085_writemem(BMP085_REGCONTROL, BMP085_REGREADPRESSURE+(BMP085_MODE << 6));
        _delay_ms(2 + (3<<BMP085_MODE));
        bmp085_readmem(BMP085_REGCONTROLOUTPUT, buff, 3);
        up = ((((long)buff[0] <<16) | ((long)buff[1] <<8) | ((long)buff[2])) >> (8-BMP085_MODE)); // uncompensated pressure value

        //calculate raw pressure
        b6 = bmp085_rawtemperature - 4000;
        x1 = (bmp085_regb2* (b6 * b6) >> 12) >> 11;
        x2 = (bmp085_regac2 * b6) >> 11;
        x3 = x1 + x2;
        b3 = (((((long)bmp085_regac1) * 4 + x3) << BMP085_MODE) + 2) >> 2;
        x1 = (bmp085_regac3 * b6) >> 13;
        x2 = (bmp085_regb1 * ((b6 * b6) >> 12)) >> 16;
        x3 = ((x1 + x2) + 2) >> 2;
        b4 = (bmp085_regac4 * (uint32_t)(x3 + 32768)) >> 15;
        b7 = ((uint32_t)up - b3) * (50000 >> BMP085_MODE);
        p = b7 < 0x80000000 ? (b7 << 1) / b4 : (b7 / b4) << 1;
        x1 = (p >> 8) * (p >> 8);
        x1 = (x1 * 3038) >> 16;
        x2 = (-7357 * p) >> 16;
        bmp085_rawpressure = p + ((x1 + x2 + 3791) >> 4);

        #if BMP085_FILTERPRESSURE == 1
        bmp085_rawpressure = bmp085_avaragefilter(bmp085_rawpressure);
        #endif
}

/*
 * get celsius temperature
 */

double bmp085_gettemperature() {
        bmp085_getrawtemperature();
        double temperature = ((bmp085_rawtemperature + 8)>>4);
        temperature = temperature /10;
        return temperature;
}

/*
 * get pressure
 */

int32_t bmp085_getpressure() {
        bmp085_getrawpressure();
        return bmp085_rawpressure + BMP085_UNITPAOFFSET;
}

/*
 * get altitude
 */

double bmp085_getaltitude() {
        bmp085_getrawpressure();
        return ((1 - pow(bmp085_rawpressure/(double)101325, 0.1903 )) / 0.0000225577) + BMP085_UNITMOFFSET;
}

/*
 * init bmp085
 */

void bmp085_init() {
        #if BMP085_I2CINIT == 1
        //init i2c
        i2c_init();
        _delay_us(10);
        #endif

        bmp085_getcalibration(); //get calibration data
        bmp085_getrawtemperature(); //update raw temperature, at least the first time

        #if BMP085_FILTERPRESSURE == 1
        //initialize the avarage filter
        uint8_t i=0;
        for (i=0; i<BMP085_AVARAGECOEF; i++) {
                bmp085_getrawpressure();
        }
        #endif
}
#endif