Part 4: Modeling and controller design – Low cost real-time closed-loop control of a consumer printer

Introductory post: link
Previous post: link

In the last post, I set up the basics of the real-time platform, such that it’s possible to run a control loop and transmit data to and from my PC over USB. I have since expanded this platform to work together nicely with Matlab: I have a Matlab function to send signals (e.g., reference or feedforward signals) to the STM32, which copies it to the right array to be used in the control loop.

With this, I can finally start with the control engineering phase. In this post, I’ll explain how I measured a Frequency Response Function (FRF) in closed loop, fit a transfer function and how I designed a simple feedback controller. This is all done with the end-goal in mind: the implementation of Iterative Learning Control (ILC) using a real-time platform worth less than €10 (not counting the power electronics).

I assume quite some prerequisite knowledge of control engineering here. If you have trouble understanding something after reading the references mentioned in the first post, feel free to ask a specific question in the comments.

FRF measurement

There is a lot of friction on this printer. To get the carriage to move at all, I need a PWM duty-cycle (which scales with voltage) of 65%, using my 24V power supply. This leads to important limitations for both the FRF measurement and controller design.

Static friction is non-linear. However, we want to make use of linear control theory, so we need a linear (approximate) model. To this end, we measure the FRF in closed loop in such a way that the carriage is moving most of the time – whenever it’s moving, it’s unaffected by static friction. Measuring in closed-loop also helps prevent the carriage from slamming into the side of the frame, waking up my dog.

A closed-loop FRF measurement does pose a challenge: we need a feedback controller, even before we have a model. The nice thing about this voltage-controlled setup is that the bode plot of the system G(s) starts with a -1 slope at low frequencies, only to decrease to -2 after the pole caused by the motor inductance. Consequently, constant input voltage leads to constant velocity, because of the back-emf of the motor. If the input were current, the system would start with a -2 slope. Since we start with a -1 slope, the Nyquist plot of the open loop, with a proportional controller C(s) = k for some small k, is stable:

Rough Nyquist sketch of a possible G(s) when starting with a -1 slope: closed-loop stability may be achieved with a small gain.

So by starting with a small gain, the closed loop will at least be stable and an FRF measurement is possible.

I opted for the three-point method (see the last part of ‘FRF estimation in closed-loop systems’ here): inject a voltage d to the system in closed-loop, measure both the error e and control effort u = d+C e, compute the sensitivity and process sensitivity and infer the system G(s) from these. As opposed to the two-point method, this doesn’t require knowledge of the controller. Of course, I implement the controller myself but since I was changing it a lot, it was convenient not having to have to keep the Matlab code consistent with the C code running on the microcontroller.

For the disturbance I chose a square wave with an amplitude of 65% duty cycle plus zero-mean white noise. With a reference of zero and a proportional controller C(s)=10 (which was found by starting with a very small gain and increasing it slightly between experiments), this leads to a back-and-forth motion around the center:

Control effort u (feedback+feedforward) and error e during the first two seconds of the FRF measurement. The total measurement took about 2 minutes.

The white noise was generated on the STM32 using this code, this way I don’t need to send huge arrays of random numbers to the microcontroller.

The FRF measurement. In closed-loop with r=0, the carriage is always ‘pulled’ towards the center.

The resulting two minute FRF of the system G, using Hann windowing with a 1/3 second window size, looks like this:

Bode plot of the FRF of the printer. You can clearly see the resonance and anti-resonance around 300 Hz.

Below 200 Hz the coherence is really not that great so the FRF should be taken with a large grain of salt:

Coherence between u and d (left), e and d (right)

It’s not perfect, but for the purpose of having a decent model for ILC, we can work with this.

Parametric model

For ILC we need a parametric model of the process sensitivity PS(s) = P(s) / (1+P(s) C(s)). To that end I made a fit of G with one integrator that looks like this:

Bode plot of the FRF and the fit.

It’s not perfect, but as I’ll show in a future post, it’s enough to lead to great results using ILC.

Controller design

The end-goal of this blog series is to implement ILC on the printer. With ILC, as I’ll explain more in a later post, a feedforward signal for a single task is learned iteratively. However, we also want a feedback controller, for e.g. attenuation of disturbances.

Controller design for this system is cumbersome, because the feedforward voltage required to get the printer to move at all is 65% of the maximum voltage. This leaves 35% for feedback. As it turned out, with any kind of pole in the controller close to the unit disc, the feedback signal would saturate in no time. Saturation, in which a duty cycle of >100% is forced back to 100% is a non-linear action, so all linear control theory can be thrown out the window. Often times, when this happened, the feedback signal would jump between 100% and -100% every sample, leading to me frantically rushing to pull the cable out.

As mentioned before, for a low bandwidth controller we really don’t need phase lead, because G starts with a -1 slope at low frequencies. I also don’t really need an integrator, because with (parallel) ILC this could lead to the ILC signal and the feedforward signal working against each other. For that reason, I went with the low bandwidth controller C(s)=10, such that the bandwidth lies around 17 Hz (very roughly, mind that the FRF isn’t perfect at low frequencies) and the Nyquist plot of the open loop looks like this:

Nyquist plot of L=CG, with C(s)=10. Mind that the quality of the FRF is not great at low frequencies, but this indicates that we very well may have closed-loop stability, assuming G has no poles in the open right half plane. Experiments confirmed this.

Since it proved that this controller with ILC led to performance that I was happy with, I didn’t go further than this. I’m aware that there are techniques that deal with saturation of the feedback signal, but I didn’t feel they were in the scope of this project.

In the next post, I’ll show how I successfully implemented Iterative Learning Control with this model and controller, leading to an error in the order of 0.1 mm (a few times the encoder resolution) during constant velocity. If you don’t want to miss it, make sure to subscribe to the e-mail notifications in the sidebar 🙂

Author: Max

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

Leave a Reply