Some DMP troubles – part 2

Alright, it appears that I’m NOT colliding with reading the FIFO and new data coming in, as I thought earlier. Instead, in a previous loop, the resetting of the FIFO probably snaps off the “head” of some data packet being pushed in by the DMP at the same time. Makes a lot more sense, doesn’t it?

I duplicated the original problem with an Arduino UNO using basically jrowberg’s code out of the box, but by removing the Interrupt handler and replacing it by polling the FIFO_COUNT in the main program loop. After eventually reading the 42-byte data packet from the FIFO, I reset the FIFO. By adding a delay of 30 ms or so into the main loop (beyond the update rate of 10ms), I get the “jitter” effect on the little “teapot” airplane. It’s not severe, but it is detectable and annoying.

Then, I modified the program a little: By polling in a loop and letting the FIFO_COUNT go up to 400-something before reading the FIFO data and resetting it, I can see the FIFO_COUNT increase like this:

Multiples of 42 for reference: 42, 84, 126, 168, 210, 252, 294, 336, 378, 420, 462, 504, 546

...
FIFO while waiting: 126
FIFO while waiting: 294
FIFO while waiting: 420
FIFO before reading: 546
Resetting FIFO

FIFO while waiting: 154
FIFO while waiting: 294
FIFO while waiting: 420
FIFO before reading: 546
Resetting FIFO

FIFO while waiting: 136
FIFO while waiting: 262
FIFO while waiting: 388
FIFO before reading: 514 --> Glitch: Read quaternion magn. not 1
Resetting FIFO

FIFO while waiting: 126
FIFO while waiting: 252
FIFO while waiting: 378
FIFO before reading: 504
Resetting FIFO
...

This shows that the increasing FIFO_COUNT before the glitch keeps showing an offset of 10 bytes, but I can’t trust it to always be some constant value when polling.

I don’t really have a solution for this, as I want to read 20 totally¬†unsynchronized sensors at the same time, but at least the problem got re-defined.

Some DMP troubles

Jeff Rowberg’s DMP code uses interrupts to notify the Arduino when a new set of data – a 42-byte packet – is available in the FIFO buffer. In the Teapot example the quaternion form this packet is sent to the PC. I modified the Arduino sketch so, that it does NOT use interrupts but instead polls the FIFO_COUNT register to see if a new packet is available i.e. the count is at least 42. If this is done fast enough it seems to work.

However, when delays are added, say 30us or more, and I read the packet from the FIFO every now and then it probably collides with the DMP writing new data into the FIFO. The result is corrupt data, I think. I found that in the case when the FIFO_COUNT read just prior to reading the FIFO buffer is not a multiple of 42 (the packet size), the quaternion extracted from that packet is not a unit quaternion as it should be.

This makes it a bit hard for my parallel TWI implementation (I don’t want to call it parallel I2C because of trademarks) to read many unsynchronized MPUs without having to discard glitchy data. Here is a related forum post, but I guess it’s only visible to registered users. I’ll quote: “DMP is meant to utilize the interrupt and FIFO system so that it can be synchronized with the host processor, and store the appropriate Quaternion data in the FIFO register. You can utilize the MPU-6050 without these features in raw data mode, but it is required for DMP operation.

(On the same note, the FIFO Count Register description first claims that it contains the “sample count” and later “the number of bytes stored”. I’ll go with “bytes stored”.)

EDIT: Haven’t yet checked if the MPU would do some I2C clock stretching (and I’m ignoring that). I’ll need to check that next.

EDIT #2: Didn’t look for clock stretching. Instead, I’ve got a new theory.

Arduino DUE’s SerialUSB and Processing

The Arduino DUE can have two serial ports over USB: the programming port and the native USB port acting as a CDC device. The programming port can be used through the Serial-object and the native port through the SerialUSB-object.

The trouble was this: I wanted to use the Arduino DUE’s SerialUSB-object (native port) to transmit application data to a Processing sketch. However Processing wouldn’t read anything from the port connected to the DUE’s native port. The Arduino IDE and PuTTY were able to read the native port just fine. The difference: When conneced to the programming port, both the Arduino IDE and PuTTY reset the Arduino (via DTR-signal) and Processing didn’t. So, I gather that it must be a handshake problem of some kind. (Apparently the Java RXTX library used by Processing doesn’t give you access to the control lines?)

Dug up the method size_t Serial_::write(const uint8_t *buffer, size_t size) in the CDC.cpp (arduino-1.5.2\hardware\arduino\sam\cores\arduino\USB) and commented out the check for if (_usbLineInfo.lineState > 0).

I think that did the trick for now… Seems like the Arduino sketch hangs when a certain (buffered?) amount of data is sent until it is actually read by the Processing sketch. Don’t know if there will be other side effects.

Here’s some code to illustrate the point for those who want to try this for themselves. First for the Arduino DUE:

uint8_t counter;

void setup() {

  Serial.begin(115200);
  SerialUSB.begin(115200); // speed is irrelevant for native port
  counter = 0;
}

void loop() {

  Serial.print("Programming port. Counter is at ");
  Serial.println( counter);

  SerialUSB.print("Native port. Counter is at ");
  SerialUSB.println( counter);

  counter++;
  delay(500);
}

And here is the Processing sketch (You’ll need to edit the line portName = Serial.list()[1]; to set the port you want to open on your machine):

import java.util.Arrays;
import processing.serial.*;

String portName;
Serial serialPort;
int speed = 115200;
int bytesReceived = 0;

void setup() {
  size(640, 480);
  System.out.println("Available serial ports are: " + Arrays.toString( Serial.list())); //debug

  // Open 2nd visible serial port
  portName = Serial.list()[1];

  // Serial.list() array's indexes on my machine (this is machine specific):
  // 0 = integrated serial on motherboard
  // 1 = Arduino DUE programming port (when plugged in) - gets received by IDE, PuTTY, Processing
  // 2 = Arduino DUE native port (when plugged in also) - gets received by IDE, PuTTY, but NOT by Processing

  serialPort = new Serial(this, portName, speed);
  System.out.println( "Opened port " + portName); //debug
}

void draw() {
  background(100);
  text("Reading: " + portName, 50, 50);
  text("Received " + bytesReceived + " bytes.", 50, 80);
}

void serialEvent( Serial port) {
  while( port.available() > 0) {
    char c = (char)port.read();
    bytesReceived++;
    System.out.print( c); //debug
  }
}