Making PCBs

There is a first time for everything and this time it’s about drawing a PCB and using a board house to manufacture it.

I drew a even smaller breakout board for the MPU-6050 with Eagle and sent the files to Seeedstudio’s “Fusion PCB service”. Now we’ll have to wait and see what comes out of it. (Btw, Seeedstudio has also a stencil service.) Eagle’s freeware version is limited to 100 x 80 mm 2-layer boards and non-profit applications. I chose Eagle over open source KiCAD, because Seeedstudio had downloadable design rules and a gerber generator that plug straight into Eagle. (One note: even though it says on the Seeedstudio site, that “the Gerber file must be RS-274x format”, the drill file generated by the gerber generator is not of that format by default. And from my very very limited experience that seems to be correct and no changes are needed.) Anyway, if these boards turn out OK, I’m likely to use this service again. It’s almost too easy and the price seems quite affordable 🙂

A couple of great tutorials have also helped me: Jeremy Blum‘s Eagle tutorials on youtube and, because he hasn’t made the 3rd part yet, this article from Dangerous Prototypes. Also there was some Spanish tutorial on youtube about the CAM stuff and Gerber generation, but I didn’t bookmark the link.. ah, well. Then there is SparkFun’s tutorial, which is something I definitely should have read before sending the files 🙂

EDIT: Sparkfun also posted this and this video recently.

EDIT #2: Ben Heck also published an Eagle tutorial. (Note: Eagle has now close ties with Farnell/Element14, but you are forced to use their services (not yet, anyway) when using Eagle.)

One of the advantages of using Eagle is the option to use nice and simple part libraries from both Adafruit and SparkFun. The latter has even a schematic and layout for the MPU-6050 breakout board linked to in the product description. They include the most common components and you won’t have to go through the whole parts jungle. If you can’t find the part you’re looking for, there’s a tutorial to create your own.

That about covers this topic for now, but as a note to self, here are some “loose ends” I’ve gathered:

Advertisements

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.

Distance measurement

Fixed the Processing sketch that attempts to measure distances based on acceleration. (It was off by a factor of 10. Guess who didn’t convert from g to m/s^2.) Anyhow, instead of compensating for tilting in code, I built a rail:

sled_1

Of course, this doesn’t mean I might not have to take the orientation into account at some point. Still, with the rail I can roughly measure the moved distance as the change in acceleration happens almost exclusively on the x axis.

sled_2

Drifting is quite bad, though. I’ve got a good 15cm of travel on the rail and measuring movement that’s done right after the measurement starts (within a couple of seconds) seems accurate within +/- 1 cm. But when measuring a completely stationary sensor over a time of 30 seconds, the measurement may have wandered off even beyond 40cm. Currently, I’m fresh out of ideas on how to counter this.

I figured that building a data glove that can track the hands position in 3D space may be quite difficult measuring the accelration of the glove alone. Because the MPU-6050 is able to produce orientation data (as a quaternion), one could of course track the hands position from the shoulder on onward. The shoulder would be a “fixed point” with a ball joint. Having sensors on the upper and fore arm measuring the direction where the arm is pointing to (and knowing one’s arm’s length), one could calculate the location of the hand in relation to the shoulder. It’s not ideal for motion capturing either since the shoulder is capeable of subtle movements, but I think it might be the way to go.

MPU-6050 /w DMP accelerometer demo

After connecting the MPU-6050 again to an Arduino, initializing the DMP and realizing that the accelrometer data is in *signed* 16-bit integers, I’ve got the following:

  • Looks like the default setup is for the 4 g range. That’s very nice.
  • The x- and y-axis are fairly precise, but in my case, the z-axis shows slightly less than 0.9 g, when it should be 1.0 g. I wonder if it varies from chip to chip..

I converted the previous demo for the analog accelerometer for the MPU-6050. You can download the thing here. (There are 2 Processing sketches: one showing the 16-bit measurements and one showing those measurements converted to g forces.)

Also: I wrote a Processing sketch that tries to measure a traveled distance based on the accelerometer. It just uses the s = 0.5 a * t^2 + v*t formula. Currently the results are way off. But this is partly, because rotation isn’t taken into account. Tilting the sensor one way causes it to “accelerate” into two directions (because I compare the acceleration to a pre-measured offset). So, there is plenty room for improvement. I uploaded it here. (Use the same sketch for Arduino as in the aforementioned “mpuAccelerometerDemo”.)