Pump PWM: High Voltage testing with Oscilloscope

Although I’ve had PWM pump modulation working in my Gaggia Classic for a while now, and have been working on an updated design, I never actually put a ‘scope on the high voltage output side, mainly due to the difficulty of doing this safely without a differential probe. Today, I finally got around to trying it.

hv_pump_pwm_test1

To limit the voltage to a sensible range, I used a potential divider made of a 180k and 1M resistor in series across the pump, then connected CHA and CHB inputs of the ‘scope across the 180k resistor. The ground clip of both CHA and CHB was connected to EARTH (the ‘scope is also earthed of course). This means that our voltage measurements will be relative to earth, rather than a differential measurement between two points. However, the math functions on the ‘scope (e.g. CHA-CHB) can be used to simulate differential measurements if needed (provided the voltage range of the ‘scope isn’t exceeded!)

The figure below shows the voltage measured at the pump for one cycle, using 1ms/div and 5V/div on the ‘scope. The PWM frequency was 1kHz, and the mains frequency was 50Hz. Therefore, there are 1000/50 = 20 PWM pulses visible in the graph below.

hv_igbt_pump_1kHz_50Hz

This graph is taken from CHB, measured at the point where the pump coil is connected to the IGBT collector. The CHA measurements look very similar. Frankly, I was surprised how clean the waveform looked! There is a little distortion, but it looks pretty good, considering the high frequency switching.

The PWM frequency isn’t synchronised with the mains frequency (being derived from the CPU crystal oscillator), so the PWM waveform slowly drifts relative to the underlying 50Hz mains sine wave. However, this shouldn’t make any appreciable difference to the output power of the pump, given the high PWM frequency.

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:

lv_igbt_cycle_500uS

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):

lv_igbt_off_10us

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):

gaggia_v3_draft1

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.

igbt_low_voltage_test

Raspberry Pi GPIO states at boot time

When external hardware is connected to the Raspberry Pi, it can be important to know the initial state of the GPIO pins at boot time. For example, if we have a motor connected to a GPIO pin, it could be a problem if the motor starts running as the system boots up. Ideally, we would want all the pins defined as inputs at start up, but that doesn’t seem to be the case with some of the Pi GPIO pins.

Fortunately, there’s now a solution in the form of the device tree pin configuration. This involves creating a pin configuration source file, and compiling that to a binary “blob” which is loaded by the OS at start up. This source file can configure pins as inputs, outputs or in special function modes (UART serial port for example). It can also configure whether a pin has pull-up or pull-down enabled.

This proved very useful for my Espiresso project, when I needed a pin to enable the pump at start up. Having run out of general GPIO pins, I was forced to use GPIO15 (RXD) which is configured as a pull-up UART pin by default. This would have resulted in the pump running as the system booted. However, by editing the device tree configuration, it was possible to set this pin as an input with pull-down mode, which prevents the external hardware being switched on during boot. The GPIO pin can then be reconfigured as an output by the application, after the Pi has booted.

As an update to this, there have been a couple of important developments with device-tree since I wrote this, which I’ll summarise briefly here:

  • You can now create device tree overlays, to configure specific GPIO pins at boot. However, with NOOBS these do not take effect immediately (in which case the dt-blob.bin will still be needed).
  • With NOOBS, the dt-blob.bin file needs to be placed on the recovery partition. Even then, I found the only way to ensure the pins stay in the desired state through the entire boot process is to have the dt-blob.bin on both recovery and /boot partitions.
  • In conclusion: avoid NOOBS for this application, and go with a vanilla Raspbian install

Persuading NVIDIA 3D Vision Pro to Sync with an unsupported Projector

Recently I did some work to persuade the NVIDIA 3D Vision Pro glasses work with six Optoma EW610ST Projectors, and made some interesting discoveries in the process. This projector is not an officially supported model on the NVIDIA compatibility list.

The projectors in our setup are connected in Mosaic mode, and we were using active stereo at 1280×720 and 120Hz on each projector, with the 3-pin VESA stereo sync cable from the graphics card connected to the NVIDIA Pyramid. In the default set up, it results in terrible ghosting (cross-talk) when used with the NVIDIA glasses.

The first problem is that these projectors have only one 3D mode: DLP-Link. This is unfortunate as DLP-Link uses a white flash to synchronise the glasses, whereas the NVIDIA 3D Vision Pro glasses use RF. The real DLP-Link glasses will obviously blank themselves during the white flash, but the NVIDIA shutters are open, so this results in poor contrast (effectively, slightly increasing the brightness of the entire scene). This was a problem in our case, as we were edge-blending the projectors. Black level blending with an offset would be possible, but would reduce the contrast of the whole image. The solution to this first problem was to simply disable 3D mode on the projector! It still seems to display 120Hz frame sequential stereo with 3D disabled.

The next problem is that there is really bad ghosting, because the timing of the glasses is wrong. To find out what was going on, I decided to measure the light output of the projector against the stereo sync signal.

I didn’t have a light sensor to hand, but fortunately LEDs can be used as a (rather insensitive) light sensor. In this case, I used a clear infra-red LED situated about 1cm from the lens, connected directly across one input of my ‘scope. To improve the response speed, I put a 1K resistor in parallel with the LED to help discharge it quickly.

LED as Light Sensor

I connected the stereo sync signal (output from the graphics card) to the second input of the scope, and set the ‘scope to trigger from the sync input.

Then I wrote some OpenGL code to draw pure white on the left stereo channel, and pure black on the right channel, so the projector was flickering full-screen white/black at 120Hz. The results are shown below. The red trace is the stereo sync signal, and the yellow trace is projector light output.

Optoma EW610ST Stereo Phase

As can be seen from the graph above, the two are out of phase with some of the image visible outside the sync period. I measured this at about 316us delay, which is about 3.8% of the frame time (which is 8.33ms for 120Hz).

The strange shape of the yellow waveform is due in part to the way the DLP projector works, with a spinning colour wheel which has separate segments for red, green, blue and white (some models use different colour combinations). Also, amongst other effects, the different colour components have different luminance levels, and we are only looking at a subset of the mirror array with our sensor.

Since the stereo sync is out of phase with the projector, the logical next step is to delay the sync signal.

Ideally this sort of stereo phase adjustment would be possible from the NVIDIA drivers (at least on the Pro version), but it doesn’t seem to be? I couldn’t find one, and there don’t seem to be any functions in the NVAPI for altering the timings either.

There are some specific parameters for each projector manufacturer/model stored in the registry (and driver INF file), which look like possible timings for the glasses:

HKLM\System\CurrentControlSet\Services\NvStUSB\Parameters\SAM_8524

However, the format is proprietary and undocumented. I made a start at successfully understanding some of these, but it occurred to me that these parameters might not be used at all when the pyramid is fed with external sync, so it seemed easier to take the direct approach of making some hardware to delay the sync.

I decided to try and rectify this phase error in the sync signal, by delaying the sync signal before feeding it to the NVIDIA pyramid. To achieve this, I used an STM8S Discovery board which is very low-cost, easily programmed via USB, and capable of high timing precision.

The hardware is very simple: the sync output from the PC is connected via a 1K resistor to a GPIO input on the STM8S (the 1K resistor is just a precaution against toasting the very expensive graphics card!) Another GPIO output is used to feed the sync input of the NVIDIA pyramid. The only other connection is the common ground, and the board is powered over USB.

STM8S Discovery Board

The firmware uses interrupts to detect the high/low transition of the input, then schedules an onboard timer to generate another interrupt after a specified delay period has elapsed. It then drives the output high or low as required. This method will support any vertical refresh rate, and allows very high precision adjustment.

Having set this up to generate a 316us delay, the sync signal is now in phase with the projector:

Optoma EW610ST with delayed sync

However, the projector is illuminating the full frame period, and there is no dark interval at all for the glasses. This is due to the projector being set up in “Presentation” display mode, which is designed to maximise image brightness. In our case, this will result in ghosting, because the LCD shutters take a little time to ‘open’ and ‘close’, during which time we need the display to be dark.

The solution to this last problem is to alter the projector settings to select a mode which gives a reasonable dark interval for the glasses. On the EW610ST, this can be achieved by setting the Display Mode to sRGB. The final result with the 316us delay and sRGB mode selected is shown below:

Optoma EW610ST acceptable stereo mode

Finally, I tried this with the NVIDA glasses, and the ghosting had been eliminated. In a realistic scene, there is imperceptible ghosting, even with very high contrast areas.

Reading Multiple Switches with one Analogue Input

The traditional way to connect a button to a GPIO pin is to have a pull up resistor to Vcc, and have the switch pull the GPIO to ground when it’s pushed. The catch is that you need one pin for every button. An alternative is to use a matrix: for example, using 4 outputs and four inputs to scan a 16 button keypad. To reduce the number of GPIOs still further, we can use a resistor ladder, something like this example below.

3 Switch Resistor Ladder

The diagram above is an attempt to use the minimum number of resistors, and a more optimal design would be possible with additional resistors.

When all the switches are open, we will see 3V3 at the analogue input AIN. When a switch is closed, it connects one of the resistors to ground, forming a potential divider and reducing the output voltage. For example, if we press S2 then the output voltage will be half the supply voltage.

When multiple switches are closed, the resistors are connected in parallel, so we will get a different value for each combination of switches. Provided the values are sufficiently different, we can detect all possible switch combinations.

It’s fairly easy to create a spreadsheet to calculate the output voltage for a given set of resistors, and switch states. The table below shows the predicted output voltage, and the actual measured voltage for every switch combination:

Voltages with 3 switch ladder

The differences between the actual and predicted voltages are due to resistor and supply voltage tolerances. These show fairly good agreement if they are normalised to supply voltage.

This is what the results look like when graphed. Note that the results are not linear, but the values are sufficiently different to be able to reliably detect different key combinations.

Voltage graph for 3 switch ladder

Having taken the analogue reading from the sensor, it can be compared to the possible values shown above. This can either be achieved with a look up table, or by fitting a function to the data. Having obtained the integer code 0 to 7, the state of an individual button can be detected by testing individual bits of that code.