Proton BASIC Compiler - Bosch BMP180 Pressure Sensor

  • Pic® Basic

  • Bosch BMP180 Pressure Sensor

    At the time of writing this article, the Bosch BMP180 pressure sensor is both cheap and readily available from sources such as eBay. It offers the ability to measure both pressure and temperature to a reasonable level of accuracy.

    Given the current pressure as measured by the sensor and a suitable value for the pressure at sea level, it is also possible to calculate altitude.

    The code below uses the I2C protocol to communicate with the BMP180 and extract the values necessary to calculate both pressure in pascals and temperature in degrees centigrade.

    Variable names in the program have been chosen, as far as is possible, to correspond with those used in the manufacturer’s datasheet.

    '*  Name    : BMP180.BAS                                        *
    '*  Author  : Bob Marshall                                      *
    '*  Date    : 5/28/2016                                         *
    '*  Version : 1.0                                               *
    '*  Notes   : This program uses a BMP180 pressure sensor        *
    '*          : to measure current pressure, temperature &        *
    '*          : altitude.                                         *
      Device = 18F25K22
      Xtal = 64
      Declare All_Digital = true
     'Calculated Baudrate = 115108 @ Xtal 64MHz, Error = -0.08%
      Declare Hserial_RCSTA  = 144 ; Enable continuous receive
      Declare Hserial_TXSTA  = 36  ; Enable transmit, BRGH = 1
      Declare Hserial_Clear  = On  ; Clear overflow automatically
      Declare Hserial_SPBRG  = 138 ; Baud Rate Generator Low Byte Value
      SPBRGH                 = 0   ; Baud Rate Generator High Byte Value
      BAUDCON.3              = 1   ; Enable the 16 bit Baud Rate Generator
      Symbol BMP180 = $EE  'BMP180 I2C address
      Symbol CalDatStAd = $AA 'Start address for cal. data.
      Symbol InitConvReg = $F4
      Symbol PReadReg = $34 
      Symbol TReadReg = $2E  
      Dim AC1 As SWord
      Dim AC2 As SWord
      Dim AC3 As SWord
      Dim AC4 As Word
      Dim AC5 As Word
      Dim AC6 As Word
      Dim B1 As SWord
      Dim B2 As SWord
      Dim B3 As SDword
      Dim B4 As Dword
      Dim B5 As SDword
      Dim B6 As SDword
      Dim B7 As Dword
      Dim MB As SWord
      Dim MC As SWord
      Dim MD As SWord
      Dim OSS As Byte
      Dim UP As  Word
      Dim UT As SWord
      Dim XLSB As Byte
      Dim UPLong As SDword
      Dim X1 As SDword
      Dim X2 As SDword
      Dim X3 As SDword
      Dim Temperature As SWord
      Dim TempOut As Float
      Dim P As SDword
      Dim POut As Float
      Dim Altitude As Float
      Dim Temp1 As Float
      DelayMS 1000
      OSS = 3 'Oversampling mode. Values of 0-3 acceptable. 
      HSerOut [10,13,"Ready to Start",13,10]
    ' Read calibration data
      HBusIn BMP180,CalDatStAd,[AC1,AC2,AC3,AC4,AC5,AC6,B1,B2,MB,MC,MD]
          HBusOut BMP180,InitConvReg,[TReadReg]  'Start temperature conversion.
          DelayMS 10   'wait for conversion to complete.
          HBusIn BMP180,$F6,[UT] 'UT has the uncompensated temperature value.
          X1 = ((UT-AC6)*AC5)/32768
          X2 = (MC * 2048)/(X1+MD)
          B5 = X1+X2
          Temperature = (B5+8)/16
          TempOut = Temperature/10
    ' $B0 is the hex value for the degree symbol.
          HSerOut ["Current temperature is: ",Dec1 TempOut,$B0,"C",13,10]
    ' Calculate the pressure in Pascals
          HBusOut BMP180,InitConvReg,[PReadReg]  'Start pressure conversion.
          DelayMS 100    'wait for conversion to complete.
          HBusIn BMP180,$F6,[UP,XLSB] 'UP+XLSB contain the uncompensated pressure value.
          UPLong =  ((UP * 256)+ XLSB) >> (8-OSS)
    ' Now lets have some fun with numbers!
          B6  = B5 - 4000
          X1  = (B2 * (B6 * B6 /4096))/2048
          X2  = (AC2 * B6)/2048
          X3  = X1+X2
          B3  = (((AC1 * 4 + X3) << OSS)+2)/4
          X1  = ( AC3 * B6 )/8192
          X2  = (B1 * (B6 * B6/4096))/65536
          X3  = ((X1 + X2 ) + 2)/4
          B4  = (AC4 * ( X3 + 32768))/32768
          B7  = (UPLong - B3) *(50000 >> OSS)
          If B7 <  $80000000 Then
              P=(B7 * 2)/B4
              P=(B7 / B4) * 2
          X1  = (P/256) * (P/256)
          X1  = (X1 * 3038)/65536
          X2  = (-7357 * P)
          X2 = X2/65536
          P   = P + ( ( X1 + X2 + 3791)/16 )
          POut = (P/100)
          HSerOut ["Current pressure: ",Dec2 POut,"hPa",13,10]
    ' Altitude = 44330*((1-(p/101325)) ^ (1/5.255))
    ' 101325 represents the 'standard' pressure at sea level. Adjust to suit.
          Temp1 = pow((P/102800),0.190295)
          Altitude =  44330 *(1-Temp1)
          HSerOut ["Current altitude: ",Dec2 Altitude ,"m",13,10,13,10]
          DelayMS 2000
    ' End of program
    ' **** Added by Fuse Configurator ****
    ' Use the Fuse Configurator plug-in to change these settings
          FOSC = HSMP    ;HS oscillator (medium power 4-16 MHz)
          PLLCFG = On    ;Oscillator multiplied by 4
          PRICLKEN = On    ;Primary clock enabled
          FCMEN = OFF    ;Fail-Safe Clock Monitor disabled
          IESO = OFF    ;Oscillator Switchover mode disabled
          PWRTEN = OFF    ;Power up timer disabled
          BOREN = SBORDIS    ;Brown-out Reset enabled in hardware only (SBOREN is disabled)
          BORV = 190    ;VBOR set to 1.90 V nominal
          WDTEN = Off    ;WDT is always enabled. SWDTEN bit has no effect
          WDTPS = 32768    ;1:32768
          CCP2MX = PORTC1    ;CCP2 input/output is multiplexed with RC1
          PBADEN = On    ;PORTB<5:0> pins are configured as analog input channels on Reset
          CCP3MX = PORTB5    ;P3A/CCP3 input/output is multiplexed with RB5
          HFOFST = On    ;HFINTOSC output and ready status are not delayed by the oscillator stable status
          T3CMX = PORTC0    ;T3CKI is on RC0
          P2BMX = PORTB5    ;P2B is on RB5
          MCLRE = EXTMCLR    ;MCLR pin enabled, RE3 input pin disabled
          STVREN = On    ;Stack full/underflow will cause Reset
          LVP = On    ;Single-Supply ICSP enabled if MCLRE is also 1
          XINST = OFF    ;Instruction set extension and Indexed Addressing mode disabled (Legacy mode)
          Debug = OFF    ;Disabled
          Cp0 = OFF    ;Block 0 (000800-001FFFh) not code-protected
          CP1 = OFF    ;Block 1 (002000-003FFFh) not code-protected
          CP2 = OFF    ;Block 2 (004000-005FFFh) not code-protected
          CP3 = OFF    ;Block 3 (006000-007FFFh) not code-protected
          CPB = OFF    ;Boot block (000000-0007FFh) not code-protected
          CPD = OFF    ;Data EEPROM not code-protected
          WRT0 = OFF    ;Block 0 (000800-001FFFh) not write-protected
          WRT1 = OFF    ;Block 1 (002000-003FFFh) not write-protected
          WRT2 = OFF    ;Block 2 (004000-005FFFh) not write-protected
          WRT3 = OFF    ;Block 3 (006000-007FFFh) not write-protected
          WRTC = OFF    ;Configuration registers (300000-3000FFh) not write-protected
          WRTB = OFF    ;Boot Block (000000-0007FFh) not write-protected
          WRTD = OFF    ;Data EEPROM not write-protected
          EBTR0 = OFF    ;Block 0 (000800-001FFFh) not protected from table reads executed in other blocks
          EBTR1 = OFF    ;Block 1 (002000-003FFFh) not protected from table reads executed in other blocks
          EBTR2 = OFF    ;Block 2 (004000-005FFFh) not protected from table reads executed in other blocks
          EBTR3 = OFF    ;Block 3 (006000-007FFFh) not protected from table reads executed in other blocks
          EBTRB = OFF    ;Boot Block (000000-0007FFh) not protected from table reads executed in other blocks
    ;**** End of Fuse Configurator Settings ****

    If the BMP180 is looked at closely, it is possible to see a tiny hole in the case. Obviously this is to allow the sensing element to respond to pressure changes. What is possibly not quite so obvious is that the same hole allows light to reach the silicon chip within the case. The practical consequence of this is that the readings produced are affected by the amount of ambient light falling on the sensor. The solution to this problem is to keep the sensor in the dark whilst ensuring it is still possible for the atmosphere to reach it.

    Have fun.