L3G4200D Gyroscope Only Outputting Negative Values

Hello,

My gyro is only outputting negative values and also seems kind of noisy. Could someone please take a look at my code below? Also, I've attached an image of some plotted data when I was rotating the gyro back and forth rather quickly. I would expect the values to go positive and be less noisy. What do you think?

[img][img][/img]
/*
 0 as the MSB is write
 1 as the MSB is read
 
 */

#include "simpletools.h"
signed int whoAmI;
signed int zL, zH, z, zSum, zAvg;
signed int statusReg;

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, 0b00100011); //Write MCTL register (register 4)to set 3-wire SPI
  shift_out(12, 13, MSBFIRST, 8, 0b00010001); //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);
  
  //Get z-axis zero-rate offset (zAvg)
  for(int i=0; i<1000; i++){
    
    /*
    //Poll status register
    low(14); //CS low selects chip
    shift_out(12, 13, MSBFIRST, 8, 0b10100111); //Send read register address (statusReg)
    statusReg = shift_in(12, 13, MSBPRE, 8); //Get value from register
    high(14); //De-select chip with CS line high
    //if(dataReady == 1){
    print("statusReg = %b\n", statusReg);
    */
    
    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("z = %d\n", z);
  }    
  zAvg = zSum/1000;
  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.0175; //Multiply by sensitivity value for 500deg/s
 
    print("%f\n",zf);
    //print("zf = %f\n", zf);
    pause(50); //Cycle at 20Hz
  }
}
929 x 290 - 49K

Comments

  • 9 Comments sorted by Date Added Votes
  • By the way, the gyro is set for 500 deg/s sensitivity and you can see from the plot that it goes from 0 to -1000. I think this part makes sense since it is +/-500 deg/s. Any help is appreciated.

    Respectfully,
    David
  • One thing I changed by comparing to the Arduino sketch was the following:
    z = (zL<<8 | zH);
    

    to
    z = (zH<<8 | zL);
    

    Noise is definitely less now, however, it still only gives negative values and if I turn the gyro CCW, the values immediately jump to -1000 and below. Definitely something weird is going on because I hooked the gyro up to my Arduino using the provided Arduino sketch and it worked beautifully. Can someone please help?

    Thanks,
    David
  • Does anyone else have this sensor and use it with Prop C? You can run my code as is below and see what I mean with the issue I'm having. I would really appreciate any hints on what I could try next.

    Many thanks,
    David
    /*
     0 as the MSB is write
     1 as the MSB is read
     
     */
    
    #include "simpletools.h"
    signed int whoAmI;
    signed int zL, zH, z, zSum, zAvg;
    signed int statusReg;
    
    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, 0b00100011); //Write MCTL register (register 4)to set 3-wire SPI
      shift_out(12, 13, MSBFIRST, 8, 0b00010001); //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);
      
      //Get z-axis zero-rate offset (zAvg)
      for(int i=0; i<1000; i++){
        
        /*
        //Poll status register
        low(14); //CS low selects chip
        shift_out(12, 13, MSBFIRST, 8, 0b10100111); //Send read register address (statusReg)
        statusReg = shift_in(12, 13, MSBPRE, 8); //Get value from register
        high(14); //De-select chip with CS line high
        //if(dataReady == 1){
        print("statusReg = %b\n", statusReg);
        */
        
        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 = (zH<<8 | zL);
        zSum += z;
        //print("z = %d\n", z);
      }    
      zAvg = zSum/1000;
      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 = (zH<<8 | zL)-zAvg; //2's complement operation
        float zf = (float) z; //Change to a float
        zf = zf*0.0175; //Multiply by sensitivity value for 500deg/s
     
        print("%f\n",zf);
        //print("zf = %f\n", zf);
        pause(50); //Cycle at 20Hz
      }
    }
    
  • Update:

    The gyro seems to work properly when I rotate it in the clockwise direction (gives negative values that start around zero and become more negative). However, when I rotate it counterclockwise it seems like it "wraps around" to -1146 and starts increasing in the positive direction from there. I hope that makes sense. What could be causing this?

    Thank you,
    David
  • I have never used the L3G4200D, but have you tried the Spin code linked on the product page to at least see if the sensor works ok? When I buy a sensor that I haven't programmed before (I normally use C), I will try one of the examples linked in the downloads & documentation, hopefully C or Blockly (since I can look at the C code generated) or at least the Spin code. Once I see how the sensor should work, then I can port the Spin to C.

    Tom
  • Hi Tom,

    Thank you very much for your reply. I am certain that the sensor works fine because I tested it on an Arduino as well as on the Propeller with some code I found for I2C interfacing. My code uses SPI and I prefer to stick with that to be consistent with the accelerometer tutorial on the Parallax Learn site. I've compared my code to the I2C code and it seems my code should work but something is still not right. What do you mean by porting from Spin to C?

    Thanks,
    David
  • What do you mean by porting from Spin to C?

    It's just translating what the Spin code does into what the C code would do, not necessarily a Spin operator to C operator translation.

    A lot of sensors use i2c, but I pefer to use spi where possible. I made a SimpleIDE library using propeller assembly (from the Proptool library) with C. The library includes functions for generic spi as well as some specific sensors (but not the 4200). The link to that discussion is here:

    https://forums.parallax.com/discussion/comment/1315065/#Comment_1315065

    I have had problems when using the standard SimpleTools library spi functions. The link below shows how I used the library I made to interface with the 5607 altimiter. You can see how the spi functions are called.

    https://forums.parallax.com/discussion/163486/altimeter-module-ms5607-29124-c-driver-using-spi

    Hope this helps.
    Tom
  • Okay, I seem to be making some progress! Adding "short" in front of the two's complement operation seems to work, but why?
    z = (short) ((zH<<8) | zL)*.0175;//-zAvg; //2's complement operation
    

    Also, for a sensitivity value of 500 deg/s, the datasheet says to multiply by 0.0175. In other code I see a division by 114 (1/114=.00877). Which one is correct and where does the division by 114 come from?

    Thank you.

    David
  • For anyone who is interested, here is my working code for all three axes using SPI:
    /*
     18 June 2018
     Working Code, xyz-axes
     0 as the MSB is write
     1 as the MSB is read
     */
    
    #include "simpletools.h"
    signed int whoAmI;
    signed int xL, xH, yL, yH, zL, zH;
    signed int statusReg;
    float x, xSum, xAvg, y, ySum, yAvg, 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);
      }   
    
      //Register 4 - Set 3-wire SPI
      low(14);                                              //CS line low (start SPI)
      shift_out(12, 13, MSBFIRST, 8, 0b00100011);           //Write MCTL register (register 4)to set 3-wire SPI
      shift_out(12, 13, MSBFIRST, 8, 0b10010001);           //Value for MCTL register (register 4) to set 3-wire SPI
      high(14);
      
      //Register 1 - 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(100);
      
      
      //Get x-axis zero-rate offset (xAvg)
      for(int i=0; i<1000; i++){
        
        low(14);                                            //CS low selects chip
        shift_out(12, 13, MSBFIRST, 8, 0b10101000);         //Send read register address (OUT_X_L)
        xL = 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, 0b10101001);         //Send read register address (OUT_X_H)
        xH = shift_in(12, 13, MSBPRE, 8);                   //Get value from register
        high(14);
        
        x = (short) ((xH<<8) | xL);
        xSum += x;
      }    
      xAvg = xSum/1000;
      print("xAvg = %f\n", xAvg);
      
      //Get y-axis zero-rate offset (yAvg)
      for(int i=0; i<1000; i++){
        
        low(14);                                            //CS low selects chip
        shift_out(12, 13, MSBFIRST, 8, 0b10101010);         //Send read register address (OUT_Y_L)
        yL = 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, 0b10101011);         //Send read register address (OUT_Y_H)
        yH = shift_in(12, 13, MSBPRE, 8);                   //Get value from register
        high(14);
        
        y = (short) ((yH<<8) | yL);
        ySum += y;
      }    
      yAvg = ySum/1000;
      print("yAvg = %f\n", yAvg);
      
      //Get z-axis zero-rate offset (zAvg)
      for(int i=0; i<1000; 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 = (short) ((zH<<8) | zL);
        zSum += z;
      }    
      zAvg = zSum/1000;
      print("zAvg = %f\n", zAvg);
      
      //Main loop
      while(1){
        // x-axis
        low(14);                                            //CS low selects chip
        shift_out(12, 13, MSBFIRST, 8, 0b10101000);         //Send read register address (OUT_X_L)
        xL = 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, 0b10101001);         //Send read register address (OUT_X_H)
        xH = shift_in(12, 13, MSBPRE, 8);                   //Get value from register
        high(14);
        
        x = (short) (((xH<<8) | xL)-xAvg)*.0175;
        
        // y-axis
        low(14);                                            //CS low selects chip
        shift_out(12, 13, MSBFIRST, 8, 0b10101010);         //Send read register address (OUT_Y_L)
        yL = 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, 0b10101011);         //Send read register address (OUT_Y_H)
        yH = shift_in(12, 13, MSBPRE, 8);                   //Get value from register
        high(14);
        
        y = (short) (((yH<<8) | yL)-yAvg)*.0175;
        
        // z-axis
        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 = (short) (((zH<<8) | zL)-zAvg)*.0175;            //2's complement operation, subtract zero rate offset, multiply by 
                                                            //sensitivity value for 500deg/s, "short" needed for 2's complement
        print("x = %f  y = %f  z = %f\n",x,y,z);
        pause(50);                                          //Cycle at 20Hz
      }
    }
    
Sign In or Register to comment.