Anyone used the Bosch BMP085 I2C baro sensor yet ?


Closed Thread
Results 1 to 40 of 52

Hybrid View

  1. #1
    Join Date
    Feb 2006
    Location
    Gilroy, CA
    Posts
    1,530


    Did you find this post helpful? Yes | No

    Default

    Sparkfun has more of their BMP085 boards in stock now, if anyone is interested. Makes it nice to breadboard with. With the board, the cost is about the same as the Intersema. Still waiting on mine.

    Name:  bmp085.jpg
Views: 5088
Size:  46.6 KB
    Last edited by ScaleRobotics; - 24th April 2010 at 02:33.

  2. #2
    Join Date
    Nov 2008
    Posts
    96


    Did you find this post helpful? Yes | No

    Default Restart i2c ?

    I've got my BMP085 now, and I'm using a serial LCD and a PIC12F683 to try converse with the sensor initially. I have a problem with i2c comms, and reading the datasheet it mentions 'Restart condition' between starting a conversion (temperature in this case for simplicity to see it changing) and reading the result.
    Now I've not come across the 'restart condition' before with i2c chips (just EEPROMS thus far).

    Is it done in the PBP i2c statements or does it need to be bit-banged ? Or am I up the whole wrong tree here altogether ?

    Cheers all,
    MArtin

  3. #3


    Did you find this post helpful? Yes | No

    Default I2C start conditions.

    PBP gives you four choices for ShiftIn and ShiftOut to set the clock idle high/low and whether the shift is MSB or LSB first. This should cover your needs with the exception that PBP does NOT give you much control over the timing of the clock and data lines. There is a DEFINE SHIFT_PAUSEUS nn command but this only delays the clock/data transition at the start of the bit and there is no control over timing at the end of the bit.

    Cable length, cloick & data slew speed and any ringing on the clock and data lines can give bulk grief that takes days to find. Been there done that.

    I found with the intersems sensors that the potted PBP ShiftIn/Out routines would only drive about 300 mm of ribbon cable but my hand written bit bang method let me run over a metre of cable.

    Intersema is not the same as the Bosch interface. DIn, DOut and SClk vs SDA and SCL but otherwise the chips are very similar so the same sort of code structure ought to work.

    Here is how I do it.

    Code:
    OutShift:
       for fa = 1 to clockbits  
          'Don't forget OutShift adds an extra clock bit at the end. 
          din = (1 & iword)   'select lowest bit via AND mask 
          pauseus 4   'want minimum - about 4 uS or so
          sclk = 4 : pauseus 4 : sclk = 0
          iword = iword >> 1    'get next LSB, clock out zeros after 16 bits
       next fa
          sclk = 1 : pauseus 4 : sclk = 0 
          'this is the extra clock per DA5541B_00513 datasheet page 13
    return
    
    ResetIntersema:      ' resets ALL pressure sensors
    '   shiftout din, sclk, 0, [85, 85, 0\5]  ' Sense of Din is IN to 5541
       output din  : output sclk
       clockbits = 20 : iword = %0101010101010101     '16 bit data word
       gosub outshift
    return
    
    ConvertDelay:        ' specific to each sensor
       if tank = 0 then
          While dout0 = 1 
          wend   
       endif      
       if tank = 1 then
          While dout1 = 1 
          wend
       endif   
       if tank = 2 then
          While dout2 = 1 
          wend
       endif
    return
    
    FetchWord: ' read specific channel reply.  Different pins for DOut0,1,2
       input dout0 : input dout1 : input dout2 : output sclk : iword = 0     
       if tank = 0 then
          for fa = 15 to 0 step -1   'need 17 clock bits so add one at end
             sclk = 1 : pauseus 4    'wait for Intersema to present next bit
             iword.0[fa] = dout0     'read the bit on selected channel
             sclk = 0                'drop clock
          next fa                    'do it 16 times
       endif
       if tank = 1 then
          for fa = 15 to 0 step -1   'need 17 clock bits so add one at end
             sclk = 1 : pauseus 1    'wait for Intersema to present next bit
             iword.0[fa] = dout1     'read the bit
             sclk = 0                'drop clock
          next fa                     'do it 16 times
       endif
       if tank = 2 then
          for fa = 15 to 0 step -1   'need 17 clock bits so add one at end
             sclk = 1 : pauseus 1    'wait for Intersema to present next bit
             iword.0[fa] = dout2     'read the bit
             sclk = 0                'drop clock
          next fa                    'do it 16 times
       endif
          sclk = 1 : pauseus 1 : sclk = 0  ' 17th clock bit 
          ii = iword.byte0 : ij = iword.byte1
    return
    
    ReadFactoryCal:   
          ' This unpacks the factory calibration coefficients from the just
          ' read W1 ~ W4.
          ' These bitmaps are unpacked into the 6 working coefficients
          ' C1 to C6 which are then stored in EEROM for later use.  
    'W1
       gosub resetintersema
    '   shiftout din, sclk, 0, [87, 1\5]    ' Send W1 pattern to all sensors
       clockbits = 12 : iword = %000101010111  'request W1 pattern
       gosub outshift
       gosub fetchword                     ' recall selected Tank reply
       W1.byte0 = ii
       W1.byte1 = ij
       if (w1 = 0) or (w1 = 65535) then 
          debug "W1 error", 13, 10
          goto readfactorycal
       endif
    
    'W2    
       gosub resetintersema
    '   shiftout din, sclk, 0, [215, 0\5]       ' Send W2 pattern 
       clockbits = 12 : iword = %000011010111
       gosub outshift
       gosub fetchword
       W2.byte0 = ii
       W2.byte1 = ij
       if (w2 = 0) or (w2 = 65535) then 
          debug "W2 error", 13, 10
          goto readfactorycal
       endif
    
    'W3
       gosub resetintersema
    '   shiftout din, sclk, 0, [55, 1\5]       ' Send W3 pattern
       clockbits = 12 : iword = %000100110111
       gosub outshift   
       gosub fetchword
       W3.byte0 = ii
       W3.byte1 = ij
       if (w3 = 0) or (w3 = 65535) then 
          debug "W3 error", 13, 10
          goto readfactorycal
       endif
    
    'W4    
       gosub resetintersema
    '   shiftout din, sclk, 0, [183, 0\5]       ' Send W4 pattern 
       clockbits = 12 : iword = %000010110111
       gosub outshift
       gosub fetchword
       W4.byte0 = ii
       W4.byte1 = ij
       if (w4 = 0) or (w4 = 65535) then 
          debug "W4 error", 13, 10
          goto readfactorycal
       endif
    
    CalcCoefficients:     ' this serves all three sensors.
    'C1
        C1 = W1 >> 3                      'unpack coefficient
        read (108 + tank*20), z.byte0   'store
        read (109 + tank*20), z.byte1
        if z<>c1 then
          write (108 + tank*20), c1.byte0   'store
          write (109 + tank*20), c1.byte1
        endif
    'C2
        C2 = ((W1 & %0000000000000111) << 10) + (W2 >> 6)
        read (110 + tank*20), z.byte0
        read (111 + tank*20), z.byte1
        if z<>c2 then
          write (110 + tank*20), c2.byte0
          write (111 + tank*20), c2.byte1
        endif
    'C3
        C3 = W3 >> 6
        read (112 + tank*20), z.byte0
        read (113 + tank*20), z.byte1
        if z<>c3 then
          write (112 + tank*20), c3.byte0
          write (113 + tank*20), c3.byte1
        endif
    'C4    
        C4 = W4 >> 7
        read (114 + tank*20), z.byte0
        read (115 + tank*20), z.byte1
        if z<>c4 then
          write (114 + tank*20), c4.byte0
          write (115 + tank*20), c4.byte1
        endif
    'C5
        C5 = ((W2 & %0000000000111111) << 6) + (W3 & %0000000000111111)
        read (116 + tank*20), z.byte0
        read (116 + tank*20), z.byte0
        if z<>c5 then
          write (117 + tank*20), c5.byte1
          write (117 + tank*20), c5.byte1
        endif
    'C6
        C6 = W4 & %0000000001111111
        read (118 + tank*20), z
        if z<>c6 then
          write (118 + tank*20), c6
        endif
    
    Show5541Coefficients:   'only used during diagnostics
    '   high txd : pause 1
    '   debug 13, 10, "Tank #", #tank, ", W1 = ", #w1, ",  W2 = ",_
    '    #w2, ",  W3 = ", #w3, ",  W4 =  ", #w4, 13, 10
    '   debug "Derived coeffs C1 = ", #C1, ", C2 = ", #C2, ", C3 = ",_
    '    #C3, ", C4 = ", #c4, ", C5 = ", #C5, ", C6 = ", #C6, 13, 10
    
    return
    HTH

    BrianT

  4. #4
    Join Date
    Nov 2008
    Posts
    96


    Did you find this post helpful? Yes | No

    Default

    Thanks Brian,

    I'm not sure quite what to say though. I'm sure the tip I need is in the reply, but most of the answer went over my head.
    I've not used shiftin/shiftout of anything in PBP so I'd rather get the i2c commands to work for me (if it's possible).
    The sensor is 20mm from the PIC, so I'm hoping distance related issues should not be a problem. I'll just have a quiet little play with the i2c commands and see if I can get some sense out of it with that for now :-)
    Thanks,
    Martin

  5. #5
    Join Date
    Nov 2008
    Posts
    96


    Did you find this post helpful? Yes | No

    Default Yippeee

    OK, got comms up. I can read the temperature sensor fine now. The issue was HW not SW this time.
    Martin

  6. #6
    Join Date
    Nov 2008
    Posts
    96


    Did you find this post helpful? Yes | No

    Default

    Well I've spent a few hours working on this over the weekend, and I've made good progress (for me) with communicating with the sensor. I have a PIC Serial LCD (20x4) attached to a PIC12F683, which has the BMP085 attached to GPIO.0 (clock) and GPIO.1(data).

    So far I can see the inbuilt temperature sensor value changing when I put a warm finger on the sensor, and also read out the eleven 16bit calibration parameters and display them (I think).

    I'm worried about two things.
    One is if I have the MSB and LSB of the calibration data in the right order when I'm storing them and then again using them. I not convinced the numbers look right on the LCD. The PBP manual I find confuses me somewhat when they talk about storing the LSB first in a word sized array of the i2c device (i2cread command description).

    The second is converting this math to PBP, given that the values of some seem to be signed and results of some operations are going to be 32bit size (unless I don't understand it at all, which is possible).
    To convert the raw temperature result UT to Deg C (T) is
    X1 = (UT - AC6) * AC5 / 2^15
    X2 = MC * 2^11 / (X1 + MD)
    B5 = X1 + X2
    T = (B5 + 8) / 2^4

    I'd love some help with some code to show how this can be done in PBP.
    Anybody ?

    Cheers,
    Martin

    Code:
    'PIC 12F683 port/pin allocations
    '-------------------------------
    'GPIO.0/Pin 7 = I2C SCL clock
    'GPIO.1/Pin 6 = I2C SDA data
    'GPIO.2/Pin 5 = spare
    'GPIO.3/Pin 4 = spare
    'GPIO.4/Pin 3 = LED
    'GPIO.5/Pin 2 = Serial TX
    
    '-----------------------
    ' PIC Defines
    ' ===========
    'Config bits set to INTERNAL OSC, Watch dog ON, Power up timer ON, Master Clear NOT used, BrownOut protection ON, 
    @ Device  pic12f683, intrc_osc, wdt_on, pwrt_on, mclr_off, bod_on ;Config switches, different from PBP default
    '@ __Config _INTRC_OSC_NOCLKOUT & _WDT_OFF & _PWRTE_ON & _MCLRE_OFF   ;USING MPASM ONLY
    
        Define Osc 4 '4Mhz clock used. Note - Set PIC config fuses on programmer to use Internal RC OSC
        
        Include "modedefs.bas"          ' Include serial modes
    
    ' Define some constants if needed
            
    ' Software Defines
        Cal_table   var word[11]         '11 word array to store calibration data
        Temp_Var    var byte             'temp variable 
        Temp_Var2   var Word	         'temp variable 
        i2c_Reg     var Byte             'variable for target i2c register address
        
        CPIN        var     GPIO.0       ' I2C clock pin 
        DPIN        var     GPIO.1       ' I2C data pin
        SO          Var     GPIO.5        'Serial out pin
        LED         var     GPIO.4        'Indicator LED, via 500ohm to +3.3V
        
    'Alias's for calibration data in the sensor to match the Bosch paramater list names
        AC1     var     Cal_table[0]     '
        AC2     var     Cal_table[1]     'BMP085 has 11 16bit values stored in EEPROM
        AC3     var     Cal_table[2]     'First byte is at $AA last at $BF
        AC4     var     Cal_table[3]     'Lowbyte is MSB, Highbyte is LSB
        AC5     var     Cal_table[4]     'some values are signed (not AC4, AC5, AC6)
        AC6     var     Cal_table[5]    
        B1      var     Cal_table[6]
        B2      var     Cal_table[7]
        MB      var     Cal_table[8]
        MC      var     Cal_table[9]    
        MD      var     Cal_table[10]    
        
    ' Initialise Processor - check for each PIC type either 12F629 or 12F675
    ' --------------------
        VRCON.7 = %0    'Comparator voltage reference OFF
        CMCON0 = %111   'Comparator inputs to OFF, all pins normal I/O
        ANSEL = 0       'Turn off al AD's     rem out for PIC12F629, use for PIC12F675
    
    ' Set initial state of GPIO port pins as Input or Output
    
        TRISIO.0 = 0    'Input(0 = output, 1 = Input)
        TRISIO.1 = 0    '
        TRISIO.2 = 1    '
        TRISIO.3 = 0    '
        TRISIO.4 = 0    '
        TRISIO.5 = 1    '
    
    ' PIC initialization code
    
            Low LED     'LED on
            pause 500
            High LED    'LED off
     
            Serout SO,N2400,[$FE,$01]               ' Clear LCD & home LCD cursor.
            pause 10                                ' wait for LCD to catch up
            Serout SO,N2400,["   FrSky Vario    "]  ' Serial print 
            Serout SO,N2400,[$FE,$C0]               ' Shift cursor to line2
            Serout SO,N2400,[" development jig  "]  ' Serial print 
            Pause 3000
            
            i2c_Reg =$AA                            'Start address of calibration data
            I2CREAD DPIN,CPIN,$EF,I2C_REG,[STR Cal_table\11],read_error1  'Read 11 words out of sensor
            Serout SO,N2400,[$FE,$01]             ' Clear LCD & home LCD cursor. 
            Pause 10                              ' wait for LCD to catch up
    Main:  
            Serout SO,N2400,[$FE,$02]             'home LCD cursor.                           
                    
            i2c_Reg = $F4                         '$F4 is the control register address
            I2CWRITE DPIN,CPIN,$EE,I2C_REG,[$2E]  ' Write $2E to set temperature conversion 
            Pause 10                              ' Delay 10ms after each write
     
            i2c_Reg = $F6                       '$F6 is the result register MSB
            I2CREAD DPIN,CPIN,$EF,I2C_REG,[Temp_Var2],read_error  'Read temperature MSB, LSB.
    
            Serout SO,N2400,[#Temp_Var2," "]       'Send Word size number to LCD
    
    'lets see whats in the cal data array for a checking math   
            Serout SO,N2400,[$FE,$C0]               ' Shift cursor to line2
            Serout SO,N2400,[#AC1," ",#AC2," ",#AC3]
            Serout SO,N2400,[$FE,$94]               ' Shift cursor to line3
            Serout SO,N2400,[#AC4," ",#AC5," ",#AC6]
            Serout SO,N2400,[$FE,$D4]
            Serout SO,N2400,[#B1," ",#B2," ",#MB]
    '        ," ",#MC," ",#MD]                  '
            pause 1000
            Toggle LED
            Goto main
            
    Read_error:
            Serout SO,N2400,[$FE,$01]             ' Clear LCD & home LCD cursor. 
            Pause 10                              ' wait for LCD to catch up
            Serout SO,N2400,["i2c bus read error"]       '        
            pause 250        
           
            Toggle LED
            Goto main
             
    Read_error1:
            Serout SO,N2400,[$FE,$01]             ' Clear LCD & home LCD cursor. 
            Pause 10 
            Serout SO,N2400,["i2c cal read error "]       '        
            
    End

  7. #7
    Join Date
    Nov 2008
    Posts
    96


    Did you find this post helpful? Yes | No

    Default

    Real values.
    If there happens to be a mathematician amongst us that likes puzzles like the one above, I have the raw values (as decimal) read out of my sensor to plug into the temperature equations as a test. The result should be around 21C.

    UT = 30814
    AC5 = 22882
    AC6 = 1368
    MC = 48596
    MD = 32777

Members who have read this thread : 0

You do not have permission to view the list of names.

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts