L3G4200D Gyroscope in SPI Mode

Hi everyone,

I'm trying again to figure out how to get data from the Parallax L3G4200D gyroscope module in 3-wire SPI mode. The datasheet can be found here: https://www.parallax.com/sites/default/files/downloads/27911-L3G4200D-Gyroscope-Manufacturer-Datasheet.pdf. My code is below:
#include "simpletools.h"
signed char z; //Stores the gyroscope measurement
int main(){
  high(14); //CS line high (SPI inactive)
  low(13); //CLK line low (prepares chip to send brief high signals or clock pulses)
  low(14); //CS line low (start SPI)
  
  shift_out(12, 13, MSBFIRST, 8, 0b01100011); //Write MCTL register (register 4) to set 3-wire SPI
  //shift_out(12, 13, MSBFIRST, 1, 0b0); //Send don't care bit
  shift_out(12, 13, MSBFIRST, 8, 0b00000001); //Value for MCTL register (register 4) to set 3-wire SPI
  
  // Set 100Hz output rate, 25Hz cutoff freq, normal mode, enable all axes
  shift_out(12, 13, MSBFIRST, 8, 0b01100000); //Write MCTL register (register 1)
  //shift_out(12, 13, MSBFIRST, 1, 0b0); //Send don't care bit
  shift_out(12, 13, MSBFIRST, 8, 0b00011111); //Value for MCTL register (register 1)
  
  high(14); //CS high(stop SPI)
  pause(1);
  
  while(1){ //Main loop
    low(14); //CS low selects chip
    shift_out(12, 13, MSBFIRST, 8, 0b11101100); //Send read register address (OUT_Z_L)
    //shift_out(12, 13, MSBFIRST, 1, 0b0); //Send don't care value
    z = shift_in(12, 13, MSBPRE, 8); //Get value from register
    z = z-0; //Remove bias
    float zf = (float) z; //Convert z from signed char to float
    high(14); //De-select chip with CS line high
    print("z = %f\n", zf);
    pause(50); //Cycle at 20Hz
  }
}

First, I initialize SPI mode. Then, I set 3-wire SPI mode by writing to register 4. I believe there is an error in the datasheet because it says to set the SIM bit to 1 in register 2, however, SIM is in register 4, not 2. After that I write to register 1, setting a 100Hz output rate, 25Hz cutoff frequency, normal mode, and enable all axes. In the main loop I read from the OUT_Z_L register. I have commented out the "send don't care bit" lines because the datasheet doesn't say that is required, unlike the accelerometer's datasheet. When I run the code as is, I get a constant stream of z = 41.00. If I do not convert z to a float I get a constant stream of 0.

Could someone please help me figure out how to get correct data? I realize I also need to get OUT_Z_H data and do something with the two values but that can be the next step. Thank you.

Respectfully,
David

Comments

  • 20 Comments sorted by Date Added Votes
  • Hello mods,

    Perhaps my post above would be better suited for the "Robotics" or "Accessories" sections. Would you mind moving it, please?

    Thank you,
    David
  • Did you try sending the "don't care bit"?
    With some SPI devices you have to send the "deselect", "select" sequence between each command. I don't know if that is the case with this one.
    Tom
  • Hi Tom,

    Yes I just tried your suggestion and the only thing that changes is I get a different value for the steady stream of outputs. I've also tried to add the Who_Am_I register to see if the chip is actually communicating. Here is the current code:
    #include "simpletools.h"
    signed int zL; //Stores the gyroscope measurement
    signed int zH;
    int whoAmI;
    
    int main(){
      high(14); //CS line high (SPI inactive)
      low(13); //CLK line low (prepares chip to send brief high signals or clock pulses)
      low(14); //CS line low (start SPI)
      
      shift_out(12, 13, MSBFIRST, 8, 0b00001111); //Write who am I register
      shift_out(12, 13, MSBFIRST, 1, 0b0); //Send don't care bit
      shift_out(12, 13, MSBFIRST, 8, 0b11010011); //Value who am I register
      whoAmI = shift_in(12, 13, MSBPRE, 8);
      print("whoAmI = %x\n", whoAmI);
      
      shift_out(12, 13, MSBFIRST, 8, 0b01100011); //Write MCTL register (register 4)to set 3-wire SPI and 250 deg/s
      shift_out(12, 13, MSBFIRST, 1, 0b0); //Send don't care bit
      shift_out(12, 13, MSBFIRST, 8, 0b10000001); //Value for MCTL register (register 4) to set 3-wire SPI and 250 deg/s
      
      shift_out(12, 13, MSBFIRST, 8, 0b00100010); //Write MCTL register (register 3)to set data ready signal
      shift_out(12, 13, MSBFIRST, 1, 0b0); //Send don't care bit
      shift_out(12, 13, MSBFIRST, 8, 0b00001000); //Value for MCTL register (register 3) to set data ready signal
      
      // Set 100Hz output rate, 25Hz cutoff freq, normal mode, enable all axes
      shift_out(12, 13, MSBFIRST, 8, 0b01100000); //Write MCTL register (register 1)
      shift_out(12, 13, MSBFIRST, 1, 0b0); //Send don't care bit
      shift_out(12, 13, MSBFIRST, 8, 0b00011111); //Value for MCTL register (register 1)
      
      high(14); //CS high(stop SPI)
      pause(1);
      
      while(1){ //Main loop
        low(14); //CS low selects chip
        shift_out(12, 13, MSBFIRST, 8, 0b10101100); //Send read register address (OUT_Z_L)
        shift_out(12, 13, MSBFIRST, 1, 0b0); //Send don't care bit
        zL = shift_in(12, 13, MSBPRE, 8); //Get value from register
        
        shift_out(12, 13, MSBFIRST, 8, 0b10101101); //Send read register address (OUT_Z_H)
        shift_out(12, 13, MSBFIRST, 1, 0b0); //Send don't care bit
        zH = shift_in(12, 13, MSBPRE, 8); //Get value from register
    
        high(14); //De-select chip with CS line high
        print("zL = %d     zH = %d\n", zL, zH);
        pause(500); //Cycle at 20Hz
      }
    }
    

    Does it appear that I've implemented the Who_Am_I call correctly? The output is hex value ff. I have no idea what that means or what I should be getting from the Who_Am_I register.

    Thanks,
    David
  • Between each complete command, try adding
    high(14); //De-select chip with CS line high
    low(14); //CS low selects chip    
    

    See the example below in your main loop.
     while(1){ //Main loop
        low(14); //CS low selects chip
        shift_out(12, 13, MSBFIRST, 8, 0b10101100); //Send read register address (OUT_Z_L)
        shift_out(12, 13, MSBFIRST, 1, 0b0); //Send don't care bit
        zL = shift_in(12, 13, MSBPRE, 8); //Get value from register
    
    // add deselect; select statements like this after each command
    // do this also for each group of commands before the while loop 
    high(14); //De-select chip with CS line high
    low(14); //CS low selects chip    
    // **************
    
        shift_out(12, 13, MSBFIRST, 8, 0b10101101); //Send read register address (OUT_Z_H)
        shift_out(12, 13, MSBFIRST, 1, 0b0); //Send don't care bit
        zH = shift_in(12, 13, MSBPRE, 8); //Get value from register
    
        high(14); //De-select chip with CS line high
        print("zL = %d     zH = %d\n", zL, zH);
        pause(500); //Cycle at 20Hz
      }
    
  • Tom,

    Thank you so much for the suggestion!! I may be on to something here. I've implemented your recommendations and I'm getting different values for zL and zH when I move the board around. Now I think the next step is for me to figure out how to combine the zL and zH numbers to get meaningful data.

    Also, I'm still getting a hex value of ff when I try the whoAmI function. Here is that block of code:
    low(14);
      shift_out(12, 13, MSBFIRST, 8, 0b00001111); //Write who am I register
      //shift_out(12, 13, MSBFIRST, 8, 0b11010011); //Value who am I register
      whoAmI = shift_in(12, 13, MSBPRE, 8);
      high(14);
      print("whoAmI = %x\n", whoAmI);
    

    Do you know how the whoAmI register function is supposed to work? I am writing the address of the whoAmI register (0b00001111) and then reading from that register, calling the output "whoAmI". Then I attempt to print the value. I'm not sure what is supposed to be printed. I thought it might to be 11010011, which is the value given in the datasheet for that register.

    Thanks again for your help! I was getting pretty frustrated and now I can see some light at the end of the tunnel!

    Respectfully,
    David
  • Tom,

    By the way, how did you know that you need to set the chip select low before each transmission and high after each transmission? Is that something you just know, or is that in the datasheet and I should have seen it?

    Also, for anyone else, I want to mention that it only outputs a constant stream of 255 if you send the "don't care bit". I believe it's important to leave that line of code out for this gyroscope module, whereas the accelerometer datasheet specifically says to send the "don't care bit".

    David
  • Tom,

    By the way, how did you know that you need to set the chip select low before each transmission and high after each transmission? Is that something you just know, or is that in the datasheet and I should have seen it?

    Also, for anyone else, I want to mention that it only outputs a constant stream of 255 if you send the "don't care bit". I believe it's important to leave that line of code out for this gyroscope module, whereas the accelerometer datasheet specifically says to send the "don't care bit".

    David

    Glad to read that you are making progress. It's been a while, but I think I first read this SPI tutorial that showed the high-low cycle after each command group here:
    learn.parallax.com/tutorials/language/propeller-c/propeller-c-simple-protocols/spi-example

    Then I tried writing code for the 1620 temperature sensor. I tried without the high-low cycle and it didn't work. So I just use it whenever I use an SPI device. When you look at the timing diagrams, it shows the CS line going high at the end of the command sequence.

    I just looked at the data sheet in the link you provided in your original post. I don't see any reference to a don't care bit (although it's 4AM here and I might have missed it.) Usually it would be clearly shown in the timing diagram. For devices where it is shown, I've always found it necessary.

    I have no idea how the who-am-I command is supposed to work. I didn't see anything in the data sheet explaining it.

    Tom
  • I'm not sure if this helpful for your SPI effort, but this works with the L3G4200D using i2c.

    This came from the following thread:
    forums.parallax.com/discussion/155488/l3g4200d-3-axis-gyroscope

    I made some modifications to the code to work with the L3G4200D rather than the MPU6050
    /*
      Test code modified for the MPU6050 gyro
      JM - Modified for the L3G4200D gyro
    */
    
    #include "simpletools.h"
    
    unsigned char i2cAddr = 0b1101001;       //I2C address of Gyro if AD0 is high
    // unsigned char i2cAddr = 0b1101000;       //I2C address of Gyro if AD0 is low
    
    //unsigned char devId = 0x75;         //Device ID register
    unsigned char devId = 0x0f;         //Device ID register
    unsigned char reply;
    
    i2c *bus;
    
    int main()
    {
      bus = i2c_newbus(2, 4, 0);      //Set I2C bus SCL = P5, SDA = P4
    
      i2c_in(bus, i2cAddr, devId, 1, &reply, 1); 
      
      //if(reply == 0b01101000)
      if(reply == 0b11010011)
        print("Device ID confirmed: %b\n", reply);
      else
        print("Error, wrong device ID: %b\n", reply);
    }
    


    When this is loaded to an Activity Board with a L3G4200D I get the following in the serial term output.
     
      Device ID confirmed: 11010011
    
    


    This seems to match the data sheet values for 'WHO_AM_I'

    WHO_AM_I r 0F 000 1111 11010011
  • Hi Tom and Jon,

    Thank you both your help. I realized my mistake with the whoAmI register was simple - I was using a write bit (0) instead of a read bit (1). I also figured out the 2's complement operation to combine the zL and zH values. The measurements jump around quite a bit, certainly more than I would expect. In the next few days I will try implementing the data ready function and perhaps some of the other available filters to see if that helps. Thank you again. My current code is below:
    #include "simpletools.h"
    signed int whoAmI;
    signed int zL, zH, z, zSum, zAvg;
    
    int main(){
      high(14); //CS line high (SPI inactive)
      low(13); //CLK line low (prepares chip to send brief high signals or clock pulses)
      
      low(14);
      shift_out(12, 13, MSBFIRST, 8, 0b10001111); //Send read register address (whoAmI)
      whoAmI = shift_in(12, 13, MSBPRE, 8);
      high(14);
      
      if(whoAmI == 0b11010011){
        print("Device ID Correct: %b\n", whoAmI);
      }
      else{
        print("Device ID Incorrect: %b\n", whoAmI);
      } 
      
      low(14); //CS line low (start SPI)
      shift_out(12, 13, MSBFIRST, 8, 0b01100011); //Write MCTL register (register 4)to set 3-wire SPI
      shift_out(12, 13, MSBFIRST, 8, 0b00000001); //Value for MCTL register (register 4) to set 3-wire SPI
      high(14);
      
      // Set 100Hz output rate, 25Hz cutoff freq, normal mode, enable all axes
      low(14);
      shift_out(12, 13, MSBFIRST, 8, 0b01100000); //Write MCTL register (register 1)
      shift_out(12, 13, MSBFIRST, 8, 0b00011111); //Value for MCTL register (register 1)
      high(14); //CS high(stop SPI)
      
      pause(1);
      
      low(14); //CS low selects chip
      shift_out(12, 13, MSBFIRST, 8, 0b11101100); //Send read register address (OUT_Z_L)
      zL = shift_in(12, 13, MSBPRE, 8); //Get value from register
      high(14); //De-select chip with CS line high
        
      low(14);
      shift_out(12, 13, MSBFIRST, 8, 0b10101101); //Send read register address (OUT_Z_H)
      zH = shift_in(12, 13, MSBPRE, 8); //Get value from register
      high(14);
      
      //Get z-axis zero-rate offset (zAvg)
      for(int i=0; i<100; i++){
        z = (zL<<8 | zH);
        zSum += z;
      }    
      zAvg = zSum/100;
      print("zAvg = %d\n", zAvg);
      
      
      
    
      while(1){ //Main loop
        low(14); //CS low selects chip
        shift_out(12, 13, MSBFIRST, 8, 0b11101100); //Send read register address (OUT_Z_L)
        zL = shift_in(12, 13, MSBPRE, 8); //Get value from register
        high(14); //De-select chip with CS line high
        
        low(14);
        shift_out(12, 13, MSBFIRST, 8, 0b10101101); //Send read register address (OUT_Z_H)
        zH = shift_in(12, 13, MSBPRE, 8); //Get value from register
        high(14);
        
        z = (zL<<8 | zH)-zAvg; //2's complement operation
        float zf = (float) z; //Change to a float
        zf = zf*0.00875; //Multiply by sensitivity value for 250deg/s
     
        
        print("zf = %f\n", zf);
        pause(50); //Cycle at 20Hz
      }
    }
    
  • Reading through my code above, I think I found another error. It looks like the z-axis zero-rate offset (zAvg) is only getting one value from OUT_Z_L and OUT_Z_H. I need to put those read register blocks within the for loop. I'll do that this evening and get back with an update.

    Thanks,
    David
  • Hi,

    I wasn't getting good measurements (noisy and biased) from my code two posts above. I'm now trying to implement some of the features of the gyroscope such as the data available feature and the digital filters. I am currently reading the status register and getting a binary value. However, to check if data is available on a certain axis, I need to read a single bit value from the string of binary. How can I do this? Please see my current code below. I've tried to highlight the code red where I am working on a block of code to read the status register. From here, I can allow the code to continue if data is available or I can make it go to the top of the loop and check again.
    #include "simpletools.h"
    signed int whoAmI, dataAvail;
    signed int zL, zH, z, zSum, zAvg;
    signed int ZOR;
    
    int main(){
      high(14); //CS line high (SPI inactive)
      low(13); //CLK line low (prepares chip to send brief high signals or clock pulses)
      
      low(14);
      shift_out(12, 13, MSBFIRST, 8, 0b10001111); //Send read register address (whoAmI)
      whoAmI = shift_in(12, 13, MSBPRE, 8);
      high(14);
      
      if(whoAmI == 0b11010011){
        print("Device ID Correct: %b\n", whoAmI);
      }
      else{
        print("Device ID Incorrect: %b\n", whoAmI);
      } 
      
      low(14); //CS line low (start SPI)
      shift_out(12, 13, MSBFIRST, 8, 0b01100011); //Write MCTL register (register 4)to set 3-wire SPI and block data update (BDU)
      shift_out(12, 13, MSBFIRST, 8, 0b00000001); //Value for MCTL register (register 4) to set 3-wire SPI and set BDU to 0
      high(14);
      
      // Set 100Hz output rate, 25Hz cutoff freq, normal mode, enable all axes
      low(14);
      shift_out(12, 13, MSBFIRST, 8, 0b01100000); //Write MCTL register (register 1)
      shift_out(12, 13, MSBFIRST, 8, 0b00011111); //Value for MCTL register (register 1)
      high(14); //CS high(stop SPI)
      
      pause(1);  
    
      //Get z-axis zero-rate offset (zAvg)
      for(int i=0; i<50; i++){
        
       [color="Red"] low(14); //CS low selects chip
        shift_out(12, 13, MSBFIRST, 8, 0b10100111); //Send read register address (STATUS_REG)
        dataAvail = shift_in(12, 13, MSBPRE, 8); //Get value from register
        high(14); //De-select chip with CS line high
        //ZOR = ;
        print("dataAvail = %b\n", dataAvail);
    [/color]    
        low(14); //CS low selects chip
        shift_out(12, 13, MSBFIRST, 8, 0b11101100); //Send read register address (OUT_Z_L)
        zL = shift_in(12, 13, MSBPRE, 8); //Get value from register
        high(14); //De-select chip with CS line high
        
        low(14);
        shift_out(12, 13, MSBFIRST, 8, 0b10101101); //Send read register address (OUT_Z_H)
        zH = shift_in(12, 13, MSBPRE, 8); //Get value from register
        high(14);
        
        z = (zL<<8 | zH);
        zSum += z;
        print("%d\n", z);
        //pause(50);
      }    
      
      zAvg = zSum/50;
      print("zAvg = %d\n", zAvg);
    
      for(int i=0; i<100; i++){
      //while(1){ //Main loop
      
        low(14); //CS low selects chip
        shift_out(12, 13, MSBFIRST, 8, 0b11101100); //Send read register address (OUT_Z_L)
        zL = shift_in(12, 13, MSBPRE, 8); //Get value from register
        high(14); //De-select chip with CS line high
        
        low(14);
        shift_out(12, 13, MSBFIRST, 8, 0b10101101); //Send read register address (OUT_Z_H)
        zH = shift_in(12, 13, MSBPRE, 8); //Get value from register
        high(14);
        
        z = (zL<<8 | zH)-zAvg; //2's complement operation
        float zf = (float) z; //Change to a float
        zf = zf*0.00875; //Multiply by sensitivity value for 250deg/s
     
        print("%f\n", zf); //"zf = %f\n", zf)
        pause(50); //Cycle at 20Hz
      }
    }
    

    Thank you,
    David
  • Hi,

    Here is some sample data from the z-axis. I kept the gyroscope stationary for about the first 100 samples, then rotated it slowly from about 100 samples to 250 samples. It was then stationary to 500 samples. From the plot, you can make out this profile, however, it is not at all clean data. There are many outliers and the data is very noisy. This is why I want to apply the other features of the gyro module. I'm wondering if the outliers are occurring due to new data not being available, but the microcontroller reads it anyway. This is why I'd like to read the status register and only sample the measurements when the status register says new data is available (please see my post above). What are your thoughts on this?

    My ultimate goal is to implement a Kalman filter to fuse these measurements with accelerometer measurements. I've already coded the matrix math functions required for a Kalman filter implementation. I just thought the raw gyroscope data should look a little better than what I am seeing.

    Thank you,
    David
    1632 x 477 - 118K
  • Hi everyone,

    I have noticed an odd behavior with this gyro when I change the sample rate. When I use a sample rate of 20 Hz (pause(50)), I am able to get a good zero-rate offset value to subtract from subsequent measurements. This results in a zero bias, for the most part. However, when I run at a very high sample rate with no pause in between measurements, I am getting an overall bias of almost 100 deg/s! Keep in mind the unit is sitting stationary on my desk. My question is, why does changing the sample rate affect the bias and shouldn't my zero-rate offset calculation take care of this? How does one determine the optimal sample rate? Here is my code for calculating the zero-rate offset value which is subtracted from subsequent measurements:
    //Get z-axis zero-rate offset (zAvg)
      for(int i=0; i<50; i++){
        
        low(14); //CS low selects chip
        shift_out(12, 13, MSBFIRST, 8, 0b11101100); //Send read register address (OUT_Z_L)
        zL = shift_in(12, 13, MSBPRE, 8); //Get value from register
        high(14); //De-select chip with CS line high
        
        low(14);
        shift_out(12, 13, MSBFIRST, 8, 0b10101101); //Send read register address (OUT_Z_H)
        zH = shift_in(12, 13, MSBPRE, 8); //Get value from register
        high(14);
        
        z = (zL<<8 | zH);
        zSum += z;
        print("%d\n", z);
        //pause(50);
      }    
      
      zAvg = zSum/50;
      print("zAvg = %d\n", zAvg);
    

    I've also attached a photo of the bias due to a very high sample rate with no pauses between measurements.

    Thanks,
    David
    1603 x 460 - 98K
  • I would write out your raw, unfiltered, un-averaged samples and look for oddities - In my use of various gyros and accelerometers, the only time I saw noise to that level when the units were stationary was when I got bad readings - you'll sometimes get a reading that's all "on" bits for whatever your bit-length is if the device isn't ready to give you a new reading. If you're outputting floats that have been scaled to a different range, it's going to be harder to see that kind of mistake.
  • Hi Jason,

    Thank you for your suggestion. I will give it a try and report back with my results.

    David
  • Hi Jason,

    I've attached a photo of the raw data that is not scaled (ie. scaled to 250 deg/s) and also that has not had its bias subtracted. By the way, to account for bias I average the first 50 measurements and subtract that average from subsequent measurements.

    Questions:
    1. I noticed that each time I plug my board into the computer and click "Run with Terminal", the device ID is always incorrect. However, on the second "Run with Terminal", the device ID is correct. What could cause this?
    2. How can I ensure that the microcontroller is only reading bits when the gyro has a new reading? I think this might be the cause of the outliers in the data.

    Thank you,
    David
    1611 x 468 - 88K
  • Most of these devices have a status value you can read that will contain a bit flag for when a new reading is available.

    Is the bias for this device in the 60000 range? That's incredibly high. Is it possible that you're reading a 16-bit value that is supposed to be signed, and you're treating it as an unsigned, or 32 bit value? That would explain a lot of your strangeness.

    16 bit unsigned numbers are in the range of 0 to 65535 ( 0x0000 to 0xFFFF), while signed 16-bit values will be -32768 to +32767 (0x8000 to 0x7FFF).

    To me, your unbiased graph looks like your numbers are 16-bit signed, with a slight negative bias. The first few negative numbers are 0xFFFF, 0xFFFE, 0xFFFD, 0xFFFC, ... and so on. Basically like taking a 16 bit unsigned number and subtracting the value so it "wraps around backwards".

    If you had readings of -10, -7, -8, -11, +2, -5, -7, +3, . . . and treated those as 16-bit unsigned numbers it would look exactly like your unbiased graph.
  • JasonDorieJasonDorie Posts: 1,927
    edited November 2 Vote Up0Vote Down
    Try this - Where you have:
        z = (zL<<8 | zH);
    
    use this instead:
        z = (short)(zL<<8 | zH);
    
    That forces the composition of low & high bytes to be treated as a signed 16 bit value before assigning it to z.

    You'll need to do that in both places you do it - IE, in the bias compute loop, and then lower where you're doing the composition and removing the bias.
  • Hi Jason,

    Thank you very much for your responses. They are very helpful to me and you continue to help me move forward when I get stuck. I've attached a new set of data using your suggestion and as you can see, the outliers have gone away and there is zero bias. I'm not sure I quite understand the explanation of why "(short)" works but I will continue to think about it.

    From the datasheet:
    1. Read STATUS_REG
    2. If STATUS_REG(1) = 0 then go to 1
    3. If STATUS_REG(5) = 1 then some data have been overwritten
    4. Read OUT_Z_L
    5. Read OUT_Z_H
    6. Data Processing
    7. Go to 1

    where the STATUS_REG is defined as: [ZYXOR | ZOR | YOR | XOR | ZYXDA | ZDA | YDA | XDA] where OR means overrun and DA means data available.

    In my case, I am working on the z-axis so I would be interested in ZOR and ZDA. When I read the status register I get something like this: dataAvail = 10110011, using the following block of code:
    low(14); //CS low selects chip
        shift_out(12, 13, MSBFIRST, 8, 0b10100111); //Send read register address (STATUS_REG)
        dataAvail = shift_in(12, 13, MSBPRE, 8); //Get value from register
        high(14); //De-select chip with CS line high
        //ZOR = dataAvail[1];
        print("dataAvail = %b\n", dataAvail);
    

    My thought is that I need to read the ZOR and ZDA bits to make the suggested loop in the datasheet. The purpose of this is to only read the sensor when new data is available. ZOR = dataAvail[1]; does not work because dataAvail is not an array, it is a string. Could you please tell me if I have the correct approach and if so, how can I index a string to read an individual binary bit from the dataAvail output?

    The other problem I see here is that the dataAvail output is almost identical throughout my 500 samples, meaning that the ZOR and ZDA bits are always 0. According to the datasheet, a 0 means new data is not available. This doesn't make sense to me.

    Thank you again.

    David


    1608 x 461 - 103K
  • If the data you're getting looks good now you can probably safely ignore the status flag. If your code runs significantly faster than the update rate of the sensor it can be useful, but since your data is correct now and doesn't appear to have lots of repeated samples, I'd say just move forward with what you have.

    To answer your question though, look at this blurb you posted:
    [ZYXOR | ZOR | YOR | XOR | ZYXDA | ZDA | YDA | XDA]

    Each of those symbols represents a single bit in a byte of data. To figure out if a particular bit is set, you read the byte, then use the "and operator" (&) to mask the other bits off and check to see if the result is non-zero.
      low(14);
      shift_out(12, 13, MSBFIRST, 8, STATUS_ADDRESS); //Send read register address (OUT_STATUS)
      status = shift_in(12, 13, MSBPRE, 8); //Get value from register
      high(14);
     
      if(status & 1)
        printf( "X data available\n");
    
      if(status & 2)
        printf("Y data available\n");
    
      if(status & 4)
        printf( "Z data available\n");
    
      if(status & 8)
        printf( "ZYX data available\n");
    
      // and so on
    

    The "mask value" to use for any bit is (1 << bitIndex), which evaluates to 1, 2, 4, 8, 16, 32, 64, and 128 - all the powers of two that fit in a single byte.

    So if you want to pursue it, it looks like ZYXDA (mask value of 8) is a short form for "X, Y, and Z are available", and just ZDA (mask value of 4) is the flag to tell you new Z data is ready.
Sign In or Register to comment.