Sound Blaster discrete PID regulator >>>> WARNING: very poor translation!!! <<<<
Following text describes discrete PID regulator with sound card as an input/output interface
to the process. This idea I saw on some forum seemed pretty interesting to me because there is no need for complex
analog/digital input/output interface. Both feedback and output signals can be processed/generated directly with
sound card (software). Warning: Following text sometimes requires at least basic knowledge of signals and systems theory and control theory. ;)
1. Input interface For my experiment I choosed small DC motor. In this case the best option for feedback is rotary encoder. Quadrature encoder can be connected directly to the LINEIN via some capacities and votlage dividers: In my case I got 70% of fullscale signal for maximal input sensitivity which is optimal. 2. Output interface The simplest control method for DC motors is PWM modulation. It can be generated directly on LINEOUT output. Following circuits amplifies the signals and drives the motor:
Used solution is not optimal but I had no other components at the time. :)
Principle of operation is simple: T1 amplifies the signal from sound card LINEOUT output, derivator C2, R5R6 generates on/off pulses for schmidt FF.
Power stage can be used for voltages up to 15V (MOSFET gates won't survive more than some 18V). Zener diode just protects the gate from peaks induced via draingate capacity.
Output choke is used for current smoothing. It's not necessary but it is better to use it at least for lower PWM frequencies. 3. Sound blaster timming Quite important problem was to setup timing. It is obvious that there is certain delay from encoder sampling start (1) to output waveform change (4). Graphical illustration of the problem:
First delay is caused by the fact that the input (feedback) is calculated as mean for whole sampling period (1) to (2),
i.e. average delay Ts/2. Next problem is that the output has to be at least double buffered so there might be new delay Ts. To reduce this interval
output buffers have half size than input ones so the delay from (3) where the buffer is filled with new data to (4) where starts its playback is only Ts/2.
Last delay that appears is necessary inputoutput time offset. This delay is essential because feedback processing and regulator output calculation takes some time.
Minimum reliable delay from (2) where feedback is available to new output request (3) is some 10ms. 4. Program structure Block diagram of whole program:
The program is splitted into (at least) three threads to ensure correct timing.
Main thread is Borland VCL GUI that controls all other modules of the program. 5. Some theory Following text describes some theory and algorithms used in this program. 5.1 Regulator At first I wanted to try just some simple discrete PID regulator but it did work fine so I decided to implement so called betaIPD topology with dynamic antiwindup because this topology gives user more options to modify closed loop response shape than ordinary PID. Block diagram of this topology:
Derivative component is of course filtered, unfiltered version usually just does more harm (especially for fast sampling).
It amplifies the noise and generates nasty spikes that are very unhealthy for mechanical parts of the process. Filtered derivative component decreases
the amplitude and stretches the pulse to longer time period so it is less harmfull to process and it also doesn't amplifies the noise so much.
The discrete approximation I used is called ImpulseAreaInvariant. This is relatively new method designed at
Brno Technical University (Faculty of Electrical Engineering and Communication) and as far as I remember it's only true equivalent
for continuous version. It is designed to have exactly the same pulse energy as continuous version independently to smapling period.
This allows to use the same regulator tuning methods as for continuous PID. 5.2 Online process identification
After debugging the input, output and regulator functions I decided to add online process model identification (realtime, insystem) and regulator autotuning.
There are lots of different methods for this but I decided to recycle one of my university projets that uses single neuron ARX model with
Steepest Descent minimising algorithm. It might sound a bit complicated but it's actually one of the simplest methods. where coefficients a_{1,2,3} and b_{1,2,3} are model parameters to identify. Third order system might be a bit much for DC motor but on the other hand at least one numerator coefficient (b1) will be "consumed" by the transfer delay and CPU power requirements are not an issue in these days. Neural "network" realization of Fs(z) system: Input weights vector w contains model parameters in this order: The SD algorithm requires only two things: Matrix X with n patterns to learn and vector t with corresponding observations. Matrix X contains delayed process inputs u and outputs y in following order: where u_{k} and y_{k} are input/output samples delayed by k periods. Every row is one pattern to learn. Vector of the observations t contains delayed output samples: The main SD algorithm with so called optimal step ε is defined as follows: Entire algorithm uses only basic matrix operations. Inversion used for ε calculation is only scalar so it's not necessary to implement. matrix inversion. The learning process is finished once the model error decreases under defined limit or if maximum number of itterations is made. Single step prediction of the model output:
Since optimal step ε is used the algorithm is quite simple to setup. It's only necessary to set
reasonable patterns count, i.e. how far to the past it sees. Minimum count is limited to some 20 because of stability of identified parameters and
maximum count to some 1000 samples because of CPU requirements. 5.3 Autotuning Probably the simplest method is good old ZieglerNichols. For this method it's necessary to calculate critical closed loop gain Kk and oscillations period Tk. From these two parameters PID setup can be calculated: K = 0.6*KkTi = 0.5*Tk Td = 0.125*Tk Alternative version for suppressed overshoot: K = 0.3*KkTi = 1.0*Tk Td = 0.125*Tk Calculation of critical parameters for 2nd order system is very simple, for 3rd order it's a bit more complex. Calculation is based on characteristic polynomial of closed loop with P regulator:
where Fw is transfer function of closed loop, Fs system transfer function, Fr regulator transfer function and Kk is critical gain to find.
Characteristic polynomial contains three poles. System can be asymptotically stable and oscillating at the same time in two cases. Two solutions can be found from following equation: One of the solutions might be valid if: If none of those is valid then the second case is possible: one real pole at unit circle (z = 1) and the remaining poles stable: Period of oscillations Tk is given by sampling rate only in this case. 6. The program and its usage The program was written in BDS2006 Turbo C++ and tested in windoze XP. It was debugged on Intel Core i5 (4 cores) but it did work even on my old P3 1GHz. The program should work in windoze 7 as well (I hope that M$ didn't modified sound APIs). It is not well optimized, I'm not using any specialized libraries for matrix operations and especially the graphs are quite uneffective because these are partially drawn via TCanvas class which is known to be very slow.
The program is composed from several units I made earlier so it's a bit inconsistent but there are
lot of comments so I hope is no problem to understand its function.
Everything except main GUI module is written in C/C++ using only standard libraries and WinApi for sound blaster
(windows.h, mmsystem.h). 6.1 License The code can be used in any project but it was designed only for learning purposes so author is not responsible for its proper function! 6.2 Sound blaster setup
At first it is necessary to choose LINEIN input and set reasonable sensitivity in sound card drivers.
Sensitivity should be set to some 6080% fullscale signal according to input waveform scope (in my case with used interface it was full sensitivity). 6.3 Encoder setup In encoder section it's possible to set impulse count per encoder revolution. Encoder is decoded always as quadrature so if single channel is used (one direction sensor) both LINEIN inputs should be feed with the same signal! If bidirectional control is required it's necessary to enable "Bidirect" checkbox in "Speed" section. PWM duty cycle for zero motor current is then 50%. 6.4 PWM setup Here you can manually control PWM duty cycle if manual mode is enabled and you can specify desired PWM frequency. Input interface was designed for range from 100Hz to 1kHz. Lower frequency is not very healthy for DC motor and higher has lower resolution which results in higher output noise. 6.5 Regulator setup
Here it's possible to choose operation mode. Manual allows to control PWM duty cycle directly by trackbar next to the PWM graph. In auto mode the regulator
is enabled and if one of additional modes is choosen the program automatically generates desired value w waveform to ease the identification and regulator tunig. 6.6 ARX model + Autotuning
In this section current model transfer function is displayed. It can be exported in two formats compatible
with Matlab and Octave simulation software. Parameters of Steepest Descent algorithm
(5.2)
can be modified here. There is also simple averaging filter. If it's not required it can be set to single period. 6.7 Closed loop critical poles viewer The pole map can be displayed via menu "View". This graph is usefull to check whether critical pole calculator works properly and the sampling period is correctly set. It should always look similarly to following picture: In case the single real pole is critical (z = 1 + j*0) the ZieglerNichols tuning method is not very successfull. This usually happens when to slow sampling period is used. 6.8 ARX model poles/zeros map The pole/zero map can be displayed via menu "View". This might be usefull for identificator stability checking. It uses cubic equation solving algorithm and I'm not totally sure it does work correctly (only few equation have been tested). 6.9 ARX model step/impulse response The function can be displayed via menu "View". The graph axis drawing algorithm is very nasty so I have no idea if it will work properly for bipolar waveforms but at least for unipolar it seems to be OK. 6.10 Other Double click to any graph should display image export dialog. The image is saved in 24bit bitmap. If the REC button is pressed the file "rec.csv" in program directory is created/truncated and program logs graphs content. 7. Results For testing purposes I've choosed small DC motor. It has no markings that can be found and probably it's not even motor. It has lot of poles, windings has no core (just impregnation) and it runs without heating up to 30V so it's probably tacho dynamo but for this purposes it's just fine. To increase dynamic a little I add some light plastic wheel. At full 12V it runs at some 3000rpm (60Hz). For a feedback I'm using some reflex type opto sensor from old video with 24 pulses per rev.
Dominant time constant is about 800ms so I've choosed sampling period to minimum 70ms. Sampling rate is also maximum for my
sound card (96kHz).
The PWM signal is quite noisy but this is caused by noise in feedback. Currently I'm using the basic method for waveform processing 
counting pulses and their total length. Response to error steps at input of the process (additive  adding some currents to motor): Conclusion: sound card can be clearly used as input/output interface for discrete regulator but it is limited by inserted delay and time resolution. The concept I used doesn't allows transfer delay lower than some 80ms. (c) 2012, Stanislav Maslan  All rights reserved.
