Close

Aud/*u*/i/*n*/o

A project log for Sonassist

Audio feedback for the brain-injured who need help learning to balance again.

simon-merrettSimon Merrett 08/31/2017 at 21:170 Comments

No, it's not a typo...

I was just trying to make a pun. And I'm sure someone has smashed audio and Arduino together in a clone-style board before. This log is about the requirements, challenges and solutions I found in generating stereo audio, using Arduino, for brain injury balance rehabilitation.

Why audio?

The brain injury specialist physiotherapist I'm working with tells me that brain injury patients' hearing abilities are among the most likely senses to survive brain injuries intact or less impaired than other senses. They would like to see whether by providing continuous, as opposed to error/boundary-based feedback, the patients can make better progress at learning to balance for standing and walking. I presume that this is because you can tell earlier if you are veering the wrong way if you have continuous sound signals, rather than waiting to receive a beep or buzz if you cross an error threshold in one direction. 

What kind of audio?

I discussed a variety options, including pulse width modulation, beep frequency but in the end, the specialist thought that the best option to start with would be to use pitch to represent weight shifting forward and backward (backward/over the heels would be low pitch, forward/over the toes would be high pitch). We are initially going to use volume to represent a shift between left and right foot (if relatively more weight is through one foot it will be louder and the other one will be quieter).

Pitch

The classic and most obvious way to produce an audio signal is to use the tone() command in the Arduino IDE. I knew that this relied on timers but I hadn't realised that this function cannot produce a tone on more than one pin at a time, let alone tones of different pitches simultaneously, which is what I want to do.

I searched and searched through various timer libraries in an attempt to generate simultaneous and different varying tones from a single Arduino and came across @Jeremy Blum 's code for 5 speakers simultaneously. Perfect.

I coupled the pitch to the capacitive sensor readings and took it for an early demonstration to the rehabilitation specialist, who said that the audio didn't sound smooth enough. I have to agree that it sounded very "8-bit" and "bleep-bloop-bloop-bleep" as it progressed up and down the frequencies. I thought this was to do with the counter limits I was using in the interrupt service routine and this was generating large frequency jumps. However, it appears that it was more to do with refresh rates, which I was surprised by. 

Human persistence of vision allows us to watch rapidly changing static images and perceive them as moving images. At around 20-30 Hz this update rate appears imperceptible (unless you rapidly turn your head). I increased the audio refresh rate so that frequencies were being updated every 25ms (40Hz) and the effect was still clunky. I then updated every 20ms (50Hz) and could still perceive a rough progression in pitch. Finally, at 15ms updates (~60Hz) I found the pitch progression to be smooth. Seems like hearing is less easy to fool than sight...

I have spent many an hour with the headphones continuously droning high pitch into one or both ears while I write, test and adjust code and I can empathise with victims of noise torture. I decided to try different frequency ranges and although there's no scientific basis for my results, I did start looking in the vicinity of Middle C (~262Hz) and played with around an octave of range. The frequency range I have settled on, because I found it large enough to tell that I was moving from front to back foot loading and because I didn't want to disturb patients with an overly screechy high pitch, is 200Hz to 480Hz.

Volume

The volume needs to be controlled by the microcontroller, so I initially tried pulse width modulation and varied the duty cycle to try and represent a volume change, using one of my piezoelectric discs as a crude speaker (they were still hanging around from the sensor experiment). This definitely didn't work as for some reason the ear doesn't care about duty and it wouldn't have allowed me to change frequency easily. I found a cool method where @Connor Nishijima cranks up the PWM frequency to be ultrasonic in his #10-bit Component-less Volume Control for Arduino!  project and libraries. I struggled to implement this with two simultaneous tones being generated and two MPR121s being polled for readings at a reasonable rate. I put this method on the back-burner, perhaps for another point in the project.

This left me looking for a hardware solution. I had bought a digital potentiometer for a power supply project that I decided was obsolete before I started, thanks to those DPS adjustable step-down units from China. The digital potentiometer was the DIP packaged MCP4261 and there's Arduino library support for it (although read the Spi (sic) bit carefully). One good characteristic of this IC is that it has two wipers, so you can have two channels independently controlled by one chip.

This is the first time I have tried anything audio-related with Arduino so I had to look up what voltage the signal should be (I haven't attempted anything more complex than a square wave by the way as it appears to make a reasonably inoffensive tone and is simple to provide on a GPIO). So a voltage divider is required to drop the GPIO down from 5V or 3.3V to around 0.8V at full volume. I managed to set up a test sketch where the Arduino produced a constant tone and ramped the digital potentiometer wiper up and down the scale (257 linear steps per channel, I think).

The use of the word "linear" in that last sentence gives a clue as to why the MCP4261 wasn't going to be useful in a working prototype (but was useful for proving digital potentiometers would give volume control by an Arduino). Human hearing response is not linear - more logarithmic. The audio electronics business has designed logarithmic rotary potentiometers for years to allow volume control which appears to be linear to the human ear, even though the voltage/energy progression is logarithmic. I searched for a logarithmic - or "taper" - digital potentiometer and found the DS1801+, which is also SPI (although a funny version which needs the CS pin held high before you transmit using the normal SPI library commands). It has fewer positions but they are all usable in the sense that each increment in resistance equates to a noticeable change in volume. There are also two channels. I have managed to interface the Arduino producing a constant tone to the DS1801+ and experienced nice smooth volume progression across the range when using a "loiter" of 10 to 100 milliseconds per increment. I only use a single 2k ohm resistor now between the Arduino 5V GPIO and the input on the digital potentiometer and this seems to produce a good volume range.

Discussions