Arduino Pseudo-Random White Noise Source

A reader (you know who you are!) proposed an interesting project that will involve measuring audio passbands and suggested using white noise to show the entire shape on a spectrum analyzer. He pointed me at the NOISE 1B Noise Generator based on a PIC microcontroller, which led to trying out the same idea on an Arduino.

The first pass used the low bit from the Arduino runtime’s built-in random() function:

Arduino random function bit timing
Arduino random function bit timing

Well, that’s a tad pokey for audio: 54 μs/bit = 18.5 kHz. Turns out they use an algorithm based on multiplication and division to produce nice-looking numbers, but doing that to 32 bit quantities takes quite a while on an 8 bit microcontroller teleported from the mid 1990s.

The general idea is to send a bit from the end of a linear feedback shift register to an output to produce a randomly switching binary signal. Because successive values involve only shifts and XORs, it should trundle along at a pretty good clip and, indeed, it does:

Arduino Galois shift reg bit timing
Arduino Galois shift reg bit timing

I used the Galois optimization, rather than a traditional LFSR, because I only need one random bit and don’t care about the actual sequence of values. In round numbers, it spits out bits an order of magnitude faster at 6 μs/bit = 160 kHz.

For lack of anything smarter, I picked the first set of coefficients from the list of 32 bit maximal-length values at https://users.ece.cmu.edu/~koopman/lfsr/index.html:
0x80000057.

The spectrum looks pretty good, particularly if you’re only interested in the audio range way over on the left side:

Arduino Galois bit spectrum
Arduino Galois bit spectrum

It’s down 3 dB at 76 kHz, about half the 160 kHz bit flipping pace.

If you were fussy, you’d turn off the 1 ms timer interrupt to remove a slight jitter in the output.

It’s built with an old Arduino Pro Mini wired up to a counterfeit FTDI USB converter. Maybe this is the best thing I can do with it: put it in a box with a few audio filters for various noise colors and be done with it.

It occurs to me I could fire it into the 60 kHz preamp’s snout to measure the response over a fairly broad range while I’m waiting for better RF reception across the continent.

The Arduino source code as a GitHub Gist:

// Quick test for random bit generation timing
// Ed Nisley KE4ZNU - 2017-10-25
// Observe output bit on an oscilloscope
// LFSR info https://en.wikipedia.org/wiki/Linear-feedback_shift_register
// This code uses the Galois implementation
// Coefficients from https://users.ece.cmu.edu/~koopman/lfsr/index.html
#define PIN_RND 13
#include <Entropy.h>
uint32_t Rnd;
byte LowBit;
void setup() {
Serial.begin(57600);
Serial.println("Random bit timing");
Serial.println("Ed Nisley KE4ZNU - 2017-10-25");
Entropy.initialize();
pinMode(PIN_RND,OUTPUT);
uint32_t Seed = Entropy.random();
Serial.print("Seed: ");
Serial.println(Seed,HEX);
randomSeed(Seed);
do {
Rnd = random();
} while (!Rnd); // get nonzero initial value
}
void loop() {
// digitalWrite(PIN_RND,Rnd & 1); // about 55 us/bit
// Rnd = random();
LowBit = Rnd & 1;
digitalWrite(PIN_RND,LowBit); // about 6 us/bit
Rnd >>= 1;
Rnd ^= LowBit ? 0x80000057ul : 0ul;
}
view raw Random_Time.ino hosted with ❤ by GitHub