Shop OBEX P1 Docs P2 Docs Learn Events
I2C for beginners (Using BMP085 Barometer) — Parallax Forums

I2C for beginners (Using BMP085 Barometer)

ShawnaShawna Posts: 508
edited 2013-04-09 16:51 in Propeller 1
Hey guys,
My Spin skills and PASM skills are not real great, I am learning more and more everyday but I am still a beginner. I want to play with a BMP085 barometer and I am trying to locate an I2C driver to use. I have been looking at the Basic I2C Driver but in the description it states that the code assumes there are no pull-up resistors on SDA and SCL. I have the BMP085 breakout board from sparkfun and the schematic shows there being pull-up resistors on the board.
My question is, can I still use this code with the BMP085, or any I2C device that already has pull up resistors built in?
Thanks
Shawn

Comments

  • SRLMSRLM Posts: 5,045
    edited 2013-04-04 18:32
    Yes, you can.
  • photomankcphotomankc Posts: 943
    edited 2013-04-05 12:28
    Be sure anything use use with that driver doesn't clock-stretch. I think basic-i2c-driver tops out at pretty slow bus rate so it may never be an issue but it is possible for a slave device to hold the clock line low to try to slow down the master so it has time to get ready for new data. If the slave is holding the line low and the master is trying to drive it high then you have an obvious problem.

    Most slave devices don't do it, but Micro-controller based modules may very well do it.
  • ShawnaShawna Posts: 508
    edited 2013-04-05 15:08
    Ok my first couple attempts failed. My SCL line is P8 and my SDA line is P9. I should have expanded more on my first question.
    My question is, can I still use this code with the BMP085, or any I2C device that already has pull up resistors built in?

    Since the answer is yes, thank you SRLM. Do I need to modify the Basic I2C Driver code? My guess is no!

    This is the simple program I wrote to read out the calibration E2PROM on the BMP085, The BMP085 manual says communication can be checked by reading these registers. 0 and FFFF are invalid numbers from these registers and I got 0 for all of them. I would say this means I did not communicate at all with the chip. I am sure I missed something simple, this should not be complicated. Here is my code if anyone would like to take a look.
    CON
            _clkmode = xtal1 + pll16x                                               'Standard clock mode * crystal frequency = 80 MHz
            _xinfreq = 5_000_000
            
    Var
    Long AC1,AC2,AC3,AC4,AC5,AC6,B1,B2,MB,MC,MD             'E2Prom variables from BMP085
    OBj
         I2C : "Basic_I2C_Driver"          'By Michael Green
         PST : "Parallax Serial Terminal"  'By Jeff Martin, Andy Lindsay, Chip Gracey
    PUB Main
      waitcnt ((clkfreq * 5) + cnt)                          'Wait 5 seconds
    
    
      PST.Start(115_200)        'Sets BaudRate for PST.
      PST.Clear                 'Clears PST Screen.
    
    
      I2C.Initialize(8)
      I2C.Start(8)
      AC1 := I2C.ReadWord(8, 10_1110, $AA)
      AC2 := I2C.ReadWord(8, 10_1110, $AC)
      ac3 := I2C.ReadWord(8, 10_1110, $AE)
      ac4 := I2C.ReadWord(8, 10_1110, $B0)
      ac5 := I2C.ReadWord(8, 10_1110, $B2)
      ac6 := I2C.ReadWord(8, 10_1110, $B4)
      b1 :=  I2C.ReadWord(8, 10_1110, $B6)
      b2 :=  I2C.ReadWord(8, 10_1110, $B8)
      mb :=  I2C.ReadWord(8, 10_1110, $BA)
      mc :=  I2C.ReadWord(8, 10_1110, $BC) 
      md :=  I2C.ReadWord(8, 10_1110, $BE)
      
      PST.Dec(AC1)
      PST.NewLine
      PST.Dec(AC2)
       PST.NewLine
      PST.Dec(AC3)
       PST.NewLine
      PST.Dec(AC4)
       PST.NewLine
      PST.Dec(AC5)
       PST.NewLine
      PST.Dec(AC6)
       PST.NewLine
      PST.Dec(B1)
       PST.NewLine
      PST.Dec(B2)
       PST.NewLine
      PST.Dec(MB)
       PST.NewLine
      PST.Dec(MC)
       PST.NewLine
      PST.Dec(MD)
       PST.NewLine
      PST.Dec(AC2) 
    

    Thanks
    Shawn
  • kuronekokuroneko Posts: 3,623
    edited 2013-04-05 16:19
    Looks like the sensor uses single byte addresses. Which means get an updated I2C driver (rev 1.3) and OR the register address with I2C#OneAddr. Also, ReadWord includes a start condition so no need to call it yourself.
  • ShawnaShawna Posts: 508
    edited 2013-04-05 16:41
    Hey guys
    PUB ReadWord(SCL, devSel, addrReg) : data
    '' Read in a single word of i2c data.  Device select code is devSel.  Device
    '' starting address is addrReg.  The device select code is modified using the
    '' upper 3 bits of the 19 bit addrReg.  This returns true if an error occurred.
       if ReadPage(SCL, devSel, addrReg, @data, 2)
          return -1
    

    If I change the address to $77 then I get a -1 back. What does the -1 signify? The code says that if a error occurs it will return true. -1 surely is not true is it? This is one thing I need to learn in order to read and write code better. So I am assuming that I have the right address since I do not get a -1 when I use the address %1110 1110. Or could the address still be wrong?

    The example that I was basing my code off of read the BMP085 registers as a word. I saw the addresses in the data sheet as byte size but I think I can read a whole word out, I don't think that is the problem. I tried modifying the code to read just one byte out and it still read out 0's.

    I might have found the problem, in order to read the device I think I have to use %1110 1111 and to write I have to use %1110 1110. I am going to try that now.

    Thanks
    Shawn
  • ShawnaShawna Posts: 508
    edited 2013-04-05 16:45
    Using 1110 1111 as devsel returns a value of -1 also I am stuck, but I am still digging.
    AC1 := I2C.ReadWord(8, 10_1110, $AA)
    

    It did not show up properly in my post above.
    Also I am using V1.3 Basic I2C Driver.

    Shawn
  • ShawnaShawna Posts: 508
    edited 2013-04-05 16:52
    The editor is getting rid of my 11111's
    I tried %1110 1110 and %1110 1111.
    Thanks
    Shawn
  • kuronekokuroneko Posts: 3,623
    edited 2013-04-05 17:06
    In case it got overlooked, when called like in post #7 the driver will send a 2 byte address (default setting for EEPROM devices). AFAICS the device needs a single byte address, i.e. I2C.ReadWord(8, $EE, I2C#OneAddr|$AA).
  • Prophead100Prophead100 Posts: 192
    edited 2013-04-05 18:18
    Tim Moore did an object in 2010 that I used for the sensor on my transparent clock project ( http://forums.parallax.com/showthread.php/143083-Transparent-Prop-Clock-with-Sensors ). You might want to look at his object.
  • ChrisGaddChrisGadd Posts: 310
    edited 2013-04-05 18:19
    It looks like it has the same I2C requirements as the MS5607 altimeter, which by a strange coincidence has the same device address %01110111. You could try using the demo code for that one, found in the store.
  • ShawnaShawna Posts: 508
    edited 2013-04-05 18:20
    Ok, thank you very much I think that fixed my first problem. I missed that in the example part in the comments at the begining of the Basic I2C Driver. Like I said I am still learning this language. I understand what this does now (I2C#OneAddr|$AA), but why does it not matter which way it is place in the code. I tried it this way I2C#OneAddr|$AA, and I tried it this way $AA|I2C#OneAddr and they both work. I also don't understand the syntax of this character |. Which I know is a big deal but I just don't understand what it does. If I look at the Prop PDF it says it is a BIT OR operator. Obviously that is not what it is used for in this case. I am sure I will have more questions, hopefully this will get me to the point where I can understand and easily hook up I2C devices.

    Thanks Again
    Shawn
  • kuronekokuroneko Posts: 3,623
    edited 2013-04-05 18:31
    Shawna wrote: »
    I understand what this does now (I2C#OneAddr|$AA), but why does it not matter which way it is place in the code.
    A|B is the same as B|A. And using it as bitwise OR is exactly what is done here (in this specific case I could have used + as well). You're calling the method with a value of $3000AA. The driver uses the 3 as flag/modifier and the $AA part as register address (see e.g. PageRead method for the masking part).
  • ShawnaShawna Posts: 508
    edited 2013-04-06 10:02
    Ok, thanks for the help.
    On to the next section of code for the BMP085. I need to send a request for a temperature reading. The register address is $F4 and the control register value should be $2E if I read the manual right. After sending the request for a temperature reading I have to wait for 4.5mS before I can try to read it. Now that I have waited 4.5mS I should be able to read the temperature out of register $F6 MSB and register $F7 LSB. When I add the code below to my main program I get a value of 128 all the time for my Temperature1 variable, it never changes. I do not think my request for a temperature reading is making it to the BMP085. The reason I don't think it is making it, is because the BMP085 has a END OF CONVERSION line that should change from a logic 0 to a logic 1 when the temperature reading is ready to be read. The EOC is never changing state to a logic 1, I hooked my scope to it.

    I tried a bunch of different things with no success.
    Repeat
      I2C.WriteByte(8, $EE, $f4, $2e) 'request for temp 
      waitcnt ((clkfreq / 220) + cnt) 'Pause 4.5 mS
      Temperature1 := I2C.ReadWord(8, $EE, $F6| I2C#OneAddr)
    

    Thanks
    Shawn
  • kuronekokuroneko Posts: 3,623
    edited 2013-04-06 16:07
    WriteByte requires the usage of I2C#OneAddr as well.
  • ShawnaShawna Posts: 508
    edited 2013-04-07 10:34
    Thanks Kuroneko,
    I tried placing the I2C#OneAddr in the writebyte command initially but I put it in the wrong spot. When I do this I2C.WriteByte(8, $EE, $f4| I2C#OneAddr, $2e) my END OF CONVERSION pin changes to a logic 1 and I am able to read a value out of the device for temperature. I haven't figured out what the variable means yet, it seems strange that a bunch of math is required just to get the temperature.

    Shawn
  • ShawnaShawna Posts: 508
    edited 2013-04-08 16:01
    Next,
    Now it is time to read out the Pressure! I am having a hard time understanding the data sheet. The Uncompensated Pressure can be read out in either a 16 bit or 19 bit value. This is what I have tried, does this look reasonable, or does it look messed up. I am about ready to write the Compensated Pressure routine. When I run this program I do get a reading. The reason I question this is, if I read out MSB, LSB, and XLSB and display them individually I get strange values. MSB should be 8 bits, LSB should be 8 bits, and XLSB should be 3 bits. However my XLSB value can be as high as 128, and I don't understand how you can get 128 from a 3 bit value.

    Also I do not understand this equation either but it came straight out of the data sheet.

    UP := (MSB<<16 + LSB<<8 + XLSB)>> (8 - Mode)
    Mode := 3
    I2C.WriteByte(8, $EE, $f4| I2C#OneAddr, $34|(mode<<6))
     
      waitcnt ((clkfreq / 38) + cnt)                       'Pause 26 mS
    
    
      MSB  := I2C.ReadByte(8, $EE, $F6| I2C#OneAddr)         
      LSB  := I2C.ReadByte(8, $EE, $F7| I2C#OneAddr)
      XLSB := I2C.ReadByte(8, $EE, $F8| I2C#OneAddr)
      
     UP := (MSB<<16 + LSB<<8 + XLSB)>> (8 - Mode)
    

    Thanks
    Shawn
  • kuronekokuroneko Posts: 3,623
    edited 2013-04-08 16:44
    I haven't checked the datasheet recently but from the equation it looks like the XLSB is left justified (the whole thing is then shifted right by 5), e.g.
    (%mmmmmmmm_llllllll_xxx-----) >> (8 - 3)
    
  • ShawnaShawna Posts: 508
    edited 2013-04-08 16:57
    That makes sense to me, I think maybe I am getting valid results, onto the compensated pressure. I live a mile south of an airfield that should be close enough to compare pressure readings shouldn't it.
    Thanks
    Shawn
  • ShawnaShawna Posts: 508
    edited 2013-04-09 16:51
    Wow that was fun, I finished the math routine to calculate compensated pressure, and I had no way of telling if it was in the ball park or not. So I found an online calculator for altitude from hPA. I plugged my value in and got an altitude back of 1225 ft. I got kind of bumbed because I thought the area I lived in was more like 2500 - 3000 ft. Anyways I looked up the altitude of the airfield that is a mile away and it said 1219 ft above sea level. I think it is working and I am stoked. Next I need to figure out how to run the math for converting hPA into altitude.

    Thanks again Kuroneko and also to Tim Moore who's program I modeled mine off of. I think I have a better understanding of the Basic I2C Drivers now also. I will post my code once I have it cleaned up.
    Shawn
Sign In or Register to comment.