Low voltage testing of IGBT and opto-coupler switching times

I was keen to know how quickly the TC426 can switch the IGBT in my pump driver. As it’s slightly more difficult and dangerous to test at mains voltage, I decided to postpone that by carrying out some basic low voltage tests with the IGBT first, simply using an LED and 300R resistor as load from 5V to the IGBT collector.

First, as expected, there’s a small delay introduced by the opto-couplers and TC426. Using a dual trace ‘scope, I found that the gate voltage rises 3.2us after the rising edge of the PWM input, and falls 20.4us after the falling edge of the PWM input. This looks fit for purpose: the pulse would be delayed by about 3us and would be about 17us longer compared to the original pulse fed to the opto-coupler.

So, how does an IGBT rated at 14A and 400V perform at just under 10mA and 5V supply? Although the IGBT was perhaps a little disappointed at being asked to switch a paltry 10mA, it seems to perform well. Here’s a plot of the gate and collector voltage at 500us/div:


This appears inverted, because when the gate voltage is high, the IGBT switches on and quickly pulls the load (close) to ground. When the gate voltage drops, the IGBT switches off and the collector voltage rises again.

The gate voltage rise and fall is extremely fast (<200ns) and I didn’t measure further. The collector voltage also falls very quickly as the IGBT switches on. The plot above is at 500us/div, but here’s a closer view of the collector voltage rising as the IGBT switches off, plotted at 10us/div (and inverted):


Updated high voltage output stage for my Es(pi)resso Machine (muhahaha…)

Here are the latest plans for the high voltage side of my Es(pi)resso machine controller. Obligatory warning: working with mains voltages as shown in this circuit is potentially very dangerous – use this circuit at your own risk.

Click to embiggen (to promulgate a neologism):


This diagram is a slight refinement of the circuit currently inside my machine. Basically, I’ve added a TC426 to drive the IGBT for improved switching times (replacing the BC556 used previously), and replaced the opto-couplers with the 4 pin HCPL-817 for reduced board area and pin count. This also leaves one spare TC426 output for future expansion, which I plan to expose on a 0.1″ header. Otherwise the circuit is exactly the same as the current working version in my Gaggia Classic.

The OC1 coupler enables the Pi to detect when the pump is powered on. As soon as mains power is applied to the pump, this open-collector output goes low. This makes it easy for the software to know when a shot is being pulled, and to count shots etc.

There are two SSRs in the circuit: K4 is used to switch the boiler elements, and K3 is used to switch power to the pump. The pump can still be manually controlled with the brew switch. When the pump SSR K3 is on, this also powers up the pump modulation circuit. The PUMP_PWM input is a 3V3 logic level PWM input for the pump. This goes through opto-coupler OC2 and the TC426 via 1K gate resistor to switch the IGBT Q3. It’s arranged so that a logic high on PUMP_PWM will switch on the pump. Therefore, PUMP_OUT and PUMP_PWM together can be used to automatically power the pump on/off, and to modulate the pump pressure via PWM (I’m currently working with 1kHz PWM frequency).

Today I carried out a low voltage test of a subset of this amended design (the HCPL-817, TC426 and IGBT), and it performs well. The next stage is to test this at mains voltage with the pump, and then I’m planning to design a custom PCB to replace the current strip-board used inside the machine.


Analogue Input Board for the Pressure Sensor (Espiresso)

Having added a pressure sensor to my Espiresso Machine, I needed an analogue input to be able to read the output voltage from the sensor. Unfortunately, the Raspberry Pi doesn’t have analogue inputs, so an external ADC is required. I settled on the Adafruit ADS1015 which has 4 inputs, 12-bit resolution, includes a programmable gain amplifier, and also uses an I2C interface:

Adafruit ADS1015

There’s some useful information on how to set up I2C on the Pi on the Adafruit site. Having done that, there is sample code available to read the sensor from Python or C. With this, it was pretty easy to get readings from the sensor, and it seems to perform well.

The pressure sensor uses a 5V supply, and has a ratiometric output which ranges from 0.5V to 4.5V, proportional to input pressure. It has a 0-300 psi range (20.68 bar). The absolute maximum analogue input for the ADS1015 is VDD+0.3V. If we are running the ADS1015 from 3.3V for compatibility with the Pi I2C voltage levels, this limits the analogue input voltage 3.6V maximum.

Theoretically, the Ulka EP5 pump can develop up to 15 bar pressure, although this is limited by the OPV in the machine to 9~10 bar. If we assume the maximum pressure is 10 bar, and the response is linear, this would result in a maximum output voltage of:

4V x (10/20.68) + 0.5V = 2.4V

So it seems that for normal use, the output voltage should be below the maximum analogue input voltage limit of 3.6V. Even if we assume peak pressure of 15 bar is possible, that would be a maximum output voltage of:

4V x (15/20.68) + 0.5V = 3.4V

Based on these calculations the current plan is to interface the pressure sensor directly to the ADS1015.

The next step was to interface the board to the Pi in the Espiresso. Unfortunately, the SCL and SDA pins on my Pi are already used as inputs to read the two front panel buttons on the machine (using one GPIO per button). Also, almost all the other GPIOs are in use, so there was no free GPIO available to relocate the buttons.

To make the SCL and SDA lines available for the ADC, I decided to use a resistor ladder to read the buttons. This will make it possible to use a single analogue input to read all the buttons.

I’m also planning to use an opto-coupler to signal the Pi when the brew (pump) switch is switched on. Since that has an open collector NPN output, I plan to connect that to the resistor ladder also, so that it can be treated as another button input.

The pressure sensor and button input will only use 2 of the 4 analogue inputs, so there will be some inputs spare for future use.

Ulka EP5 Pump PWM Pressure Modulation

Recently I’ve been experimenting with using PWM to control the pump pressure in my Gaggia Classic. People have used various methods to control the pump pressure, ranging from triac/thyristor dimmers to using series resistance. A few have used PWM (notably Jonr on CG forums), and this looked by far the best solution, so I decided to use high frequency PWM with an IGBT. This would need to be opto-isolated so it could be driven safely from the Raspberry Pi.

I started off looking at the HCPL-3120 optocoupler with gate drive outputs. There are hundreds of suitable IGBTs. However, as I started sketching out the design, including 15V supply etc. it seemed a lot of components were needed for this solution. Instead, I decided to look at using an IGBT with logic level gate drive to simplify the design, preferably one with a TO-220 package. It turns out that there are very few which meet those requirements, so I’ll list them here in case it helps someone else:

  • IRGB14C40LPBF (430V / 20A) from IRF
  • ISL9V3040P3 (21A) and ISL9V5036P3_F085 (46A) from Fairchild
  • STGP18N40LZ (30A) from ST

From that list, the only one I could find at reasonable cost without importing was the IRGB14C40LPBF, so I settled with that one.

To safely interface with the Raspberry Pi, I use a 4N25 opto-isolator with a 270R series resistor, which is driven directly from a 3V3 GPIO pin (tested at a little under 8mA). Note that the series resistor would need to be increased for 5V input.

The NPN output of the opto-isolator is inverted by a BC556 PNP transistor to switch the IGBT input through a 1K series resistor.

The power supply is the VTX-214-003-105. This is a compact module which provides 5V at 600mA from 90V-240V AC mains input. Caution: in this circuit, note that the DC output GND is connected directly to mains NEUTRAL, meaning that the 5V and GND lines in this circuit are not isolated from the mains. This means that they should be insulated and boxed up.

On the output side, the IGBT is wired in series with the pump. There’s a series diode to prevent AC passing, and a flyback diode in parallel with the pump for protection.

Here’s the current circuit diagram for this design (to be used strictly at your own risk):

EP5 Pump PWM with IGBT

To test it, I built a small prototype on strip-board. Note that the IGBT is separate, as I plan to mount the board inside an enclosure, and mount the IGBT externally. Ultimately I would like to make a custom PCB for this. After extended testing, the IGBT is absolutely stone cold so the heat-sink appears redundant.

Pump PWM Prototype

Since I’m using the Raspberry Pi’s one and only hardware PWM pin to drive the boiler, I used the excellent ServoBlaster which provides high resolution software PWM on any GPIO pin. Initially I set this up for 1kHz PWM, and varied the duty from 0% to 100%. For example, to set up 1kHz PWM on GPIO pin P1-22 and using the PCM hardware, you would use:

sudo ./servod --pcm --cycle-time=1000 --min=0% --max=100% --p1pins="22"

To set up 50% duty cycle on that pin, you would use:

echo P1-22=50% > /dev/servoblaster

Before testing this with the pump, I tested with a 60W incandescent light bulb and series diode. Adjusting the duty cycle allowed the lamp to be smoothly and precisely dimmed. The average voltage drop across the IGBT was around 0.33V and (after fully disconnecting mains power) it was cold to the touch.

I then moved onto testing this with the EP5 pump. For easier testing, the machine was temporarily rewired so that the brew switch supplied power to the entire circuit above, so that I could kill power if needed, without relying on the IGBT alone.

Using a Portafilter pressure gauge, the pump was tested at various duty cycles from 0% to 100%. I found that the pump only seems to start operating at about 30%, and then pressure rises to about 1 bar. Increasing the duty cycle allows the pressure to be controlled quite easily between 1 to 9 bar (or wherever your OPV is set).

So far I’m really pleased with performance. The next step is to box it up and wire it in more permanently. I’m also thinking of adding a small SSR to switch the solenoid. Once I’ve done some further testing, I’ll upload graphs of duty cycle versus pressure.

Update: check out the slightly amended design here which replaces the BC556 with the TC426 driver.

The Pressure Sensor Arrives…

After much searching, I found a reasonably priced pressure sensor for my project. It’s a Danfoss AKS 32R, which has 0-300psi range (20.68 bar). It takes a 5V supply, and the output is analogue ratiometric, ranging between 0.5V and 4.5V DC.


No prizes for guessing where I plan to install this sensor!

This is an ebay special, so the first challenge was to track down some more detail on the sensor. The male thread is about  16mm long, and has 8 tracks in 11.4mm which is about 18 TPI. It clearly tapers, and the thread OD is about 13.3~13.8mm, so it looks like a 1/4-18 NPT thread.

I was keen to see if the sensor worked, so I tried hooking up a meter and blowing into the end. This produced a miniscule change in output voltage. After a bit of  research, it seems that maximum lung pressure during exhalation is only about 2.1psi for an adult male, which is less than 1% of the sensor’s measurement range. Hmm… that explains why it didn’t give much of a reading then!

Quite a bit of work will be needed to plumb this in. I might need to fit a pulse snubber to protect the sensor. To be continued…

Replacing the Gaggia Classic Coffee Thermostat with a TSIC 306

For some time I’ve been using the DS18B20 to measure boiler temperature, but decided to upgrade to the TSIC 306 which has a wider temperature range and faster update rate.

The TSIC 306 is a fairly small TO92 package (about 4.5mm wide, 2.2mm thick and 4mm high) so I decided to try encapsulating it in an M4 hex M/4 spacer (as suggested here). This worked out pretty well, as shown below, pictured alongside the original thermostat from the Gaggia Classic.


The spacer is M4 Aluminium, 20mm high, 7mm across faces, male to female (Richco HTSA-M4-20-2, Farnell 1898535). The male thread has been filed down to about 6mm length, to match the existing thermostat.

I drilled out the female thread in the spacer with a 4.5mm bit to 15mm depth, filled with heat transfer compound and pushed the sensor deep into the spacer. The three sensor leads are individually insulated with heat shrink tubing, and more heat shrink is used to encapsulate the cable and sensor.

Aluminium has excellent thermal conductivity, and simply touching the case with a fingertip is enough to trigger an immediate change in temperature reading!

The only awkward part was fitting it into the boiler. I wasn’t able to do this in situ, but had to remove the steam wand and knob, unscrew the four allen bolts around the group to free the boiler. This allowed enough freedom to tilt and move the boiler slightly to the right, so that I could screw in the sensor by hand.

The new sensor is up and running on the machine, and I’ve left the DS18B20 installed in parallel, so I can compare performance.

Linux Kernel Module for the TSIC 306

I’ve made my first foray into the kernel, by writing a kernel module for the TSIC 306 temperature sensor. After overcoming the difficulties in setting up the tools, the actual driver development was much easier than expected. The source code is up on Google Code and is basically working, but needs a little more development.

This maps the sensor to the file-system, so you can load the module and read the temperature like this:

$ sudo insmod tsic.ko
$ cat /sys/kernel/tsic/temp

In the example above, the temperature is 14.68°C and all the values are scaled by 1000 to avoid floating point maths in the module, and to match the behaviour of existing sensors such as:

$ cat /sys/class/thermal/thermal_zone0/temp 

Writing the module turned out to be easier than expected, and there are some great libraries such as gpiolib and kobject which simplify development. Documentation is a bit scarce, but there are some useful resources:

Eventually I plan to add support for multiple sensors on configurable GPIO pins,  make it more robust and clean up a few issues such as the lack of time-outs in the I/O.

Temperature Sensor Upgrade: the TSIC 306

I’ve been using the DS18B20 for a while now, but wanted something with a higher temperature range and faster update rate, but with a similar digital interface. After a lot of searching, it became clear that there are very, very few parts that fit these requirements…

Finally, I found a neat sensor called the TSIC 306. This has a temperature range of -50 °C to +150 °C and the update rate is a very respectable 10Hz. Better still, it’s available in a 3-wire TO92 package, similar to the DS18B20. It has one small disadvantage: it looks as if you can only have one device on the bus, so each sensor will need a dedicated GPIO pin. That said, it still looks ideal to upgrade the sensors in my coffee machine, so here goes!

The hardware interface to the Pi is very straightforward: it can accept 3V3 power, and the data line is actively driven low/high, so it can be wired directly to a GPIO line with no pull up resistor. However, it’s worth noting that the data suggests that 5V supply yields better measurement accuracy, so it may be preferable to power from 5V and use two resistors as a potential divider to reduce the data output to 3V3 logic levels for the Pi.

To date I have managed to read the sensor from C++ on the Pi, but it’s a little unreliable as it’s difficult to get accurate timing from user mode. It looks like a Kernel Driver may be needed…

Replacing the Gaggia Classic Thermostat with a DS18B20

For my Espiresso Machine, I needed to replace the stock thermostat on the Gaggia Classic with a DS18B20 (Digital Thermometer). My first attempt was pretty basic, and consisted of smearing the DS18B20 with thermal paste and using a cable tie to tether it the side of the boiler (just beneath the steam thermostat). This actually worked well in practice, but I wanted to come up with a better mounting technique.

Someone on the Gaggia Users Group forum suggested modifying this Circuit Board Standoff, which would have been perfect but unfortunately all the UK stock seem to be 7mm AF instead of 10mm AF, which wouldn’t be large enough to drill out.

Instead, I decided to make a mounting block for the sensor. I used some 10x10mm square section Aluminium bar stock, cut it down to 25mm length, drilled and countersunk a 4.5mm hole through the bar at 5mm from one end. This is designed to mount on the side of the boiler in place of the existing coffee thermostat, using an M4x0.7mm brass screw. There’s another perpendicular 6mm hole along the length of the bar, to accomodate the DS18B20 sensor (this is the waterproof version, which is encapsulated in a stainless steel tube).

The picture below shows the original thermostat (left), and the new mounting block, M4 brass screw and encapsulated DS18B20:

ds18b20_mount_vs_tstatThe 6mm hole intersects the 4.5mm hole, so that it can be filled with thermally conductive paste to ensure a good contact with the temperature sensor. The picture below shows the sensor and brass screw inserted into the block. The screw has been cut down to leave about 6mm of thread exposed, to match the existing thermostat.


The final picture shows the sensor block mounted on the side of the boiler in place of the existing coffee thermostat (taking care not to over-tighten).


It was a challenge to tighten the screw in situ! Ideally I would have preferred an aluminium socket cap screw, but decided to use the materials to hand, rather than wait on another delivery 😉