Design Brief

Since this is an entry for the Return of the Square Inch Project, the first requirement is that it must fit into one square inch. The challenge then is to get as much power into that square inch as possible. Other requirements are as follows:

This means that I need to use surface mount parts, some sort of microcontroller, and SMD parts with the highest level of integration I can get. It also means I'll need an encoder interface. Since I've already been playing with some parts for a line of CANBUS nodes I've been noodling, I already had some parts in mind.

Parts Selection

MCP25625 CANBUS Interface

This is essentially two chips stuffed into a single package -- the MCP2515 CAN controller and MCP2551 CAN driver. That pair is the heart of the typical hacker/maker/hobbyist/etc CAN interface board, including the offerings from Sparkfun and Seeed. The host microcontroller talks to it via SPI and it does all the protocol stuff. Combining the two chips into a single chip saves a bunch of board space and routing, as well as a bit of money. It requires a crystal or resonator, and provides a clkout line that allows us to drive the clock on the host microcontroller.

The driver and logic sides of this chip have different power supplies. The driver requires 5V but the logic side can go from 2.7V to 5.5V. Since we're trying to keep things small and tidy, we'll hook both power supplies up to 5V.

BTM7752G DC Motor Driver

This chip is the real star of the show, and takes up more space than all other chips put together. It's a 12A/28V driver with all the protection (overtemp/overcurrent/overvolt/undervolt) you'd expect. The user has direct control over both half-bridges and a global enable. Current feedback and fault annunciation share the same line. It's as big and simple a lump of power silicon as I thought I could fit on the board.

ATTINY816 Microcontoller

This is the brains of the operations. It's not one of the typical ATTinies seen in maker & hacker projects because it's not yet supported by the Arduino IDE. It has a lot of nice features over the other ATTinies; for this project the most important are the improved PWM, improved ADC, and more flexible interrupts for interfacing with the encoder.

Power Arrangements

A 5VDC LDO hooked into the main motor power drives the logic. I found a cheap three terminal LDO in SOT-23 form factor.

Connectors

This is the place where the size restrictions bite the hardest. The power input and output connectors are just areas of bare copper on the board you can solder wires to. Not the best, but hard to do better in a square inch.

The logic connectors (CAN, ICSP, and encoder) are all JST SH series. They're tiny and I'm already familiar with them from the Beaglebone Blue.

Software Arrangements

The typical way a position controller works is three nested loops -- current control, velocity control, and position control. For truly excellent motion control, you can add acceleration control to tame jerk. This reduces vibration in machines, but is a bit beyond this project. Similarly, the loops will all be standard issue PID loops with no feed forward terms. That limits their ultimate performance but keeps the software task in bounds for a contest that closes in a few weeks.

The gating item is the PWM frequency, which is limited to 25 kHz by the motor driver chip. With a 16 MHz main clock, this gives me 640 duty cycle steps, which is more than enough here. Ideally, the current loop needs to run about an order of magnitude slower than this for stability, or about 2500 Hz. We'd like the outer positioning loop to run at 100 Hz, which implies that we should run the velocity loop half way between (at least on a log scale) at 500 Hz. Since these speeds are integer multiples of each other, the whole business can run off a single timer interrupt. The spare time in the loop is long enough to exchange 3-4 bytes with the CAN interface on each current loop, so no interrupts are required there.

The encoder, however, does need to use interrupts to function correctly. For example, I have a 34:1 gear motor with a no-load output speed at rated voltage of 280 rpm and a 48 cpr encoder on the drive motor. If I want to pick up all four edges, I can expect to sample 30,464 events per second. If I overdrive the voltage (safe enough with current control), it can be even faster. Luckily, this is a very fast function, so its calls should slip neatly between the events called in the main time loop.

The requirement that we pick up every event on the encoder puts some fairly strict requirements on how long we can spend in interrupt context when the timer interrupt fires. Luckily, we can get away with setting a flag and rely on a busy-wait in the main loop to take over outside of interrupt context when the timer fires and leave the encoder interrupt free to fire.