Notice. New forum software under development. It's going to miss a few functions and look a bit ugly for a while, but I'm working on it full time now as the old forum was too unstable. Couple days, all good. If you notice any issues, please contact me.
|
Forum Index : Microcontroller and PC projects : Micromite MK2: BMP180 pressure sensor
Author | Message | ||||
matherp Guru Joined: 11/12/2012 Location: United KingdomPosts: 8592 |
I'm converting a bunch of code from picaxe to micromite. Basically, given the new features in the micromite version 4.6, I'm going to give up using the larger picaxe chips. The smaller 08M2 and 14M2 will still have a use but I can no longer see any reason to use any of the bigger ones. Given that I will slowly convert some of my picaxe code across. To handle the BMP180 pressure and temperature sensor on the picaxe required writing a multiple precision integer library for it (works but slow). On the micromite it is trivial . If is is useful I will post code as I convert, but please let me know if I am just jamming up the board. I think it would be useful to have a separate forum for code snippets and complete programs - any chance? I've used a couple of trivial cFunctions in the code (really just because they are available, the c code is included as comments) but it could easily have been done just in basic. Best Regards Peter cpu 48 OPTION EXPLICIT OPTION DEFAULT INTEGER const i2caddr=&B1110111 const MS7=7 'set default wait period const signed=1 const unsigned=0 ' dim i2cin$ length 8 'max size for integer conversion dim UT,UP,i,j dim ac1,ac2,ac3,ac4,ac5,ac6,b1,b2,mb,mc,md 'bmp180 parameters dim x1,x2,b5,b6,x3,b3,b4,b7,OSS dim temperature,pressure DIM altitude as float dim OSSdata(4) dim OSSscale(4) I2C OPEN 100,1000 init: OSS=1 'set oversampling ratio ' OSS=0 ' Uncomment this line to check algorithm against datasheet OSSdata(0)=&H34 OSSdata(1)=&H74 OSSdata(2)=&HB4 OSSdata(3)=&HF4 OSSscale(0)=1 OSSscale(1)=2 OSSscale(2)=4 OSSscale(3)=8 I2C WRITE i2caddr,1,1,&HAA 'send read calibration data command I2C READ i2caddr,0,22,i2cin$() 'read in calibration data ac1=intconv(mid$(i2cin$,1,2),signed) ac2=intconv(mid$(i2cin$,3,2),signed) ac3=intconv(mid$(i2cin$,5,2),signed) ac4=intconv(mid$(i2cin$,7,2),unsigned) ac5=intconv(mid$(i2cin$,9,2),unsigned) ac6=intconv(mid$(i2cin$,11,2),unsigned) b1=intconv(mid$(i2cin$,13,2),signed) b2=intconv(mid$(i2cin$,15,2),signed) mb=intconv(mid$(i2cin$,17,2),signed) mc=intconv(mid$(i2cin$,19,2),signed) md=intconv(right$(i2cin$,2),signed) ' ' Uncomment this block to check algorithm against datasheet ' ' AC1=408 ' AC2=-72 ' AC3=-14383 ' AC4=32741 ' AC5=32757 ' AC6=23153 ' B1=6190 ' B2=4 ' MB=-32768 ' MC=-8711 ' MD=2868 main: I2C WRITE i2caddr,0,2,&HF4,&H2E 'send temp conversion pause MS7 'wait for temperature conversion I2C WRITE i2caddr,1,1,&HF6 'send read data I2C READ i2caddr,0,2,i2cin$() 'read 2 bytes UT=intconv(i2cin$,unsigned) ' UT=27898 ' Uncomment this line to check algorithm against datasheet I2C WRITE i2caddr,0,2,&HF4,ossdata(oss) 'send pressure conversion pause (oss+1)*ms7 'wait for the pressure conversion I2C WRITE i2caddr,1,1,&HF6 'send read data I2C READ i2caddr,0,3,i2cin$() 'read 3 bytes UP=intconv(i2cin$,unsigned) up=up>>(8-oss) 'scale the output by the number of unused bits in the xlsb byte ' UP=23843' Uncomment this line to check algorithm against datasheet calc_temp calc_pressure print "Temperature = ",str$(temperature/10,4,1),"Deg C" print "Local Pressure = ",str$(pressure/100,4,1),"Hectopascal/Mb" input "Altitude in meters? ",Altitude print "Sea level pressure = ",str$(pressure/((1-(altitude/44330))^5.255)/100,4,1),"Hecto pascal/Mb" end ' ' calc_temperature: calculate the temperature from the raw temperature given the calibration parameters ' sub calc_temp: X1=(UT-AC6)*AC5\powerof2(15) X2=MC*powerof2(11)/(X1+MD) 'This needs to be a floating divide to match the datasheet B5=X1+X2 temperature=(B5+8)\powerof2(4) end sub ' ' calc_pressure: calculate the pressure from the raw pressure given the calibration parameters and temperature output ' sub calc_pressure: B6=b5-4000 x1=(b2*(b6*b6/powerof2(12)))\powerof2(11) x2=ac2*b6\powerof2(11) x3=x1+x2 b3=(((ac1*4+x3)*ossscale(oss))+2)\4 X1=AC3*B6\POWEROF2(13) X2=(B1*(B6*B6/POWEROF2(12)))\POWEROF2(16) x3=((x1+x2)+2)\4 b4=ac4*(abs(x3+32768))\powerof2(15) b7=abs(up-b3)*(50000\ossscale(oss)) pressure=(b7*2)\b4 x1=(pressure\powerof2(8))*(pressure\powerof2(8)) x1=(x1*3038)\powerof2(16) x2=(-7357*pressure)\powerof2(16) pressure=pressure+(x1+x2+3791)\powerof2(4) end sub ' 'cFunctions source and binary ' 'unsigned long long intconv(unsigned char innumber[],unsigned int *signednum){ ' int i,j; ' union utype{ ' unsigned long long b; ' unsigned char a[8]; ' }u; ' u.b=0; ' j=innumber[0];//get the number of bytes ' for(i=1;i<=innumber[0];i++)u.a[j-i] =innumber; ' if (*signednum){i=u.a[j-1] & 0x80;//get the top bit ' if(i){ ' for( ;j<=7;j++)u.a[j]=0xFF;//sign extend ' } ' } ' return u.b; '} 'unsigned long long powerof2(unsigned int *power){ ' int octet,place; ' union utype{ ' unsigned long long b; ' unsigned char a[8]; ' }u; ' u.b=0; ' octet=*power/8; ' place=*power-(octet*8); ' u.a[octet]=1<<place; ' return u.b; '}' CFunction intconv 00000000 27bdfff8 00001021 00001821 afa20000 afa30004 90880000 1900000b 01003821 2503ffff 03a31821 24020001 00823021 90c60000 a0660000 24420001 00e2302a 10c0fffa 2463ffff 8ca20000 1040000d 03a81021 9042ffff 30420080 10400009 29020008 10400007 03a81021 27a40008 2403ffff a0430000 24420001 5444fffe a0430000 8fa20000 8fa30004 03e00008 27bd0008 End CFunction ' CFunction powerof2 00000000 27bdfff8 00001021 00001821 afa20000 afa30004 8c820000 000218c2 03a32021 000318c0 00431023 24030001 00431004 a0820000 8fa20000 8fa30004 03e00008 27bd0008 End CFunction |
||||
G8JCF Guru Joined: 15/05/2014 Location: United KingdomPosts: 676 |
Go for it. The more code there is in the public domain, the better. Peter The only Konstant is Change |
||||
twofingers Guru Joined: 02/06/2014 Location: GermanyPosts: 1133 |
Hello PeterM, I didn't try, but the code looks good! Well done! I think many (!) people appreciate your examples. If I had a wish free, then I would have a separate forum for bug reporting only. (beta testers). Regards Michael Edit: @Peter C., full ack! |
||||
paceman Guru Joined: 07/10/2011 Location: AustraliaPosts: 1328 |
@matherp, I've just ordered a BMP180 module Peter and I'm looking forward to be able to give your code a go when the module arrives - unfortunately that's usually 3 or 4 weeks away. At least it'll give me time to (hopefully) get my head around the conversion to altitude because I'd like to check it against the altimeter in my brother-in-law' light plane when I visit them early next year. Greg |
||||
matherp Guru Joined: 11/12/2012 Location: United KingdomPosts: 8592 |
paceman The routines for converting measured pressure (Hpa) to altitude (in feet) given a known sea-level pressure are: function calcaltitude(sealevelpressure, localpressure) calcaltitude=((10^(log10(localpressure/sealevelpressure)/5.2 558797))-1)/-6.8755856 *1000000 end function ' function log10(x) log10=log(x)/2.302585093 end function You will see that the calcaltitude function is independent of the pressure units as it only relies on the ratio of pressures. There is bug in 4.6b21 that Geoff knows about relating to passing floats to functions when OPTION DEFAULT INTEGER is defined so these routines can only currently be used if the default datatype is FLOAT To get round this I've modified the original program to work by explicitly defining all the integer variables using the % syntax. I've also included the altitude calculation code and the program now derives your altitude from the current sea-level pressure (in aviation this is known as QNH). This is attached below. This should be more useful for your test Best Regards Peter cpu 48 OPTION EXPLICIT OPTION DEFAULT FLOAT const i2caddr=&b1110111 const MS7=7 'set default wait period const signed=1 const unsigned=0 ' dim i2cin$ length 8 'max size for integer conversion dim UT%,UP% dim ac1%,ac2%,ac3,ac4%,ac5%,ac6%,b1%,b2%,mb%,mc%,md% 'bmp180 parameters dim x1%,x2%,b5%,b6%,x3,b3%,b4%,b7%,OSS% dim temperature%,pressure% DIM altitude,QNH,pressureinHpa dim OSSdata%(4) dim OSSscale%(4) I2C OPEN 400,1000 init: OSS%=1 'set oversampling ratio ' OSS%=0 ' Uncomment this line to check algorithm against datasheet OSSdata%(0)=&H34 'commands to sample pressure% with different levels of oversampling OSSdata%(1)=&H74 OSSdata%(2)=&Hb4 OSSdata%(3)=&HF4 OSSscale%(0)=1 'scale factors for calcs when oversampled OSSscale%(1)=2 OSSscale%(2)=4 OSSscale%(3)=8 ' I2C WRITE i2caddr,1,1,&HAA 'send read calibration data command I2C READ i2caddr,0,22,i2cin$() 'read in calibration data ac1%=intconv(mid$(i2cin$,1,2),signed) ac2%=intconv(mid$(i2cin$,3,2),signed) ac3=intconv(mid$(i2cin$,5,2),signed) ac4%=intconv(mid$(i2cin$,7,2),unsigned) ac5%=intconv(mid$(i2cin$,9,2),unsigned) ac6%=intconv(mid$(i2cin$,11,2),unsigned) b1%=intconv(mid$(i2cin$,13,2),signed) b2%=intconv(mid$(i2cin$,15,2),signed) mb%=intconv(mid$(i2cin$,17,2),signed) mc%=intconv(mid$(i2cin$,19,2),signed) md%=intconv(right$(i2cin$,2),signed) ' ' Uncomment this block to check algorithm against datasheet ' ' ac1%=408 ' ac2%=-72 ' AC3=-14383 ' ac4%=32741 ' ac5%=32757 ' ac6%=23153 ' b1%=6190 ' b2%=4 ' mb%=-32768 ' mc%=-8711 ' md%=2868 main: I2C WRITE i2caddr,0,2,&HF4,&H2E 'send temp conversion pause MS7 'wait for temperature% conversion I2C WRITE i2caddr,1,1,&HF6 'send read data I2C READ i2caddr,0,2,i2cin$() 'read 2 bytes UT%=intconv(i2cin$,unsigned) ' UT%=27898 ' Uncomment this line to check algorithm against datasheet I2C WRITE i2caddr,0,2,&HF4,ossdata%(oss%) 'send pressure% conversion pause (oss%+1)*ms7 'wait for the p ressure% conversion I2C WRITE i2caddr,1,1,&HF6 'send read data I2C READ i2caddr,0,3,i2cin$() 'read 3 bytes UP%=intconv(i2cin$,unsigned) UP%=UP%>>(8-oss%) 'scale the oUT%pUT% by the numb%er of unused bits in the xlsb byte ' UP%=23843' Uncomment this line to check algorithm against datasheet calc_temp calc_pressure pressureinHpa=pressure%/100 print "Temperature = ",str$(temperature%/10,4,1),"Deg C" print "Local pressure = ",str$(pressure%/100,4,1),"Hectopascal/mb" inpUT "QNH in Hpa/Mb ? ",QNH altitude=calcaltitude(QNH,pressureinHpa) print "Current altitude in feet = ",altitude print "Reverse calculate Sea level pressure = ",calcQNH(altitude,pressureinHpa),"Hectopascal/mb" end ' ' calc_temperature%: calculate the temperature% from the raw temperature% given the calibration parameters ' sub calc_temp: x1%=(UT%-ac6%)*ac5%\powerof2(15) x2%=mc%*powerof2(11)/(x1%+md%) 'This needs to be a floating divide to match the datasheet b5%=x1%+x2% temperature%=(b5%+8)\powerof2(4) end sub ' ' calc_pressure: calculate the pressure% from the raw pressure% given the calibration parameters and temperature% oUT%pUT% ' sub calc_pressure b6%=b5%-4000 x1%=(b2%*(b6%*b6%/powerof2(12)))\powerof2(11) x2%=ac2%*b6%\powerof2(11) x3=x1%+x2% b3%=(((ac1%*4+x3)*ossscale%(oss%))+2)\4 x1%=AC3*b6%\POWEROF2(13) x2%=(b1%*(b6%*b6%/POWEROF2(12)))\POWEROF2(16) x3=((x1%+x2%)+2)\4 b4%=ac4%*(abs(x3+32768))\powerof2(15) b7%=abs(UP%-b3%)*(50000\ossscale%(oss%)) pressure%=(b7%*2)\b4% x1%=(pressure%\powerof2(8))*(pressure%\powerof2(8)) x1%=(x1%*3038)\powerof2(16) x2%=(-7357*pressure%)\powerof2(16) pressure%=pressure%+(x1%+x2%+3791)\powerof2(4) end sub ' FUNCTION calcQNH(currentaltitude,localpressure) calcQNH=(localpressure*100)/((1-(currentaltitude*0.3048/4433 0))^5.255)/100 end function ' function log10(x) log10=log(x)/2.302585093 end function ' function calcaltitude(sealevelpressure, localpressure) local a as float, b as float calcaltitude=((10^(log10(localpressure/sealevelpressure)/5.2 558797))-1)/-6.8755856 *1000000 end function ' 'cFunctions source and binary ' 'unsigned long long intconv(unsigned char innumb%er[],unsigned int *signednum){ ' int i,j; ' union UT%ype{ ' unsigned long long b; ' unsigned char a[8]; ' }u; ' u.b=0; ' j=innumb%er[0];//get the numb%er of bytes ' for(i=1;i<=innumb%er[0];i++)u.a[j-i] =innumb%er; ' if (*signednum){i=u.a[j-1] & 0x80;//get the top bit ' if(i){ ' for( ;j<=7;j++)u.a[j]=0xFF;//sign extend ' } ' } ' return u.b; '} 'unsigned long long powerof2(unsigned int *power){ ' int octet,place; ' union UT%ype{ ' unsigned long long b; ' unsigned char a[8]; ' }u; ' u.b=0; ' octet=*power/8; ' place=*power-(octet*8); ' u.a[octet]=1<<place; ' return u.b; '}' CFunction intconv 00000000 27bdfff8 00001021 00001821 afa20000 afa30004 90880000 1900000b 01003821 2503ffff 03a31821 24020001 00823021 90c60000 a0660000 24420001 00e2302a 10c0fffa 2463ffff 8ca20000 1040000d 03a81021 9042ffff 30420080 10400009 29020008 10400007 03a81021 27a40008 2403ffff a0430000 24420001 5444fffe a0430000 8fa20000 8fa30004 03e00008 27bd0008 End CFunction ' CFunction powerof2 00000000 27bdfff8 00001021 00001821 afa20000 afa30004 8c820000 000218c2 03a32021 000318c0 00431023 24030001 00431004 a0820000 8fa20000 8fa30004 03e00008 27bd0008 End CFunction |
||||
paceman Guru Joined: 07/10/2011 Location: AustraliaPosts: 1328 |
Excellent Peter, that'll save me some serious headaches. Do you know how much QNH might typically change on say a one hour flight at 100 knots. I'm thinking of one airfield in Tasmania (42oS) to another. Do altimeters have a real time update of QNH from met stations via GPS coordinates e.g. Greg |
||||
matherp Guru Joined: 11/12/2012 Location: United KingdomPosts: 8592 |
QNH is typically reported by each airfield you talk to on route and it is up to the pilot to update the alimeter. Normal days, within 1 hour, you are unlikely to see it move by more than 1 or 2Hpa. If a front is approaching you may see more but you probably shouldn't be flying in the first place! In terms of user interface, two switches for up and down would be ideal. Press both together to set 1013.25 which is what you fly at in the "flight levels". In the UK this would be above what is called the transition altitude or 3000ft. I don't know the height of the transition altitude in Tasmania so can't help on that. Best Regards Peter |
||||
BobD Guru Joined: 07/12/2011 Location: AustraliaPosts: 935 |
Greg Even if you don't get reports from the airfield you can get some info about the area you are flying by looking here. http://www.bom.gov.au/tas/observations/tasall.shtml On that page you can click on a location and that will take you to a details page which includes QNH and MSL calculations. Most of these readings are every 30 minutes so you can see the trend. READ THE HELP so you will understand what it all means. Another useful set of pages are the weather radar. http://www.bom.gov.au/products/national_radar_sat.loop.shtml As you can see, Tasmania has two radar stations. Click on the one that interests you and zoom in or out as needed. On this page tick the box for Weather Observations. It will give you local (somewhat) wind strength and direction. If you want the big picture then see this one. http://www.bom.gov.au/australia/charts/synoptic_col.shtml Use the toolbar just above the map to see the progress of the weather fronts. There are similar reports for many parts of Australia. Bob Edit: for those who may be interested in weather on a large scale this may be useful http://earth.nullschool.net/#current/wind/surface/level/orth ographic=149.26,-41.86,3000 You can zoom in and out. Click on the word EARTH for options. Drag it to your part of the world. |
||||
TassyJim Guru Joined: 07/08/2011 Location: AustraliaPosts: 5909 |
I used to listen to the beacons transmitted by the local airports. They gave the up-to-date weather info. It's been a while and they might have been replaced with something more high tech by now. I think if you check the destination airport before taking off, not a lot will change by the time you arrive. The BMP180 is identical to the BMP085 code wise. The only difference I can see is better accuracy for pressure with the BMP180. The code I use for the BMP085 is on my micromite test server at tassyjim.ddns.net port 3002. It was written well before we had integers to play with. I use metres for altitude. FUNCTION myAlt(p, p0)
' given local pressure (p) and pressure at sea level (p0) ' returns altitude in metres myAlt = 44330*(1-(p/p0)^0.1903) END FUNCTION FUNCTION Psl(p, alt) 'given local pressure and altitude, returns pressure at sea level Psl= p/(1- alt/44330)^5.255 END FUNCTION Jim VK7JH MMedit MMBasic Help |
||||
TassyJim Guru Joined: 07/08/2011 Location: AustraliaPosts: 5909 |
I forgot to mention that the test micromite mentioned above is accessed by Telnet, not http. Use TeraTerm or MM Edit. There is a difference in temperature of about 2 degrees between the BMP085 and the DHT22. I believe the DHT22. If you are using MMEdit, you can easily download the program, using TeraTerm, ^C then LIST. Jim VK7JH MMedit MMBasic Help |
||||
paceman Guru Joined: 07/10/2011 Location: AustraliaPosts: 1328 |
@matherp, OK - but talking to the airfields often won't be an option because a lot of the Tassie airfields we might use won't be manned. In fact the one we'll leave from is a levelled paddock at the back of a house - sometimes with sheep on it! Fronts are a pretty common thing in Tassie too (good ol' roaring 40's) but you're right, stay home if one's coming. Re the 'transition level' etc - the pilot/owner-builder is my brother-in-law and he'll know all that stuff - hopefully I might query him about it first and not go if the answers don't seem convincing! Thanks for the suggestion re just up/down switches - that makes it pretty simple. @BobD, Yes, the bom.gov.au site was where I thought I'd be chasing it up. The Packet Weather app on the smartphone feeds BOM info including the radars in real time, and you can get real time wind speed/direction for whatever met station you set. Not sure what 3G/4G reception would be like in the 'plane but there's always the radio and no doubt the bigger airports, Launceston, Devonport etc could fill you in. @TassyJim, I'd forgotten about beacons Jim - we used to listen to them during yacht races in Bass Strait and navigate with them using an RDF unit. That was the early 70's I think, or maybe late-ish 60's I'll have a go at downloading from your Telnet ddns, I've been intending to try that for awhile and hadn't gotten around to it. Greg |
||||
TassyJim Guru Joined: 07/08/2011 Location: AustraliaPosts: 5909 |
The code is also here: http://www.thebackshed.com/forum/forum_posts.asp?TID=7080&PN =4 @matherp, It is really good to see your posts. It helps to see code converted from other versions of Basic (and C etc). It is usually easier to adapt someones working code than it is to start from nothing. So if you have any more devices you are talking to..... Jim VK7JH MMedit MMBasic Help |
||||
Print this page |