Shop OBEX P1 Docs P2 Docs Learn Events
10DOF L3G4200D+ADXL345+HMC5883L+BMP085 Not working? — Parallax Forums

10DOF L3G4200D+ADXL345+HMC5883L+BMP085 Not working?

VadooVadoo Posts: 92
edited 2014-03-04 10:45 in Propeller 1
I recently purchased a cheap 10DOF board at: http://www.newegg.com/Product/Product.aspx?Item=9SIA2C51450314

I cant get the thing to work. Iv'e tried more programs then I can count. I have been able to get some information from the pressure sensor, but even that is screwy. I thought it was a problem with the module, so I had them send me another one, but I'm getting the same results. I thought I had the gyro and compass working at one point with the first board. I even notated the programs as "working". But after having some success from the pressure sensor, I went back to those "working" programs and got nothing. All "0" or "-1" x y z values.

I'm a bit lost at the moment. I doubt I have two bad modules. It has to be something I'm doing..... Can anyone point me in the right direction?
Thanks!

Comments

  • VadooVadoo Posts: 92
    edited 2014-02-25 13:34
    Iv'e attached the code I'm working with right now in an attempt to use the ADXL345. I swear this worked before. Its one on the first programs I tried. Now Its failing to see the device..
  • ChrisGaddChrisGadd Posts: 310
    edited 2014-02-26 06:25
    There's a problem in the Read2byte method in ADXL345Object.
    Read2byte(_axis) : data | t1
    
       StartI2C
       Write(deviceAddressWrite | 0)
       Write(_axis)
       StartI2C
       Write(deviceAddressRead | 0)
    
       data := 0
       dira[SDA]~                          ' Make SDA an input
       repeat 8                            ' Receive data from SDA
          outa[SCL]~~                      ' Sample SDA when SCL is HIGH
          data := (data << 1) | ina[SDA]
          outa[SCL]~
    
    ' The ACK bit wasn't being sent correctly, so the routine was only reading one byte
    
       dira[SDA]~~                         ' data to output
       outa[SDA] := ACK                    ' Output ACK
       outa[SCL]~~                         ' clock high
       outa[SCL]~                          ' clock low      
       dira[SDA]~                          ' data to input
    {
     The data is retrieved low-byte first, then high byte
      there are numerous ways to rearrange it to high-byte/low-byte, but your method doesn't do it
     Simplest, IMO, is to store the low-byte in a local variable (t1 in this case) and
      append it to the high-byte after it's been shifted
    }
    
      t1 := data                           ' store data in a local variable
      data := 0                            ' initialize data for high_byte
    
       repeat 8                            ' Receive data from SDA
          outa[SCL]~~                      ' Sample SDA when SCL is HIGH
          data := (data << 1) | ina[SDA]
          outa[SCL]~
          
    '  data := data << 16                  ' Shift data bits 16 bits left these are LSB
       data := ~data << 8                  ' sign-extend high-byte data and shift to bits 15-8
       data |= t1                          ' OR low byte into bits 7-0
     
       outa[SDA] := NAK                    ' Output NAK to SDA
       
       dira[SDA]~~
       outa[SCL]~~                         ' Toggle SCL from LOW to HIGH to LOW
       outa[SCL]~
       outa[SDA]~                          ' Leave SDA driven LOW
       StopI2C
    
    '  data := data <- 8                   ' puts the 8MSB to the 8LSB
    '  data := ~data                       ' extend sign
    
  • VadooVadoo Posts: 92
    edited 2014-02-26 07:06
    Thank you very much for the reply.

    I greatly appreciate the corrected and notated code. This should help avoid any trouble once that program is able to read data.Right now it is having trouble seeing the device. The method ReadDeviceID seems to be the area of issue. I am getting an "ADXL345 Chip Not Present...Aborting!" message.

    I did find another bit of code last night that is able to read from the ADXL345 accelerometer. I have also been able to read from the HMC5883L Compass and the BMP085 Pressure Sensor. I do have problems with some of the information I'm receiving from those devices, but I believe its in my code, not the devices, so I'll come back to that.

    What I still can not get any response from is the L3G4200D Gyro. I am attaching some code I am playing with for that. I have spent hours going through the code and the gyro documentation, but it looks right. I think I'm spending too much time on it, and am probably overlooking something simple...
  • ChrisGaddChrisGadd Posts: 310
    edited 2014-02-26 07:47
    As luck has it I happen to have a L3G4200D module from Parallax, and it seems to working just fine with your object. The Ang rate instantly shows what the sensor is doing, the integrated doesn't quite return to the starting value, but gets close.

    I notice that this object and the ADXL345 object both include their own I2C driver methods and use the same I2C pins. If you're running all of these objects simultaneously they could well be interfering with each other on the bus.
    There are numerous stand-alone I2C object in the obex, including a couple in my sig. Just call the appropriate method in the I2C object and use the returned data in your main routine.

    I had another thought about the Read2byte method; just juse Mike Green's existing methods like so:
    PUB Read2byte(_axis) | low_byte, high_byte
    
      StartI2C
      Write(deviceAddressWrite)
      Write(_axis)
      StartI2C
      Write(deviceAddressRead)
    
      low_byte := read(Ack)
      high_byte := read(NAK)
    
      StopI2C
    
      result := ~high_byte << 8 | low_byte
    
    As for why your demo isn't seeing it, the demo is trying to address the module at device ID $53, which requires the ALT address pin to be grounded, so that's where I'd check next.
    Included in the I2C routines in my sig is a I2C poller that returns the 7-bit address of everything on the bus.
  • User NameUser Name Posts: 1,451
    edited 2014-02-26 09:20
    Vadoo wrote: »
    Can anyone point me in the right direction?

    Too funny!
  • VadooVadoo Posts: 92
    edited 2014-02-26 12:06
    ChrisGadd wrote: »
    As for why your demo isn't seeing it, the demo is trying to address the module at device ID $53, which requires the ALT address pin to be grounded, so that's where I'd check next.
    I'll try to check this.
    ChrisGadd wrote: »
    Included in the I2C routines in my sig is a I2C poller that returns the 7-bit address of everything on the bus.
    I first tried this by changing only the scl, sda pins to 26 and 27. I then tried a few other things but cant get anything out of it. I also tried the gyro demo with no luck. It seems to get stuck somewhere.
    I like the idea of a polling routine. That seems to be the simplest way of verifying what I have works. At this point I'm starting to wonder if I have two bad boards??
  • ChrisGaddChrisGadd Posts: 310
    edited 2014-02-26 13:28
    Gyah, why is it never simple?

    Okay, try this poller based on Mike Green's routines. My I2C routines require pull-ups on both the SDA and SCL lines, whereas Mike's routines drive them high, so I figure this is at least worth a shot.

    Poller - Archive.zip
  • VadooVadoo Posts: 92
    edited 2014-02-26 15:21
    ChrisGadd wrote: »
    Gyah, why is it never simple?

    Okay, try this poller based on Mike Green's routines. My I2C routines require pull-ups on both the SDA and SCL lines, whereas Mike's routines drive them high, so I figure this is at least worth a shot.

    Poller - Archive.zip

    The good news is I did get a reply from this one!
    The bad news is I only got three replies....
    Device found at 0011110
    Device found at 1101001
    Device found at 1110111
    Finished
    I have not looked to see what the addresses are yet, but I'm betting its all but the gyro. I'll check the data sheets in a few..

    Thanks!
  • VadooVadoo Posts: 92
    edited 2014-02-26 17:19
    According to the datasheets I should be getting:
    HMC5883L=1E 00011110 (which I received)
    L3G4200D=D2 1101001 (which I received) This is the Gyro. It lives???
    ADXL345= E5 11100101 (NOT RECEIVED) ???
    BMP085= EF or EE 1110111 (I think I got an EE, not sure since the bin is 7 digits. I tried adjusting the code but it put a 0 at the front not the back where it should be)
  • ChrisGaddChrisGadd Posts: 310
    edited 2014-02-26 20:29
    I'm at a loss as to why the ADXL345 doesn't return an address, however your gyro code failed for the same reason that my poller routine failed.
    There are a couple solutions to that one, either put pull-up resistors on the SDA and SCL lines, or use an I2C driver that drives the SDA and SCL lines high and low.
  • VadooVadoo Posts: 92
    edited 2014-02-27 06:57
    ChrisGadd wrote: »
    There are a couple solutions to that one, either put pull-up resistors on the SDA and SCL lines, or use an I2C driver that drives the SDA and SCL lines high and low.
    I really thought the board included pull-ups. Of course I opted for a cheap chinese board with no support/documentation, so who knows...
    I'll try playing with this and see what happens shortly.
  • VadooVadoo Posts: 92
    edited 2014-02-27 08:34
    So I tried adding 2k resistors from vcc to scl and vcc to sda. I tried it with all the different programs I have with no change. I did manage to find a way of bringing up a lot of information on this specific board searching for part number GY-80. Unfortunately this brings up lots of Arduino code only, and I have been resisting the urge to switch platforms for a while. However they do have a LOT of support for a lot of stuff... Sorry, shouldn't say that on here! But maybe someone here is bilingual and can help me interpret the apparent functional code offered all over the internet for the Arduino?
  • VadooVadoo Posts: 92
    edited 2014-02-27 19:29
    I found the pull up resistors should be 10k, which I tried, no change..

    So here's what I'm working on now in an attempt to communicate with the Gyro:
    CON
      _clkmode = xtal1 + pll16x                                                      
      _xinfreq = 5_000_000
    
       SCL      = 26       ' I2C SCL Pin
       SDA      = 27       ' I2C SDA Pin  
       write    = $D2
       read     = $D3
       DeviceID = $69
       Register = $28
    VAR
    
    
    OBJ
      I2C   : "Basic_I2C_Driver"
      FDS   : "FullDuplexSerial"
    
    PUB Main | Device_ID, x
      FDS.start(31,30,0,115_200)
      I2C.initialize(SCL)
      waitcnt(cnt + clkfreq*5)
      FDS.tx($00)
                                          
      repeat 
        I2C.start(SCL)
        I2C.write(SCL, write << 1)
        I2C.write(SCL, Register << 1)
        I2C.start(SCL)
        I2C.write(SCL, read << 1)
        X := (I2C.read(SCL, 1)) | (I2C.read(SCL, 0)) <<8
        I2C.stop(SCL)
    
       FDS.tx($00)
       FDS.str(string("x: "))
       FDS.dec(x)
    

    So far all I get out of it is (x: 255).
  • VadooVadoo Posts: 92
    edited 2014-02-28 06:05
    I added some code to look at each acknowledgement from the Gyro.

    Here's the code:
      repeat 
        sak1 := I2C.start(SCL)
        sak2 := I2C.write(SCL, write << 1)
        sak3 := I2C.write(SCL, Register << 1)
        sak4 := I2C.start(SCL)
        sak5 := I2C.write(SCL, read << 1)
        data := (I2C.read(SCL, 1)) | (I2C.read(SCL, 0)) <<8
        sak6 := I2C.stop(SCL)
    
       FDS.tx($00)
       FDS.str(string(13, "sak1: "))
       FDS.hex(sak1, 2)
       FDS.str(string(13, "sak2: "))
       FDS.hex(sak2, 2)
       FDS.str(string(13, "sak3: "))
       FDS.hex(sak3, 2)
       FDS.str(string(13, "sak4: "))
       FDS.hex(sak4, 2)
       FDS.str(string(13, "sak5: "))
       FDS.hex(sak5, 2)
       FDS.str(string(13, "sak6: "))
       FDS.hex(sak6, 2)
       FDS.str(string(13, "data: "))
       FDS.hex(data, 2)
       waitcnt(cnt + clkfreq/50)
    

    Here's the response:
    sak1: 00
    sak2: 01
    sak3: 01
    sak4: 00
    sak5: 01
    sak6: 00
    data: FF

    All is as expected but the data being returned.

    What is not expected, I get the same reply when the SCL is disconnected. I do get all 0's when the SDA is disconnected.
  • ChrisGaddChrisGadd Posts: 310
    edited 2014-02-28 11:54
    Vadoo wrote: »
    I found the pull up resistors should be 10k, which I tried, no change..

    So here's what I'm working on now in an attempt to communicate with the Gyro:
    CON
      _clkmode = xtal1 + pll16x                                                      
      _xinfreq = 5_000_000
    
       SCL      = 26       ' I2C SCL Pin
       SDA      = 27       ' I2C SDA Pin  
       write    = $D2
       read     = $D3
       DeviceID = $69
       Register = $28
    VAR
    
    
    OBJ
      I2C   : "Basic_I2C_Driver"
      FDS   : "FullDuplexSerial"
    
    PUB Main | Device_ID, x
      FDS.start(31,30,0,115_200)
      I2C.initialize(SCL)
      waitcnt(cnt + clkfreq*5)
      FDS.tx($00)
                                          
      repeat 
        I2C.start(SCL)
    [color=red]    I2C.write(SCL, write [b]<< 1[/b])[/color]
        I2C.write(SCL, Register << 1)
        I2C.start(SCL)
    [color=red]    I2C.write(SCL, read [b]<< 1[/b])[/color]
        X := (I2C.read(SCL, 1)) | (I2C.read(SCL, 0)) <<8
        I2C.stop(SCL)
    
       FDS.tx($00)
       FDS.str(string("x: "))
       FDS.dec(x)
    

    So far all I get out of it is (x: 255).

    This is more of that 7-bit / 8-bit device ID confusion. You already have the 8-bit address $D2 defined for write, and $D3 defined for read, so you don't need to shift any. Try it again without the << 1.
    Alternately, use the 7-bit address defined in DeviceID ($69), with a << 1 for write, and a << 1 | 1 for read.

    Also, you're trying to read register $28 << 1, which is register $50, and the datasheet doesn't mention what lives there.
    Register $28 is the low-byte of the gyro X-axis, however LG4200 is non-standard in that in order to read consecutive bytes, the msb must set.
    In order to read consecutive registers starting from $28 (%0010_1000), you need to address $A8 (%1010_1000).
  • VadooVadoo Posts: 92
    edited 2014-02-28 12:55
    ChrisGadd wrote: »
    This is more of that 7-bit / 8-bit device ID confusion. You already have the 8-bit address $D2 defined for write, and $D3 defined for read, so you don't need to shift any. Try it again without the << 1.
    When I remove <<1, I lose the acknowledgement from the Gyro at each step I remove it from.
    Also, you're trying to read register $28 << 1, which is register $50, and the datasheet doesn't mention what lives there.
    Register $28 is the low-byte of the gyro X-axis, however LG4200 is non-standard in that in order to read consecutive bytes, the msb must set.
    In order to read consecutive registers starting from $28 (%0010_1000), you need to address $A8 (%1010_1000).
    I just went back to the Gyro documentation and this makes sense now.
    "The 7 LSb represent the actual register address while the MSB enables address auto-increment. If the
    MSb of the SUB field is 1, the SUB (register address) is automatically incremented to allow
    multiple data read/write."
  • ChrisGaddChrisGadd Posts: 310
    edited 2014-02-28 14:21
    Hmm, curiouser and curiouser. Do you by chance have an EEPROM on the same I2C bus as the gyro? $D2 (%1101_0010) << 1 was sending %1_1010_0100 to the I2C routine, which was chopping off the high bit and sending %1010_0100, which is a write to an EEPROM type device.
    I looked at it on a logic analyzer, and sure enough it was trying to write to $A4, which was not being acknowledged by anything on my board.

    I did eventually manage to get the following code to at least show some activity when gyro was jostled.
    CON
      _clkmode = xtal1 + pll16x                                                      
      _xinfreq = 5_000_000
    
       SCL      = 26       ' I2C SCL Pin
       SDA      = 27       ' I2C SDA Pin  
       write    = $D2
       read     = $D3
       DeviceID = $69
       Register = $A8'$28
    VAR
    
    
    OBJ
      I2C   : "Basic_I2C_Driver"
      FDS   : "FullDuplexSerial"
    
    PUB Main | Device_ID, x
      FDS.start(31,30,0,115_200)
      I2C.initialize(SCL)
      waitcnt(cnt + clkfreq * 5)
      FDS.tx($00)
    
      I2C.start(SCL)
      I2C.write(SCL,write)
      I2C.write(SCL,$22)
      I2C.write(SCL,$08)                                    ' Enable data read signal
      I2C.stop(SCL)
    
      I2C.start(SCL)
      I2C.write(SCL,write)
      I2C.write(SCL,$23)
      I2C.write(SCL,$80)                                    ' Enable block data update
      I2C.stop(SCL)
    
      I2C.start(SCL)
      I2C.write(SCL,write)
      I2C.write(SCL,$20)
      I2C.write(SCL,$1F)                                    ' Enable all axis, 100Hz update
      I2C.stop(SCL)
    
      repeat
        I2C.start(SCL)                                      ' Check to see if new data is available for x, y, or z                         
        I2C.write(SCL,write)                                                        
        I2C.write(SCL,$27)
        I2C.start(SCL)
        I2C.write(SCL,read)
        x := (I2C.read(SCL,1))
        I2C.stop(SCL)
        if x & $08
           dira[16]~~
           dira[16]~
                                                                                    
           I2C.start(SCL)
           I2C.write(SCL,write)                                                          
           I2C.write(SCL,$A8)
           I2C.start(SCL)
           I2C.write(SCL,read)
           X := (I2C.read(SCL,0) | I2C.read(SCL,0) << 8)    ' For whatever reason, it only works when both bytes are sent with ACKs
           I2C.stop(SCL)
           
          FDS.tx($00)
          FDS.str(string("x: "))
          FDS.dec(x)
    

    I don't at all understand why both bytes needed to be ACK'd, but without that all I got were static readings.

    And I'm also not at all sure why Mike's driver is working when no others are. I've modified my driver to drive SCL and SDA high and low, as the pull-up resistors are really the only non-standard thing I see about his driver.
    Gyroscope demo - Archive.zip
  • VadooVadoo Posts: 92
    edited 2014-02-28 14:40
    THIS WORKS!!!! I haven't gone through the code yet to see why, but thank you very much!
    Now for the rest of my troubles :)
    I'll get to the specifics once I have a chance to wrap my brain around the solution to this problem. But ultimately I would like to write a program to read all values from this board to share with everyone, as it seems to have become a popular board (at least with the Audrino community) and should probably be equally supported here!
  • VadooVadoo Posts: 92
    edited 2014-02-28 15:05
    I see this is setting three registers:
     I2C.Write(I2C#Gyro,$22,$08)                                                   ' Enable data read signal
     I2C.Write(I2C#Gyro,$23,$80)                                                   ' Enable block data update
     I2C.Write(I2C#Gyro,$20,$1F)                                                   ' Enable all axis, 100Hz update
    
    Which I had tried at one point after seeing it in other code. Though I dodn't completely understand all of the settings in those registers.

    But this seems to be the key:
    repeat until I2C.Read(I2C#Gyro,$27) & $08
    
    Though I don't understand some of the characters and what they are doing, it seems its waiting for a change in the x, y, z values before reading them.
  • ChrisGaddChrisGadd Posts: 310
    edited 2014-02-28 16:32
    I forget how I got those configuration settings. According to the datasheet, bit 4 in register $22 sets 'Date Ready on DRDY/INT2'. I thought it might be the new-data flag, but commenting it out doesn't seem to have any noticeable effect, so it's probably something I copied from someone else's code without knowing why.
    Bit 7 in register $23 I believe ensures that when you perform a multi-byte reading, as in reading the high-byte and low-byte of a sample, both bytes come from the same sample... I think.
    $1F written to register $20 sets the bandwidth, sets normal mode or sleep mode, and enables the three axis.
    Bit 8 in register $27 is, as you figured, set when new data is available to be read.

    Oh, and as for the acknowledgements that you were seeing when addressing $D2 << 1, the SDA line is pulled low to indicate ACK, or left floating (pulled up high) to indicate a NAK, so a '1' returned is NAK, '0' returned is ACK.
  • VadooVadoo Posts: 92
    edited 2014-03-04 10:45
    So far I have good control over the read and write variables in the Gyro and Compass. I am also able to read everything from the pressure sensor, but have some problems with the calculations of temp and pressure. The temp is coming out as 100+c. It goes down if I blow on it so it seems to be working, but calculating wrong? Also, the calculated pressure doesn't change, though the UP variable does. I've attached "Pressure Demo".

    I'm also having problems with the accelerometer. I can't figure out how to read anything from it yet.

    I'll attach "10DOF" which reads from the Gyro and Compass. It then tries to read from the accelerometer, but seems to only loop through (repeat) one time then lock up. The data it puts out for the accel is 65535 for x, y and z. This is the object I'm building for reading everything from the 10DOF.

    I'll also attach "ADXL3450ObjectDemo", a functional program that is able to read from the accelerometer. I can't figure out what its doing that I'm not.
Sign In or Register to comment.