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 : I2C pressure transducer
Author | Message | ||||
TassyJim Guru Joined: 07/08/2011 Location: AustraliaPosts: 6101 |
I recently purchased a BMP085 pressure transducer (I2C). As usual, I went for an Arduino module to save soldering etc. Mine cost $3.91 each. The data sheet has plenty of information and sample software for the Arduino is easy to find. Each IC has been individually calibrated and you have to read the 11 data values in before converting the raw data to real values. One problem I found was the sample software assumes signed and unsigned 16 bit numbers. It took a bit of work to get things calculating correctly on the Maximite but fortunately the datasheet provides sample data for testing the maths. Because of this, the maths looks a bit strange but it does work reliably. ' reading the BMP085 pressure sensor
' TassyJim 06 JAN 2014 Cls Dim BMPData(2) ' store data from BMP085 dim cal(11) ' calibration data oss = 0 ' over sampling 0 to 3 alt = 240 ' your altitude in metres f$="%6.1f" ' format string BMP085calMEM = &HAA ' start of 11 calibration values BMP085address = &H77 ' BMP085 address BMP085control = &HF4 ' BMP085 control register BMP085temp = &H2E ' BMP085 temperature command BMP085pres = &H34 ' BMP085 pressure command BMP085pres = BMP085pres + oss*&H40 ' adjust command for oversampling BMP085reading = &HF6 ' register for results of reading I2CEN 400, 200 ' Enable I2C. use slow speeds for long leads pause 20 z = Calibrate() ' read the calibration data do t=temperature() p=pressure(oss) p0=Psl(p,alt) print time$,"T:",format$( t,f$);" P:",format$(p/100,f$);" P(sl):",format$(p0/100,f$) pause (300000) ' delay 5 minutes between readings loop until k$ = "q" or k$ = "Q" end function Calibrate() ' needs to be called once for each module. ' safest to do it on every program start. local n, calMEM calMEM= BMP085calMEM for n = 1 to 11 I2CSEND BMP085address, 0, 1, calMEM ' first calibration location pause 1 I2CRCV BMP085address, 0, 2, BMPData(0) 'print BMPData(1), BMPData(0)*256 + BMPData(1) cal(n) = BMPData(0)*256 + BMPData(1) if n < 4 or n > 6 then ' need to convert some to signed numbers if cal(n) > 32767 then cal(n) = cal(n) - 65536 endif endif 'print n,cal(n) pause 1 calMEM=calMEM+2 ' advance to the next calibration location next n end function function temperature() ' returns the temperature in degrees C to one decimal place local UT, x1, x2, b5 I2CSEND BMP085address, 0, 2, BMP085control, BMP085temp pause 5 I2CSEND BMP085address, 0, 1, BMP085reading I2CRCV BMP085address, 0, 2, BMPData(0) UT = BMPData(0)*256 + BMPData(1) 'calculate true temperature x1= int( (UT-cal(6))*cal(5)/32768) x2=int( cal(10)*2048/(x1+cal(11))) b5=x1+x2 temperature = int((b5+8)/16)/10 end function function pressure(oss) ' returns the pressure in pascals. Divide by 100 for millibars ' recalculates the temperatre. ' time could be saved by reading the temperature once evry 10 minutes ' when taking readings at short intervals local UT, UP, x1, x2, x3, b5, b6, b7, pres, p pres = BMP085pres + oss*&H40 I2CSEND BMP085address, 0, 2, BMP085control, BMP085temp pause 5 I2CSEND BMP085address, 0, 1, BMP085reading I2CRCV BMP085address, 0, 2, BMPData(0) UT = BMPData(0)*256 + BMPData(1) I2CSEND BMP085address, 0, 2, BMP085control, pres if oss = 0 then ' different oversampling requires different pause 5 ' reading times elseif oss = 1 then pause 8 elseif oss = 2 then pause 14 else pause 26 endif I2CSEND BMP085address, 0, 1, BMP085reading I2CRCV BMP085address, 0, 2, BMPData(0) UP = BMPData(0)*256 + BMPData(1) I2CSEND BMP085address, 0, 1, BMP085reading+2 I2CRCV BMP085address, 0, 1, BMPData(0) UP=(UP*256+BMPData(0))/2^(8-oss) 'calculate true temperature x1= int( (UT-cal(6))*cal(5)/32768) x2=int( cal(10)*2048/(x1+cal(11))) b5=x1+x2 t=int((b5+8)/16)/10 'print "Temperature: ",t 'calculate true atmospheric pressure b6 = b5 - 4000 x1 = int((cal(8)*(b6*b6/4096))/2048) x2 = int(cal(2)*b6/2048) x3 = x1 + x2 b3 = int(((cal(1)*4+x3)*2^oss +2)/4) x1 = int(cal(3)*b6/8192) x2 = int((cal(7)*(b6*b6/4096))/65536) x3 = int(((x1+x2)+2)/4) b4 = int(cal(4)*x3/32768+cal(4)) b7 = int((UP - b3)*(50000/2^oss)) p = int((b7*2)/b4) x1 = int(int(p/256)*int(p/256)) x1 = int((x1*3038)/65536) x2 = int((-7357*p)/65536) pressure = int(p+(x1 + x2 + 3791)/16) 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 The next step is to waterproof one and throw it into the water tank to make a water level gauge. Jim VK7JH MMedit MMBasic Help |
||||
MOBI Guru Joined: 02/12/2012 Location: AustraliaPosts: 819 |
Looks similar to a Silicon Chip project of a few years ago. They had a bit of trouble keeping it water tight and had a few permutations. What degree of accuracy do you need? Some time back, I did a capacitive probe consisting of twin flex wrapped around a pole (for extra length of wire). It worked on calculating the time a RC network (probe) took to trip a comparator in the PIC. It wasn't linear but a lookup table took care of that. The ends of the twin flex in the water needed to be sealed. Temperature wasn't a problem. The capacitance of the probe increased as the level of water in the tank increased. i.e. as the dielectric constant changed. Never took it past the prototype but is still on my "to do" list for when I get around to radio controlling the solar bore pump. The tank and pump are about 200mtrs apart. David M. |
||||
paceman Guru Joined: 07/10/2011 Location: AustraliaPosts: 1329 |
I've been going to get one of these for a project I was thinking about Jim but hadn't really looked at the datasheet. Just as well you've done the hard work for us, I didn't realize it would be that complicated. Your code would be good for the MM library. Greg |
||||
TassyJim Guru Joined: 07/08/2011 Location: AustraliaPosts: 6101 |
I have dug out the Silicon chip articles to see how they did things. I think I know how I will do the probe. Just need time to experiment. I am lucky, my bore is right beside the shed so mains power was not a problem. Jim VK7JH MMedit MMBasic Help |
||||
Keith @ Senior Member Joined: 19/06/2011 Location: AustraliaPosts: 167 |
"The next step is to waterproof one and throw it into the water tank to make a water level gauge." With a static water level in the tank won't the reading vary with changing atmospheric pressure? Could the atmospheric changes be cancelled out using a second sensor to measure the atmospheric pressure outside of the tank? How will you waterproof? I'm look forward to more on this topic ... the sensor is certainly cheap enough to wreck a couple in the process of learning. I'm looking at possibly using it in a tank mounted on a truck so it would have to be mounted into a fixed fitting in the bottom of the tank or one of the pipes under the tank. ... excellent work Jim The more we know, the more we know we don't know ! |
||||
TassyJim Guru Joined: 07/08/2011 Location: AustraliaPosts: 6101 |
One metre of water is about 98 hPa so reasonable accuracy should be obtainable. In theory, 1cm resolution. I will have a second unit measuring atmospheric pressure. I expect I will use some soft tubing or heatshrink for waterproofing and it will be fitted inside a tee fitting placed in the outlet of the tank(s). It might take a few attempts to get it right. Jim VK7JH MMedit MMBasic Help |
||||
palcal Guru Joined: 12/10/2011 Location: AustraliaPosts: 1873 |
I am using a BMP085 in my Weather Station, works really well. But for measuring water level I have also used MPX2202 to which you can attach a tube so the device can be remote to the tank. The device outputs a voltage directly proportional to the pressure. Paul. "It is better to be ignorant and ask a stupid question than to be plain Stupid and not ask at all" |
||||
Print this page |