Part 6: On implementation aspects of control – Low cost real-time closed-loop control of a consumer printer

Introductory post: link
Previous post: link

In the previous post, the end goal of this project was reached: the implementation of Iterative Learning Control using less than €10 worth of hardware.

In this post, I’ll explain what I’ve learned on the implementation aspects of control during this project. A lot of these things are probably elementary if you have a background in electrical engineering, but as a control engineer with a mechanical engineering background, I had to figure these things out as I went. Hopefully, this post can help people with a similar background to learn more about the practical side of things. Disclaimer: I’m no expert by any means when it concerns electronics, so if I’m wrong about something, I’d love to be corrected in the comments or through the contact form.

First, I’ll cover what I learned about the implications of using PWM in a control loop. Second, I’ll explain what I learned about the difference between current control and voltage control. Lastly, I’ll give a more general evaluation of the project and point to some possible improvements.

What it means to use PWM in a control loop

From my university classes in the Mechanical Engineering department, I’m used to the convenient assumption that we can apply any input u(t) to a system. If only things were so simple in practice.

I learned that when working with microcontrollers, there are two main ways to send an analog signal: 1) using a DAC, and 2) using PWM. These two methods have a few things in common:

  • The signal coming from the microcontroller is <5V, so some kind of amplifier is needed in between the microcontroller and the DC motor.
  • The resolution of the analog signal is limited to 2n possible values of u(t), where n is a number of bits.

As far as I’m aware, a major advantage of switched methods such as PWM is increased efficiency. Since I got an L298N motor driver board early on, which works with PWM, I didn’t look much further into DACs. Therefore, from here on, I’ll focus on PWM.

Using PWM to generate analog signals

As it turns out, PWM can be used to ’emulate’ a DAC: we compute a desired u(t) on the microcontroller, set a duty-cycle to generate a high-low pulse signal (i.e. we encode our desired input to PWM), and by low-pass filtering this signal, an analog signal is obtained (it is decoded again).

But how do we know the ‘decoded’ signal matches our original desired signal u(t)? Is this operation of encoding and decoding even linear? Since I wanted to use linear control theory, this is a critical requirement. Eventually, I learned that indeed, knowing whether the analog signal matches the original desired u(t) is not at all trivial.

What can go wrong with PWM? Why even worry?

This page of Open Music Labs nicely explains it. In short, when the carrier frequency of PWM is insufficiently high with respect to the sampling frequency, we get harmonic distortion of the real signal u(t) with respect to the desired signal u(t). Also, recall from Part 3 that if we want twice as much resolution (possible values that u(t) can take), we need to halve the carrier frequency.

Now, there are some very interesting techniques to get rid of PWM distortion completely using sophisticated nonlinear computation of the duty cycle, and it would be very interesting to see the difference that these methods make in practice, but this just goes beyond the scope of my project. Let’s keep the scope limited to selecting the right carrier frequency.

On the STM32F407VET6, there is a 16-bit timer running at 168 MHz, so if we want a 12-bit resolution, we have a carrier frequency of at most 41 kHz. We want the sample time of the control loop to be sufficiently high because discrete-time delays can limit the achievable performance of the closed-loop. From the page on Open Music Labs, we find that if we sample too fast, we can end up with quite some harmonic distortion of the signal. This is why I’d been worried about this in the first place.

Trade-off between sample time, resolution and PWM distortion

In this project, the open-loop bandwidth was around 20 Hz, and phase lag caused by discrete-time delays was not the limiting factor. Therefore, I decided to lower the sample time to 2 kHz and choose a carrier frequency that was a factor 8 higher. I used a continuous-time Simulink model with a PWM block to verify that with these numbers, the PWM distortion was acceptable (it really wasn’t when the carrier frequency was around 2 times higher). This allowed for a 14-bit resolution. It might have been better to lower the resolution in return for even more carrier frequency, but at this point, I realized something that largely ended all my worries about making the right choices with PWM.

Why I probably didn’t need to worry that much about PWM distortion anyway

Let’s view the harmonic distortion on u(t) caused by PWM as a disturbance d(t), i.e., input noise. The same holds for quantization effects; we don’t have an infinitely high resolution, so let’s say that the mismatch with the desired u(t) is also lumped into d(t).

Both of these input disturbances are likely high-frequent, varying roughly at the time scale of the sample time but not around the bandwidth of ~20 Hz. In closed-loop, the transfer from d(t) to the error e(t) is the process sensitivity, i.e., PS(z) = P(z) / (1+C(z)P(z)). At high frequencies, the process sensitivity approximately equals the plant P(z), which has a negative slope at high frequencies.

So it might be a good idea to be aware of the fact that the carrier frequency is not too low w.r.t. the sample time, and you don’t want your input resolution to be too low either (I think 12 bit is used a lot in practice), but if the choice is imperfect, its contribution to the error will likely be marginal because it is filtered with the process sensitivity. Output noise on y(t), on the other hand, is transferred to the error through the complementary sensitivity T(z) = P(z) C(z) / (1+C(z) P(z)), which approximately equals P(z)C(z) at high frequencies. With high controller gain, output noise is therefore much more likely to be problematic than input noise.

Nevertheless, it was very interesting to learn more about this, and at least I feel like I know much more about different sources of input noise now.

On voltage control vs. current control

When modeling motion systems, it can be convenient to view the torque T(t) as an input to the system. In DC motors, torque is proportional to the current. However, the output of our microcontroller is a voltage. So do we just use voltage as an input? Or do we need to do something more?

Consequences of using voltage as an input

From this model of a DC motor, we have the following transfer function:

$$ P(s) = \frac {\dot{\Theta}(s)}{V(s)} = \frac{K}{(Js + b)(Ls + R) + K^2} \qquad [ \frac{rad/sec}{V}] $$

If we measure position instead of velocity, an integrator is added to the transfer function. The resulting 3rd order system then has one integrator and two poles, the location of which depends on motor inductance, electric resistance, viscous friction, the motor constant, and inertia. With only one integrator, a constant input (voltage) leads to a constant velocity of the printhead.

Suppose we want to control the torque of the motor directly – for example, because we want to use basis functions feedforward based on the differential equations of the dynamics (where input is torque). What do we do then?

Using cascaded control to effectively have current be the input

With feedback, you can change the location of the poles. With cascaded control (see e.g. Multivariable feedback control by Skögestad), you could change the printer system from being an open-loop system P(s) to being a closed-loop system P(s)C(s)/(1+P(s)C(s). The reference to this closed-loop system is desired current (expressed physically by a voltage) and the output is the measured current.

From the link at the beginning of this section, it can be derived that the transfer from voltage to voltage to current resembles a low-pass filter. Hence, a high bandwidth can be reached easily using a simple PI-controller. Since the closed-loop transfer is approximately one below the bandwidth, this means that up until this high bandwidth, you can essentially control the torque by changing the reference voltage (which represents desired current now).

I worked this out in a simple Matlab script to demonstrate how this could work as an example. How to actually implement this current controller is a topic for another project. In this printer project, I just used the voltage as an input, which is perfectly possible too.

Evaluation & conclusions

This project taught me a lot about discrete-time control, real-time systems, and electronics. I find that doing such a large project is a great way to learn how to apply theory in real systems.

So, as it turns out, it’s perfectly possible to implement advanced motion control techniques even with cheap hardware. It is more cumbersome to write C than to drag and drop Matlab blocks, but at such a low price it’s great.

I already have some ideas for the next project, which will likely involve MIMO control, repetitive control, or both. Subscribe to the newsletter in the sidebar to get a notification when I write a new post and feel free to leave questions in the comments.

Author: Max

I'm a Dutch PhD candidate at the Control Systems Technology group of TU/e.

Leave a Reply