PC Engines Home
  ALIXAPUCompactFlash AdaptersTest ToolsAtticInfoShopSupport
AC 97 based motion control
This is a design idea on how to do medium performance stepper motor control on the cheap using ALIX hardware. Implement at your own risk, I have not tested this. Expect some grinding of gears, gnashing of teeth, flying sparks and a lot of fun. If you decide to go for it, please contact me for additional information and support.

Typical low-end CNC systems control stepper motors using a parallel port interface. For each axis, one pin controls the direction, another pin issues the steps. This pulse train is fed into a microstepping stepper motor driver, e.g. Geckodrive or US Digital MD2S. Microstepping means that multiple pulses have to be sent for a full step. The motor driver generates the correct phase currents to interpolate the positions. This results in smoother operation and higher resolution than full step operation.

To achieve controlled speed operation and avoid missing steps, the pulses need to be sent by the host PC with relatively critical timing. Project like LinuxCNC achieve this through the use of hard real time extensions. But having a 50 kHz interrupt rate to send pulses to a stepper motor is not a good use of CPU time.

A better solution is to stream the pulse train using hardware. Suitable hardware designed for uninterrupted bus mastering data transfer is included "for free" in almost every PC chipset, including the AMD CS5536 companion chip: the AC97 audio interface. You just have to get at it in digital form. Analog audio is not suitable for motion control, as the audio outputs are AC coupled by capacitors. The AC97 interface is very compact, and only requires four pins:

bitclk = bit clock, sent by the AC97 codec. Usually 48 kHz * 256 = 12.28 MHz, but for this application other frequencies could also be used.
sync = frame synchronisation, sent by the AC97 host. This signal indicates the start of the 256 bit frame.
data_out = output data, sent by the AC97 host.
data_in = input data, sent by the AC97 codec to the host.

Each 256 bit frame consists of 13 slots, a 16 bit header and 12 x 20 bit data channels (CS5536 only supports 16 bit resolution):

0tag (16 bit)tag (16 bit)
1command addressstatus address
2command datastatus data
3pcm leftpcm left
4pcm rightpcm right
5line 1 dacline 1 adc
6pcm centermic adc
7pcm left surrreserved
8pcm right surrreserved
9pcm bassreserved
11headset dacheadset adc
12gpio outgpio in

To send a data stream, the host CPU has to prepare the audio (or motion) data in a buffer, and then start the AC97 bus master engine to stream out the data. Data will be sent out at a constant rate controlled by the AC97 bitclk, and if the software does its job right, there will be no interruptions in the stream. As long as the process gets a sufficient priority, this should be doable even with a normal (non real-time) kernel.

How to control motion with this ? There are three options:

• Send pulse / direction data. This is the easiest to implement, and will work with legacy motor drives. Each 16 bit channel can control 8 motors, so you could theoretically control 48 motors at once when using the available 5.1 audio channels... Limitation: Pulses are always aligned to the frame rate of 48 kHz, so there will be some jitter (up to about 20 µs) compared to an ideal implementation.

• Send phase current data. For each stepper two phases are used, e.g. 2 x 8 bits. This data can be fed directly into a DAC to control the target motor current. With this approach the phase current can also be controlled to save power, e.g. reduce the current while the motor is standing still, or doing a stable speed motion. The chopper should run at the sample rate to avoid aliasing.

• Send phase angle + optional current data. This saves bandwidth for 3 phase PM DC motors, and allows higher angle resolution. The drive can calculate the individual phase angles using a sinewave lookup table. The chopper should run at the sample rate to avoid aliasing.

How to synchronize multiple channels ? There is a special bit in the bus master registers to synchronize multiple channels for clean 5.1 audio playback. Synchronizing output and input channels is a bit more challenging, but could be achieved by copying marker synchronization bits from one of the output channels to the input.

How to close the loop ? The input channels can be used to get encoder data back into the system. Expect some latency and pain to synchronize... This approach is not ideal for true closed loop control, better to put more intelligence in the individual motor drivers.

How to control spindle speed ? PWM data could be sent over one of the channels, convert to analog using a simple R-C filter.

How about GPIO ? AC97 supports up to 16 inputs and 16 outputs, which are updated once per frame. This should be good enough for typical control or limit switches.

How to get at the AC97 signals ? Please see the ALIX board schematics for details. On alix2d2 you can pick them up on the miniPCI connector, a little more tricky on other models. Please note that the audio controller is disabled on the standard BIOS version, ask for a special BIOS.

Can I do this on boards other than ALIX ? Yes, any chipset or CPU that supports the AC97 could be used for this.

Sample implementation: The AC97 to pulse decoder can easily fit into a 64 or 100 pin Xilinx XC9572XL CPLD (about $3 at Digi-Key).


reset#		(power on reset for reliable startup)
ac_bitclk  	(bit clock from oscillator, same clock is driven to the host)
ac_sync    	(synchronisation pulse)
ac_s_out   	(AC97 data from host)
gpi0..15   	(16 general purpose inputs)


ac_s_in	   	(AC97 data to host)
pulse0..7  	(8 pulse outputs)
dir0..7	   	(8 direction outputs)
gpo0..15   	(16 general purpose outputs)

total 53 pins used


D-FF to generate delayed version of ac_sync (to detect leading edge)

8 bit frame counter, stopped after reset, starts on leading edge of ac_sync

16 D-FF for pulse + direction signals (updated as they arrive from the frame)

8 gates for the pulse signals (issue pulses during the first 32 cycles of the
AC97 frame to get minimum 2 µs pulse width)

16 D-FF for GP output signals (updated as they arrive from frame)

16:1 multiplexer for general purpose input (return on ac_s_in at the
right bit times of the frame)

Please see the AC97 specification and the AMD CS5536 data sheet for more information. As they say, the rest is software...

Pascal Dornier 2/2/2010.

© 2002-2014 PC Engines GmbH. All rights reserved.