Avalanche Noise Amp: Sampling

The relatively low bandwidth of the amplified noise means two successive samples (measured in Arduino time) will be highly correlated. Rather than putz around with variable delays between the samples, I stuffed the noise directly into the Arduino’s MISO pin and collected four bytes of data while displaying a single row:

unsigned long UpdateLEDs(byte i) {
unsigned long NoiseData = 0ul;
	NoiseData |= (unsigned long) SendRecSPI(~LEDs[i].ColB);				// correct for low-active outputs
	NoiseData |= ((unsigned long) SendRecSPI(~LEDs[i].ColG)) << 8;
	NoiseData |= ((unsigned long) SendRecSPI(~LEDs[i].ColR)) << 16;
	NoiseData |= ((unsigned long) SendRecSPI(~LEDs[i].Row))  << 24;

	analogWrite(PIN_DIMMING,LEDS_OFF);			// turn off LED to quench current
	PulsePin(PIN_LATCH);						// make new shift reg contents visible

	return NoiseData;

The bit timing looks like this:

SPI Sample - noise data - 01
SPI Sample – noise data – 01

The vertical cursors mark the LSB position in the first and last bytes of the SPI clock. The horizontal cursors mark the minimum VIH and maximum VIL, so the sampled noise should produce 0 and 1 bits at the vertical cursors. Note that there’s no shift register on the input: MISO just samples the noise signal at each rising clock edge.

I picked those two bit positions because they produce more-or-less equally spaced samples during successive rows; you can obviously tune the second bit position for best picture as you see fit.

Given a pair of sequential samples, a von Neumann extractor whitens the noise and returns at most one random bit:

#define VNMASK_A 0x00000001
#define VNMASK_B 0x01000000

enum sample_t {VN_00,VN_01,VN_10,VN_11};

typedef struct {
	byte BitCount;					// number of bits accumulated so far
	unsigned Bits;					// random bits filled from low order upward
	int Bias;						// tallies 00 and 11 sequences to measure analog offset
   unsigned SampleCount[4];	// number of samples in each bin
} random_t;

random_t RandomData;

... snippage ...

byte ExtractRandomBit(unsigned long RawSample) {
byte RetVal;

	switch (RawSample & (VNMASK_A | VNMASK_B)) {
	case 0:							// 00 - discard
		RetVal = VN_00;
	case VNMASK_A:					// 10 - true
		RetVal = VN_10;
		RandomData.Bits = (RandomData.Bits << 1) | 1;
	case VNMASK_B:					// 01 - false
		RetVal = VN_01;
		RandomData.Bits  = RandomData.Bits << 1;
	case (VNMASK_A | VNMASK_B):		// 11 - discard
		RetVal = VN_11;
	RandomData.Bias = constrain(RandomData.Bias,-9999,9999);
	RandomData.SampleCount[RetVal] = constrain(RandomData.SampleCount[RetVal],0,63999);

	return RetVal;

The counters at the bottom track some useful statistics.

You could certainly use something more complex, along the lines of a hash function or CRC equation, to whiten the noise, although that would eat more bits every time.

The main loop blips a pin to show when the extractor discards a pair of identical bits, as in this 11 sequence:

SPI Sample - noise flag - 11
SPI Sample – noise flag – 11

That should happen about half the time, which it pretty much does:

SPI Sample - noise flag - 1 refresh
SPI Sample – noise flag – 1 refresh

The cursors mark the same voltages and times; note the slower sweep. The middle trace blips at the start of the Row 0 refresh.

On the average, the main loop collects half a random bit during each row refresh and four random bits during each complete array refresh. Eventually, RandomData.Bits will contain nine random bits, whereupon the main loop updates the color of a single LED, which, as before, won’t change 1/8 of the time.

The Arduino trundles around the main loop every 330 µs and refreshes the entire display every 2.6 ms = 375 Hz. Collecting nine random bits requires 9 x 330 µs = 3 ms, so the array changes slightly less often than every refresh. It won’t completely change every 64 x 8/7 x 3 ms = 220 ms, because dupes, but it’s way sparkly.

In the spirit of “Video or it didn’t happen!”, there’s a low-budget Youtube video about that…

Avalanche Noise Amp: Spectra

Given this schematic:

Noise Source - Schematic
Noise Source – Schematic

The noise spectrum at the collector of the NPN transistor looks dead flat:

Noise spectrum - 2N3904 collector
Noise spectrum – 2N3904 collector

In fact, it’s down 3 dB at 4 MHz, 10 dB at 10 MHz, and has some pizzazz out through 50 MHz.

The cursor marks the second harmonic of the 125 kHz SPI clock that’s shoving bits into the shift registers that drive the LED display. In principle, you can’t get 250 kHz from a 125 kHz square wave, so we’re looking at various & sundry logic glitches that do have some energy there.

The big peak at 0 Hz comes from the LO punching through the IF filters; I should have set the start frequency to 9 kHz (the HP 8591 spectrum analyzer’s lower cutoff frequency) to let the filter get some traction.

With that setup, the first LM324 with a gain of 10 produces this dismal result:

Op Amp 1 10x gain spectrum - 9-209 kHz
Op Amp 1 10x gain spectrum – 9-209 kHz

Past an op amp’s -3 dB cutoff, the response drops at 10 dB/decade for a while. Squinting at that curve, it’s down 10 dB at 40 kHz and the cutoff looks to be around 4 kHz… not the 100 kHz you’d expect from the GBW/gain number.

[Edit: You’d expect a 6 dB/octave = 20 dB/decade drop from a single-pole rolloff. That’s obviously not what’s happening here.]

The LM324 has a large-signal slew rate of about 0.5 V/µs that pretty well hobbles its ability to follow full-scale random noise components.

Both traces come from a kludged 10 dB AC coupled “attenuator” probe: a 430 Ω resistor in series with a 1 µF Mylar cap, jammed into a clip-lead splitter on the BNC cable to the analyzer. Probably not very flat, but certainly good enough for this purpose.

The SA is averaging 100 (which was excessive) and 10 (more practical) successive traces in those pix, which gives the average of the maximum value for each frequency bin. That reduces the usual hash you get from a full-frontal noise source to something more meaningful.

Avalanche Noise Amp

This lashes a pretty good avalanche noise source to an absolute dog of an op amp:

Noise Source - Schematic
Noise Source – Schematic

It’s built into the formerly vacant space on the 8×8 LED matrix board last seen generating random numbers by timing Geiger detector pulses:

Reverse-bias noise amplifier - overview
Reverse-bias noise amplifier – overview

The LM317 tweaks the reverse bias voltage to ram about 10 µA of DC current through the 2N2907A base-emitter junction; I picked that transistor because it has a 5.0 V breakdown spec that translates into about +8 V in reality, plus I have a few hundred lying around.

The 4.7 kΩ collector resistor sets the operating point of the 2N3904 NPN transistor at a bit over 6 V with a collector current of 1.6 mA, around which there appears ±500 mV of pure noise:

Noise - NPN C inv - op amp
Noise – NPN C inv – op amp

The 2N3904 spec says hFE > 100 and, indeed, I measure 200: 8 µA in, 1.6 mA out.

The bottom trace is the output of the first LM324. With a GBW of 1 MHz and a voltage gain of 10, it should have a cutoff at 100 kHz, but that’s obviously not true; the 0.5 V/µs large-signal slew rate just kills the response. The flat tops at 3.8 V show that it’s definitely not a rail-to-rail op amp.

The horizontal cursors mark the ATmega 328 minimum VIH and maximum VIL; the actual thresholds lie somewhere between those limits. What you don’t get is the crisp transition from a comparator.

The trimpot setting the logic level lets you tune for best picture; in this case, that means balancing the number of 0 and 1 bits. It’s a bit more complex, of course, about which, more later.

I picked the LM324 for pedagogic reasons; it’s a Circuit Cellar column and I get to explain how a nominally good analog circuit can unexpectedly ruin the results, unless you know what to look for…

Drying Rack Rung Repair

One of the rungs in the drying rack that keeps my bath towel from crawling away broke:

Drying Rack - broken rung
Drying Rack – broken rung

The rungs have turned-down pegs on the ends that slide through the inner side strut and anchor into the outer strut with a nail through the end. You can see the peg between the struts.

Removing the nail split the end of the strut, so I slobbered urethane glue into the crack and clamped it together overnight:

Drying Rack - strut gluing
Drying Rack – strut gluing

Rather than removing the strut and doing it right, I gingerly freehanded a 3/8 inch hole into the end with a Forstner bit:

Drying Rack - drilled reinforced rung
Drying Rack – drilled reinforced rung

Yes, that’s off-center, but it’s dead on the scar where the peg broke off. I have no idea how they could turn down a cylinder to get an eccentric peg on the end.

The black heatstink tubing reinforces the absurdly thin wood shell remaining around the hole. It’s probably not required, given that I’m about to fill the hole with a hardwood peg; nothing exceeds like excess.

Cut a suitable length from a nearby foam paint brush handle that just happens to be both hardwood and 3/8 inch in diameter, dab urethane glue in the holes (but not in the inner strut!), stuff peg through inner strut, seat in outer strut, stretch things enough to slide peg into rung, separate struts to avoid inadvertently pasting them together:

Drying Rack - reassembled
Drying Rack – reassembled

Took about fifteen minutes over the course of three days while the glue cured.


Those of long memory may recall a similar repair to the previous rack; we do, occasionally, toss things. I did, of course, add some of its dowels to the Long Things Stockpile.

Alpha Geek Clock: New Battery

After the CR123A lithium cell in the Alpha Geek Clock gave out:

Packaged Alpha-Geek Clock
Packaged Alpha-Geek Clock

I duct-taped a pair of D cells onto the case and returned it to the bedroom shelf. According to the date scrawled on the tape, that was five years ago: 26 November 2010.

Over the last few months, the LED gradually faded from a blink to a steady glow as the battery voltage dropped below 2 V and the WWVB receiver output no longer reached the MOSFET’s threshold.

We’ll see how long these last:

Alpha Geek Clock - new batteries
Alpha Geek Clock – new batteries

Yeah, I should probably do something involving 3D printing…

Sony 64 GB MicroSDXC Card: Another Failure

A little over a year ago, I bought two Sony 64 GB MicroSDXC cards (let’s call them A and B). Both cards failed after less than six months in service and were replaced under warranty with Cards C and D:

Sony 64 GB MicroSDXC cards - front
Sony 64 GB MicroSDXC cards – front

The top card (C) is the most recent failure, the bottom (D) is the as-yet-unused replacement for Card D. Note that the difference: SR-64UY vs. SR-64UX, the latter sporting a U3 speed rating.

Note that the failure involves the card’s recording speed, not its read-write ability or overall capacity. Card C still has its nominal 64 GB capacity and will store-and-replay data just fine, but it can’t write data at the 25 Mb/s rate required by the camera… which is barely a third of the card’s speed rating. Also note that the writing speed is always a minute fraction of the reading speed that you see on the card.

I use these in a Sony HDR-AS30V action camera on my bike, so it’s pure Sony all the way. Although I don’t keep track of every trip, I do have a pretty good idea of what happened…

In service: about 2015-07-10
Failed to record 1920×1080 @ 60 f/s video: 2015-09-22

In round numbers, that’s 70 days of regular use.

My NAS drive has room for about a month of video, depriving me of a complete record of how much data it absorbed, but from 2015-08-21 through 2015-09-22 there’s 425 GB from 25 trips in 30 days. Figuring the same intensity during the complete 70 days, it’s recorded 800 to 900 GB of data (including my verification test). With 60 GB available after formatting, that amounts to filling the card 14 times.

That’s reasonably close to the 1 TB of data I’d been estimating for the failures of Cards A and B, so these Sony cards reliably fail their speed rating after recording 750 GB, more or less, of data.

We’ll see if they replace the replacement…