Anda di halaman 1dari 9

06/01/2016

ReadingtheBMP180pressuresensorwithanAttiny85|Arduino

Arduino
Arduinoandrelatedstuff
ArduinoinAttiny

May26,2015August3,2015

2,034Words

ReadingtheBMP180pressuresensorwith
anAttiny85
TheBMP180pressuresensorisarelativelycheapandpopularsensortoreadatmospheric
pressure.Additionallyitcanreadtemperature.
Ifyouwanttousethissensoronanarduino,Adafruithasalibrary(fortheBMP085andthe
BMP180)thatwilreaditforyou.However,thenewlibraryalsoneedstheirgeneralSensor
libraryandthosearememoryguzzlers.PerhapsOKonanArduino,butnotonanattiny.They
dohaveonefortheTiny85aswell(https://github.com/cano64/ATTiny85ATTiny84BMP085
ArduinoLibraryFastAltitude/blob/master/tinyBMP085.cpp).Sparkfunalsohasalibrary
(https://learn.sparkfun.com/tutorials/bmp180barometricpressuresensorhookup)forthe
Arduino.
Furthermore,theBMP180isanI2CdeviceandI2CisnotastandardontheAttinyseries.
So,ifyouwanttoreadtheBMP180sensoronanattiny,youwouldneedtodosomework
yourself.
Fortunately,thedatasheet(http://www.adafruit.com/datasheets/BSTBMP180DS00009.pdf)is
veryveryclear.Page15tellsusexactlywhattodo.
Thesequenceisasfollows:
1Readthechipspecificcalibrationdata
2Readtheuncorrectedtemparaturevalue
3Readtheuncorrectedpressurevalue
4Calculatetruetemperature
5calculatetruepressure
Italsoshowsyouwhatshouldbeinaloopandwhatnot:
readingthecalibrationdataonlyneedstobedoneonceandthereforegoesintheSetup
routine.Therestisinaloopandthereforegoesinthelooproutine.
So,programmingisabreezeifyoufollowtheflowchartonpage15.weonlyneedto
translatethatintolanguagetheI2Cprotocolunderstands.
Wethereforestarttheprogramwithdefiningsomegeneralparameters:
FortheAttinythereistheTinyWireMlibrarythatimplementsanI2Cprotocolontheattiny,so
weneedtoloadthatlibrary.

https://arduinodiy.wordpress.com/2015/05/26/readingthebmp180pressuresensorwithanattiny85/

1/9

06/01/2016

ReadingtheBMP180pressuresensorwithanAttiny85|Arduino

weneedtoloadthatlibrary.
WeneedtheI2CaddressoftheBMP180(whichis0x77),andweneedtodeclareawholebunch
ofvariables.Mostofthevariablesusedwillcontainthechipspecificcalibrationdatathatwe
willbereadingfromthechipsEEPROM,wewillneedsomevariablesforthevarious
calculationsandwewillneedsomevariablestocontaintheoutput(temperatureandpressure)
Tokeepiteasy,Ihavechosennamesforthevariablesasmentionedinthedatasheet.
So,thefirstlinesofaprogramwilllooklikethis:

//TheconnectionforAttiny&BMP180areSDApin5,SCLpin7forI2
C
#include<TinyWireM.h>
#defineBMP180_ADDRESS0x77//I2CaddressofBMP180
//definecalibrationdatafortemperature:
intac1;
intac2;
intac3;
unsignedintac4;
unsignedintac5;
unsignedintac6;
intb1;
intb2;
intmb;
intmc;
intmd;
longb5;
//definevariablesforpressureandtemperaturecalculation
longx1,x2;
//definevariablesforpressurecalculation
longx3,b3,b6,p;
unsignedlongb4,b7;
//definevariablesfortemperatureandpressurereading
shorttemperature;
longpressure;
constunsignedcharOSS=0;//OversamplingSetting
/*blz12Datasheet
OSS=0ultraLowPowerSetting,1sample,4.5ms3uA
OSS=1StandardPowerSetting,2samples,7.5ms5uA
OSS=2HighResolution,4samples,13.5ms7uA
OSS=3UltraHighResolution,2samples,25.5ms12uA
*/

ThenwehavetodefinetheSetuproutine.Frankly,theonlythingwehavetodothereisread
thecalibrationdata.Tokeepitsimple,iwilljustcallaprocedurebmp180ReadInt(address),
whichwethencanimplementlater.
OurSetupthereforewilllooklikethis:
https://arduinodiy.wordpress.com/2015/05/26/readingthebmp180pressuresensorwithanattiny85/

2/9

06/01/2016

ReadingtheBMP180pressuresensorwithanAttiny85|Arduino

voidsetup(){
//FirstreadcalibrationdatafromEEPROM
ac1=bmp180ReadInt(0xAA);
ac2=bmp180ReadInt(0xAC);
ac3=bmp180ReadInt(0xAE);
ac4=bmp180ReadInt(0xB0);
ac5=bmp180ReadInt(0xB2);
ac6=bmp180ReadInt(0xB4);
b1=bmp180ReadInt(0xB6);
b2=bmp180ReadInt(0xB8);
mb=bmp180ReadInt(0xBA);
mc=bmp180ReadInt(0xBC);
md=bmp180ReadInt(0xBE);
}

OfcourseIcouldhavejustcalled1procedureandcallthatbmp180ReadCalibrationbutthat
procedurethenwoulddothesameasInowdefinedalreadyinthesetup
Theloopprocedureisequallysimple.Itisbasically
Readuncorrectedtemperature
Correctthatuncorrectedtemperature
Readuncorrectedpressure
Correctthatuncorrectedpressure
Butasnooneisinterestedintheuncorrecteddata,wemakethatprocedure:
Correct(ReadUncorrectedtemperature)
Correct(ReadUncorrectedpressure)
likethis:

voidloop(){
//first,readuncompensatedtemperature
//temperature=bmp180ReadUT();
//andthencalculatecalibratedtemperature
temperature=bmp180CorrectTemperature(bmp180ReadUT());
//then,readuncompensatedpressure
//pressure=bmp180ReadUP();
//andthencalculatecalibratedpressure
pressure=bmp180CorrectPressure(bmp180ReadUP());

Sothatisit.Wenowonlyhavetodefinetheproceduresthatwecall.
Wewillstartwithbmp180ReadInt(address)
ThisprocedurewillusetheTinyWireMlibrarytoreadanintegerfromagivenaddress.In
gettingdatafromanI2Cdevice,thegeneralruleistofirstwritetothatdevicetotellitwhatto3/9

https://arduinodiy.wordpress.com/2015/05/26/readingthebmp180pressuresensorwithanattiny85/

06/01/2016

ReadingtheBMP180pressuresensorwithanAttiny85|Arduino

gettingdatafromanI2Cdevice,thegeneralruleistofirstwritetothatdevicetotellitwhatto
doandthentoreadataspecificaddressfortheoutcome.Aswewillbereadingfromthe
EEPROMthereisnospecificcommandwehavetosend,otherthantonotifytheI2Cport
wherewewanttobe(attheI2Caddressofthechip)andsendtheaddresswewanttoreadand
howmanybyteswewanttoread.Wethencombinethosetwobutesinanintegerandreturn
that.
Ourprecedurewillthuslooklikethis:

intbmp180ReadInt(unsignedcharaddress)
{
unsignedcharmsb,lsb;
TinyWireM.beginTransmission(BMP180_ADDRESS);
TinyWireM.send(address);
TinyWireM.endTransmission();
TinyWireM.requestFrom(BMP180_ADDRESS,2);
while(TinyWireM.available()<2);
msb=TinyWireM.receive();
lsb=TinyWireM.receive();
return(int)msb<<8|lsb;
}

Thenextprocedureweneedistoreadtheuncompensatedtemperature.Togetthatwehaveto
firstsendthevalueof0x2Etoregister0xF4andwaitatleast4.5msec.Thatisthetimethechip
needstotake1reading.Afterwewaitedwewillreadtheuncompensatedtemperaturefrom
registers0xF6and0xf7.Thatlastreadwedowiththeearlierdefinedbmp180ReadInt
procedurethatreads2bytesandcombinesthemintoaninteger.
Theprocedurethuswilllooklikethis:

https://arduinodiy.wordpress.com/2015/05/26/readingthebmp180pressuresensorwithanattiny85/

4/9

06/01/2016

ReadingtheBMP180pressuresensorwithanAttiny85|Arduino

unsignedintbmp180ReadUT()
{
unsignedintut;

//Write0x2EintoRegister0xF4andwaitatleast4.5mS
//Thisrequestsatemperaturereading
//withresultsin0xF6and0xF7
TinyWireM.beginTransmission(BMP180_ADDRESS);
TinyWireM.send(0xF4);
TinyWireM.send(0x2E);
TinyWireM.endTransmission();

//Waitatleast4.5ms
delay(5);

//Thenreadtwobytesfromregisters0xF6(MSB)and0xF7(LSB)
//andcombineasunsignedinteger
ut=bmp180ReadInt(0xF6);
returnut;
}

Subsequentlywehavetocalculatethecorrectedtemperaturefromtheuncorrected
temperature.
Thedatasheetdefinesthatasfollows:
UT=uncompensatedtemperature
X1=(UTAC6)*AC5/2^15
X2=(MC*2^11/(X1+MD)
B5=X1+X2
T=(B5+8)/2^4
insoftwarethatlookslikethis

doublebmp180CorrectTemperature(unsignedintut)
{
x1=(((long)ut(long)ac6)*(long)ac5)>>15;
x2=((long)mc<<11)/(x1+md);
b5=x1+x2;
return(((b5+8)>>4));
}

Wellthetemperatureisdone,nowweneedtoreadtheuncompensatedpressure.Forthatwe
needtowritethevalue0x34intheregister0xF4,butwealsohavetosetthevaluevorthe
oversamplingrate.
Theoversamplingratedeterminestheamountofsamplesthechipneedstomakebeforegiving
aresult.
Page4ofthedatasheettellswehave4choices:

https://arduinodiy.wordpress.com/2015/05/26/readingthebmp180pressuresensorwithanattiny85/

5/9

06/01/2016

ReadingtheBMP180pressuresensorwithanAttiny85|Arduino

Page4ofthedatasheettellswehave4choices:
OSS=0ultraLowPowerSetting,1sample,4.5ms3uA
OSS=1StandardPowerSetting,2samples,7.5ms5uA
OSS=2HighResolution,4samples,13.5ms7uA
OSS=3UltraHighResolution,12samples,25.5ms12uA
ForthisprogramIhavechosentheOSStobe0
TheOSScontainsbits6and7inregister0xF4.Bit04determinethecontrolofthe
measurement.
ifwewritethevalue0x34thatisinbinary:00110100.Bits0to4arenotsoimportantfornow,
butbit5willalsobesetandthusstarttheconversion.Itwillstayhighduringtheconversion
andresettoLOWaftertheconversion.Inordertosetthebits6andor7wehavetoleftshift6
thevalueofOSS.SupposewehadwantedtosetOSSas3.inbinarythatis0b11ifweleftshift6
that,itwillbe11000000(=192dor0xC0),whichwillsetbits6and7.
0x34+0xC0=0xF4=0b11110100whichaswecanseeisthesameas0x34plusbit6and7set.
Asweareusing0fortheOSSvalue,bothbit6and7willnotbeset.
afterwestarttheconversionwehavetowaitbetween4.5and25.5msecs(dependingonOSS).
AswehaveOSS=0wewillwait5msec.
Subsequentlywewillread3bytesasthetemperatureisalong(4bytes)notaninteger,we
willhoweveronlyneed3bytes.
Withregardtothedelay,itwouldbeniceifwewilldefineitasadependencyoftheOSSso
youdonotneedtomanuallychangeitwhenyouchangetheOSS.TheAdafruitlibrarysolevs
thiswithsomeIFstatements:
if(oversampling==BMP085_ULTRALOWPOWER)
delay(5);
elseif(oversampling==BMP085_STANDARD)
delay(8);
elseif(oversampling==BMP085_HIGHRES)
delay(14);
else
delay(26);
However,Ihopedtofindaformulathatwilldetermineit.Asitisntastrictlinearfunction,the
closestonegetsistheformula:5+(OSS*5).
OSS=0>5
OSS=1>10
OSS=2>15
OSS=3>25
Well,Iguessthatwouldbecloseenough
Theprocedureisasfollows

https://arduinodiy.wordpress.com/2015/05/26/readingthebmp180pressuresensorwithanattiny85/

6/9

06/01/2016

ReadingtheBMP180pressuresensorwithanAttiny85|Arduino

/
//Readtheuncompensatedpressurevalue
unsignedlongbmp180ReadUP()
{
unsignedcharmsb,lsb,xlsb;
unsignedlongup=0;

//Write0x34+(OSS<<6)intoregister0xF4
//Requestapressurereadingw/oversamplingsetting
TinyWireM.beginTransmission(BMP180_ADDRESS);
TinyWireM.send(0xF4);
TinyWireM.send(0x34+(OSS<<6));
TinyWireM.endTransmission();

//Waitforconversion,delaytimedependentonOSS
delay(5+(5*OSS));

//Readregister0xF6(MSB),0xF7(LSB),and0xF8(XLSB)
TinyWireM.beginTransmission(BMP180_ADDRESS);
TinyWireM.send(0xF6);
TinyWireM.endTransmission();
TinyWireM.requestFrom(BMP180_ADDRESS,3);

//Waitfordatatobecomeavailable
while(TinyWireM.available()<3)
;
msb=TinyWireM.receive();
lsb=TinyWireM.receive();
xlsb=TinyWireM.receive();

up=(((unsignedlong)msb<<16)|((unsignedlong)lsb<<8)|(un
signedlong)xlsb)>>(8OSS);

returnup;
}

Nowthatisdone,weneedtocorrecttheuncompensatedpressure.TheresultwillbeinPascal

https://arduinodiy.wordpress.com/2015/05/26/readingthebmp180pressuresensorwithanattiny85/

7/9

06/01/2016

ReadingtheBMP180pressuresensorwithanAttiny85|Arduino

doublebmp180CorrectPressure(unsignedlongup)
{
b6=b54000;
//CalculateB3
x1=(b2*(b6*b6)>>12)>>11;
x2=(ac2*b6)>>11;
x3=x1+x2;
b3=(((((long)ac1)*4+x3)<<OSS)+2)>>2;

//CalculateB4
x1=(ac3*b6)>>13;
x2=(b1*((b6*b6)>>12))>>16;
x3=((x1+x2)+2)>>2;
b4=(ac4*(unsignedlong)(x3+32768))>>15;

b7=((unsignedlong)(upb3)*(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;

returnp;
}

Withtheaboveprogramonecandecideforoneselfwhattodowiththefounddata:either
sendittoadisplay,orperhapssenditviaanRFlinktoabasestation.
Assaid,theoutputofthepressurereadingisinPascal(Pa).hectoPascalsareamoreconvenient
unit.Someotherunitsitcanbecalculatedinare:
1hPa=100Pa=1mbar=0.001bar
1hPa=0.75006168Torr
1hPa=0.01450377psi(poundspersquareinch)
1hPa=0.02953337inHg(inchesofmercury)
1hpa=0.00098692atm(standardatmospheres)
Onelastadvicestill:WhenyouusetheBMP180,rememberitneeds3.3Volt.5Voltwillkillit.
UsingitontheI2Cfroma5Voltmicrocontrollershouldnotcauseaproblemthough.Various
breakoutboardsactuallydohavea3.3Voltageregulatoronit.
Warning
WhenIwantedtodisplaythevaluesfoundbytheBMP180,IgrabbedatwowireLCD
interfacethatIahdbuildwitha164ShiftRegister.Isubsequentlytriedtofigureoutforseveral
https://arduinodiy.wordpress.com/2015/05/26/readingthebmp180pressuresensorwithanattiny85/
8/9
hourswhyIwasntgettinganydecentreadout.Infact,thereadoutdidntchangewetherI

06/01/2016

ReadingtheBMP180pressuresensorwithanAttiny85|Arduino

hourswhyIwasntgettinganydecentreadout.Infact,thereadoutdidntchangewetherI
connectedtheBMP180ornot.AftermanymanytrialsIstartedtosuspectmydisplayinterface
anddecidedtohookupanI2CLCD.Thatworkedlikeacharm.
TheLiquidCrystal_I2CfromFranciscoMalpertidadoesntworkontheAttiny85.Iusedthe
classicLiquidCrystal_I2CthatisadaptedbyBroHogantoworkontheAttiny85aswell.
Hedidthatbychangingtheline:
#include<Wire.h>
into
#ifdefined(__AVR_ATtiny85__)||(__AVR_ATtiny2313__)
#include"TinyWireM.h"//includethisifATtiny85orATtiny2313
#else
#include<Wire.h>//originallibinclude
#endif
About these ads (https://wordpress.com/about-these-ads/)

Tagged:
BMP180

OnethoughtonReadingtheBMP180pressure
sensorwithanAttiny85
Pingback: I2C|werbasteltmit?

BlogatWordPress.com.|TheIndependentPublisherTheme.

https://arduinodiy.wordpress.com/2015/05/26/readingthebmp180pressuresensorwithanattiny85/

9/9

Anda mungkin juga menyukai