8

For DIY, how to program Arduino Mini Pro to act as an Audio Frequency White Noise generator?

Presumably,

a) using one Digital Output pin

b) feed to a simple passive RC low pass filter to reduce out of band signal

c) feed to a simple class-D IC chip audio amplifier and speaker

d) since it is DIY and noise, lo-fi (not hi-fi) is good enough.

Specific questions,

a) How to program?

b) Wonder if it is better to use to chip act a Pulse Width Modulated 'digital to analogue converter'?

c) How to calculate value for RC filter (assume amplifier has high input impedance)?

Many years ago, I have programmed a hardware sound generator chip as part of a game machine. It has two registers for amplitude and 'frequency' control (band of 'white' noise). It worked very well. I once looked at the output using oscilloscope and it was square wave. I believe that it works, basically, using the above principles. Since I do not have the chip now, I cannot verify it. Now, I would like to duplicate its function using Arduino in software.

EEd
  • 904
  • 1
  • 14
  • 21

2 Answers2

6

I don't know that you need all that - just an Arduino and a piezo speaker and a pot if you want to play with the volume.

byte speakerPin = 1;

void generateNoise() { static unsigned long int reg = 0x12345678; //seed unsigned long int newr; unsigned char lobit; unsigned char b31, b29, b25, b24; b31 = (reg & (1L << 31)) >> 31; b29 = (reg & (1L << 29)) >> 29; b25 = (reg & (1L << 25)) >> 25; b24 = (reg & (1L << 24)) >> 24; lobit = b31 ^ b29 ^ b25 ^ b24; newr = (reg << 1) | lobit; reg = newr; digitalWrite (speakerPin, reg & 1); delayMicroseconds (50); // Changing this value changes the frequency. }

Dave X
  • 2,350
  • 15
  • 29
Mike
  • 326
  • 2
  • 3
5

Mike's answer uses a Fibonacci Linear Feedback Shift Register configuration, but the compactness Galois Linear Feedback Shift Register Configuration could be faster:

#define speakerPin 8

unsigned long lastClick;

void setup() { // put your setup code here, to run once: pinMode(speakerPin,OUTPUT); lastClick = micros();
}

/* initialize with any 32 bit non-zero unsigned long value. / #define LFSR_INIT 0xfeedfaceUL / Choose bits 32, 30, 26, 24 from http://arduino.stackexchange.com/a/6725/6628

  • or 32, 22, 2, 1 from
  • http://www.xilinx.com/support/documentation/application_notes/xapp052.pdf
  • or bits 32, 16, 3,2 or 0x80010006UL per http://users.ece.cmu.edu/~koopman/lfsr/index.html
  • and http://users.ece.cmu.edu/~koopman/lfsr/32.dat.gz
  • or generate a one with https://github.com/hayguen/mlpolygen

*/
#define LFSR_MASK ((unsigned long)( 1UL<<31 | 1UL <<15 | 1UL <<2 | 1UL <<1 ))

unsigned int generateNoise(){ // See https://en.wikipedia.org/wiki/Linear_feedback_shift_register#Galois_LFSRs static unsigned long int lfsr = LFSR_INIT; /* 32 bit init, nonzero / / If the output bit is 1, apply toggle mask. * The value has 1 at bits corresponding * to taps, 0 elsewhere. */

if(lfsr & 1) { lfsr = (lfsr >>1) ^ LFSR_MASK ; return(1);} else { lfsr >>= 1; return(0);} }

void loop() { /* ... */ if ((micros() - lastClick) > 50 ) { // Changing this value changes the frequency. lastClick = micros(); digitalWrite (speakerPin, generateNoise()); }

}

For a 16 bit implementation (faster, but only a cycle of 2^16) try:

#define LFSR_MASK 0x8016 
static uint16_t lfsr = LFSR_INIT;  /* 16 bit init, nonzero */

Written in a more compact form:

#define speakerPin 8

#define LFSR_INIT 0xfeed /* non-zero seed value for generateNoise() / #define LFSR_MASK 0x8016 / magic number from http://users.ece.cmu.edu/~koopman/lfsr/ */

unsigned long lastClick;

void setup() { // put your setup code here, to run once: pinMode(speakerPin,OUTPUT); lastClick = micros();
}

unsigned int generateNoise(){ // Return 1 bit of noise using a Galois Linear Feedback Shift Register // See https://en.wikipedia.org/wiki/Linear_feedback_shift_register#Galois_LFSRs

static uint16_t lfsr = LFSR_INIT;

if(lfsr & 1) { lfsr = (lfsr >>1) ^ LFSR_MASK ; return(1);} else { lfsr >>= 1; return(0);} }

void loop() { /* ... */ if ((micros() - lastClick) > 50 ) { // Changing this value changes the frequency. lastClick = micros(); digitalWrite (speakerPin, generateNoise()); }

}

For an 8 bit implementation (faster than 32 bit, slightly slower than 16, but only a cycle of 2^8) try:

#define LFSR_MASK 0x8e

static byte lfsr = LFSR_INIT; /* 8 bit init, nonzero */

Where the mask constants are from the 8.txt and 16.txt files at http://users.ece.cmu.edu/~koopman/lfsr/index.html

The https://github.com/hayguen/mlpolygen program can search for maximum length feedback polynomials of various bit sizes.

Dave X
  • 2,350
  • 15
  • 29