Accessing two i2c devices over 2 different channels simultaneously

Hi,

I have 2 devices (accelerometers) connected to 2 different i2c channels. Currently, I am accessing them sequentially i.e. I read from one, then the other one.

I was thinking that since they are using different buses physically, is it possible to read them simultaneously, so as to reduce the read time significantly?

Any ideas?

Thanks

Which Arduino?
The data for the 8-bit parts has to go over the same internal 8-bit bus, so they can't really be read at the same time.

CrossRoads:
Which Arduino?

Arduino Zero

If you use a FPGA and design a circuit, then it is possible. But not with an Arduino board.
You can try to set the bus speed to 200 kHz or 400 kHz with Wire.setClock().
If you need more speed, then you should use a sensor with SPI interface.

The Arduino Wire library was designed for slow 16 MHz microcontrollers. The Wire.endTransmission() and Wire.requestFrom() wait until everything is finished and the I2C bus is idle. That means the Arduino Zero has to wait a lot when using the Wire library. There are a few alternative I2C libraries, but I have not seen a good one yet.
Therefor the SPI bus is so much better when timing is important.

You are not using the old MPU-6050 I hope ? The MPU-9250 can do both SPI and I2C. It can do 1 MHz SPI, but for the actual sensor data it has a special high speed of 20 MHz SPI.

Koepel:
The Wire.endTransmission() and Wire.requestFrom() wait until everything is finished and the I2C bus is idle. That means the Arduino Zero has to wait a lot when using the Wire library. There are a few alternative I2C libraries, but I have not seen a good one yet.
Therefor the SPI bus is so much better when timing is important.

Does this even apply when you have 2 physical buses? So, one bus is transmitting data but the other one is free. Can we use both the buses at the same time?

SPI is indeed a better choice and I am now going to use it instead of I2C. However, apart from SPI being faster, can we use two SPI buses on 2 different channels simultaneously, more like in parallel?

Thanks

One or two busses does not matter, it is the same waiting when using the Wire library. It is never executed at the same time. In most cases it is no problem to wait a millisecond a number of times per second.

It is the same for the SPI bus. They are not run simultaneously.

Arduino was designed by a student. It is ment for easy prototyping and it is easy to use and it is to make a smooth start to learn programming. That turned out to be very successful.

Arduino was not designed by a team of software engineers with decades of experience with event driven realtime preemtive multitasking software.

You don't have to use Arduino. With the Atmel Studio you can write your own code.

Which sensor(s) do you use and what is it for ? A common mistake is when someone has code with a lot of delay(), either in the sketch or in libraries, and tries all kind of weird solutions instead of removing all the delay(). For a fast responding Arduino, avoid the delay() and don't use NeoPixel, FastLED, DHT, or OneWire libraries. Perhaps you should avoid the SD memory card library as well, the Arduino does not have a hardware controller for that, everything is done in software.
You have not shown us any code, therefor I wonder what your code looks like.

I am not using any delay(). I have set up a timer interrupt that sets a flag every 10 millisecond, which I then use to poll data from the sensor. I need to sample higher that this rate. I am aiming at 1K samples / second or read every millisecond.

I am now using SPI instead of I2C and it has reduced the read time significantly. Almost 43% of what it took with I2C. This is at 5MHz, which is the highest the sensor can go.

So, what I take from this is that simultaneous access over 2 different channels is is not possible with Arduino libraries. Right? But is it possible any other way? Say, I write my own code with Atmel Studio. Does it involve dealing with DMA?

Can anyone point me in the right direction?

The code is like this,

Setup SPI:

 pinMode(_clk, OUTPUT);
 digitalWrite(_clk, HIGH);
 pinMode(_do, OUTPUT);
 pinMode(_di, INPUT);*/
 SPI.begin();
 SPI.beginTransaction (SPISettings (5000000, MSBFIRST, SPI_MODE3)); 
 pinMode(_cs,OUTPUT);
 digitalWrite(_cs, HIGH)

Read Register:

void Accel::ReadRegister(uint8_t regAddress, uint8_t values[], uint8_t numberOfBytes)
{
  regAddress |= 0x80;

  // set the multi-read byte if required
  if (numberOfBytes > 1) {
    regAddress |= 0x40;
  }
  
  digitalWrite(_cs, LOW);
  SPI.transfer(regAddress);
  
  // read the data
  for(int i=0; i<numberOfBytes; i++){
    values[i] = SPI.transfer(0x00);
  }

  digitalWrite(_cs, HIGH);
}

Setting the pinMode also sets the output hard LOW. That activates the chip select. You can do a digitalWrite HIGH before the setMode and perhaps a delay after initializing.

For all Atmel chips (AVR and SAMD) it is okay to set a pin HIGH or LOW before setting that pin as OUTPUT.

Doing simultaneously I2C or SPI seems strange to me. I don't know why.

DMA combined with SPI, now that would be awesome.
I think some work has been done for the Teensy: GitHub - crteensy/DmaSpi: DMA SPI for the Teensy LC/3.0/3.1/3.2/3.5/3.6
The Teensy has more libraries that use DMA, I have not seen it for the normal Arduino boards.

Some processor speeds:
Arduino Zero: 48 MHz, 32-bit ARM Cortex M0+
Arduino Due: 84 MHz, 32-bit ARM Cortex M3
Teensy 3.6: 180 MHz, 32-bit ARM Cortex M4F (with floating point unit).

Have you told us yet what kind of accelerometer it is and what your project is ? Perhaps there are other ways.

Koepel:
Doing simultaneously I2C or SPI seems strange to me. I don't know why.

Have you told us yet what kind of accelerometer it is and what your project is ? Perhaps there are other ways.

My system has multiple sensors (ADXL375 accelerometers). I need to read data from all of these accelerometers to create a data packet before processing. Because, the data is accessed in a sequential manner, the total access time adds up. (Total access time= Access time of 1 accelerometer x no. of sesnors). I have multiple SPI channels enabled, but they serve no purpose as when the data is being accessed on 1 channel, the other channel is idle. What I am thinking is that if somehow both channels access data simultaneously, the total access time will be almost halved. Not sure if this can be done without DMA.

Also with DMA it adds up, unless there is more than one DMA channel.
It always adds up.

As far as I know, the only way to retrieve data parallel is to use extra hardware. I mentioned a FPGA, but perhaps more than one Arduino board or perhaps there is a SPI to parallel chip so the Arduino can read the data parallel.

I think that with 5MHz SPI, retrieving multiple sensors with a sample rate of about 1kHz should work. Does retrieving all the data with the SPI code that you showed take more than 10% of the cpu time ?

I don't know how many µs the digitalWrite() for a Arduino Zero takes, perhaps you can optimize that.

I have come to the limit of my knowledge. If no one else has a better idea, try to continue with your SPI code.

Another Arduino would certainly do it but it will be additional cost. I am more inclined toward using just one. I need to look more into SPI to Parallel solutions. Thanks for mentioning it.

At 5MHz SPI, ADXL375's access time is 170 micro seconds. I found out via experimenting that it totally depends on the sensor, a Bosh sensor that I had, had access time in milliseconds.

For 1 K samples/second, I have only 1 millisecond to get data from all the 5 sensors and process it, which seems really difficult; considering that I am spending about 850 micro seconds in just polling data.

If I can reduce this added up access time somehow, it will be great.