APC Australia

Turn a Cortex-M3 board into a digital audio recorder

It has no SD card port and isn’t designed for audio recording. Darren Yates shows how to turn this STM32F103 board into a digital audio recorder using the Arduino IDE.

-

Digital audio recording has always been one of the top two most popular topics we’ve covered in our Arduino masterclas­s (the other being robots). The problem with most microcontr­oller unit (MCU) boards, though, is that they’re not designed for digital audio. Previously, we’ve cajoled older 8-bit Arduino boards such as the Nano, Uno and Mega2560 into recording audio, but this month, we’re taking on our first ARM Cortex-M3 MCU version using the popular mini STM32F103 board selling on eBay for under $5.

CORTEX-A VS CORTEX-M

The tiny Nano-style board we’re using for this project features ST Microelect­ronics’ STM32F103C­8T6 MCU based on ARM’s popular 32-bit Cortex-M3 processor core. Android phones use Cortex-A series CPUs designed to run a full-blown operating system, but the Cortex-M series are for ‘embedded’ applicatio­ns where there’s usually only one job to do — running your source code. The STM32F103C­8T6 MCU clocks along at 72MHz, has 20KB of RAM and 64KB of flash — not earth-shattering, but plenty when there’s no OS to weigh everything down.

Two key things about this project — first, you’ll need soldering skills. Don’t have them? Get them, or rope in a knowledgea­ble mate. Second, as this board is not standard Arduino-issue, we need to go next-level and program it via an external link module. We’ll show you how, but it’s not as easy as plugging in a USB cable, so be warned.

FEATURE-TWEAKING

With only 64KB of flash storage, we’ll also need external storage to store our audio, but before that, the STM32F103 has no audio inputs or a Secure Digital Input/Output (SDIO) port for SD card storage. So we feature-tweak. The chip does have two 12-bit analog-to-digital converters (ADCs) and two Serial Peripheral Interface (SPI) ports — with some coding tricks, we can knock them into shape.

ANALOG-TO-DIGITAL CONVERSION

The two ADCs in the STM32F103 are fully-programmab­le and have a top speed of one million samples per second (1Msps), but for audio CD-standard recording, we need 44,100 samples of 16-bit depth per second

or ’44.1kHz/16-bit’ sampling. Here’s what we do. First, we set the two ADCs to sample simultaneo­usly — one grabs the left-channel, the other the right. Next, we use one of the chip’s counters or ‘timers’ to trigger an interrupt as close to 44,100 times per second as we can. This is done by dividing the 72MHz CPU clock by a counter number that gives us the nearest interrupt trigger rate. That number is ‘1,632’. Divide 72,000,000 by 1,632 and you get 44,117, which is less than 0.03% off 44,100. We use this to trigger the ADCs into grabbing an audio sample — but from where?

ANALOG INPUTS

The MCU chip has 10 analog inputs — we need just two and we’re using inputs PA4 and PA5. They’re not specifical­ly designed for audio, but we can make them accept audio by setting the DC voltage level of each input separately to half the 3.3VDC supply rail using two sets of two 10kohm/1% resistors as voltage dividers. The junction connects to the analog input pin and sets the voltage to within 1% of half-way (1.65VDC). We then add a DC-blocking capacitor to this junction and feed in the audio to the other end of the capacitor. The audio is overlaid onto the 1.65VDC voltage so that the full waveform is captured within the 0 to 3.3VDC range of the ADCs. The limitation with this method, however, is that you must feed in ‘line-level’ audio, anywhere up to 1.2Vrms. You cannot direct-connect a mic — microphone­s typically generate just 0.01Vrms, which simply won’t register (a 40dB-gain preamp will fix this, though).

GETTING 16 BITS FROM 12

This still leaves us with the problem of the ADCs producing 12-bit samples, rather than the 16 required by CD-standard audio. However, there is an easy fix — we take each 12-bit sample and ‘ bit-shift’ it four places to the left, turning 12-bit samples into a 16-bit number. For example, the sample ‘1101001110­01’ becomes ‘1101001110­010000’. The four least significan­t digits will always be zero and really, it’s a bit like using the digital zoom on your camera — we’re just making the samples larger. However, in this case, it’s a necessary step to force the samples into 16-bit compliancy.

SERIAL PERIPHERAL INTERFACE

The MCU chip may not have a dedicated SDIO port, but SD cards also support the simpler SPI standard and we use this here with our tiny microSD card reader module. However, in order to power the module and minimise digital noise on the audio, we add in an external voltage regulator. The STM32F103 takes power via USB, but at 5VDC, this voltage is too high for both the chip and the microSD, which both work on 3.3VDC. The MCU board has a small 3.3VDC voltage regulator on board, however, it’s quite tiny, so to lighten the load, we use an external 3.3VDC regulator that takes power from the board’s 5VDC pin and creates a separate 3.3VDC voltage rail to power the card module.

JUGGLING THE TASKS

But these tweaks only solve half the problem — with only 20KB of RAM, we still need to code the process of capturing audio samples at 44.1kHz and storing them to microSD card. Of these two tasks — sampling audio and storing the samples — sampling the audio is the most critical. If we don’t sample at exactly every 22.67 microsecon­ds, the sampled audio will be all over the shop when we play it back. This is why we use the timer triggered interrupt we mentioned earlier — by hook or by crook, when that interrupt goes off, audio samples will be taken. However, it only takes

“This board is not standard Arduino-issue, we need to go next-level and program it.”

around 29 clock cycles to capture those samples, leaving us with around 1,600 clock cycles of free ‘downtime’ before the next sample must be taken. So we use this ‘downtime’ to write the samples to the microSD card.

To give us even more leeway, we use a special technique called a ‘ring buffer’. We create two arrays from RAM, each capable of storing 3,072 samples (we’d love more, but that’s all 20KB of RAM will allow us, after accounting for our code’s other needs). Keeping in mind we need to store two samples at each point, one for each channel, 3,072 samples is approximat­ely 34.8 millisecon­ds of storage, so while one buffer is recording the current samples, the other buffer is being written to the microSD card. Provided that buffer is written to the card in less than 34.8 millisecon­ds, the system runs smoothly. However, if it takes longer, we’ll suffer ‘ buffer overrun’, where the current buffer fills but the next buffer isn’t free because it’s still waiting for the card to finishing writing. The result sounds like brief ‘chirping’ on the audio.

Now 34.8 millisecon­ds isn’t very long and it’s made worse by having to use SPI transfer rather than the much faster SDIO. Throw in the fact that microSD cards have different writedelay or ‘latency’ times and you might wonder how the whole thing works at all. However, it does — but in our experience, you need a fast, low-latency microSD card to remove the buffer overruns. We’ve had excellent results with a 16GB Sandisk Ultra microSD cards — you’ll find these for around $12.

BUILDING THE RECORDER

We’ve built our digital audio recorder on a 400-point breadboard. Use the overlay diagram as a guide. The key components are the STM32F103C­8T6 ‘ blue pill’ board, the microSD card reader module, the AMS1117 3.3VDC regulator module, two-pin pushbutton switch and the 3.5mm TRRS socket module, all available from eBay.

PROGRAMMIN­G THE MCU BOARD

Normally with Arduino boards, you plug them into your PC via the USB port, select the COM port in the Arduino IDE and away you go. Not here — the STM32F103 boards are not standard Arduino-issue, so we have a few things we need to do. First, you’ll need to also purchase an ST-Link V2 module — this does the job of translatin­g ‘USB’ between the Arduino IDE and the STM32 chip. These cost about $4 on eBay. It’ll come with a number of connecting wires that link between the back of the ST-Link module and the four pin headers on the opposite end of the MCU board to the USB port. Our programmin­g wiring diagram above will help you get the connection­s

right (only one GND and 3.3V connection is required).

SETTING UP LIBRARIES

The other problem is the Arduino IDE has no idea what the STM32F103 chip is, again, since it’s not standard Arduino issue. To fix that, first launch the Arduino IDE (get it from www.arduino.cc/downloads) and from the main menu, select Tools, choose Board from the drop-down menu and ‘Boards Manager’. From the list, click on ‘Arduino SAM boards (32-bit ARM Cortex-M3)’ and install it. This gives us the basic 32-bit compiler to turn our source code into code the chip can use. After that, you need to grab the Arduino_STM32 board library, created by Roger Clark, an Australian software engineer, from the GitHub page at tinyurl.com/ybpwbwdn (zip file). Unzip the file and copy the folder to \my documents\arduino\hardware. If that path doesn’t exist, make it. Now reboot the IDE. This folder contains all the necessary code for the IDE to understand how to code the STM32F103.

Now, there’s just one more library to install — and that’s the ‘SdFat’ library that handles the file allocation table (FAT) format of the microSD card (hint: you must format your microSD card in FAT format for this to work). Launch the Arduino IDE and from the menu, select ‘Sketch > Include Library > Manage Libraries’. When the Libraries Manager appears, wait for it to update, then in the search bar, type “sdfat”. Click on ‘SdFat by Bill Greiman’, select version ‘1.0.3’ and press the Install button (later versions don’t work with our code).

Once it’s installed, head to the \my documents\arduino\libraries\ sdfat\src subfolder and open up the ‘sdfatconfi­g.h’ file in any text editor. Scroll down until you find ‘#define ENABLE_EXTENDED_TRANSFER_ CLASS 0’ and change the ‘0’ to a ‘1’. Save the file.

The last thing you’ll need to make this work is our source code — you’ll find it on our website at www.apcmag. com/magstuff. Open up the ‘STM32rec. ino’ file in the IDE. Plug in your STM32F103 board via the STLink module, then on the IDE, choose Tools from the menu, select Board, scroll down until you find ‘Generic STM32F103C series’ and select it. Go back to the Tools menu, come down to Variant and select the ‘20k RAM, 64K flash’ option. Once again, select the Tools menu and ensure the clock speed is set to ‘72MHz (normal)’. Now one last time, choose the Tools menu and set the ‘Upload Method’ option to ‘STLink’. Press the right-arrow Upload button and the source code will be compiled and uploaded via the STLink module to the STM32 board.

USING THE DIGITAL RECORDER

To keep things simple(!), this project has no playback, it just records. It also only has one button. When you power up the first time, if no recognised FAT-formatted microSD card is in the module, the on-board red LED will continuous­ly slow-flash. Press the board’s reset button to restart. If it recognises a FAT-ready card, it’ll flash twice and go out. When you’re ready, press the button, the LED will again blink twice and recording will begin. When you’re ready to stop, press the button again and you’ll see a series of fast LED flashes. When the LED goes out, remove the microSD card, load it into your PC or notebook’s card reader, double-click on the ‘rec0.wav’ file and it’ll begin playing (every media player worth its code handles WAV files). Our source code generates the required WAV file header, automatica­lly incrementi­ng the file number based on the current maximum.

ADJUSTING SAMPLE RATES

Look in the source code and you’ll see a code line where you can set the sample rate. If you find you’re getting buffer overrun chirps in your audio output, try dropping the sample rate down — most players support a range of sample rates below 44.1kHz. Start with ‘32000’, then try ‘24000’, ‘22050’ and ‘16000’, but note, the lower the sample rate, the lower the quality.

DRAWBACKS OF READY-MADE BOARDS

Purists will scoff at 12-bit audio, but the fact is it works. However, the popular ‘ blue pill’ board we’ve used here does have an issue. To minimise digital noise on the ADC inputs, most MCUs provide the ADC with separate power supply lines. The STM32F103C­8T6 has these, called ‘ VDDA’ (+) and ‘ VSSA’ (0V), however, these are tied to the digital power lines on this board and together with the lack of shielding on our breadboard layout, allow digital noise from the microSD card writing process to leak into the audio. In theory, 12-bit sampling should give you 72dB dynamic range, or better than FM radio, but because of the digital noise, the signal-to-noise ratio (SNR) here is nearer 45dB. You won’t likely notice it on heavy rock music, but softer passages of classical music won’t sound great. Shielded audio cable to the ADC inputs may help a little, but the better option would be a dedicated external ADC chip. In the meantime, this has been a useful exercise in how to improvise without the right features and still end up with something most phones can’t do — record stereo sound.

 ??  ?? Our digital audio recorder captures WAV files to microSD card.
Our digital audio recorder captures WAV files to microSD card.
 ??  ?? This 3.5mm TRRS socket can be used to input audio from your phone.
This 3.5mm TRRS socket can be used to input audio from your phone.
 ??  ?? This AMS1117 3.3V regulator provides power to the microSD reader.
This AMS1117 3.3V regulator provides power to the microSD reader.
 ??  ?? This tiny microSD card reader is designed for 3.3V MCUs like the STM32.
This tiny microSD card reader is designed for 3.3V MCUs like the STM32.
 ??  ?? You program this MCU board via a $5 ST-Link V2 USB module.
You program this MCU board via a $5 ST-Link V2 USB module.
 ??  ?? Set the board to ‘Generic STM32F103C series’ in the Arduino IDE.
Set the board to ‘Generic STM32F103C series’ in the Arduino IDE.
 ??  ?? Use the Arduino IDE Library Manager to install the SdFat library version 1.0.3.
Use the Arduino IDE Library Manager to install the SdFat library version 1.0.3.
 ??  ?? Use this overlay diagram to build your own version of our DAR.
Use this overlay diagram to build your own version of our DAR.
 ??  ?? Ensure you install the ‘Arduino SAM boards’ package before compiling.
Ensure you install the ‘Arduino SAM boards’ package before compiling.
 ??  ?? The ST-LINK v2 module includes jumper wires to connect to the STM32 board.
The ST-LINK v2 module includes jumper wires to connect to the STM32 board.
 ??  ?? This 32-bit Cortex-M3 STM32F103 MCU board sells on eBay for around $5.
This 32-bit Cortex-M3 STM32F103 MCU board sells on eBay for around $5.

Newspapers in English

Newspapers from Australia