Sonsivri
 
*
Welcome, Guest. Please login or register.
Did you miss your activation email?
November 25, 2024, 07:27:06 07:27


Login with username, password and session length


Pages: [1]
Print
Author Topic: BMP085 - Library in XC8 compiler  (Read 4678 times)
0 Members and 1 Guest are viewing this topic.
Finzi
Newbie
*
Offline Offline

Posts: 18

Thank You
-Given: 22
-Receive: 23


« on: March 25, 2014, 11:24:02 23:24 »

Hi, friends. Today (tonight) I am going to share my library that communicates with the Bosh BMP085 Temperature and Pressure Digital Sensor. This Library presupposes the use of I2C.h library from the XC8 compiler. The same library can be used with the XC16 compiler. There are a few comments in portuguese (I am too lazy to erase them  Grin ), but the functions are described in english. Functions for communication, temperature calculation and pressure are all working.
I hope you enjoy.

ps: My next post will present you a library to use de ADLX345 Accelerometer. It is almost finished.

Finzi

Code:
#include <plib/i2c.h>
#include <math.h>
//Barômetro e sensor de temperatura Digital
#define BMP085_ADDRESS_READ                  0xEF
#define BMP085_ADDRESS_WRITE                 0xEE
#define BMP085_CONTROL_RESGISTER             0xF4
#define BMP085_CONTROL_RESGISTER_DATA_TEMP   0x2E
#define BMP085_CONTROL_RESGISTER_DATA_PRESS  0x34
#define BMP085_RESULT_RESGISTER_MSB          0xF6

#define OVERSAMP_UL    (unsigned char) 0   //Ultra low Power, tempo aquisiçào de 4.5ms, ruído de 0.5m
#define OVERSAMP_STD   (unsigned char) 1   //Padrão, tempo aquisiçào de 7.5ms, ruído de 0.4m
#define OVERSAMP_HRES  (unsigned char) 2   //Padrão, tempo aquisiçào de 13.5ms, ruído de 0.3m
#define OVERSAMP_UHRES (unsigned char) 3   //Padrão, tempo aquisiçào de 25,5ms, ruído de 0.25m

const char OSS = OVERSAMP_UHRES; //Define o modo de oversampling

#define _XTAL_FREQ 48000000 

#define USE_OR_MASKS

//Variáveis globais de calibração usadas nos cálculos
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;
long b5;

void writeI2CByte(unsigned char addrDev)
{

    char status;
    //Escreve o endereço do Dispositivo
    status = WriteI2C( addrDev);
    //Verifica se houve algum problema
    if(status == (char) -1) {
//            data = SSPBUF;      //limpa do buffer
            SSPCON1bits.WCOL=0; //limpa o bit de colisão
    }
}

long readNBytes_BMP085(unsigned char addr, char numBytes)
{
    char res[3], div;
    long ret = 0;

    res[2] = 0; res[1] = 0; res[0] = 0;
    //1. Iniciar o barramento i2C   
    StartI2C();
    //1.1 Aguarda a condição de START estar concluída
    while(SSPCON2bits.SEN);
    //2. Lê qualquer informação inicialmente existente no buffer para limpar o BUFFER FULL status
//    data = SSPBUF;
    //3. Escreve o endereço do dispositivo e indica que será feita uma operação de escrita
    writeI2CByte(BMP085_ADDRESS_WRITE); IdleI2C();
    //4. Escreve o endereço do registro  que será lido
    writeI2CByte(addr);                 IdleI2C();
    //5. Envia uma condição de RESTART para o BMP
    RestartI2C();
    //5.1 Aguarda a condição de RESTART estar concluída
    while(SSPCON2bits.SEN);
    //6. Escreve o endereço do dispositivo e indica que será feita uma operação de leitura
    writeI2CByte(BMP085_ADDRESS_READ);  IdleI2C();
    //7. Executa a leitura de 2 bytes referentes ao dado da EEPROM no endereço fornecido
    while(getsI2C(res,numBytes)); //garante que a leitura será feita
    IdleI2C();
    //8. Envia o fim de transação por meio de um NACK
    NotAckI2C();
    //8.1 Aguarda pelo conclusão do comando
    while( SSPCON2bits.ACKEN!=0);
    //9. Conclui a comunicação i2C
    StopI2C();
    //9.1 Aguarda a condição de STOP estar concluída
    while(SSPCON2bits.SEN);
    //10. Monta o dado inteiro. O MSB é retornado primeiro
    if(numBytes == 2)   div = 8; //Leitura de temperatura em apenas 2 bytes
    else                div = (8 - OSS); //Leitura de pressão

    ret = ( ( ((long) res[0]) << 16) + (((long)res[1]) << 8) + ((long)res[2]) ) >> div ;
    return(ret);
}

void getCalibrationData_BMP085()
{
  ac1 = (int)           readNBytes_BMP085(0xAA,2);
  ac2 = (int)           readNBytes_BMP085(0xAC,2);
  ac3 = (int)           readNBytes_BMP085(0xAE,2);
  ac4 = (unsigned int)  readNBytes_BMP085(0xB0,2);
  ac5 = (unsigned int)  readNBytes_BMP085(0xB2,2);
  ac6 = (unsigned int)  readNBytes_BMP085(0xB4,2);
  b1  = (int)           readNBytes_BMP085(0xB6,2);
  b2  = (int)           readNBytes_BMP085(0xB8,2);
//  mb  = (int)           readNBytes_BMP085(0xBA,2);
  mc  = (int)           readNBytes_BMP085(0xBC,2);
  md  = (int)           readNBytes_BMP085(0xBE,2);
}

void sendStartConvCMD_BMP085(unsigned char cmd)
{
    //1. Inicia comunicação i2C
    StartI2C();
    //1.1 Espera até que a condição de START esteja concluída
    while (SSPCON2bits.SEN);
    //2. Escreve o endereço do dispositivo e indica que será feita uma operação de escrita
    writeI2CByte(BMP085_ADDRESS_WRITE);     IdleI2C();
    //3. Escreve o endereço do registro que receberá o comando de conversão da temperatura
    writeI2CByte(BMP085_CONTROL_RESGISTER); IdleI2C();
    //4. Escreve o conteúdo do registro indicando o tipo de conversão a ser iniciada
    writeI2CByte(cmd);                      IdleI2C();
    //5. Concluir a comunicação
    StopI2C();
    //5.1 Aguarda a condição de STOP estar concluída
    while(SSPCON2bits.SEN);
}

long readUT_BMP085()
{
    long ut;

    sendStartConvCMD_BMP085(BMP085_CONTROL_RESGISTER_DATA_TEMP);
    //2. Aguarda pelo tempo de conversão da temperatura
    __delay_ms(5); //mínimo de 4.5ms
    //3. Efetuar a leitura da temperatura no registrador MSB de resultados
    ut = (long ) readNBytes_BMP085(BMP085_RESULT_RESGISTER_MSB, 2);

    return(ut);
}

long calcTemperature_BMP085(long ut)
{
  long x1, x2;

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

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


long readUP_BMP085()
{
    long up;
    //1. Envia o comando de conversão de pressão com base no que foi selecionado para o modo OSS
    sendStartConvCMD_BMP085(BMP085_CONTROL_RESGISTER_DATA_PRESS + ((unsigned char)(OSS << 6)));
    //2. Aguarda pelo tempo de conversão da pressão
    switch(OSS)
  {
      case OVERSAMP_UL:    __delay_ms(6); break;
      case OVERSAMP_STD:   __delay_ms(8); break;
      case OVERSAMP_HRES:  __delay_ms(15); break;
      case OVERSAMP_UHRES: __delay_ms(14); __delay_ms(14); break;
  }
    //3. Efetuar a leitura da pressão no registrador MSB de resultados
    if(OSS == 0)
        up =  readNBytes_BMP085(BMP085_RESULT_RESGISTER_MSB, 2);
    else
        up =  readNBytes_BMP085(BMP085_RESULT_RESGISTER_MSB, 3);
    return(up);
}

long calcPressure_BMP085(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;
 
  return p;
}
Logged
Pages: [1]
Print
Jump to:  


DISCLAIMER
WE DONT HOST ANY ILLEGAL FILES ON THE SERVER
USE CONTACT US TO REPORT ILLEGAL FILES
ADMINISTRATORS CANNOT BE HELD RESPONSIBLE FOR USERS POSTS AND LINKS

... Copyright © 2003-2999 Sonsivri.to ...
Powered by SMF 1.1.18 | SMF © 2006-2009, Simple Machines LLC | HarzeM Dilber MC