Needing more than a spark test?

I tracked down some major problems with my pulse qualification code. One slap-the-forehead problem was in the function that updates the circular buffer and was simple to correct (once I found it), but the other was more subtle. The interrupt routine that runs the ADC does several things, one of which is to set a flag if a lowpass-filtered version of the input is greater than the trigger level (the intent is to reject noise). My main pulse-processing routine waits for that trigger flag to be set, and as soon as it happens it starts processing the pulse data. And that was the problem -- since the processor clock runs at 600MHz it was outpacing the ADC by a huge factor. So the data it was seeing in my circular buffer didn't contain any information regarding the current pulse.

The solution was fairly simple, basically insert a delay in the pulse processing code to allow the circular buffer to capture the entire pulse. After that I started getting some valid pulses. Most pulses still weren't right, but just reflected the fact that I had done a lot of guessing on the expected pulse width values (maximum-valid pulse width and minimum-valid pulse width). I also hadn't initialized my "goodness of fit" parameter so my pulse qualification code was rejecting everything.

One thing that needs some attention actually is that goodness of fit parameter. The values I'm seeing are consistently very low, ranging from 0 to .01. Given the liklihood of pulse overlap plus system noise, I think there should be some pulses being rejected for an excessively high error coming out of the fitting routine so....more code validation is in the near future.

I could upload my latest version to my Google Drive for folks to examine, but at this point it's full of debug code and not useful for a real MCA.
 
Most excellent stuff!
I was trying out circular buffer sampling right at the beginning. Basically, it runs all the time, and is big enough to capture 20uS. There may later be a case to change that, but I was, and still am into pulses that have not been significantly stretched.

When a threshold is seen by the trigger, it might be noise, it might be a mangled "two arrivals", or a direct radiation photon way oversize, but regardless, the numbers taken from the buffer are from an address some microseconds worth of samples earlier. I guess that was my version of a "delay". Also, I was only using C-R filtered signal generator "pulses". Getting the tiny hardware to work with my attempt at manual prototype breadboard assembly did not go so well. I broke stuff, and I have now gone for SO8 size first IC.

I would be interested in what front-end circuit you built using the pocket geiger PCB, and what you used to get a low pass, noise-filtered version. Did you have to hack the tracks a lot?

I have the op-amp hardware trigger still planned to be in there, but I have been attempting to use number testing on the sample as it is put into the circular buffer. If the most recent four samples in a row in the buffer are greater than a threshold number, the assumption is that some kind of pulse is under way, so that constitutes a "software trigger". This also messed up, but I can't see anything wrong with the idea, so I will try again.

I can't yet buy a Raspberry Pi Zero at reasonable cost. So far, I am using an old Raspberry Pi 3B. It seems to do everything OK, though to be fair, "everything" is so far, not much asked. Yes, the PyMCA software does run, but it still needs the fast front end to make the data files the PyMCA works on. Also, I am being tempted by Teensy and Beaglebone.

I am so impressed that you do this. If you do manage to repeatedly capture whole pulses, do let us know what they look like. :)
 
Hi Graham,

Still working my way through some programming problems so I don't have any pretty pictures yet, but I think that will happen pretty soon. I'm trying to use the Arduino serial plotting utility since that's the most expedient way to plot data. I was initially concerned that my polynomial curve-fitting routine wasn't working right because the fit error was so low, but that just took some scaling-up to start seeing some significant pulse-to-pulse variations. I _have_ succeeded in plotting the portion(s) of pulses that are used for the curve fitting routine so I know I'm doing something wrong when I try to plot the whole thing. Since my rather slow ADC only acquires about 10 samples around the peak the plots look pretty jagged.

Regarding your question about the approach I used for the low-pass filter, it is similar to your 4 samples in a row idea. I implemented a second circular buffer that only contains 8 sequential samples, sum them and use that to trigger the pulse processor. It's a dead simple FIR filter, AKA "the rolling average". However, to avoid summing all 8 samples every time I want to get the rolling average, I realized that all I really needed to do was to calculate the difference between the latest sample and the one being bumped out of the buffer, then add the result to the rolling average value. The rest of the samples are already represented in the rolling average so why recalculate the whole thing. I know that part works, verified using my oscilloscope triggered by a pulse generated by the S/W.

Like its analog cousin, the rolling average lags the signal but I know exactly by how much. So when my pulse processor is triggered the code looks back a little ways into the main circular buffer to capture the actual start of the pulse. Pretty much like what you've done.

I haven't modified the pocket geiger "much". The analog signal path is the same, which does have some low pass filtering, just one RC network around the second amplifier in the chain. I just tapped into the output of the second stage, routing the analog signal to the signal-conditioning board I made (basically to provide some additional gain). The significant modification was to remove the switching regulator to get rid of the switching noise. It was pretty bad. I also added a 1uf plastic-film capacitor to the bias voltage circuit in an attempt to reduce low-frequency noise but I don't think it was particularly successful. It was a pain in the butt to add it, since the footprint for the original ceramic capacitor was so small.
 
Yes, I think the most recent 8 average, as it climbs up from zero, is a statistically very reliable indicator that a proper pulse is under way. It might later have to satisfy more critera, like it's not totally OTT, or something, but at least you know something significant is going on, and can use it as a reliable trigger, with the luxury of being able to get at pre-trigger values. I may adopt this way.

My original scheme was even more brutal! I adapted it from a switch de-bounce circuit I used years ago. The value of each sample individually must be above a threshold, with no regard to what average the group might have. All four states (flags) feed a logical "AND" gate, which delivers a reliable trigger. One can, of course, increase the set of them contributing to the gate, but in my scheme, everything is happening much faster. The whole pulse is over in about 13uS. At 2MHz sampling rate, that's only 26 samples for the whole pulse! I struggle to get as many as "10 around the peak".

To be able to go a bit slower is why I was interested in your earlier confirmation that, within reason, a benign low pass filter that "slows the whole thing down", still retains most or all of the original pulse shape curve fit information, only scaled in time as in "pulse stretcher". I may yet deploy at least some of that, and there is place in my circuit to add op-amp low-pass, but for now, I make it go as fast as possible. A small slowdown, and sampling at 1MHz instead, would help me a lot.

The extent to which "pulse stretching" was taken in the first circuits we saw was mad! The filtering itself distorted the pulse badly. There was nothing much left of the pulse shape, other than a slow rise that went beyond a window comparator trigger, good enough to signal a "count". We wanted more! We needed to know how much of a count. The peak amplitude is all we have to differentiate materials elements. I think the more we slug it in slow-down filtering, the harder it becomes to expand the range around the peaks to have high resolution. If filtered to the extent very slow ADCs can deal with it, I feared it may limit the performance in discovering elements. This is the basic reason I keep trying to capture the pulse with high speed stuff.

Re: Bias voltage noise
Everything I could do to make "clean" voltages for the bias, and also the ADC, was blighted by switcher regulators. In the end, the clunky, but effective way was to use 3 x Lithium 3.3V cells. My lash-up had 3 x CR25, just because I had handy a cheapo bubble pack full of them from replacing motherboard CMOS batteries, but in the end, I would use the smallest, CR12 or something. The scheme allows to choose 3.3V, 6.6V or 9.9V for bias.

Here is where we have the first trade-off, and the first stage of "pulse stretching". Reverse biased diodes seem to be magnificent noise generators. Using 3.3V lowers the dark current noise (which we want), but saddles us with 160pF of photodiode capacitance. Using 3 batteries for 9.9V increases the dark current noise, but we have only 84pF reverse bias capacitance, which, I think, doubles the size of the pulse we can have into the TIA. I think the only way is to build it with three batteries, and experiment, reducing to two, and then to one. My instinct so far is telling me the pulse gets bigger faster than the noise increases, so bias near 10V seems to be best.

I fitted the curve of PIN capacitance estimated from the (zoomed up) data sheet. You can have an equation from a spreadsheet. I post ODF and xlsx here.

Noise at the ADC
Having a separate ADC forces some tough design. At first, with input short-circuited, I could not get a number (out of 65536) any lower than some several hundreds. Even the way registers roll over in 5V computing anythings make ground bounce noise. Things slowed up when I trashed an ADC. I mourned because the AD7622BSTZ originally costing £29.68 was more than £38, and is now £49.09 !! At this rate, I would be looking for a lower cost ADC. I was trying to make this kit "low cost".

The only way was to start with a cleaned up 3.3V stolen from the Pi, and regulate down to 2.5V using a ultra low noise linear regulator, and then make sure that the current summing point is right under the ADC, and that nothing else shares that path. Even SDI clocking stuff gets some resistance in the leads, uses a separated 2.5V, and I was even considering opto-isolation. You can get the zero down to two digit numbers, but it's not easy!

At home
Right now, flooring is going down in the shop, and other building operations are happening at the house. I want to get this stuff out of the way, so I can play xrf and machines again. One good thing I have discovered about the outhouse shop is that the insulation is pretty good. I did, of course, use double-glazed windows, but it does have two large view windows. Yesterday afternoon, temperature was about 4C (about 39°F). I turned on a blower-fan heater for about 15-20 minutes, bringing the temperature up to about 11C ( about 52°F), which was OK. Then, with no further heating, I worked in there for about 2 hours, and it still showed temperature holding above 9C. I can't think my "working" would have had much contribution :)

The picture is from some days ago. I now have more than 3/4 floor area of the oak engineered flooring down. There will always be woodwork, but the planer-thicknesser-jointer will eventually be moved back to the garage. That spot is prime lathe space!

Flooring#1.jpg
 

Attachments

  • X100-7 PIN Capacitance Characteristic.ods
    21.7 KB · Views: 0
  • X100-7 PIN Capacitance Characteristic.xlsx
    8.1 KB · Views: 0
Last edited:
You're going to have a very nice shop there! It looks like it should be a pleasure to use.

I have thought that a simple charge pump might be suitable for a bias generator. The bias current should be very low on average so the CP wouldn't need to run very fast, nor would it need substantial capacitors in the multiplier portion of the circuit.

I designed an ionization type radiation detector that uses a charge pump to sweep radiation-created ions out of a collection tube, but haven't built it yet. It is designed to generate 50V from a 10V power supply bus. Simple thing really, just the bias generator plus a TIA and the mechanical bit, a tube with an electrode down the middle. I've been thinking it could be used to characterize my AM241 sources, making it possible to get an approximate number for things like count rate -- in turn useful as a sanity check for a functioning XRF system.
 
I finally am able to capture and plot pulses coming out of my analog front end. It turns out that the pulse acquisition process is more complex than I originally thought. Fortunately, having a fairly deep circular buffer makes it possible to "look back in time" once the the pulse amplitude exceeds a set trigger level. That was one of the problems, I wan't going far enough back to process/display the entire pulse. Right now I'm going back a fixed amount, but that can easily be refined. The Teensy4.0 is fast enough to do a lot of processing before there's any danger of overwriting the pulse data.

Another thing I initially neglected to consider is that the magntude of the RMS error between the fitted curve and data depends on the amplitude of the pulse, so I now am normalizing that value by dividing it by the (fitted) peak voltage. Something difficult to do in the analog world!

Anyway, here's a screen shot showing a pulse. I set the trigger level to 400mV and am going back in time by 20 sample intervals. I'm using the Arduino Serial plotter tool for this.

XRF pulse.JPG
 
Is the "straight line" part simply that the ring buffer length ran out shortly after the peak? No matter, so long as we get the peak! :)
 
Back
Top