The Goal

This is an attempt to replace the q-switch trigger found in my Quantel laser with one which is a bit more... operational.

The idea is to observe the pump light from the flash lamps, and then trigger the q-switch as the "right" time. My current definition of "right" is 2/3 of the way through the approx 250 microsecond pump flash. Once things are functional, I'll try different values and hill-climb.

Then, just to get fancy... how about monitor the two amplifier lamps as well. If all three lamps don't fire close enough together, don't trigger the q-switch. And last but not least, observe the laser's trigger signal, to ponder the oscillator lamp's jitter.

Finally, put a serial port on it (everything is better with a serial port...) and spit out all the metrics. One can configure it the same way.

The Specifics

I have a tool-chain for using TI's MSP430 microcontroler, and a pile of existing code and experience. MSP430s have a nifty little timer module (called timerb) which will capture and compare a counter, on the rising and/or falling edges of pulses with up to 7 inputs/outputs.

So, I clock timerb with the CPU clock, which is about 8 MHz. The timer has a 16 bit counter, and when the lamps go off the hardware copies the counter into a register and I get an interrupt. If everything is all happy, I compute a timestamp for the q-switch and put it into another register. When the (continuously running) counter hits that time, the hardware generates a pulse and I get another interrupt.

As long as I can decide in time, and I have on the order of 100 microseconds to do so, its precise to 1/8 of a microsecond. (My clock is a 32768 Hz watch crystal, its accuracy is probably not impressive...)

The photo diodes are PIN diodes, connected to an op-amp which is way off into comparator mode, as opposed to small signals land. But I'm looking for edges, so thats OK. The photo diodes are mounted directly on the board, as opposed to being attached to their respective lamp housings. I'm using 1mm plastic optical fiber to carry the light from the lamp housings, to avoid long signal lines near the flash lamp power lines. To attach the optical fiber to the PIN diode, I'm using heat-shrink tubing.

To observe the Quantel's trigger, I have an NPN transistor as a level shifter. The Quantel's trigger is 24V active low. The rise time of the transistor is lousy, on the order of 3 microseconds, but I can calibrate the delay.

The q-switch requires an approximately 3 kv pulse to get a 1/4 wave length retardation. I'm using the original avalanche transistor circuitry (described here, look for q-switch driver). One change I did make was to replace the 2N5551 transistors with 2N3904 transistors. They avalanche at a lower voltage, so my power supply is sufficient. I reverse-engineered the original TTL logic level to weird driver circuitry, and did a bit of cargo-cult with it. It seemed to work during the shakedown (no smoke! :-).

The MSP430449 chip which I'm using has two uarts. They are both connected to a max232 line driver chip, and then a D9 and a 3 pin header. I don't really need both, but its easier to do them both now than later.

I also broke out nearly every port the MSP430 has, so I'll have somewhere to put whatever the next feature is (LED user interface?). I put four photo-diode circuits and two output driver circuits for the same future-proofing reason. If I hadn't done that, the board would probably have been 1/2 the size...

And last but not least, a guy at HacDC had an interesting idea for what to do with extra flash memory: put the source-code into it. There is 60K of flash, I have about 11K of code, and a gziped tarball of the entire source is 14K... Who knows, maybe someday a reverse-engineer will be very happy. Issue the command "src" to get it.


The D9 connector has a command line interface on it... 9600 8n1. ? will get a command list.

lamp 0(TB6) is the oscillator. If everything is sane, the q-switch will be opened offset clocks after the rising edge of lamp 0. lamps 1 and 2 are the first and second amplifiers respectively. lamp 3 is not populated. lamp 4 is the 24V trigger. The q-switch output is on TB1. TB0 is not populated.

When a xenon flash is detected, most of the logic is in the ISR. After the last falling edge, it generates a report which looks like:

decision at 0x9395    val= 0x1710
lamp 0  0x924e 0x988c  len 203 usec
lamp 1  0x9141 0x986d  len 233 usec
lamp 2  0x90a4 0x982a  len 244 usec
lamp 3  0x0 0x0  len 0 usec
lamp 4  0x9095 0x9234  len 52 usec
Qswitch target 0x984e actual 0x984e 195 usec

Each lamp line has the timestamps of the rising and falling edge (absolute timestamp, in hex), then the duration in micro-sec (not clocks). There are four lamp inputs, lamp 4 is really the trigger pulse (but the lamp data structure was what I needed). Since thats what triggers the lamps, it really should always occur first...

The decision was made 0x300 clocks after the first rising edge, at absolute time 0x9395. The most significant byte of val is a set of flags for the rising edges, the least significant byte is of the falling edges. So ideally it would be 0x1700, in this case, the trigger pulse had already dropped, but thats more or less expected.

The q-switch was scheduled to be opened at 0x984e, 0x600 clocks after lamp 0's rising edge. It really did occur at that time, and was 195 usec after the rising edge. If the sanity had failed (IE too much jitter, or a lamp not firing) it would have declared a miss-fire, and the line would have read "Q-switch target missfire".

Source-code and Drawings

This is still a work in progress. Some assembly required, all parts user serviceable (it is open-source...), and will unfortunately need it. You will need to know how to solder, program in C, etc.


The source-code and hardware design are released under the terms of the GPL.

Copyright (C) 2010 Tommy Johnson