Senzor de presiune/altitudine BMP085
#1
Postat 07 January 2015 - 07:33 PM
Folosesc un senzor bmp085 bosch.
Raportat la presiunea standard la nivelul marii care este 1013.25 hpa, mie in timisoara imi indica o presiune de 1024.4 (la meteo imi da 1037hpa ).
Acu in formula de conversie pt altitudine pentru 1024.45hpa imi masoara -92 metri. Ceea ce mi se pare dubios, peste tot unde am cautat, Timisoara este undeva la +90metrii fata de nivelul marii.
A intampinat cineva probleme de genul asta? Exista vreo solutie?
#2
Postat 07 January 2015 - 08:03 PM
In acelasi punct ai presiune in permanenta schimbare dupa cum e vremea, insorita sau furtuna.
De asta sistemele de altitudine bazate pe presiune se reseteaza la punctul de plecare si se calculeaza diferentiala fata de acel punct, si cu corectii de temperatura permanente.
In articolul asta ai mai detaliata pobestea:
https://www.sparkfun.com/tutorials/253
Aceasta postare a fost editata de renatoa: 07 January 2015 - 08:06 PM
#3
Postat 08 January 2015 - 09:53 AM
moro696, la 07 January 2015 - 07:33 PM, a spus:
uita de inaltimea absoluta. dupa cum a spus si renato, presiunea atmosferica e in continua modificare, in functie de vreme.
cand pornesti jucaria, iei primele valori drept nivel zero, dupa care calculezi altitudinea relativa fata de punctul de zero.
/------------------------\ |~~\_____/~~\__ | | Hash84 |______________ \______====== )-+ | | ~~~|/~~ | \------------------------/ ()
#6
Postat 10 January 2015 - 01:50 AM
moro696, la 09 January 2015 - 09:05 AM, a spus:
La inceput fac o medie de 10 masuratori, apoi iau aceea valoare drept "bias"
Si in bucla tot timpul fac asa altitutinea reala = altitudine masurata - bias
Asa am o abatere de maxim 0.5- 1 metru cu senzorul pe birou.
De ce faci 10 masuratori la inceput ?
Intre momentul de START citire si CITIREA efectiva a valorii trebuie o pauza in program. La BMP085 nu ai voie sa ai asa abateri mari!
Ce limbaj de programare folosesti ?
#7
Postat 10 January 2015 - 08:31 AM
DigitAll, la 10 January 2015 - 01:50 AM, a spus:
Intre momentul de START citire si CITIREA efectiva a valorii trebuie o pauza in program. La BMP085 nu ai voie sa ai asa abateri mari!
Ce limbaj de programare folosesti ?
Cam aceasi experienta o am si eu, BMP085 are "zgomot" mare, in sensul ca mai multe citiri repetate iti dau valori intr-o plaja de pana la 1m, de asta se face o mediere coontinua (running average) intre ultimele 10 citiri ca sa ai ceva utilizabil. Precizia/rezolutia teoretica de 25 cm in modul 16 biti nu am atins-o niciodata.
Adica se fac 10 citiri, se face media, apoi a 11a citire, se elimina citirea 1 si se face media de la 2 la 11, samd.
Posibil colegul sa nu aiba burete pus peste senzor si atunci si daca respira langa el conteaza :)
Aceasta postare a fost editata de renatoa: 10 January 2015 - 08:32 AM
#8
Postat 10 January 2015 - 11:22 AM
Daca citirile se fac consecutiv fara pauze intre ele, erorile sunt f mari.
Daca este obligatorie o medie a 10 masuratori, atunci acest senzor nu corespunde scopului propus...
#10
Postat 11 January 2015 - 06:20 PM
Pana la urma n-am mai facut masuratorile cu medie de 10, pentru ca rezultatul este acelasi.
Senzorul este configurat pe rezolutia cea mai inalta ( oss = 3 )
Citeaza
De aceea folosesc pinul senzorului ( EOC - end of conversion) atat pt temperatura cat si presiune, pe oss=3 conversia dureaza in jur de 30ms
Bun pontul cu buretele, ma gandeam la un moment dat sa il pun intr-un fel de minge de pinpong cu o gaurica mica in el.
O sa incerc si faza cu buretele
Limbajul este scris in C , ca si compilator/ide folosesc iar ewarm .
Libraria bmp085.c pe care o folosesc in main.c de mai jos
#define rAddr 0xEF #define wAddr 0xEE #define oss 3 void bmp085_intENABLE(void){ GPIO_InitTypeDef GPIO_InitStruct; EXTI_InitTypeDef EXTI_InitStruct; NVIC_InitTypeDef NVIC_InitStruct; RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOE, ENABLE); RCC_APB2PeriphClockCmd(RCC_APB2Periph_SYSCFG, ENABLE); /* Set pin as input PE1 */ GPIO_InitStruct.GPIO_Mode = GPIO_Mode_IN; GPIO_InitStruct.GPIO_OType = GPIO_OType_PP; GPIO_InitStruct.GPIO_Pin = GPIO_Pin_1; GPIO_InitStruct.GPIO_PuPd = GPIO_PuPd_UP; GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init(GPIOE, &GPIO_InitStruct); /* Tell system that you will use PE1 for EXTI_Line1 */ SYSCFG_EXTILineConfig(EXTI_PortSourceGPIOE, EXTI_PinSource1); EXTI_InitStruct.EXTI_Line = EXTI_Line1; /* PE1 is connected to EXTI_Line1 */ EXTI_InitStruct.EXTI_LineCmd = ENABLE; /* Enable interrupt */ EXTI_InitStruct.EXTI_Mode = EXTI_Mode_Interrupt; /* Interrupt mode */ /* Triggers on rising and falling edge */ EXTI_InitStruct.EXTI_Trigger = EXTI_Trigger_Rising;//EXTI_Trigger_Falling; EXTI_Init(&EXTI_InitStruct); /* Add IRQ vector to NVIC */ /* PE1 is connected to EXTI_Line1, which has EXTI1_IRQn vector */ NVIC_InitStruct.NVIC_IRQChannel = EXTI1_IRQn; /* Set priority */ NVIC_InitStruct.NVIC_IRQChannelPreemptionPriority = 1; /* Set sub priority */ NVIC_InitStruct.NVIC_IRQChannelSubPriority = 2; /* Enable interrupt */ NVIC_InitStruct.NVIC_IRQChannelCmd = ENABLE; /* Add to NVIC */ NVIC_Init(&NVIC_InitStruct); } void bmp085_tempMeasurement_trigger(void){i2c_send_cmd2(wAddr,0xF4,0x2E);} void bmp085_presureMeasurement_trigger(void){i2c_send_cmd2(wAddr,0xF4,(0x34+(oss<<6)));} int32_t fRegs[11]={0,0,0,0,0,0,0,0,0,0,0}; int32_t AC2,AC3,MB,MC,MD,B1,B2; uint16_t AC5,AC6,AC4; int16_t AC1=0; void bmp085_calib_registers(){ int8_t bmpReg[11]={0xAA, 0xAC, 0xAE, 0xB0, 0xB2, 0xB4,0xB6, 0xB8, 0xBA,0xBC, 0xBE}; for(int gg=0;gg<11;gg++){ i2c_start_com2(); i2c_wrAddr2(wAddr); i2c_Wrbyte2(bmpReg[gg]); I2C2->CR1 |= I2C_CR1_STOP; i2c_start_com2(); i2c_rdAddr2(rAddr); uint8_t rMSB = i2c_rdAck2(); uint8_t rLSB = i2c_rdNack2(); I2C2->CR1 |= I2C_CR1_STOP; int16_t rr=(rMSB<<8)+rLSB; fRegs[gg]=rr; rr=0; } AC1=fRegs[0]; AC2=fRegs[1]; AC3=fRegs[2]; AC4=fRegs[3]; AC5=fRegs[4]; AC6=fRegs[5]; B1=fRegs[6]; B2=fRegs[7]; MB=fRegs[8]; MC=fRegs[9]; MD=fRegs[10]; } long get_bmp085_ut(){ i2c_send_byte2(0xEE,0xF6); i2c_read2(0xEF); uint8_t tMSB = i2c_rdAck2(); uint8_t tLSB = i2c_rdNack2(); I2C2->CR1 |= I2C_CR1_STOP; long UT=(tMSB<<8)+tLSB; return UT; } long get_bmp085_up(){ i2c_send_byte2(0xEE,0xF6); i2c_read2(0xEF); uint8_t hMSB = i2c_rdAck2(); uint8_t lMSB = i2c_rdNack2(); I2C2->CR1 |= I2C_CR1_STOP; i2c_send_byte2(0xEE,0xF8); i2c_read2(0xEF); uint16_t pLSB = i2c_rdNack2(); I2C2->CR1 |= I2C_CR1_STOP; long UP = ((hMSB<<16)+(lMSB<<8)+pLSB)>>(8-oss); return UP; } double altitude; float altbuf; void bmp_calc_temp_pressure(long UP, long UT,int cnt,double bias, double *myalti,double *mytemp){ int32_t X1,X2,X3,B3,B5,B6; uint32_t B4, B7; int32_t pp,tt; X1 = (UT - AC6) * (AC5) >> 15; X2 = ((int32_t)MC << 11) / (X1+MD); X1=(UT-AC6)*AC5>>15; X2=(MC<<11)/(X1+MD); B5=X1+X2; tt=(B5+8)>>4; *mytemp=(double)tt/10; B6 = B5 - 4000; X1 = (B2 * ( (B6 * B6)>>12 )) >> 11; X2 = (AC2 * B6) >> 11; X3 = X1 + X2; B3 = (((AC1*4 + X3) << oss) + 2) / 4; X1 = (AC3 * B6) >> 13; X2 = (B1 * ((B6 * B6) >> 12)) >> 16; X3 = ((X1 + X2) + 2) >> 2; B4 = (AC4 * (X3 + 32768)) >> 15; B7 = (UP - B3) * ( 50000UL >> oss ); if (B7 < 0x80000000) { pp = (B7 * 2) / B4;} else { pp = (B7 / B4) * 2; } X1 = (pp >> 8) * (pp >> 8); X1 = (X1 * 3038) >> 16; X2 = (-7357 * pp) >> 16; pp = pp + ((X1 + X2 + (int32_t)3791)>>4); /// presure in Pascals altitude = 1 - pow( (((float)pp/100)/1013.25),0.1903 ); altitude *=44330; *myalti=altitude; } void bmp_setZero(double *bias){ double myt,myp; bmp085_tempMeasurement_trigger(); delay_ms(7); long ttt=get_bmp085_ut(); bmp085_presureMeasurement_trigger(); delay_ms(30); long rrrt=get_bmp085_up(); bmp_calc_temp_pressure(rrrt,ttt,0,0,&myp,&myt); *bias=myp; } float trueAltitude(float bias, float real){ float altitude1=real-bias; return altitude1; }
Si main program
void EXTI1_IRQHandler(void) { // Make sure that interrupt flag is set if (EXTI_GetITStatus(EXTI_Line1) != RESET) { if(bmpf==4){bmpf=5; } else { bmpf=2; } EXTI_ClearITPendingBit(EXTI_Line1);// Clear interrupt flag } } int main(void){ bmp085_calib_registers(); // citesc registrii senzorului bmp_setZero(&bBias); // setez biasul bmp085_intENABLE(); // pornesc pinul pt intreruperea EOC while(1){ if(bmpf==0){ bmp085_tempMeasurement_trigger(); bmpf=1; } if((bmpf==2)){ UT=get_bmp085_ut(); bmpf=3; } if(bmpf==3){ bmpf=4; bmp085_presureMeasurement_trigger(); } if(bmpf==5){ UP=get_bmp085_up(); bmp_calc_temp_pressure(UP,UT,1,bBias,&myalti,&mytemp); bmpf=0;} sprintf(txt67,"%0.1f",mytemp ); sprintf(txt66,"%0.1f",trueAltitude(bBias,myalti)); } }