ايران ويج

نسخه‌ی کامل: سنسور BOSCH BMP180
شما در حال مشاهده‌ی نسخه‌ی متنی این صفحه می‌باشید. مشاهده‌ی نسخه‌ی کامل با قالب بندی مناسب.
سلام..
دوستان این سنسور با پرتکا i2c کار میکنه.. تو دیتا شیتش یه سری مطالب دیدم ولی راستش از بس سرم شلوغ شده برای کارای دیگه(مسابقات) نتونستم دقیق روش کار کنم و از شما کمک میخوام...
این دستگاهی که قرار بسازیم یه قسمت از طرح برای مسابقاته..
دوستان مطالعه کنن و یاری کنن..
برای کالیبره کردن باید یه سری کد بفرستم که جواب بده.. گفته اینو که مثلا پارامتر ac1 رو باید این کد ها 0xaa برای پر ارزش و 0xab برای بیت های کم ارزش که رو هم میشه 16 بیت....رو بفرستی که جواب بده این درسته.؟؟.. یه مثال هم زده
این سنسور برای سنجش فشار و دما است..
ممنون
سلام.

چند وقت پيش به مدت 2 روز با BMP085 سر و كله زدم و مطابق گفته ي بقيه راش انداختم ، منتها ، جوابي كه مي داد خيلي عجيب بود و رفع هم نشد ،‌منم وقت نداشتم رفعش كنم و قيدش رو زدم تا در فرصت هاي آيندهه ... . ( البته به خراب بودن خود سنسور هم شك دارم ، ارتباط برقرار مي شه اما خروجي ها ...! )

اين BMP180 رو چك نكردم ، نمي دونم چقدر شباهت دارهه.

به هر حال اگر كسي هست كه سنسور رو دارهه و مي خواد بكوب بشينه پاش و راش بندازهه و هنوز لايبرريش رو آماده نكردهه ، اعلام كنه تا سر فرصت لايبرري رو كه از نت جمع آوري كردم بذارم و روش كار كنه ، البته به شرطي كه نتيجه اش رو در همين تاپيك براي بقيه ي دوستان هم بذارهه.
سلام..
من مجبورم که راش بندازم چون این مدل کوچک ترین سایز سنسور فشار بود که پیدا کردم..
در مورد سوال های من جوابی نداشتی sharin جان؟؟؟
یعنی برای خوندن پارامتر های AC1 , و بقیه که اول بایستس بخونیم برای کالیبره کردن سنسور و بعد هم بقیه داستان رو چجور میشه خوند..
چه دستسوری بفرستم تا بخونم؟؟
الان كلياتش تو ذهنم هست. اگر مي خوايد نهايت تا 2-3 روز ديگه لايبرري BM085 رو سعي مي كنم براتون بذارم ( مشابه سنسور مد نظر هست؟ )
بايد از لابه لاي كدها درش بيارم الان نمي رسم آماده اش كنم.

تا جايي كه يادمه كلياتش اينه كه ، اول كاليبرهه مي كنيم و بعد يه فرمان مي فرستيم براي محاسباتي كه با سنسور دماش هست و بعد از اون يه فرمان ديگه مي فرستيم براي محاسبه ي فشار و يا ارتفاع و ... . بجز كاليبره كردن بقيه ي كارا رو بايد مدام در حلقه اي انجام بديم. ( پروتكل I2C و آدرس ها هم كه مشخصه اما چون براي چند ماه پيش بود دقيق تو ذهنم نيست )
این یه نمونه برنامه

این هم یه برنامه دیگه که من نمیدونم برای گالیبره کردن به چه صورت اطلاعات رو بفرستم و بعدش بخونم..دوستان یاری کنن
کد:
#include "mbed.h"

#define EE 22
#define BMP085ADDR 0xEF

long b5;
int calcPress(int upp);
int calcTemp(int ut);
short ac1;
short ac2;
short ac3;
unsigned short ac4;
unsigned short ac5;
unsigned short ac6;
short b1;
short b2;
short mb;
short mc;
short md;

#define COEFZ 21
static int k[COEFZ];
static int movAvgIntZ (int input);

I2C i2c(p28, p27);        // sda, scl
InterruptIn dr(p26);

uint32_t drFlag;
void cvt();
void drSub();

Serial pc(USBTX, USBRX); // tx, rx

int main() {

    // let hardware settle
    wait(1);

    /////////////////////////////////////////////////
    // set up timer to trigger pressure conversion
    /////////////////////////////////////////////////
    Ticker convert;
    convert.attach_us(&cvt, 50000); // 50 ms, 20 Hz

    /////////////////////////////////////////////////
    // set up data ready interrupts
    /////////////////////////////////////////////////
    // set up interrupts
    __disable_irq();
    // ADC data ready
    drFlag = 0;
    dr.mode(PullDown);
    dr.rise(&drSub);

    /////////////////////////////////////////////////
    // set up i2c
    /////////////////////////////////////////////////
    char addr = BMP085ADDR; // define the I2C Address
    char rReg[3] = {0,0,0};
    char wReg[2] = {0,0};
    char cmd = 0x00;

    /////////////////////////////////////////////////
    // get EEPROM calibration parameters
    /////////////////////////////////////////////////

    char data[EE];
    cmd = 0xAA;

    for (int i = 0; i < EE; i++) {
        i2c.write(addr, &cmd, 1);
        i2c.read(addr,rReg,1);
        data[i] =  rReg[0];
        cmd += 1;
        wait_ms(10);
    }

    // parameters AC1-AC6
    ac1 =  (data[0] <<8) | data[1];
    ac2 =  (data[2] <<8) | data[3];
    ac3 =  (data[4] <<8) | data[5];
    ac4 =  (data[6] <<8) | data[7];
    ac5 =  (data[8] <<8) | data[9];
    ac6 = (data[10] <<8) | data[11];
    // parameters B1,B2
    b1 =  (data[12] <<8) | data[13];
    b2 =  (data[14] <<8) | data[15];
    // parameters MB,MC,MD
    mb =  (data[16] <<8) | data[17];
    mc =  (data[18] <<8) | data[19];
    md =  (data[20] <<8) | data[21];


    //int tCounter = 200;
    //int pCounter = 0;
    int temp = 0;

    // ready to start sampling loop
    __enable_irq();

    /////////////////////////////////////////////////
    // main
    /////////////////////////////////////////////////

    while (1) {

        if (drFlag == 1) {

            /////////////////////////////////////////////////
            // uncompensated pressure
            /////////////////////////////////////////////////
            cmd = 0xF6;
            i2c.write(addr, &cmd, 1);
            i2c.read(addr,rReg,3);
            int up = ((rReg[0] << 16) | (rReg[1] << 8) | rReg[2]) >> 5;

            /////////////////////////////////////////////////
            // temperature
            // only do this every 10 sec or so
            /////////////////////////////////////////////////

            //if (tCounter == 200) {
                wReg[0] = 0xF4;
                wReg[1] = 0x2E;
                i2c.write(addr, wReg, 2);
                wait_ms(4);

                // uncompensated temperature
                cmd = 0xF6;
                i2c.write(addr, &cmd, 1);
                i2c.read(addr,rReg,2);
                int ut = (rReg[0] << 8) | rReg[1];

                // compensated temperature
                temp = calcTemp(ut);

                //tCounter = 0;
            //}
            /////////////////////////////////////////////////
            // compensated pressure
            /////////////////////////////////////////////////

            int press = calcPress(up);
            int pressZ = movAvgIntZ(press);
            //if (pCounter == 20) {
                pc.printf("%d\t%d\n",pressZ,temp);
                //pCounter = 0;
           // }

            /////////////////////////////////////////////////
            // data ready cleanup tasks
            /////////////////////////////////////////////////

            // reset data ready flag
            drFlag = 0;
            //tCounter++;
            //pCounter++;

        }
    }
}

////////////////////////////////////////////////////////////////////////////////////
// start pressure conversion
////////////////////////////////////////////////////////////////////////////////////

void cvt() {

    char w[2] = {0xF4, 0xF4};
    i2c.write(BMP085ADDR, w, 2);
}

////////////////////////////////////////////////////////////////////////////////////
// Handle data ready interrupt, just sets data ready flag
////////////////////////////////////////////////////////////////////////////////////

void drSub() {

    drFlag = 1;
}

/////////////////////////////////////////////////
// calculate compensated pressure
/////////////////////////////////////////////////

int calcPress(int upp) {

    long pressure,x1,x2,x3,b3,b6;
    unsigned long b4, b7;
    int oversampling_setting = 3;

    unsigned long up = (unsigned long)upp;

    b6 = b5 - 4000;
    // calculate B3
    x1 = (b6*b6) >> 12;
    x1 *= b2;
    x1 >>=11;

    x2 = (ac2*b6);
    x2 >>=11;

    x3 = x1 +x2;

    b3 = (((((long)ac1 )*4 + x3) <<oversampling_setting) + 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>>oversampling_setting));
    if (b7 < 0x80000000) {
        pressure = (b7 << 1) / b4;
    } else {
        pressure = (b7 / b4) << 1;
    }

    x1 = pressure >> 8;
    x1 *= x1;
    x1 = (x1 * 3038) >> 16;
    x2 = (pressure * -7357) >> 16;
    pressure += (x1 + x2 + 3791) >> 4;  // pressure in Pa

    return (pressure);
}

/////////////////////////////////////////////////
// calculate compensated temp from uncompensated
/////////////////////////////////////////////////
int calcTemp(int ut) {

    int temp;
    long x1,x2;

    x1 = (((long) ut - (long) ac6) * (long) ac5) >> 15;
    x2 = ((long) mc << 11) / (x1 + md);
    b5 = x1 + x2;
    temp = ((b5 + 8) >> 4);  // temperature in 0.1°C

    return (temp);
}

////////////////////////////////////////////////////////////////////////////////////
// int version of moving average fliter
////////////////////////////////////////////////////////////////////////////////////

static int movAvgIntZ (int input) {

    int cum = 0;

    for (int i = 0; i < COEFZ; i++) {
        k[i] = k[i+1];
    }

    k[COEFZ - 1] = input;

    for (int i = 0; i < COEFZ; i++) {
        cum += k[i];
    }

    return ( cum / COEFZ ) ;
}
و یه برنامه دیگه با مگا 8 به همراه شماتیک که فایلش ضمیمه شد
سلام... درست شد..
میدونستین با این سنسور میشه ارتفاع رو هم سنجید..
درجه حرارت و فشار هوا رو که من دارم الان بدون هیچ مشکلی کار میکنه....
ارتفاع رو هم انگار یه فرمول داره..
در مورد برنامه که من تا چند وقت دیگه میزارم تو وبلاگم..(hex)
خیلی اذیت کرد ولی بالاخره تسلیم شد...

راه اندازی سنسور BOSCH BMP180 هم دقیقا مشابه این سنسور است...
سنسور BMP085 يه سنسور فشار بارومتريك هست و يكي از كار بردهاي اصليش اندازهه گيريه ارتفاع هست.
توي ماژول هاي IMU هم به عنوان 1 درجه آزادي براي اندازهه گيريه ارتفاع وارد مي شه.
همينطور براي تصحيح خطاي GPS براي ارتفاع ، در كنارش استفاده مي شه.

خوب اينم سورسي كه قولش رو دادهه بودم. هدف منم بدست آوردن ارتفاع بود و كدهاش هم توي كتابخونه گذاشتم.
شايد همين هم كامل باشه و جواب بدهه ، اگر كسي از دوستان امتحان كرد و جواب گرفت خبرش رو بدهه. اگرم كسي از دوستان اشكالش رو دريافت ممنون مي شيم رفعش كنه و با بقيه به اشتراك بذارهه. تو دو روزي كه قبلا روش كار كردم ، خروجي معقولي نگرفتم! ديگه هم نشد بيشتر روش وقت بذارم.
و از ظهر امروز به اينور ، عملا به اين سنسور دسترسي ندارم.

اين كتابخانه اي كه ايجاد كردم.

کد php:
#ifndef __BMP085_H__
#define __BMP085_H__

//----------------------------

   #define BMP085_ADDRESS (0x77<<1)  // I2C address of BMP085

     #define OSS  3  // Oversampling Setting      //const unsigned char
     #define BARO_TAB_SIZE 21

    // Calibration values
    
int ac1 =0,ac2 =0,ac3 =0;
    
unsigned int ac4 =0,ac5 =0,ac6 =0;
    
int b1 =0,b2 =0,mb =0,mc =0,md =0;
    
long b5 =0
    
    
float temperature =0pressure =0pressure_sum =0Hpressure =0atm =0altitude =0baroPressureSum =0;
    
uint16_t calibratingB 10;
    
float temperature0 =0pressure0 =0atm0 =0altitude0 =0baro_first=1;

// loop()
// {
//// b5 is calculated in bmp085GetTemperature(...), this variable is also used in bmp085GetPressure(...)
//// so ...Temperature(...) must be called before ...Pressure(...).

//  float temperature = bmp085GetTemperature(bmp085ReadUT()); //MUST be called first
//  float pressure = bmp085GetPressure(bmp085ReadUP());
//  float atm = pressure / 101325; // "standard atmosphere"
//  float altitude = calcAltitude(pressure); //Uncompensated caculation - in Meters 
// }


void bmp085Calibration(void);
float bmp085GetTemperature(unsigned int ut);
long bmp085GetPressure(unsigned long up);
void bmp085TrigUT(void);
unsigned int bmp085ReadUT(void);
void bmp085TrigUP(void);
unsigned long bmp085ReadUP(void);
float calcAltitude(float pressure);
void Baro_Common(void);
void getEstAltitude(void);

#endif



// 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
void bmp085Calibration()
{
  
ac1 read16_rev(BMP085_ADDRESS,0xAA);  //_rev
  
ac2 read16_rev(BMP085_ADDRESS,0xAC);
  
ac3 read16_rev(BMP085_ADDRESS,0xAE);
  
ac4 read16_rev(BMP085_ADDRESS,0xB0);
  
ac5 read16_rev(BMP085_ADDRESS,0xB2);
  
ac6 read16_rev(BMP085_ADDRESS,0xB4);
  
b1 read16_rev(BMP085_ADDRESS,0xB6);
  
b2 read16_rev(BMP085_ADDRESS,0xB8);
  
mb read16_rev(BMP085_ADDRESS,0xBA);
  
mc read16_rev(BMP085_ADDRESS,0xBC);
  
md read16_rev(BMP085_ADDRESS,0xBE);
}

// Calculate temperature in deg C
float bmp085GetTemperature(unsigned int ut){
  
long x1x2;
  
float temp;

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

  
temp = ((b5 8)>>4);
  
temp temp /10;
// temp = (b5 * 10 + 8) >> 4; // in 0.01 degC (same as MS561101BA temperature)

  
return temp;
}

long bmp085GetPressure(unsigned long up){
  
long x1x2x3b3b6p;
  
unsigned long b4b7;
  
long temp;

  
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;
    
b3 = ((int32_tac1 x3 2) << 1;

  
// 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));
//  b7 = ((unsigned long)(up >> (8-OSS)) - b3) * (50000>>OSS);


  
if (b7 0x80000000)
    
= (b7<<1)/b4;
  else
    
= (b7/b4)<<1;

  
x1 = (p>>8) * (p>>8);
  
x1 = (x1 3038)>>16;
  
x2 = (-7357 p)>>16;
  
+= (x1 x2 3791)>>4;

  
temp p;
  return 
temp;
}

// Trig for start temprature conversion
void bmp085TrigUT(){
  
// Write 0x2E into Register 0xF4
  // This requests a temperature reading
  
writeRegister(BMP085_ADDRESS0xF40x2E);
  
  
// Wait at least 4.5ms
//  delay_ms(5);
}

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

//  writeRegister(BMP085_ADDRESS, 0xF4, 0x2E);
//  delay_ms(5);

  // Read two bytes from registers 0xF6 and 0xF7
  
ut read16_rev(BMP085_ADDRESS,0xF6);      //_rev
  
return ut;
}


// Trig for start uncompensated pressure conversion
void bmp085TrigUP(){

  
// Write 0x34+(OSS<<6) into register 0xF4
  // Request a pressure reading w/ oversampling setting
  
writeRegister(BMP085_ADDRESS0xF40x34 + (OSS<<6));

  
// Wait for conversion, delay time dependent on OSS
//  delay_ms(2 + (3<<OSS));

}

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

  
unsigned long up 0;
//  writeRegister(BMP085_ADDRESS, 0xF4, 0x34 + (OSS<<6));
//  delay_ms(5 + (3<<OSS));

  // Read register 0xF6 (MSB), 0xF7 (LSB), and 0xF8 (XLSB)
  
up read24_rev(BMP085_ADDRESS0xF6);  //_rev
  
return up;
}

float calcAltitude(float pressure){

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

  return 
C;
}

  
void Baro_Common() {
    static 
int32_t baroHistTab[BARO_TAB_SIZE];
    static 
uint8_t baroHistIdx;
      
uint8_t indexplus1;
    
    
indexplus1 = (baroHistIdx 1);
    if (
indexplus1 == BARO_TAB_SIZEindexplus1 0;
    
baroHistTab[baroHistIdx] = pressure;
    
baroPressureSum += baroHistTab[baroHistIdx];
    
baroPressureSum -= baroHistTab[indexplus1];
    
baroHistIdx indexplus1;  
  }

  
void getEstAltitude()
  {
     
int32_t  BaroAlt;
     static 
float baroGroundTemperatureScale,logBaroGroundPressureSum;

     if(
calibratingB 0) {
     
logBaroGroundPressureSum log(baroPressureSum);
     
baroGroundTemperatureScale = (temperature 27315) *  29.271267f;
     
calibratingB--;
     }
    
     
// baroGroundPressureSum is not supposed to be 0 here
     // see: https://code.google.com/p/ardupilot-mega/source/browse/libraries/AP_Baro/AP_Baro.cpp
     
BaroAlt = ( logBaroGroundPressureSum log(baroPressureSum) ) * baroGroundTemperatureScale;
    
     
altitude = ((int)altitude BaroAlt 2) >> 3// additional LPF to reduce baro noise (faster by 30 µs)
  



اين سنسور بايت هاي پر ارزش و كم ارزشش ظاهرا برعكس سنسورهاي ديگست كه روي اعصاب بود.
روي AVR كار نمي كردم ، بنابراين I2C با خودتون مي شه...

------------------------

روش استفاده هم تا جايي كه من فهميدم ، به شرح زيرهه ، اگر اشتباه هست دوستان اصلاح كنن لطفا.


1. تابع ()bmp085Calibration رو فراخوني مي كنيد ( 1 بار در ابتداي برنامه )
2. تابع ()bmp085TrigUT رو فراخوني مي كنيد كه سنسور مشغول محاسبات دما بشه.
3. يه سري از كاراتون رو در فاصله انجام مي ديد ( زمانش فكر كنم 6ms طول مي كشيد ،‌تو ديتاشيتش نوشته ،‌مطمئن نيستم! )
4. بعد اطلاعات دما رو با تابع زير ذخيرهه مي كنيد.
کد php:
temperature bmp085GetTemperature(bmp085ReadUT()); //MUST be called first 

5.در همين لحظه تابع ()bmp085TrigUP رو فراخوني مي كنيد تا سنسور مشغول محاسبات فشار بشه.
6.باز مي ريد قدري از كارهاتون رو انجام مي ديد.( ديتاشيت رو براي زمان محاسبه چك كنيد )
7.حالا اطلاعات فشار رو به اين صورت ذخيرهه مي كنيد
کد php:
pressure bmp085GetPressure(bmp085ReadUP()); 

8. در همين زمان از تابع هاي زير هر چي رو كه خواستيد استفاده مي كنيد.
کد php:
atm pressure_sum 101325// "standard atmosphere"
altitude calcAltitude(pressure_sum); //Uncompensated caculation - in Meters 
Baro_Common();
getEstAltitude(); 
9.در همين حال به مرحله ي 2 پرش مي كنيد و اين حلقه مدام بايد تكرار بشه.


موفق باشيد.
سلام دوستان

میشه بفرمایید با زبان بیسیک چطوری میتونم اطلاعات این ماژول BMP180 رو بخونم

لطفا کمکم کنید

با تشکر
کسی نیست کمکم کنه؟