I'm trying to use an Arduino Due to interface with an ADIS16364 IMU from Analog Devices (product info here) via SPI.
There are two modes for retrieving the measurements from this particular IMU (six 16 bit values, 3 acc, 3 gyros):
The first mode is, if I'm not wrong, the standard one with SPI, in which each successive transfer command retrieves the last data requested and indicates which one should be retrieved next.
The second possibility is a so called "burst mode". For this one you have to request the 0x3E00 register. After that, the IMU will burst out the six measurements (plus a few other bits of information like temperature and supply voltage). From the specs sheet:
The problem is, I can not manage to make the Arduino read the data using this burst mode. This is the code I'm using to test the communication:
#include <SPI.h>
#define SerialBT Serial2
short supply, xgyro, ygyro, zgyro, xacc, yacc, zacc, xtemp, ytemp, ztemp, aux;
volatile byte fDataIMUtoRead = 0;
int pauseBetweenTransfers;
void setup() {
SerialBT.begin(230400);
pinMode(52, OUTPUT);
// Configure SPI
SPI.begin(52);
SPI.setClockDivider(52, 200); // 84e6/200 = 420kHz
SPI.setDataMode(52, SPI_MODE3);
SPI.setBitOrder(52, MSBFIRST);
// Set sample rate
float Fs = 1; // Target sampling frequency [Hz]
float tb = 0.61035 * (Fs >= 12.7009) + 18.921 * (Fs < 12.7009);
unsigned long tbsel = 0 * (Fs >= 12.7009) + 1 * (Fs < 12.7009);
unsigned long Ns = (uint16_t) round((1000.0 - tb * Fs) / (tb * Fs));
float Feff = 1000 / (tb * (Ns + 1));
SerialBT.print("Selected freq: ");
SerialBT.println(Feff, DEC);
digitalWrite(52, LOW); // Doesn't seem to be necessary
SPI.transfer16(52, (0L << 15) | (0x36L << 8)); delayMicroseconds(100);
SPI.transfer16(52, (1L << 15) | (0x36L << 8) | (tbsel << 7) | Ns ); delayMicroseconds(100);
SPI.transfer16(52, (0L << 15) | (0x36L << 8)); delayMicroseconds(100);
zgyro = SPI.transfer16(52, 0x00);
digitalWrite(52, HIGH);
SerialBT.print("SMPL_PRD = ");
SerialBT.println(zgyro, HEX);
attachInterrupt(3, availableIMUData, RISING);
}
void loop() {
if (fDataIMUtoRead) {
SerialBT.print("Loop... ");
// Read values (standard mode)
pauseBetweenTransfers = 100;
digitalWrite(52, LOW); // Doesn't seem to be necessary
SPI.transfer16(52, 0x0400, SPI_CONTINUE); delayMicroseconds(pauseBetweenTransfers);
xgyro = SPI.transfer16(52, 0x0600, SPI_CONTINUE); delayMicroseconds(pauseBetweenTransfers);
ygyro = SPI.transfer16(52, 0x0800, SPI_CONTINUE); delayMicroseconds(pauseBetweenTransfers);
zgyro = SPI.transfer16(52, 0x0A00, SPI_CONTINUE); delayMicroseconds(pauseBetweenTransfers);
xacc = SPI.transfer16(52, 0x0C00, SPI_CONTINUE); delayMicroseconds(pauseBetweenTransfers);
yacc = SPI.transfer16(52, 0x0E00, SPI_CONTINUE); delayMicroseconds(pauseBetweenTransfers);
zacc = SPI.transfer16(52, 0x0000, SPI_CONTINUE);
digitalWrite(SS, HIGH);
/*
// Read values (burst mode)
pauseBetweenTransfers = 5;
digitalWrite(52, LOW); // Doesn't seem to be necessary
SPI.transfer16(52, 0x3E00); delayMicroseconds(pauseBetweenTransfers); // Request data burst
supply = SPI.transfer16(52, 0x0000, SPI_CONTINUE); delayMicroseconds(pauseBetweenTransfers);
xgyro = SPI.transfer16(52, 0x0000, SPI_CONTINUE); delayMicroseconds(pauseBetweenTransfers);
ygyro = SPI.transfer16(52, 0x0000, SPI_CONTINUE); delayMicroseconds(pauseBetweenTransfers);
zgyro = SPI.transfer16(52, 0x0000, SPI_CONTINUE); delayMicroseconds(pauseBetweenTransfers);
xacc = SPI.transfer16(52, 0x0000, SPI_CONTINUE); delayMicroseconds(pauseBetweenTransfers);
yacc = SPI.transfer16(52, 0x0000, SPI_CONTINUE); delayMicroseconds(pauseBetweenTransfers);
zacc = SPI.transfer16(52, 0x0000, SPI_CONTINUE); delayMicroseconds(pauseBetweenTransfers);
xtemp = SPI.transfer16(52, 0x0000, SPI_CONTINUE); delayMicroseconds(pauseBetweenTransfers);
ytemp = SPI.transfer16(52, 0x0000, SPI_CONTINUE); delayMicroseconds(pauseBetweenTransfers);
ztemp = SPI.transfer16(52, 0x0000);
digitalWrite(52, HIGH);
*/
SerialBT.println(zgyro, DEC); // Print the reading
fDataIMUtoRead = 0; // Reser the "there is new data"-flag
}
}
void availableIMUData() {
fDataIMUtoRead = 1; // Set the "there is new data"-flag
}
The standard way to communicate seems to work without any problem, provided that I set the right delays after each transfer16 command. But I'm not able to make the Arduino read the data in burst mode (commented in the code above).
So does anybody have any ideas on how to make the Arduino retrieve the readings in this burst mode? I understand this is a tricky unless you have (had) access to the same hardware, but any suggestion will be welcome.
Thanks a lot.