I have done a pretty good search on the forums and haven't found anything that is exactly what i need. I am working on a Lynxmotion scout, and have gotten it pretty well situated. I got kind of angry that it kept falling over and just jumped in without any research (my mistake) and bought a parallax L3G4200D 3-axis gyro... i thought "how hard could it be to program"
I don't even begin to know how to modify the basic source code here:
#include <Wire.h>
#define CTRL_REG1 0x20
#define CTRL_REG2 0x21
#define CTRL_REG3 0x22
#define CTRL_REG4 0x23
int Addr = 105; // I2C address of gyro
int x, y, z;
void setup(){
Wire.begin();
Serial.begin(9600);
writeI2C(CTRL_REG1, 0x1F); // Turn on all axes, disable power down
writeI2C(CTRL_REG3, 0x08); // Enable control ready signal
writeI2C(CTRL_REG4, 0x80); // Set scale (500 deg/sec)
getGyroValues(); // Get new values
delay(100); // Wait to synchronize
}
void loop(){
getGyroValues(); // Get new values
// In following Dividing by 114 reduces noise
Serial.print("X:"); Serial.print(y / 114);
Serial.print(" Y:"); Serial.print(x / 114);
Serial.print(" Z:"); Serial.println(z / 114);
delay(500); // Short delay between reads
}
void getGyroValues () {
byte MSB, LSB;
MSB = readI2C(0x29);
LSB = readI2C(0x28);
x = ((MSB << 8) | LSB);
MSB = readI2C(0x2B);
LSB = readI2C(0x2A);
y = ((MSB << 8) | LSB);
MSB = readI2C(0x2D);
LSB = readI2C(0x2C);
z = ((MSB << 8) | LSB);
}
int readI2C (byte regAddr) {
Wire.beginTransmission(Addr);
Wire.write(regAddr); // Register address to read
Wire.endTransmission(); // Terminate request
Wire.requestFrom(Addr, 1); // Read a byte
while(!Wire.available()) { }; // Wait for receipt
return(Wire.read()); // Get result
}
void writeI2C (byte regAddr, byte val) {
Wire.beginTransmission(Addr);
Wire.write(regAddr);
Wire.write(val);
Wire.endTransmission();
}
to get to something i need...
my questions:
Is a gyro all i need, do i need to buy an IMU, an accelorometer?
Can someone point me in a direction or recommend a better and easier to use sensor, a kind of all-in-one device?
how can i calibrate the sensor to 0 when it starts up, meaning have 0 be standing straight... the sensor just keeps constantly redefining 0 at whatever position it is at after a second or two.
What about some learning material, a guide to get to know how to use a gyro correctly?
A gyroscope detects angular rate. So if you're turning quickly, it will have a high value, if you're turning slowly, it'll have a low value, and if you're stopped it should be zero -- no matter what actual angle you're at. The solution to this is to integrate (read: add all the values of) the output. That is as simple as taking the output of the sensor and adding it to a global variable.
However, it's probably a good idea to understand the example code, first. What don't you get about it? Do you understand the writeI2C function? The readI2C function? The getGyroValues function? Don't give up because it looks complicated, just dive in and figure out what everything does. Post here if you're wondering what something like "x = ((MSB << 8) | LSB);" means. Actually, I'll go ahead and explain that.
MSB is the Most Significant Byte. So if you had the binary number 1010011000111001, 10100110 would be the Most Significant Bye (a byte is 8 digits) and 00111001 is the Least Significant Byte. So since the sensor can only send back one byte at a time, first the code asks for the MSB, then the LSB. x = ((MSB << 8) | LSB); is better explained with some crappy ASCII art:
0000.0000.0000.0000 // 16 bit "int" reading 0 (dots for clarity)
0000.0000.xxxx.xxxx // MSB. Since it's only 1 byte long, the top eight bits are zero
xxxx.xxxx.0000.0000 // MSB << 8. The << means "shift left" and just takes the bits and puts them somewhere else.
0000.0000.yyyy.yyyy // LSB. It's also just 1 byte long
xxxx.xxxx.yyyy.yyyy // (MSB << 8) | LSB. The | means "or" and says "for each bit, make the resulting bit a 1 if either of the two corresponding input bits is a 1. Since MSB<<8 ends with 8 0s and LSB starts with 8 0's, this ends up just squishing the two together
xxxx.xxxx.yyyy.yyyy // x, which is the 16 bit number that the sensor read.
Thank you both for the help, the MSB and LSB were one of the biggest problems for me...
I think I understand it a lot better now...
How would the global variable look?
Like:
A - global variables
B
C
Outputs of X,Y,Z are added to A,B,C if positive or subtracted if negative?
How would you reupdate XYZ as ABC after the loop, or would I just use ABC in the rest of the code?
Maybe an example por favor?
I have also just started working with this gyroscope and I have the same base code. I also can't read it to save my life.
Thank you WizenedEE for explaining what MSB and LSB means, I wasn't that far yet but I was going to get there sometime. Actually now that I look at the code that was about half of my questions. lol
Other than that, can anyone point me to formal documentation of the writeI2C, ReadI2C, and getGyroValues commands? I can't seem to find any website that tells me how they work.
Last question, can someone help me figure out or point me to a paper that will help me figure out how why CTRL_REG1 is given the value 0x20, is this a bytes thing? Why do we write 0x1F to CTRL_REG1 in the start of the void setup? I can make the connection between CTRL_REG1 and the datasheet I have for the gyro, but I don't know where we pull the "0x1F" and "0x20" stuff from.
I have read the datasheet, however it assumes I have background knowledge I don't have. I had posted here hoping someone could expline it to me in simpler and more practical terms.
I can draw some conclusions from the datasheet but I'm still at a lost as to why we format the data being sent to the master device and slave device.