I'm trying to connect a XV-3500CB gyro with my Arduino Diecimila...just for fun. I've done simple stuff with my arduino (blinking LEDs, etc) but never tried connecting anything like this before so please forgive my ignorance. I bought the gyro from ebay. It came connected to a breakout board from sure electronics.
I didn't connect the ANA0 on the board to anything since I'm not quite sure what it's for. Then I used the CMPS03 library from GrapeLabs to get the reading from the gyro since, I assume, that's the same way I'm supposed to read the data via I2C from my board but I get no results. It writes to the board okay but I get a whole bunch of 0.
Where did I go wrong? My connection or my code? Any help you can give is appreciated since I'm in way over my head here (but i guess that's how you learn ). Thanks in advance.
When I print the output of ANA0 I get varying levels whenever I tilt the board, ranging between 270 and 288. according to the data sheet, this is the "Analog voltage output end of angular-rate sensor". I guess that means I've connected everything correctly so it must be a problem with my code.
OK my mistake (I think) was using the CMPS03 library since a lot of things are different to my setup such as the I2C address of the AD converter (MCP3421 in my case). Trying to fix that now.
Well, first off... something that your datasheet doesn't explicitly tell you is that the onboard ADC is running on a 3V supply, and therefore your I2C data and clock lines need to be level shifted to the proper voltages.
Here is the datasheet I found for the onboard ADC:
I2C input voltages (about middle of page 3) should not exceed Vdd, which is 3.0V from the schematic on the module's datasheet.
The ATmega requires an input voltage of 60% of its power supply voltage to register as a "1" on the digital inputs. With 5V power supply that would be 3V.
Hmm, the ADC sheet annoyingly doesn't say what the output voltage is for a "1" but this is often about 80% and up of the supply voltage. So with 3V supply: 2.4V to 3V.
That makes a very marginal design. It's very likely that the ADC output can't produce high enough output voltage to drive the ATmega inputs to a high reliably, hence a reading of all "0". And in any case the ATmega output voltage is too high for the ADC's digital inputs. (It may work, but will "shorten" the life of the ADC.)
Of course, the I2C interface is only reading the module's onboard ADC. You could forego that and just read the ANAO with the Arduino analog input, but you will lose some resolution. Your onboard ADC is 18-bit over a 3V span for about 11 uV per count. The ATmega is 10-bit and by default is over a 5V span. You can switch to a lower reference voltage of 2.56V (http://arduino.cc/en/Reference/AnalogReference) which then gives you 2.5 mV per count.
It's output voltage is going to be 1.350 V +/- 0.067V over its full-range.
This is from it having a range of +/- 100 deg/s, an output of 0.67 mV/deg/s, and a bias of 1350 mV.
So.... with the Arduino analog input and a 5V reference:
Firstly thanks dilbert98122 and daveg360 for the help so far. I've found someone else who used the same gyro with the arduino (so I guess it must be possible to get this working) but he's done things a little differently. This is my code at the moment (modified after my previous mistake):
#include "Wire.h"
// I2C device address is 1 1 0 1 0 0 0
#define GYRO_ADDRESS (0xD << 3)
#define REGISTER_INPUT (0)
void setup() {
Serial.begin(9600);
Wire.begin();
}
int i2cread () {
int data = 0;
//Send input register address
Wire.beginTransmission(GYRO_ADDRESS);
Wire.send(REGISTER_INPUT);
Wire.endTransmission();
//Connect to device and request two bytes
Wire.beginTransmission(GYRO_ADDRESS);
Wire.requestFrom(GYRO_ADDRESS, 2);
if (Wire.available()) {
data = Wire.receive();
}
if (Wire.available()) {
data |= Wire.receive() << 8;
}
Wire.endTransmission();
return data;
}
void loop() {
Serial.println(i2cread());
delay(1000);
}
val = ((((analogRead(xPin)-xZero)/148.48)* 180/3.1415926535897932384626433832795))*-1); //accelerometer angle calculation
valG = valG + ((analogRead(gyroPin) - gZero)*4.8099347014925373134328358208962)/200; //integration of gyro and gyro angle calculation
angle = (val * 0.005) + (valG * 0.995); //complementary filter
valG = angle; //drift correction of gyro integration
I think he's using an accelerometer so that's why there's the extra bit of calculation. What I don't understand is why he's just using analogRead() to read from the gyro.
The ATmega requires an input voltage of 60% of its power supply voltage to register as a "1" on the digital inputs. With 5V power supply that would be 3V.
Hmm, the ADC sheet annoyingly doesn't say what the output voltage is for a "1" but this is often about 80% and up of the supply voltage. So with 3V supply: 2.4V to 3V.
That makes a very marginal design. It's very likely that the ADC output can't produce high enough output voltage to drive the ATmega inputs to a high reliably, hence a reading of all "0". And in any case the ATmega output voltage is too high for the ADC's digital inputs. (It may work, but will "shorten" the life of the ADC.)
What if I use a resistor to step down the voltage for the IICCLK and IICDAT like detailed here?
One could also set a reference Voltage of 1.4V at the AREF pin
probably using a voltage divider, and get a lot of resolution.
On the other hand, if I2C MUST be used, for whatever reason,
one could try to use a bootloaded ATmega168(or whatever) powered by 3.3V,
so the I2C data levels will much between the mC an the sensor board ADC.