EDIT: I2C Communication Setup with Arduino Mega and Razor IMU

Hi, I'm trying to read in values from my Razor IMU (https://www.sparkfun.com/products/10736) through my Arduino Mega. Unfortunately, every time I have my wires in TX0 and RX0, I get the error avrdude: stk500v2_getsync() timeout communicating with programmer when I try to upload the program. I'm attempting to use the code found here: http://code.google.com/p/sf9domahrs/.

I have the pins wired such that: Mega Ground > IMU Ground Mega TX0 > IMU RX1 Mega RX0 > IMU TX0 Mega 3.3V > IMU 3.3V

Though I first thought my lack of understanding might be to blame (and that could still be the problem), I came across someone suggesting that I try connect TX0 to RX0 directly to see if I could read whatever I output to the serial port. Whenever I run a wire directly between TX0 and RX0, I get the same error. It now seems to me that the only way for me to read in data from the RX0 port is if I send the data from a port that is not TX0. For example, with TX1 and RX1 wired together, I was able to connect my RX0 wire to RX1 and read the data being output over Serial1.

I have been through as many posts as I can find on the issue, have tried multiple fixes (updating firmware, checking the boards.txt file, etc.) and have even tried it with a secondary Arduino board. I hope I'm just missing something simple, but I guess I'm looking for possible solutions to the problem.

When trying to upload, the RX and TX LEDs flash occasionally.

I'm running Windows 10 and have Arduino 1.6.5

Thank you for any suggestions in advance.

If you have a Mega why are you connecting to Rx0 and Tx0 when you could use Rx1, Rx2 or Rx3 etc.

Rx0 and Tx0 are used for communication with the PC and if you connect something to them it interferes with uploading a program.

...R

Thank you for the information. Okay, I am now attempting to use the TX1 and RX1 pins, but the program is now outputting that there is an error reading the accelerometer info. This is specified in the code to output when not all the bytes are received. The program uses I2C communication. I was under the impression that for I2C you had to use the SDA and SCL pins, but the IMU has its pins labelled as TX0 and RX1.

When the program is communicating with the IMU, it begins transmission to an address (this can be any number greater than 7 correct?), then writes two specific addresses 0x2D and 0x08. These addresses are labelled in the comments as power register and measurement mode respectively. I assume this is telling the IMU to begin measuring, but I am not sure where he found the specific address for the measurement mode. Would it be correct to assume that this is somewhere in the documentation and I have just missed it? Also, is it generally possible to use serial communication instead of I2C. I imagine that each piece of hardware is different, but in general can devices work from both?

I know this is probably all because of my lack of knowledge of communication standards so I am trying to learn how they work on the Arduino.

Also, should either DTR or CTS be connected to GND, or are they fine simply not connected?

Should I be using a logic level shifter? I know the IMU runs at 3.3V and the Arduino outputs at 5V so should I be worried about damage and hooking them directly together? If so, would a 5K resistor be good enough?

Post your code so we can see what you are talking about. And please use the code button </> so your code looks like this and is easy to copy to a text editor

…R

This is the code for the accelerometer. The magnetometer and gyroscope are done similarly but right now I am only concerned with the accelerometer. Thank you again.

// I2C code to read the sensors

// Sensor I2C addresses
#define ACCEL_ADDRESS ((int) 0x53) // 0x53 = 0xA6 / 2
#define MAGN_ADDRESS  ((int) 0x1E) // 0x1E = 0x3C / 2
#define GYRO_ADDRESS  ((int) 0x68) // 0x68 = 0xD0 / 2

// Arduino backward compatibility macros
#if ARDUINO >= 100
  #define WIRE_SEND(b) Wire.write((byte) b) 
  #define WIRE_RECEIVE() Wire.read() 
#else
  #define WIRE_SEND(b) Wire.send(b)
  #define WIRE_RECEIVE() Wire.receive() 
#endif


void I2C_Init()
{
  Wire.begin();
}

void Accel_Init()
{
  Wire.beginTransmission(ACCEL_ADDRESS);
  WIRE_SEND(0x2D);  // Power register
  WIRE_SEND(0x08);  // Measurement mode
  Wire.endTransmission();
  delay(5);
  Wire.beginTransmission(ACCEL_ADDRESS);
  WIRE_SEND(0x31);  // Data format register
  WIRE_SEND(0x08);  // Set to full resolution
  Wire.endTransmission();
  delay(5);
  
  // Because our main loop runs at 50Hz we adjust the output data rate to 50Hz (25Hz bandwidth)
  Wire.beginTransmission(ACCEL_ADDRESS);
  WIRE_SEND(0x2C);  // Rate
  WIRE_SEND(0x09);  // Set to 50Hz, normal operation
  Wire.endTransmission();
  delay(5);
}

// Reads x, y and z accelerometer registers
void Read_Accel()
{
  int i = 0;
  byte buff[6];
  
  Wire.beginTransmission(ACCEL_ADDRESS); 
  WIRE_SEND(0x32);  // Send address to read from
  Wire.endTransmission();
  
  Wire.beginTransmission(ACCEL_ADDRESS);
  Wire.requestFrom(ACCEL_ADDRESS, 6);  // Request 6 bytes
  while(Wire.available())  // ((Wire.available())&&(i<6))
  { 
    buff[i] = WIRE_RECEIVE();  // Read one byte
    i++;
  }
  Wire.endTransmission();
  
  if (i == 6)  // All bytes received?
  {
    // No multiply by -1 for coordinate system transformation here, because of double negation:
    // We want the gravity vector, which is negated acceleration vector.
    accel[0] = (((int) buff[3]) << 8) | buff[2];  // X axis (internal sensor y axis)
    accel[1] = (((int) buff[1]) << 8) | buff[0];  // Y axis (internal sensor x axis)
    accel[2] = (((int) buff[5]) << 8) | buff[4];  // Z axis (internal sensor z axis)
  }
  else
  {
    num_accel_errors++;
    if (output_errors) Serial.println("!ERR: reading accelerometer");
  }
}

I thought, from your references to Rx0 and Tx0 that your problem was with Serial communication? The code in your snippet is using the Wire library.

What does the code actually do? What should it do?

You need to post a complete program.

...R

Right, so I’m just trying to read in the data from my IMU using an I2C connection. I can get the data over serial with

//Connect IMU to TX1 and RX1 and then connect RX0 to TX1 and steal the data

String sensorData;
char c;
void setup() {
  Serial.begin(57600);
  Serial1.begin(57600);
  Serial.println("9DOF Test"); 
}
  
void loop() {

  while (Serial1.available()) {  
    if (Serial1.available() >0) {
  c = Serial1.read(); 
  //sensorData += c; //adds c to the sensorData string
       Serial1.print(c); //see whatever came in on Serial.read()
    }
  }
  while (Serial.available()) {  
    if (Serial.available() >0) {
  c = Serial.read(); 
  //sensorData += c; //adds c to the sensorData string
       Serial.print(c); //see whatever came in on Serial.read()
    }
  }
  
  if (sensorData.length() >0) {
   Serial.println(sensorData);  //output the string
//readString=""; //resets reString for the next iteration of the loop
  } 
}

However, I found the code here https://github.com/ptrbrtz/razor-9dof-ahrs/tree/master/Arduino/Razor_AHRS (which consists of six tabs so I won’t post it all unless you want me to). Anyway, this code handles all of the calibration and math that I would need to implement so I was going to try to just use it instead. The code I posted in my last post was the part of the code which reads in data from the IMU. Now, this is probably where my unfamiliarity with I2C made helping me difficult. The IMU has TX and RX pins on it so I assumed I needed to use TX and RX from my Arduino even though the code uses I2C and not Serial. I know from the datasheets that the IMU can be used with I2C.

I guess this all boils down to ask how I should connect my Arduino to my IMU to utilize an I2C connection (as used by the code found on github) even though the only six pins on the IMU are GND, 3.3V, DTR, CTS, TX0, and RX1. As of now (when I hooked up my IMU using the TX and RX pins of the Arduino and IMU), the Arduino is not receiving data from the IMU. I suppose this is because you can’t do an I2C connection over the Arduino’s TX and RX pins.

So any help or direction would be greatly appreciated. Thanks again and let me know if you need any more information.



EDIT: There are also six AVR SPI pins. As your signature says, reading documentation helps. I didn’t understand before, but I think I’m on the right track now. On page 10 of the datasheet (found here: https://www.sparkfun.com/datasheets/Sensors/Accelerometer/ADXL345.pdf), it gives a I2C connection diagram where not CS is connected to VDD I/O, SDA is connected in parallel to a processor’s D in/out and to a resistor that is connected in series with VDD I/O, Alt address is grounded, and SCL is connected in parallel to D out and a resistor that is connected in series with VDD I/O.

The alternative address for a grounded alternative address pin matches the one used in the program I found. According to the IMU’s documentation, the CS pin is already set to 3.3V so I should be good there. So do all I need to do is connect the SDA to one of the digital pins on the Arduino for input, and connect the SCL to another digital pin for output? I don’t see the Alt address pin of the acclerometer on the IMU’s schematic, but could this be the SD0 pin?

Also, the accelerometer’s I2C connection diagram (found here: http://cdn.sparkfun.com/datasheets/Sensors/IMU/9DOF-Razor-v22.pdf) specifies using resistors to connect the SDA and SCL to the VDD I/O. In the IMU’s schematic, these outputs are not shown to have resistors. This may be a very ignorant question, but it’s a safe bet that the resistors were not included with the IMU’s wiring (even though it seems it has the CS and Alt Address pins connected where they need to be), correct?

The address for writing is 0xA6 and the I2C address is 0x53. The I2C address is exactly half of the writing address, is this a coincidence?

For clarification, the IMU contains three sensors. The accelerometer, the magnetometer, and the gyroscope. That is, the accelerometer and IMU are distinct.

I have no experience with I2C. Presumably someone else will offer advice. But the title of your Thread might lead them to conclude that your query has nothing to do with I2C. I assumed it the query was about Serial comms.

Read the documentation 12 more times and you may figure it out. That usually works for me :)

...R

Well thank you anyway for your suggestions, it helped me move in the right direction. I don't suppose there's any way to change the subject of the thread? Doesn't seem to be, so I guess I'll have to start a new topic unfortunately.

Thanks again!

BStricklin: I don't suppose there's any way to change the subject of the thread?

If you modify your Original Post you can change the title.

...R

Thanks again Robin!

Note: Maybe this should be in the General Electronics section now, but it started based on an error message.

So for anyone willing to help, I’m trying to set up the wiring between my Razor 9DOF IMU (https://www.sparkfun.com/products/10736) and my Arduino Mega so that I can use the code I found here (https://github.com/ptrbrtz/razor-9dof-ahrs/tree/master/Arduino/Razor_AHRS).

For clarification, the IMU contains three sensors. The accelerometer, the magnetometer, and the gyroscope. That is, the accelerometer and IMU are distinct.

On page 10 of the accelerometer’s datasheet (found here: https://www.sparkfun.com/datasheets/Sensors/Accelerometer/ADXL345.pdf), it gives a I2C connection diagram (for the accelerometer contained within the IMU) where not CS is connected to VDD I/O, SDA is connected in parallel to a processor’s D in/out and to a resistor that is connected in series with VDD I/O, Alt address is grounded, and SCL is connected in parallel to D out and a resistor that is connected in series with VDD I/O.

The alternative address for a grounded alternative address pin matches the one used in the program I found. According to the IMU’s documentation, the CS pin is already set to 3.3V so I should be good there. So do all I need to do is connect the SDA to one of the digital pins on the Arduino for input, and connect the SCL to another digital pin for output? I don’t see the Alt address pin of the acclerometer on the IMU’s schematic, but could this be the SD0 pin?

Also, the accelerometer’s I2C connection diagram (found here: http://cdn.sparkfun.com/datasheets/Sensors/IMU/9DOF-Razor-v22.pdf) specifies using resistors to connect the SDA and SCL to the VDD I/O. In the IMU’s schematic, these outputs are not shown to have resistors. This may be a very ignorant question, but it’s a safe bet that the resistors were not included with the IMU’s wiring (even though it seems it has the CS and Alt Address pins connected where they need to be), correct?

The address for writing is 0xA6 and the I2C address is 0x53. The I2C address is exactly half of the writing address, is this a coincidence?