2

This question already has an answer here:

Is it possible to connect more than one or to be specific 5 MPU9250 into 1 Arduino lilypad? How will I set the addresses, and where should I put the pins for SDA and SCL? I hope someone out there could help me on this project.

Cheers!

What if I have this working codes, how will I edit this to connect more than two MPU9250? Please guide me. Thanks.

 #include <Wire.h>
 #include <TimerOne.h>

 #define    MPU9250_ADDRESS            0x68


 #define    MAG_ADDRESS                0x0C

 #define    GYRO_FULL_SCALE_250_DPS    0x00  
 #define    GYRO_FULL_SCALE_500_DPS    0x08
 #define    GYRO_FULL_SCALE_1000_DPS   0x10
 #define    GYRO_FULL_SCALE_2000_DPS   0x18

 #define    ACC_FULL_SCALE_2_G        0x00  
 #define    ACC_FULL_SCALE_4_G        0x08
 #define    ACC_FULL_SCALE_8_G        0x10
 #define    ACC_FULL_SCALE_16_G       0x18



 // This function read Nbytes bytes from I2C device at address Address. 
// Put read bytes starting at register Register in the Data array. 
void I2Cread(uint8_t Address, uint8_t Register, uint8_t Nbytes, uint8_t*      Data)
{
// Set register address
Wire.beginTransmission(Address);
Wire.write(Register);
Wire.endTransmission();

// Read Nbytes
Wire.requestFrom(Address, Nbytes); 
uint8_t index=0;
while (Wire.available())
Data[index++]=Wire.read();
}


// Write a byte (Data) in device (Address) at register (Register)
void I2CwriteByte(uint8_t Address, uint8_t Register, uint8_t Data)
{
// Set register address
Wire.beginTransmission(Address);
Wire.write(Register);
Wire.write(Data);
Wire.endTransmission();
}



// Initial time
long int ti;
volatile bool intFlag=false;

// Initializations
void setup()
{
// Arduino initializations
Wire.begin();
Serial.begin(115200);

// Set accelerometers low pass filter at 5Hz
I2CwriteByte(MPU9250_ADDRESS,29,0x06);
// Set gyroscope low pass filter at 5Hz
I2CwriteByte(MPU9250_ADDRESS,26,0x06);


// Configure gyroscope range
I2CwriteByte(MPU9250_ADDRESS,27,GYRO_FULL_SCALE_1000_DPS);
// Configure accelerometers range
 I2CwriteByte(MPU9250_ADDRESS,28,ACC_FULL_SCALE_4_G);
 // Set by pass mode for the magnetometers
 I2CwriteByte(MPU9250_ADDRESS,0x37,0x02);

 // Request continuous magnetometer measurements in 16 bits
 I2CwriteByte(MAG_ADDRESS,0x0A,0x16);

 pinMode(13, OUTPUT);
 Timer1.initialize(10000);         // initialize timer1, and set a 1/2   second period
 Timer1.attachInterrupt(callback);  // attaches callback() as a timer overflow interrupt


 // Store initial time
 ti=millis();
 }





 // Counter
 long int cpt=0;

 void callback()
  { 
  intFlag=true;
  digitalWrite(13, digitalRead(13) ^ 1);
  }

  // Main loop, read and display data
  void loop()
  {
  while (!intFlag);
  intFlag=false;

  // Display time
  Serial.print (millis()-ti,DEC);
  Serial.print ("\t");


   // _______________
  // ::: Counter :::

   // Display data counter
  //  Serial.print (cpt++,DEC);
 //  Serial.print ("\t");



  // ____________________________________
  // :::  accelerometer and gyroscope ::: 

 // Read accelerometer and gyroscope
 uint8_t Buf[14];
 I2Cread(MPU9250_ADDRESS,0x3B,14,Buf);

 // Create 16 bits values from 8 bits data

// Accelerometer
int16_t ax=-(Buf[0]<<8 | Buf[1]);
int16_t ay=-(Buf[2]<<8 | Buf[3]);
int16_t az=Buf[4]<<8 | Buf[5];

// Gyroscope
int16_t gx=-(Buf[8]<<8 | Buf[9]);
int16_t gy=-(Buf[10]<<8 | Buf[11]);
int16_t gz=Buf[12]<<8 | Buf[13];

 // Display values

// Accelerometer
Serial.print (ax,DEC); 
Serial.print ("\t");
Serial.print (ay,DEC);
Serial.print ("\t");
Serial.print (az,DEC);  
Serial.print ("\t");

// Gyroscope
Serial.print (gx,DEC); 
Serial.print ("\t");
Serial.print (gy,DEC);
Serial.print ("\t");
Serial.print (gz,DEC);  
Serial.print ("\t");


// _____________________
// :::  Magnetometer ::: 


// Read register Status 1 and wait for the DRDY: Data Ready

uint8_t ST1;
do
{
 I2Cread(MAG_ADDRESS,0x02,1,&ST1);
}
while (!(ST1&0x01));

// Read magnetometer data  
uint8_t Mag[7];  
I2Cread(MAG_ADDRESS,0x03,7,Mag);


// Create 16 bits values from 8 bits data

// Magnetometer
int16_t mx=-(Mag[3]<<8 | Mag[2]);
int16_t my=-(Mag[1]<<8 | Mag[0]);
int16_t mz=-(Mag[5]<<8 | Mag[4]);


// Magnetometer
Serial.print (mx+200,DEC); 
Serial.print ("\t");
Serial.print (my-70,DEC);
Serial.print ("\t");
Serial.print (mz-700,DEC);  
Serial.print ("\t");



// End of line
Serial.println("");
//  delay(100);    
 }

marked as duplicate by Dmitry Grigoryev, user31481, gre_gor, dhimaspw, KIIV Feb 7 '18 at 10:00

This question has been asked before and already has an answer. If those answers do not fully address your question, please ask a new question.

1

Is it possible to connect more than one or to be specific 5 MPU9250 into 1 Arduino lilypad?

Yes, that is possible with both SPI and I2C. With SPI you will need MOSI(11), MISO(12), SCK(13), and CSn where CSn is CS0..CS4 are digital pins in output mode for chip select.

With I2C the following pins are needed SDA(A4), SCL(A5), and CSn. The chip select pin is connected to AD0 on the device. AD0 is used for the lowest bit in the I2C address. Addressing is achieved by connecting AD0 to CSn and keeping all high except the one that is addressed. The I2C address is the same for all access. The CSn pin defines which device will response.

The example code below uses the lower address and chip select is put low for the selected device.

// Chip select pin device#0
const int CS0 = 4;
...
void setup() 
{
  ...
  // Initiate chip select pin for device#0
  pinMode(CS0, OUTPUT);
  digitalWrite(CS0, HIGH);
  ...
}
...
void loop()
{
   ...
   // Select device#0 
   digitalWrite(CS0, LOW);
   MPU9250_someFunction();
   digitalWrite(CS0, HIGH);
   ...
}

How will I set the addresses, and where should I put the pins for SDA and SCL?

SDA is connected to A4 and SCL to A5.

Using the above given example code (from the question) a rewrite of the I2Cread function could be:

// This function read Nbytes bytes from MPU9250 device with chip select pin. 
// Put read bytes starting at register Register in the Data array. 

void MPU9250_read(uint8_t CS, uint8_t Register, uint8_t Nbytes, uint8_t* Data)
{
  digitalWrite(CS, LOW);

  // Set register address
  Wire.beginTransmission(MPU9250_ADDRESS);
  Wire.write(Register);
  Wire.endTransmission();

  // Read Nbytes
  Wire.requestFrom(Address, Nbytes); 
  uint8_t index = 0;
  while (Wire.available()) Data[index++] = Wire.read();

  digitalWrite(CS, HIGH);
}
...
// Read magnetometer data from device#3
uint8_t Mag[7];  
MPU9250_read(CS3, 0x03, 7, Mag);

Cheers!

  • Please see above @MikaelPatel I posted the code that I am using from the internet. – Thomas Jan 27 '16 at 2:30
  • What was the question? Do you want to know how to change that? It is really bad. There must be better drivers to change. And if we do that we should make that shared. A possible fork on github on a good driver? – Mikael Patel Jan 27 '16 at 8:36
  • I have added a rewrite of I2Cread to give you a hint how to do this. – Mikael Patel Jan 27 '16 at 9:00
3

where should I put the pins for SDA and SCL?

Same as on a Uno:

  • SDA is on pin A4
  • SCL is on pin A5

Can you suggest me some links that can help me learn more about SPI?

I have an SPI page and also one about I2C.

There is also a page about SPI on this site: How do you use SPI on an Arduino?

If you want to use 5 devices, it sounds like Majenko's recommendation is good: Use SPI. You would share MOSI/MISO/SCK between all devices (D11/D12/D13), and give each one a separate SS (slave select) line.

  • Thank you for responding to my concern. Can I ask you if you have the existing codes already on it? @NickGammon – Thomas Jan 25 '16 at 7:04
  • No I don't, sorry. There are dozens of Arduino models these days, and hundreds, if not thousands, of things you can connect to them. I don't happen to have a Lilypad and 5 x MPU9250 devices. However the links I provided should help you to get started in writing your own. – Nick Gammon Jan 25 '16 at 8:03
  • Please see above @NickGammon I posted the code that I am using from the internet. – Thomas Jan 27 '16 at 2:31
1

According to the datasheet the MPU-9250 can work in either I2C or SPI mode.

When it is in SPI mode you can connect up as many MPU-9250s as you have spare IO pins. With SPI the clock and data lines are all shared, and each slave device has its own Slave Select line.

In I2C mode it is possible to only use 2 devices at once - the AD0 pin configures which is which device (connect it to GND or VCC to identify the two devices).

Interestingly the MPU-9250 does include an I2C master module for connecting other sensors to it. Theoretically it should be possible to connect the master port of an MPU-9250 to two other MPU-9250s, and each of those could connect to a further two MPU-9250s each, and so on and so forth in a huge tree. However the programming of such an environment would be an absolute nightmare and not something I would like to undertake.

So in summary: use SPI mode, it's simpler.

  • Thank you for giving me that idea. It helped me enlighten my mind about this project. @Majenko Can you suggest me some links that can help me learn more about SPI, or some working codes which can be a stepping stone to start making the said project work? Cheers! – Thomas Jan 25 '16 at 2:31
  • Please see above @Majenko posted the code that I am using from the internet. – Thomas Jan 27 '16 at 2:33
0

If you use I2C, you can use an I2C multiplex chip to handle the arbitration to handle lots of MPU-9250s. I had a setup with 6x of them going. I did find however, that the amount of CPU time that it takes for I2C communication is high, so once you get in to that many 9250s, you don't have much CPU time left over for other things. Using SPI is a bit trickier to get going, but it is wicked fast and also lets you take advantage of the FIFO buffer on the 9250s.

Majenko mentioned using the I2C master functionality on the 9250 to daisy chain - I had also tried that approach before I tried the I2C multiplexer. I have to say it was a horrible experience. When you use that I2C master function, you are actually programming the advanced functionality of the 9250 instead of using the Arduino coding in C. Once it all starts working (if it does), it acts quite flaky. That functionality on the chip was really designed to enable using an external magnetometer on the 6250 to get 9dof. Any more complex use than that gets hairy with the interchip timing, and initializing on startup is also rough.

Final answer - put in the time to learn how to use the SPI bus as mentioned in some of the other answers. Once you get through the learning curve, it can run at up to 20khz communication speed. SPI is designed for high speed communication. I2C is designed to be easier to use but for things with lower update rates.

Not the answer you're looking for? Browse other questions tagged or ask your own question.