Drafting out the Mind Mirror analogue filters, scaling values to the nearest good combination of series resistors looks good at 1% tolerances of resistors and capacitances, according to LTspice
but realistically the capacitance tolerances are 10% although resistors are 5%, and that’s makes a mess of some channels
in particular the 6,7.5, 9, 10.5, 12.5 and 19, 24, 30 and 38Hz channels. These are simulated using multiple-feedback bandpass filters (MFBP). I then simulated the same spread on the highest Q so most sensitive 9Hz band on the dual amplifier bandpass topology (DABP) and the state variable topology (SVBP) using three opamps per stage.
Both the latter are meant to have a lower sensitivity to tolerances, and both have the advantage of having a defined gain, whereas the MFBP gain varies quite dramatically with fractional bandwidth and Q.
There’s not much to be won here with the different topologies regarding sensitivity to tolerances, which surprised me. Williams states that the DABP is less sensitive to component tolerances than the MFBP and the SVBP less still. Examining the SVBP I got a variation in level of 5dB, the MFBP of 2.4dB and the DABP of 3.07. I have the suspicion I will need to tune these, in which case the DABP is easier, since the MFBP has interaction between fc and Q in tuning, as well as a wider spread of resistor values with Q² as opposed to with Q in the DABP. However, that is 14ch × 2 stages × 2 sides = 56 pots or S.O.T. resistors 😉 As they said
The original analogue filters in Mind Mirrors 1 and 2 were precise but expensive to manufacture. The digital Band Pass filters parameters were modelled on the band pass characteristics of the analogue filters, and were able to more accurately guarantee the performance of the filters.
Lining up the analogue filters isn’t too hard – Williams 1 says set the input frequency to be the desired centre frequency, monitor the input and output of the filter on a scope set to XY mode and adjust filter centre frequency until the Lissajous figure closes to a straight line. The thought of doing this 56 times does not fill me with joy, however. So one last time, how about DSP?
The siren song of DSP
Certainly if you’re going to make more than one you’d go DSP, even I am tempted along the DSP route seeing the effect of tolerances on simulation, but that would make the whole thing too dear, and I have no DSP development system. It is possible to transform the analogue filters into IIR digital domain filters using the bilinear transformation so there’s no particular magic about getting a DSP implementation, apart from the learning curve and the price for a one-off.
I could use a Raspberry Pi and something like GNURadio to do that job. Power consumption will skyrocket, but I get to forget about tuning the filters. Alternatively something like octave with the signal package might work, but I haven’t convinced myself that this will display in real time. There also seems to be some degree of hurt available with IIR filters – GNURadio focuses on FIR filters and doesn’t seem to feature IIR very much. Perhaps because of that hurt 😉
The trouble is that I am a total noob with DSP, and to match the Mind Mirror shapes and delays I need to transform the analogue filters, which means IIR from the maths. And IIR seems to be the area that causes noobs trouble, in terms of the filters not settling due to truncation errors.
The obvious way is to use a FFT, or more likely the DFT implementation., but the catch at these low frequencies is that to get the frequency resolution to match the older filters I’d need sub-1Hz resolution. The DFT frequency resolution is fs/N. So imagine I sample at 1000Hz I need 1000 samples before I get any output, giving me a 1s latency. This seems to be the basis of the issues in using FFT to replicate the Mind mirror results. There is the very real possibility of Mind Mirror talking their book of course 😉
Or I could try an Arduino. With an analogue antialiasing filter of about 200Hz and a sampling rate of 1000Hz I could use IIR filters from http://www.schwietering.com/jayduino/filtuino/ and sample on change of millis(), the Arduino could then also do the LED display. Depending on how long the floating point maths takes I might be able to run two channels on the Arduino, so I will end up with a rig with 14 Arduino chips. Sampling with the Arduino is doable, as shown here.
If I’m going to go microcontroller I could also consider a PIC, a 16F88 is £2.50 at 10-off prices, has onboard A/D. I use JAL as a high-level language for PICs because I’m not prepared to pay out £200 for a C compiler for those, so floating point is resource-hungry, but I understand interrupts etc on the PIC 16 series, where I don’t really on Arduino. The ATMega328 used in Arduino Uno is a similar price, which sort of favours the Arduino as there’s more example code and the sorta C compiler is free. But I get to either buy preprogrammed Arduino chips which are dearer or I get to buy an AVR programmer for about £20 to program the Arduino bootloader onto vanilla ATmega 328s
Every time I look at everything else I need to do to make this happen digitally I am drawn back to the analogue solution. Lining up filters is tedious, particularly at such low frequencies, but easy. I have a LCR meter so I could screen the capacitors to get a better tolerance, I could probably match them to 1% and recalculate the resistors for whatever value they are measured at. The DABP can be done with a single LM324 per channel, at 50p rather than £2.50 Arduino, and LM3914s are to be had cheaply from China. But before I actually go that way, I will take a step back, and investigate again what people have already done in this space. Researching this post picked up a fair amount of open source work in this field, and some of it looked like it would support IIR filtering.
- Electronic Filter Design Handbook, A Williams, McGraw-Hill, 1981, p5-46 ↩