Jump to content
ELFORUM - Forumul Electronistilor
Sign in to follow this  
moro

Senzor barometric BMP085 si PIC18F

Recommended Posts

Va salut, m-am apucat de un mic proiect ce se vrea a fi un altimetru

 

Am facut urmatorul cod

 

int AC1;                int AC2;                int AC3;                unsigned AC4;                unsigned AC5;                unsigned AC6;                int mB1;                int mB2;                int MB;                int MC;                int MD;                long UT=0, UP=0,UPP=0, avv=0, _B3, _B5, _B6, X1, X2, X3, pp;                unsigned long _B4, _B7;                int tmp_out;                int oss,ii;                float pres;                float hpa;                float altitude;                char txt3[8];                char txt2[12];                char txt4[12];void bmp085_calibration() {  // calibration params from sensor's eepromAC1=8340;AC2=-1232;AC3=-14440;AC4=-31743;AC5=24449;//old 32757;AC6=25123;// old 23153;MB=-32768;MC=-11075;// old -8711;MD=2432;// old 2868;mB1=5498;mB2=67;}                void call_temp() {i2c1_start();i2c1_wr(0xee);i2c1_wr(0xf4);i2c1_wr(0x2E); //i2c1_stop();delay_ms(5); // wait aprox 4.5 ms for sensor to measure tempi2c1_start();i2c1_wr(0xee); // addr + wi2c1_wr(0xf6); // select reg F6i2c1_repeated_start();i2c1_wr(0xef); // addr + rHi(UT) =I2C1_Rd(1);Lo(UT) =I2C1_Rd(0);i2c1_stop();//calculate true temperatureX1 = (UT-AC6);X1 *= AC5;X1 >>= 15;X2 = ((long)MC << 11);X2 /= (X1 + MD);_B5 = X1 + X2;tmp_out =(_B5 + 8)/16;// >> 4 ) / 10;inttostr(tmp_out,txt3);lcd_chr(2,10,txt3[3]);lcd_chr(2,11,txt3[4]);lcd_out(2,12,".");lcd_chr(2,13,txt3[5]);lcd_out(2,14,"C");}                                                                            void call_pressure() {    // get pressure raw dataoss=3;   i2c1_start();  //  BMP085_I2C_Start();   i2c1_wr(0xEE); //  BMP085_I2C_Wr( BMP085_ADDRESS );   i2c1_wr(0xF4); //  BMP085_I2C_Wr( BMP085_CONTROL );   i2c1_wr(0x34); // BMP085_I2C_Wr( cmd );   i2c1_stop();//BMP085_I2C_Stop();    delay_ms(26);    i2c1_start();                  // BMP085_I2C_Start();    i2c1_wr(0xEE);                 // BMP085_I2C_Wr( BMP085_ADDRESS );    i2c1_wr(0xF6);                 // BMP085_I2C_Wr( BMP085_PRESSUREDATA );    i2c1_repeated_start();         // BMP085_I2C_Start();    i2c1_wr(0xEF);                 // BMP085_I2C_Wr( BMP085_ADDRESS | 1 );    Higher(UP) = i2c1_rd(1);       // BMP085_I2C_Rd(1);    Hi(UP) = i2c1_rd(1);           // BMP085_I2C_Rd(1);    Lo(UP) = i2c1_rd(0);           // BMP085_I2C_Rd(0);    i2c1_stop();                   // BMP085_I2C_Stop();    Highest(UP) = 0;    UP >>= ( 8 - oss );     // calculate presure _B6 = _B5 - 4000;X1 = pow(_B6, 2);X1 >>= 12;X1 *= (long)mB2;X1 >>= 11;X2 = ((long)AC2 * _B6);X2 >>= 11;X3 = X1 + X2;_B3 = (long)AC1 * 4;_B3 += X3;_B3 <<= oss;_B3 += 2;_B3 >>= 2;X1 = (AC3 * _B6);X1 >>= 13;X2 = (_B6 * _B6);X2 >>= 12;X2 *= mB1;X2 >>= 8;X2 >>= 8;X3 = ((X1 + X2) + 2 );X3 >>= 2;_B4 = AC4;_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 *= 1519;        X1 >>= 15;    X2 = (-7357 * pp);        X2 >>= 8;        X2 >>= 8;        pres = pp + ( (X1 + X2 + 3791) >> 4);                    hpa=pres/100; // convert pascal to hecta Pascal    //calculate altitude    altitude = 1 - pow( (hpa/1013.25),0.190295 );    altitude *= 44330;floattostr(hpa,txt4);floattostr(altitude,txt2);//lcd_out(1,1,txt2);lcd_chr(2,1,txt2[0]);lcd_chr(2,2,txt2[1]);lcd_chr(2,3,txt2[2]);lcd_chr(2,4,txt2[3]);lcd_chr(2,5,txt2[4]);lcd_out(2,7,"M");lcd_chr(1,1,txt4[0]);lcd_chr(1,2,txt4[1]);lcd_chr(1,3,txt4[2]);lcd_chr(1,4,txt4[3]);lcd_chr(1,5,txt4[4]);lcd_chr(1,6,txt4[5]);lcd_chr(1,7,txt4[6]);lcd_chr(1,8,txt4[7]);lcd_out(1,10,"hPA");        }

Presiunea masurata de senzor este data de UP inainte sa intre in bucla de calcul, as vrea sa fac un average la macar 10-20 citiri si apoi s-o bag in bucla, sau chiar la final.

Am zis sa fac inainte de bucla ca sa nu manipulez valori flotante ( UP este declarat ca integer)

 

am incercat functia asta

for (ii = 0 ; ii < 64 ; ii++ ){                            //  64 samples     avv += UP;                                 // sum the values  }  avv >>= 6;                                             //get average

dar imi afiseaza balarii.

In rest presiunea este corecta, celputin corelat cu un site meteo care-mi zice ca in timisoara acum sunt 1015.92 mbar/hPA, iar pe senzor am 1016.17.

Cum as putea face un average? Ar fi prima oara cand incerc lucrul asta si n-ar strica putin ajutor

Share this post


Link to post
Share on other sites

Ai asteptat sa citeasca de 64 de ori? E clar ca la primele citiri, valoarea rezultata va fi apropiata de 0.

Share this post


Link to post
Share on other sites

Faza cu sample a pornit de la presiunea atmosferica, stand pe loc senzorul imi detecteaza variatii ale presiunii care ating si +/- 1 metru diferenta.

Ma gandeam ca daca fac un average, va fi ceva mai stabil.

Am facut o medie "the hard way"

 

while(1) {get_raw_pressure(); // s1=raw_p;get_raw_pressure();s2      =raw_p;get_raw_pressure();s3       =raw_p;get_raw_pressure();s4       =raw_p;get_raw_pressure();s5       =raw_p;get_raw_pressure();s6       =raw_p;get_raw_pressure();s7       =raw_p;get_raw_pressure();s8       =raw_p;get_raw_pressure();s9       =raw_p;get_raw_pressure();s10       =raw_p;get_raw_pressure();s11=raw_p;get_raw_pressure();s12      =raw_p;get_raw_pressure();s13       =raw_p;get_raw_pressure();s14       =raw_p;get_raw_pressure();s15       =raw_p;get_raw_pressure();s16       =raw_p;get_raw_pressure();s17       =raw_p;get_raw_pressure();s18       =raw_p;get_raw_pressure();s19       =raw_p;get_raw_pressure();s20       =raw_p;UP=(s1+s2+s3+s4+s5+s6+s7+s8+s9+s10+s11+s12+s13+s14+s15+s16+s17+s18+s19+s20)/20; // media celor 20 de masuratoricall_pressure(); // de aici functia isi ia valoarea lui UP pt determinarea altitudinii

am spart functia call presure in doua functii, respectiv get_raw_pressure care isi ia datele din senzorul hardware, si fac chestia asta de 20 ori, apoi la fiecare apelare a functiei atribui valoarea s1...s20 cu valoarea raw_p care mi-o da get_raw_pressure, apoi imi rezulta UP (valoarea celor 20 de raw_pressure) dupa care o bag in functia de calcul "call_pressure"

 

Incercasem cu bucla aceea for() dar imi aduna la infinit cu el insusi, nu`s guru in scris coduri, insa incerc sa gandesc logic :))

Share this post


Link to post
Share on other sites

O metoda ar fi folosirea unui buffer "rotativ" de 64 de valori.Astfel, la "avv" adaugi noua valoare citita si scazi cea mai veche valoare citita (care se gaseste in buffer).avv va contine in felul acesta tot timpul suma ultimeor 64 valori citite.Un pointer intr-un buffer rotativ de 64 valori se misca in felul urmator (nu prea le am cu C-ul):i ++;i &= 63;iar cea mai veche valoare se gaseste la:j = i+1;j &= 63;

Share this post


Link to post
Share on other sites

Nu m-am uitat pe cod dar sa tii cont unde ajungi cu valorile cand faci calculele la medie , ele trebuia sa se incadreze in tipul de variabila alocata. Suma a 20 de integer nu da intotdeauna un integer

Share this post


Link to post
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Sign in to follow this  

×
×
  • Create New...

Important Information

We have placed cookies on your device to help make this website better. You can adjust your cookie settings, otherwise we'll assume you're okay to continue.