The pressure profiling feature allows us to precisely control the pressure produced by the pump. The majority of semi-automatic espresso machines use an Ulka vibratory pump. These pumps run directly on mains voltage. They include a diode which means that only the positive half-cycles of the AC current are used to power the pump. How can we control these pumps?

There are many ways that have been tried:

  • SSR + PWM similar to the PID water temperature control system. This basically turns the power on for a variable number of full half-cycles per period of time. It’s pulsing the pump to produce lower pressure over time, where each pulse is a certain number of full half-cycles. This solution is the easiest to implement, since it only requires a zero-cross SSR and a PWM signal from the micro-controller. Nonetheless, it has a low resolution and high water pressure jitter (which could actually make channeling worst!). In addition, the pump (inductor) creates a phase difference on the AC signal between voltage and current. Since the SSR is zero(voltage)cross, it will switch while the current is high, which generates back-EMF. Back-EMF can cause a multitude of issues, so a snubber circuit would be required, which adds more complexity and heat to the circuit. You can see the Espressuino project for an example of this approach.
  • Using a potentiometer to lower the voltage at the pump offers a higher resolution solution than the SSR + PWM. On the flip side, it produces heat in the potentiometer. Additionally, since there exists no high power digital potentiometers (the pumps uses approximately 50W), the only possible control method here is manual (with a knob). So this isn’t an option for us.
  • A popular approach is to use a triac based light dimmer circuit. These circuits are relatively simple and cheap. They implement phase control to manipulate the power to the pump. Phase control is elegant and high resolution. It works by delivering equally partial half-cycles to the load. It’s basically a circuit that waits a user configurable amount of time after zero-cross to switch on. The longer the wait, the more of the half-cycle is “cut-off”, the less power gets delivered to the load. The easiest way is to use an off-the-shelf light dimmer. These circuits use the AC signal going through a high power potentiometer to control the phase/power, this means you will be limited to manually (by hand) changing the pressure. Here is a picture of a triac light dimmer we pulled out of a lamp dimmer box:

    You can find a good tutorial on triac dimmer circuits at
  • Alternatively, it is possible to build your own triac based circuit that can be controlled directly by a micro-controller I/O pin. The micro-controller would receive a zero-cross signal (this will require a zero-cross voltage or current detect circuit) and set a timer to switch on the triac. In addition to it’s simplicity, the other cool feature of these circuits is that the triac will automatically turn off on zero-current at each half cycle, so no back-EMF is produced by these circuits (see below for more details on back-EMF). On the flip side, they require that mains AC and your micro-controller to be on the same circuit (triac requires a common reference point). We prefer to keep our mains isolated from our low-voltage electronics, so we will look for another solution. Here are a few good links sent to me by James if you wish to read up more on micro-controller driven triac phase control:
  • James has come up with his own solution – which uses an IGBT. Since the IGBT is very fast at switching and can switch at any given moment, his idea is to very quickly (multiple times per half-cycle) switch on and off, essentially chopping away chunks of power from each half-cycle. You can see what his chopped signal looks like here. This solution provides high resolution, but creates considerable amounts of back-EMF due to the high frequency of switches, which in turns generates heat across the board. The IGBT needs to be on the same reference (GND) as the input signal from the micro-controller, so this would usually involve mixing AC mains and the electronics, but James added some circuitry to isolate them (basically adding an optocoupler and a DC power supply). This works well, but adds to the cost and complexity.
    We initially implemented this solution because it offered the best performance from the available options. It worked great once we got it going (we burnt and exploded a few components along the way!), but we always felt that there must be a simpler and cheaper way of achieving high resolution pressure profiling.

Micro-controller based phase control

Having Jame’s working IGBT circuit in our hands, we quickly realized that we could use the fast switching IGBT, the micro-controller and a zero-cross detect circuit to implement software based phase control without a triac. A zero-cross detect circuit would send a signal to the micro-controller when the AC voltage crosses zero, this would then start a configurable countdown timer. When that timer expires, the IGBT is switched on. This is what things would look like:

A bit of soldering & coding followed by a quick test, and it worked! We are now able to get very high precision (the LPC1768 runs at 96MHz) pressure profiling via software phase control!

But wait, we are not done yet.

When we switch off (blue graph), there is a negative voltage spike of over 400V. No surprise here. Indeed, for a pure inductor, the voltage is given by the following equation:
\[V_{L}(t) = -L\cdot \frac{\mathrm{d} i}{\mathrm{d} t}\]
This means that the faster the current change, the bigger the voltage. So switching off while the current is highest induces a very sudden change from max-current to 0, producing a voltage spike, aka as back-EMF.

The pump behaves like an inductor, let’s assume it is pure for now (it probably isn’t). Pure inductor dephases voltage from current by 90 degrees. Therefore, when voltage is zero, the current is at it’s max. Since we are switching off when voltage crosses zero, we are inducing a near maximum back-EMF. Since we are using our micro-controller to switch on the IGBT, we can eliminate the back-EMF by simply waiting a bit past the zero-cross event before switching off. This is happening during the “empty” half-cycle (our pump has a diode that only lets positive half cycles through), so waiting a bit makes no difference in terms of power going to the pump.
This wait is found at DELAY_AFTER_STOP in phasecontrol.cpp and is set to a quarter cycle. Ideally, we would measure the phase difference and use that exact value instead. Nonetheless, even with this estimate, we are able to eliminate the back EMF as can be seen in the graph below.

We now had a very high resolution, back-EMF free pressure profiling solution.

In order to minimize circuit complexity, cost while maintaining isolation between the high voltage AC load circuit from the micro-controller circuit, we replaced Jame’s IGBT circuit with a fast switching random-fire SSR. This allowed us to replace the power supply, CMOS driver and opto-coupler with the SSR.

For the zero-cross detect circuit, we used a simple and common opto-coupler based circuit. You can find the details on the zero-cross detect circuit on the hardware mods or the schematics page.

We are nearly done. One small complication that we still need to address is that the amount of power delivered to the pump is not linearly proportional with the amount of time (_timeout_usec in phasecontrol.cpp) we wait before switching on. So we need a formula to convert the 0-100% pump power setting to _timeout_usec. Unfortunately, that is easier said than done – we would need a measurement the power (W) delivered to the pump during each cycle. We know what our voltage looks like (normal sine wave at RMS/0.707 amplitude), but we not our current, specially the exact amount of phase drift it has with the voltage. We would need to measure the impedance (resistance, reactance and phase drift) of the pump to get the current. To keep things simple, we decided to use our voltage sine wave for now.

So, we know that the total amount of voltage delivered from an AC half-cycle to the pump in a phase controlled signal is given by:

\[\int_{x}^{\pi }\sin(t)dt\]

Converting the range of x -> [0, Pi] to z -> [0, 100] (pump power %) and then solving the integral gives us:

\[\_timeout\_usec = HALF\_PERIOD\_USEC \cdot \frac{\arccos(\frac{2z}{100} – 1)}{\pi}\]

We pre-calculated the values of _timeout_usec for integer values of z from 0 to 100 and stored them in the array _timeouts_usec[].

Our work-around seems to give good enough results as you can see from the graph below:

This first graph is taken with no portafilter, so there is no actual pressure. This allows us to measure the pure flowrate to pump power ratio. As you can see, the flowrate is nicely correlated to the pump power setting. In addition, we have no water flow under 30% pump power (which is corroborated by other pressure profile mods).

This second graph shows flowrate and pressure with a loaded portafilter (actually it’s a portafilter with a pressure gauge and a manual valve that simulates a coffee puck). We can still observe good correlation between actual pressure and pump power setting. In addition, it is interesting to notice the increased pump jitter at the higher pressures. This is partly due to the OPV valve operating at the 12 bar mark (we should adjust our OPV to 15 or 16 bars since we don’t need it anymore), but even at lower pressures we observe the jitter change.

3 Comment threads
2 Thread replies
Most reacted comment
Hottest comment thread
3 Comment authors
Philippe KalafDavidJm Recent comment authors
newest oldest most voted
Notify of

Other thing I don’t understand. The vibration pump include a diode. So only positive alternance of source voltage make the pump working. The diode cut voltage for negative alternance. So, in that case there is never back EMF applied to the pump. So it that case it is not necessary to delay the cut off power no ? I don’t understand somewhere I think. Let me know.



Could you explain me where you found this :


What does it corresponds exactly ? Is it an area, Ueff, ?

Your article is really interesting but I don’t understand the previous formula
Thanks to help me.