BMP180 ile basınç ölçme (PIC mikrodenetleyicisi)

faruk97

Üye
Katılım
1 Haz 2020
Mesajlar
38
Puanları
1
Yaş
27
Merhaba arkadaşlar şu an uğraşmış olduğum yeni bir proje var. PIC16F1509 mikrodenetleyicisi kullanarak BMP180'den basınç ve sıcaklık değerlerini okumaya çalışıyorum. Ama bazı yerlerde hatam var. Çok uğraşmama rağmen bulamadım. Ve yardımlarınızı bekliyorum.Kodları internetten bir forumdan buldum MikroC için yazılmış ben XC8 derleyicisine uyarlamaya çalıştım. Ama bir sonuç tam olarak alamadım.

Devrenin kodları:
main.c

Kod:
// PIC16F1509 Configuration Bit Settings

// 'C' source line config statements

// CONFIG1
#pragma config FOSC = HS        // Oscillator Selection Bits (HS Oscillator, High-speed crystal/resonator connected between OSC1 and OSC2 pins)
#pragma config WDTE = OFF       // Watchdog Timer Enable (WDT disabled)
#pragma config PWRTE = ON       // Power-up Timer Enable (PWRT enabled)
#pragma config MCLRE = ON       // MCLR Pin Function Select (MCLR/VPP pin function is MCLR)
#pragma config CP = OFF         // Flash Program Memory Code Protection (Program memory code protection is disabled)
#pragma config BOREN = OFF       // Brown-out Reset Enable (Brown-out Reset enabled)
#pragma config CLKOUTEN = OFF   // Clock Out Enable (CLKOUT function is disabled. I/O or oscillator function on the CLKOUT pin)
#pragma config IESO = OFF       // Internal/External Switchover Mode (Internal/External Switchover Mode is disabled)
#pragma config FCMEN = OFF      // Fail-Safe Clock Monitor Enable (Fail-Safe Clock Monitor is disabled)

// CONFIG2
#pragma config WRT = OFF        // Flash Memory Self-Write Protection (Write protection off)
#pragma config STVREN = OFF     // Stack Overflow/Underflow Reset Enable (Stack Overflow or Underflow will not cause a Reset)
#pragma config BORV = LO        // Brown-out Reset Voltage Selection (Brown-out Reset Voltage (Vbor), low trip point selected.)
#pragma config LPBOR = OFF      // Low-Power Brown Out Reset (Low-Power BOR is disabled)
#pragma config LVP = OFF        // Low-Voltage Programming Enable (High-voltage on MCLR/VPP must be used for programming)

// #pragma config statements should precede project file includes.
// Use project enums instead of #define for ON and OFF.

#include <xc.h>
#include "BMP180.h"
#include "I2C.h"
#include "lcd.h"
#include <stdio.h>


#define _XTAL_FREQ 8000000


void main(void) {
    CM1CON0bits.C1ON=0;
    CM2CON0bits.C2ON=0;
    ANSELB=0;
    ANSELC=0;
    TRISC=0;
  
    i2c_kur();
  
    lcd_baslat();
  
    lcd_mesajyaz(1,1,"bmp180");
    lcd_mesajyaz(2,1,"Genc Mucitler");
    __delay_ms(1000);
    lcd_sil();
  
    BMP_Init();
    while(1){
      
        BMP_Read( 0 );
        lcd_git(1,1);
            //sonuc=50;
      
            printf("%d",UT);
            lcd_git(2,8);
            printf("%d",TrueT);
            //lcd_mesajyaz(1,1,'res');
            lcd_mesajyaz(2,1,"sonuc");
    }
  
    //return;
}

"BMP180.c" dosyası;

Kod:
#include <xc.h>
#include "I2C.h"
// Note: #include "BMP180.h" in main module

#define CAL_DATA_ADDR         0xAA    // start address of calibration data
#define BMP_CONTROL           0xF4    // see Figure 6 in datasheet, ctrl_meas F4h (oss, sco, meas)
#define BMP_OUT_MSB           0xF6    // see Figure 6 in datasheet, out_msb
#define BMP_READTEMPCMD       0x2E
#define BMP_READPRESSURECMD   0x34


#define _XTAL_FREQ 8000000

// Calibration data in E2PROM (named as in datasheet but with c suffix on B1 & B2 or redifined)
int AC1, AC2, AC3 ;
unsigned int AC4, AC5, AC6 ;
int B1c, B2c, MB, MC, MD ;           // c suffix added to B1 & B2

// Global variables for display in main function
int TrueT ;          // temperature in 0.1 degrees (named T in datasheet) so 20deg = 200
long TrueP ;         // pressure in Pa (named P in datasheet) so 1013 hPa = 101300
// Global for debug purposes
int UT ;                    // uncompensated value of temperature
long UP ;                   // uncompensated value of pressure
char i2c_r;

// Internal functions
void delayOss (char oss)
{ // delay depending on oversampling oss 0 to 3, approximates to 2x^2 + x + 5
  char i, do1mS ;
  do1mS = 2*oss*oss + oss + 5 ; // (0, 1, 2, or 3 gives 5, 8, 15, or 26)
  for (i = 0 ; i < do1mS ; i++)
    __delay_ms(1) ;
}



int BMP_I2C_Rd16b (char ackm)
{ // return MSB<<8 + LSB, send ACKM if parameter ackm is 1, NACKM if ackm 0
  i2c_r=i2c_oku();
  return ( (i2c_r << 8) + i2c_r ) ;
}

void BMP_I2C_SetU( char reg )
{ // setup for read of UT or UP, do delay on return
  BMP_I2C_Start();
  BMP_I2C_Wr( I2C_ADDR_WR );
  BMP_I2C_Wr( BMP_CONTROL );          // 0xF4
  BMP_I2C_Wr( reg );                  // write 0x2E or 0x34 into reg 0xF4
  BMP_I2C_Stop();
}

void BMP_I2C_SetReg( char reg )
{ // setup for read of calibration data 0xAA, or UT/UP data 0xF6
  BMP_I2C_Start();                // start condition
  BMP_I2C_Wr( I2C_ADDR_WR );      // module address write command 0xEE
  BMP_I2C_Wr( reg );              // select read register (calibration data 0xAA, UT/UP data 0xF6)
  BMP_I2C_Start();                // restart condition
  BMP_I2C_Wr( I2C_ADDR_RD );      // module address read command 0xEF
}

// Global functions
void BMP_Read( char oss )
{// read uncompensated values UT & UP, convert to true, save in global variables: TrueT & TrueP
  long B3, B5, B6, X1, X2, X3, pp ;
  unsigned long B4, B7;

  // read uncompensated value UT
  BMP_I2C_SetU( BMP_READTEMPCMD ) ;                  // write 0x2E into reg 0xF4: setup for UT
  __delay_ms( 5 ) ;                                    // delay 4.5mS minimum
  BMP_I2C_SetReg ( BMP_OUT_MSB ) ;                   // select read register start 0xF6
  UT = BMP_I2C_Rd16b(0) ;                            // read 16 bits into UT, send NACKM
  BMP_I2C_Stop() ;                                   // stop

  // DEBUG Example from Bosch datasheet (TrueT should be 150, TrueP should be 69964).
  // UT = 27898 ;

  // read uncompensated value UP
  BMP_I2C_SetU( BMP_READPRESSURECMD | (oss << 6) ) ; // write 0x34 into reg 0xF4: setup for UP
  delayOss( oss ) ;                                  // delay depends on oss
  BMP_I2C_SetReg( BMP_OUT_MSB ) ;                    // select read register start 0xF6
  UP = BMP_I2C_Rd16b(1) ;                            // read MSB + LSB into UP, send ACKM

  UP = UP<<8 | BMP_I2C_Rd(0) ;                       // read XLSB into UP, send NACKM
  UP = UP>>(8-oss) ;                                 // adjust for oss
  BMP_I2C_Stop() ;                                   // stop

  // DEBUG Example from Bosch datasheet
  // UP = 23843;

  //Calculate True Temperature
  X1 = (( (long)UT - (long)AC6)*(long)AC5) >> 15 ;
  X2 = ( (long)MC << 11)/(X1 + MD) ;
  B5 = X1 + X2 ;                       // long B5 used in calculation of True Pressure
  TrueT = ( (B5 + 8) >> 4 ) ;          // TrueT is temperature in 0.1 degrees

  //Calculate True Pressure
  // Calculate B6
  B6 = B5 - 4000 ;
  // Calculate B3
  X1 = ((long)B2c * (long)(B6*B6)>>12) >>11 ;
  X2 = ((long)AC2 * (long)B6) >>11 ;
  X3 = X1 + X2 ;
  B3 = ((( (long)AC1*4 + X3) <<oss) + 2) >>2 ;
  // Calculate B4
  X1 = (AC3 * B6) >>13 ;
  X2 = (B1c * ((B6 * B6)>>12)) >>16 ;
  X3 = ((X1 + X2) + 2 ) >>2 ;
  B4 = (AC4 * (unsigned long)(X3 + 32768)) >>15 ;

  B7 = ((unsigned long)(UP - B3) * (unsigned long)(50000 >>oss)) ;
  if( B7 < 0x80000000 )
  { pp = ((B7 <<1) / B4) ; }
  else
  { pp = ((B7 / B4) <<1) ; }

  X1 = (pp >>8)*(pp >>8) ;
  X1 = (X1 * 3038) >>16;                   // original says * 1519; ???
  X2 = (-7357 * pp) >>16;
  TrueP = pp + ((X1 + X2 + 3791) >>4) ;   // pressure in Pa 101300
}

void BMP_Init()
{
  BMP_I2C_SetReg ( CAL_DATA_ADDR ) ; // select read register at start of calibration data 0xAA
  // load up calibration data
  AC1 = (int)BMP_I2C_Rd16b(1) ;
  AC2 = (int)BMP_I2C_Rd16b(1) ;
  AC3 = (int)BMP_I2C_Rd16b(1) ;
  AC4 = (unsigned int)BMP_I2C_Rd16b(1) ;
  AC5 = (unsigned int)BMP_I2C_Rd16b(1) ;
  AC6 = (unsigned int)BMP_I2C_Rd16b(1) ;
  B1c  = (int)BMP_I2C_Rd16b(1) ;
  B2c  = (int)BMP_I2C_Rd16b(1) ;
  MB  = (int)BMP_I2C_Rd16b(1) ;
  MC  = (int)BMP_I2C_Rd16b(1) ;
  MD  = (int)BMP_I2C_Rd16b(0) ; // send NACKM before stop
  BMP_I2C_Stop();

  // DEBUG Example from Bosch datasheet
  // AC1 = 408; AC2 = -72; AC3 = -14383; AC4 = 32741; AC5 = 32757; AC6 = 23153;
  // B1c = 6190; B2c = 4; MB = -32768; MC = -8711; MD = 2868;
}

Akış Şeması
 
MicroC için muhtemelen lcd.h/c ve I2C.h/c
dosyaları hazırda var. Bunları XC8 için de
yazmanız gerekecek.
 
Teşekkürler hocam. Peki bu kütüphaneleri nereden bulabilirim acaba?
 
Projeyi MikroC'ye aldım. Ama maalesef sonuçlar doğru değil. (Ekte simulasyon fotoğraflarını koydum.)BMP180.c'yi kontrol ettim ama bir şey bulamadım. Nerede hata yapıyorum yardımcı olabilir misiniz? Yardımlarınız şimdiden için teşekkürler.

main.c
Kod:
#include "BMP180.h"

sbit LCD_RS at RC6_bit;
sbit LCD_EN at RC7_bit;
sbit LCD_D4 at RC0_bit;
sbit LCD_D5 at RC1_bit;
sbit LCD_D6 at RC2_bit;
sbit LCD_D7 at RC3_bit;

sbit LCD_RS_Direction at TRISC6_bit;
sbit LCD_EN_Direction at TRISC7_bit;
sbit LCD_D4_Direction at TRISC0_bit;
sbit LCD_D5_Direction at TRISC1_bit;
sbit LCD_D6_Direction at TRISC2_bit;
sbit LCD_D7_Direction at TRISC3_bit;
// End LCD module connections

char txt[7];
char txt2[7];

void main() {

     TRISC=0;
     TRISB=0xFF;
     C1ON_bit=0;
     C2ON_bit=0;
     ANSELB=0;
     ANSELC=0;
     TRISC=0;
 
     Soft_I2C_Init();
 
     Lcd_Init();                        // Initialize LCD

     Lcd_Cmd(_LCD_CLEAR);               // Clear display
     Lcd_Cmd(_LCD_CURSOR_OFF);          // Cursor off
     Lcd_Out(1,6,"Hello");                 // Write text in first row

     Lcd_Out(2,2,"Pressure Gauge");                 // Write text in second row
     Delay_ms(2000);
     Lcd_Cmd(_LCD_CLEAR);               // Clear display
 
     BMP_Init();
    while(1){

        BMP_Read( 0 );
        Lcd_Out(1,1,"Basinc:");                 // Write text in first row
        IntToStr(TrueP,txt);  // txt is " -4220" (one blank here)
        Lcd_Out(1,8,txt);                 // Write text in first row
        Lcd_Out(2,1,"Sicaklik:");                 // Write text in first row
        IntToStr(TrueT,txt2);  // txt is " -4220" (one blank here)
        Lcd_Out(2,10,txt2);                 // Write text in first row
        //lcd_git(2,8);
    }
}

BMP180.c
Kod:
//#include <built_in.h>
#include "I2C.h"
// Note: #include "BMP180.h" in main module

#define CAL_DATA_ADDR         0xAA    // start address of calibration data
#define BMP_CONTROL           0xF4    // see Figure 6 in datasheet, ctrl_meas F4h (oss, sco, meas)
#define BMP_OUT_MSB           0xF6    // see Figure 6 in datasheet, out_msb
#define BMP_READTEMPCMD       0x2E
#define BMP_READPRESSURECMD   0x34

// Calibration data in E2PROM (named as in datasheet but with c suffix on B1 & B2 or redifined)
int AC1, AC2, AC3 ;
unsigned int AC4, AC5, AC6 ;
int B1c, B2c, MB, MC, MD ;           // c suffix added to B1 & B2

// Global variables for display in main function
int TrueT ;          // temperature in 0.1 degrees (named T in datasheet) so 20deg = 200
long TrueP ;         // pressure in Pa (named P in datasheet) so 1013 hPa = 101300
// Global for debug purposes
int UT ;                    // uncompensated value of temperature
long UP ;                   // uncompensated value of pressure

// Internal functions
void delayOss (char oss)
{ // delay depending on oversampling oss 0 to 3, approximates to 2x^2 + x + 5
  char i, do1mS ;
  do1mS = 2*oss*oss + oss + 5 ; // (0, 1, 2, or 3 gives 5, 8, 15, or 26)
  for (i = 0 ; i < do1mS ; i++)
    Delay_ms(1) ;
}

int BMP_I2C_Rd16b (char ackm)
{ // return MSB<<8 + LSB, send ACKM if parameter ackm is 1, NACKM if ackm 0
  return ( (BMP_I2C_Rd(1) << 8) + BMP_I2C_Rd(ackm) ) ;
}

void BMP_I2C_SetU( char reg )
{ // setup for read of UT or UP, do delay on return
  BMP_I2C_Start();
  BMP_I2C_Wr( I2C_ADDR_WR );
  BMP_I2C_Wr( BMP_CONTROL );          // 0xF4
  BMP_I2C_Wr( reg );                  // write 0x2E or 0x34 into reg 0xF4
  BMP_I2C_Stop();
}

void BMP_I2C_SetReg( char reg )
{ // setup for read of calibration data 0xAA, or UT/UP data 0xF6
  BMP_I2C_Start();                // start condition
  BMP_I2C_Wr( I2C_ADDR_WR );      // module address write command 0xEE
  BMP_I2C_Wr( reg );              // select read register (calibration data 0xAA, UT/UP data 0xF6)
  BMP_I2C_Start();                // restart condition
  BMP_I2C_Wr( I2C_ADDR_RD );      // module address read command 0xEF
}

// Global functions
void BMP_Read( char oss )
{// read uncompensated values UT & UP, convert to true, save in global variables: TrueT & TrueP
  long B3, B5, B6, X1, X2, X3, pp ;
  unsigned long B4, B7;

  // read uncompensated value UT
  BMP_I2C_SetU( BMP_READTEMPCMD ) ;                  // write 0x2E into reg 0xF4: setup for UT
  Delay_ms( 5 ) ;                                    // delay 4.5mS minimum
  BMP_I2C_SetReg ( BMP_OUT_MSB ) ;                   // select read register start 0xF6
  UT = BMP_I2C_Rd16b(0) ;                            // read 16 bits into UT, send NACKM
  BMP_I2C_Stop() ;                                   // stop

  // DEBUG Example from Bosch datasheet (TrueT should be 150, TrueP should be 69964).
  // UT = 27898 ;

  // read uncompensated value UP
  BMP_I2C_SetU( BMP_READPRESSURECMD | (oss << 6) ) ; // write 0x34 into reg 0xF4: setup for UP
  delayOss( oss ) ;                                  // delay depends on oss
  BMP_I2C_SetReg( BMP_OUT_MSB ) ;                    // select read register start 0xF6
  UP = BMP_I2C_Rd16b(1) ;                            // read MSB + LSB into UP, send ACKM
  UP = UP<<8 | BMP_I2C_Rd(0) ;                       // read XLSB into UP, send NACKM
  UP = UP>>(8-oss) ;                                 // adjust for oss
  BMP_I2C_Stop() ;                                   // stop

  // DEBUG Example from Bosch datasheet
  // UP = 23843;

  //Calculate True Temperature
  X1 = (( (long)UT - (long)AC6)*(long)AC5) >> 15 ;
  X2 = ( (long)MC << 11)/(X1 + MD) ;
  B5 = X1 + X2 ;                       // long B5 used in calculation of True Pressure
  TrueT = ( (B5 + 8) >> 4 ) ;          // TrueT is temperature in 0.1 degrees

  //Calculate True Pressure
  // Calculate B6
  B6 = B5 - 4000 ;
  // Calculate B3
  X1 = ((long)B2c * (long)(B6*B6)>>12) >>11 ;
  X2 = ((long)AC2 * (long)B6) >>11 ;
  X3 = X1 + X2 ;
  B3 = ((( (long)AC1*4 + X3) <<oss) + 2) >>2 ;
  // Calculate B4
  X1 = (AC3 * B6) >>13 ;
  X2 = (B1c * ((B6 * B6)>>12)) >>16 ;
  X3 = ((X1 + X2) + 2 ) >>2 ;
  B4 = (AC4 * (unsigned long)(X3 + 32768)) >>15 ;

  B7 = ((unsigned long)(UP - B3) * (unsigned long)(50000 >>oss)) ;
  if( B7 < 0x80000000 )
  { pp = ((B7 <<1) / B4) ; }
  else
  { pp = ((B7 / B4) <<1) ; }

  X1 = (pp >>8)*(pp >>8) ;
  X1 = (X1 * 3038) >>16;                   // original says * 1519; ???
  X2 = (-7357 * pp) >>16;
  TrueP = pp + ((X1 + X2 + 3791) >>4) ;   // pressure in Pa 101300
}

void BMP_Init()
{
  BMP_I2C_SetReg ( CAL_DATA_ADDR ) ; // select read register at start of calibration data 0xAA
  // load up calibration data
  AC1 = (int)BMP_I2C_Rd16b(1) ;
  AC2 = (int)BMP_I2C_Rd16b(1) ;
  AC3 = (int)BMP_I2C_Rd16b(1) ;
  AC4 = (unsigned int)BMP_I2C_Rd16b(1) ;
  AC5 = (unsigned int)BMP_I2C_Rd16b(1) ;
  AC6 = (unsigned int)BMP_I2C_Rd16b(1) ;
  B1c  = (int)BMP_I2C_Rd16b(1) ;
  B2c  = (int)BMP_I2C_Rd16b(1) ;
  MB  = (int)BMP_I2C_Rd16b(1) ;
  MC  = (int)BMP_I2C_Rd16b(1) ;
  MD  = (int)BMP_I2C_Rd16b(0) ; // send NACKM before stop
  BMP_I2C_Stop();

  // DEBUG Example from Bosch datasheet
  // AC1 = 408; AC2 = -72; AC3 = -14383; AC4 = 32741; AC5 = 32757; AC6 = 23153;
  // B1c = 6190; B2c = 4; MB = -32768; MC = -8711; MD = 2868;
}

/* ORIGINAL FROM LIBSTOCK
  //Calculate True Pressure
  // Calculate B6
  B6 = B5 - 4000 ;
  // Calculate B3
  X1 = pow(B6, 2) ;
  X1 >>= 12 ;
  X1 *= (long)B2c ;
  X1 >>= 11 ;

  X2 = ((long)AC2c * B6) ;
  X2 >>= 11 ;

  X3 = X1 + X2 ;

  B3 = (long)AC1c * 4 ;
  B3 += X3 ;
  B3 <<= oss ;
  B3 += 2 ;
  B3 >>= 2 ;

  X1 = (AC3c * B6) ;
  X1 >>= 13 ;

  X2 = (B6 * B6) ;
  X2 >>= 12;
  X2 *= B1c ;
  X2 >>= 8 ;
  X2 >>= 8 ;

  X3 = ((X1 + X2) + 2 ) ;
  X3 >>= 2 ;

  B4 = AC4c ;
  B4 *= (unsigned long)(X3 + 32768) ;
  B4 >>= 15 ;

  B7 = (unsigned long)(UP - B3) ;
  B7 *= (unsigned long)(50000 >> oss) ;
  if( B7 < 0x80000000 )
  {
     pp = ((B7 * 2) / B4) ;
  }
  else
  {
     pp = ((B7 / B4) * 2) ;
  }

  X1 = pow((pp >> 8), 2) ;
  X1 *= 3038 ;                  // original says         X1 *= 1519; ???
  X1 >>= 15 ;

  X2 = (-7357 * pp) ;
  X2 >>= 8;
  X2 >>= 8;

  TrueP = pp + ( (X1 + X2 + 3791) >> 4) ;   // pressure in Pa 101300
}

*/

I2C.h

Kod:
// Software I2C connections required for software I2C library

sbit Soft_I2C_Scl           at RB6_bit;     // PORT A B0=I2CSCL
sbit Soft_I2C_Sda           at RB4_bit;     // PORT A B1=I2CSDA
sbit Soft_I2C_Scl_Direction at TRISB6_bit;
sbit Soft_I2C_Sda_Direction at TRISB4_bit;

// use software I2C port
#define BMP_I2C_Rd         Soft_I2C_Read
#define BMP_I2C_Start      Soft_I2C_Start
#define BMP_I2C_Stop       Soft_I2C_Stop
#define BMP_I2C_Wr         Soft_I2C_Write

#define BMP_Scl            Soft_I2C_Scl
#define BMP_Sda            Soft_I2C_Sda
#define BMP_Scl_Direction  Soft_I2C_Scl_Direction
#define BMP_Sda_Direction  Soft_I2C_Sda_Direction

#define I2C_ADDR_WR    0xEE       // I2C address of BMP180 module for write operations
#define I2C_ADDR_RD    0xEF       // I2C address of BMP180 module for read operations
 

Ekli dosyalar

  • devre_şeması.jpg
    354.8 KB · Görüntüleme: 25
  • simülasyon.jpg
    389.7 KB · Görüntüleme: 21
Son düzenleme:
Bu siteyi kullanmak için çerezler gereklidir. Siteyi kullanmaya devam etmek için onları kabul etmelisiniz. Daha fazla bilgi edin…