L3G4200D 3-Axis Gyroscope?
briank77479
Posts: 36
I've just finished the Propeller C tutorial on the MMA7455 3-Axis Accelerometer and was wonder if there are any plans to add the L3G4200D 3-Axis Gyroscope to the tutorial list?
Thanks Brian
Thanks Brian
Comments
http://forums.parallax.com/showthread.php/151972-The-problem-about-I2C-communication?p=1223045&viewfull=1#post1223045
http://forums.parallax.com/showthread.php/151972-The-problem-about-I2C-communication?p=1223341&viewfull=1#post1223341
Andy
https://github.com/libpropeller/libpropeller/tree/master/libpropeller/l3gd20
Thank you so much,
Brian
When I run the program I'm reading the Accelerometer okay and it appears that I'm reading the Z-axis of the Gyroscope; at least when I move the Gyroscope the value changes. However on the X and Y axis of the Gyroscope it reads 79 & 0 respectively.
I get the feeling I'm looking at this incorrectly; a conflict between the two sensors.
Any advice would be greatly appreciated.
Thanks in advance, Brian
- Increase stack arrays to 128
- Only use print statements from within cog 0, (main function in your particular program)
- Change return types of functions that run in other cogs to void
Andy
Thank you very much for your help!!
Will update on my results.
Brian
Much appreciated on your help!!
Brian
Please guide me what I need to change to make it work again.
Thank you
unsigned char addrW = 0xd2; //I2C write address
unsigned char addrR = 0xd3; //I2C read address
use
unsigned char i2cAddr = 0x69; //I2C address
The i2c_in/out functions also use the value of the register you want to access within the device. It was using the address of the variable containing the register previously. So change:
i2c_in(bus, addrR, &devId, 1, &reply, 1);
to
i2c_in(bus, i2cAddr, devId, 1, &reply, 1);
Note that I also changed addrR to i2cAddr
Thank you very much for the assistance. I tried to carry the revisions over to the L3G4200D code you created earlier to read the Gyro scope; see attached.
Evidently I missed something as the results are x = 6, y = 4, z = 82 and they don't vary when the device is moved.
What did I miss?
Again, Thank you
Brian
Looks like you got everything right with the code modifications. I loaded it onto mine, and it worked correctly on the first download, no bugs.
I'm not sure what's up with yours. Re-run the previous example program. Did it confirm that the Gyro is replying? If no, check wiring. If yes, let's look at your most recent program's project settings. Click the bottom-left Show Project Manager, and check the Project Options tab. Compiler Type = C, Memory Model = CMM Main RAM Compact..., Optimization -OS Size. Click compiler. 32bit Double should be checked, and -std=c99 should be in the Other Compiler Options field. In Linker, Math Lib is checked.
Andy
This is where I slap my forehead I was so used to running programs with the correct settings that I sometimes forget to check periodically. Sure enough a couple of settings weren't.
Very much appreciated the help!!!
Brian
I would like to apply your code to MPU6050 Gyro + Accelerometer, and would like to know the details of your code.
It is appreciated if you could explain the followings;
1) What value of ready are you expecting in the line i2c_in(bus, i2cAddr, status, 1, &ready, 1); ?
How shall I amend the next line ready = 1 & (ready >>= 3); for MPU6050 ?
2) Why is 3 obtained by n = i2c_out(bus, i2cAddr, ctrl3, 1, &cfg3, 1); ?
3) Why do you not use while(i2c_busy( , ) instead of if(n != 9) ?
Thanks Kaeru no Ojisan
"1) What value of “ready” are you expecting in the line “i2c_in(bus, i2cAddr, status, 1, &ready, 1);” ?
How shall I amend the next line “ready = 1 & (ready >>= 3);” for MPU6050 ?"
In this Register Map document:
http://invensense.com/mems/gyro/documents/RM-MPU-6000A.pdf
Bit 0 of the INT_STATUS register 0x3A is 1 when data is ready, and 0 after the info is read. Depending on how other registers have been configured, it should be possible to declare status to 0x3A (instead of 0x27). Then, you could use:
i2c_in(bus, i2cAddr, status, 1, &ready, 1);
ready = 1 & ready;
This also assumes that i2cAddr has been updated. I see from this Product Spec document
http://www.cdiweb.com/datasheets/invensense/MPU-6050_DataSheet_V3%204.pdf
...that the AD0 pin can be set high for an address of 0b1101001 or low for an address of 0b1101000. One of these values should be the device's I2C address (in place of 0x69).
"2) Why is 3 obtained by “n = i2c_out(bus, i2cAddr, ctrl3, 1, &cfg3, 1);” ?"
3 is the total number of bytes sent. The first byte is the 7-bit I2C address + read/write bit. The second byte is ctrl3, and the third byte is cfg3. If it returns a different number, it might mean that it did not receive an ACK signal after attempting to send one of the bytes. One situation that could lead to this is if the I2C address sent doesn't match what the chip thinks its address is.
"3) Why do you not use “while(i2c_busy(…,…)” instead of “if(n != 9)” ?"
Some chips are designed to be polled for an ACK signal while they are busy processing. That's the case for the EEPROM in the I2C tutorial http://learn.parallax.com/propeller-c-simple-protocols/diy-i2c. The i2c_busy function accommodates that. Other devices have other ways of reporting whether they are ready. We find out these details by reading the device datasheet. If I remember correctly, the datasheet for the L3G4200D explained that bit 3 of register 0x69 would contain that information if bit 3 of register 0x22 is set. See usage of ctrl3 and cfg3 in the program. Note, it also depended on several other settings that the first three i2c_out statements configured. So, the equivalent of while(i2c_busy...)) for the L3G4200D ended up being this:
int ready = 0;
while (!ready)
{
i2c_in(bus, i2cAddr, status, 1, &ready, 1);
ready = 1 & (ready >>= 3);
}
In a more direct answer to your question, I used if(n != 9) for troubleshooting while writing the code. I think I left it in there as a diagnostic in case there were problems. ...or, maybe I just forgot to remove it after getting everything running.
Have you tried modifying the smaller program yet? After poking around in the Product Spec and Register Map documents, this is my guess at what the program would look like if modified for your chip. The if... condition was arrived at based on the description in the Register Map's WHO_AM_I register description on page 46.
P.S. Note that there are two versions of the i2cAddr variable declaration. I guessed that your module has AD0 set high, but it might be grounded instead. If that's the case, you'll need to comment the one declaration and uncomment the other.
Thank you very much and I appreciated your help.
I made new thread relevant to this matter (I think).
http://forums.parallax.com/showthread.php/156107-MPU6050-Quaternion?p=1273916#post1273916
It is also very much appreciated if you can help on this problem.
Kaeru no Ojisan