Jump to: navigation, search


cappaddy is a portable audio sample player with capacitive touch controls.

A work-in-progress prototype to try out different things with capacitive touch interfaces and learn more about ARM dev, STM32's peripherals (SPI, TIMER, DAC, DMA, TSC...) and some nice new parts like SPI flash, a new mono audio amp and a 3.3V voltage regulator/boost-converter, ideal for normal AAA cells.

Cappaddy rev0.03 caseV4 DSCN1111.jpg

Hardware (Electronics)

General Notes

Key parts:

Revision 0.03


  • 13 touch channels (15 when UART is not used)
  • Small 8 Ohm Speaker
  • 16 MB SPI Flash
  • Powered by 2x AAA batteries
  • Debug LED
  • 5 GPIOs
  • SWD Connector
  • UART Connector
  • Optional I2C connector
  • Optional USB connector


Cappaddy rev0.03 schematics 2016-04-24.png


Reference			Value			Digikey			Count	Unit		SUM

cappaddy:U1			STM32F072x8		STM32F072C8T6-ND	1	2.00 EUR	2.00 EUR (estimated)

cappaddy:U2			N25Q128A13ESE40E	557-1562-ND		1	1.56 EUR	1.56 EUR

cappaddy:U3			TPA2006D1		296-20783-1-ND 		1	0.97 EUR	0.97 EUR

cappaddy:U4			AS1337			AS1337A-BTDTCT-ND	1	1.46 EUR	1.46 EUR
cappaddy:C13 C14 C17		1u			490-6423-1-ND 		3	0.09 EUR	0.27 EUR
cappaddy:C18			100pf			490-8180-1-ND 		1	0.09 EUR	0.09 EUR
cappaddy:C19			4u7			490-6407-1-ND		1	0.12 EUR	0.12 EUR
							490-12606-1-ND		0	0.13 EUR	0.00 EUR
cappaddy:C3-C6 C15 C16		100n			490-10777-1-ND		6	0.09 EUR	0.54 EUR
cappaddy:C7-C12			1n			490-6349-1-ND		6	0.09 EUR	0.54 EUR
cappaddy:R1-R3 R20 R27 R28	10k			CR0402-FX-1002GLFCT-ND 	6	0.09 EUR	0.54 EUR
cappaddy:R4			470R			CR0402-FX-4700GLFCT-ND 	1	0.09 EUR	0.09 EUR
cappaddy:R5-R19			1k			CR0402-FX-1001GLFCT-ND	15	0.08 EUR	1.22 EUR
cappaddy:R21-R23		100R			CR0402-FX-1000GLFCT-ND	3	0.09 EUR	0.27 EUR
cappaddy:R24			560k			1276-4267-1-ND		1	0.09 EUR	0.09 EUR
cappaddy:R25			330k			1276-4244-1-ND		1	0.09 EUR	0.09 EUR
cappaddy:R26			1M			CR0402-FX-1004GLFCT-ND	1	0.09 EUR	0.09 EUR
cappaddy:L1			4u7			490-6642-1-ND		1	0.39 EUR	0.39 EUR
cappaddy:D1			LED			511-1651-1-ND		1	0.41 EUR	0.41 EUR
cappaddy:battery_case		BC2AAAL-ND		battery_case		1	0.92 EUR	0.92 EUR

							speaker			1	1.50 EUR	1.50 EUR (estimated)

													13.16 EUR

Note: The prices of the microcontroller and the speaker were estimated, those parts were ordered on Aliexpress (Speaker: Asus Padfone 2 A68 replacement).

Digikey BOM (MCU and speaker not included):

1,296-20783-1-ND ,cappaddy:U3
3,490-6423-1-ND ,cappaddy:C13 C14 C17
1,490-8180-1-ND ,cappaddy:C18
6,490-10777-1-ND,cappaddy:C3-C6 C15 C16
6,CR0402-FX-1002GLFCT-ND ,cappaddy:R1-R3 R20 R27 R28
1,CR0402-FX-4700GLFCT-ND ,cappaddy:R4

To estimate the total price the PCB cost, casing, the touch pad material, optional power switch, 2 batteries, cables etc. need to be added (~20 Euros in total?).

The price as well as the amount of assembly work could be lowered A LOT by placing everything on one two-sided PCB. The touch pads, the tiny speaker (with a small tube on it?), the (coin cell) battery (enough capacity?). That would save one a lot of trouble with assembling the thing. A simple case to cover the sensitive parts can still be made. Another benefit of placing the touch pads on the PCB and cover it with solder mask is reliability I guess. Using custom pads with cables gives quite inconsistent results.


Get it at: OSH Park

Cappaddy 0.03m render 00c.png

Cappaddy rev0.03m oshpark 00b.jpg

Cappaddy rev0.03 pcb soldered.jpg

Errata / Known Bugs

  • flash footprint wrong! -> can still be soldered by bending legs. -> or order the right QFN part next time...
  • R23: audio amp ~SD pin: 100R -> 100K
  • audio amp: input caps -> 3.3 nF
  • audio amp: decoupling cap -> 1uF
  • audio amp: input resistor -> 1MOhm (- 100k) -> 200k is not bad!
  • spi / flash: pullup on chip select line and pull down on clock like in datasheet? (100kOhm)
  • uart connector further apart from swd connector
  • uart connector wider: for pin headers, not cables
  • consider pin placement inside case! - where do the physical cables connecto to what? easy assembling!!!
  • proper mounting holes

Hardware (Enclosure)

The case here just serves as a enclosure for the prototype. It is not really playable with touch pads like that.

OnShape project

Cappaddy rev0.03 caseV4 DSCN1043 600.jpg


Currently used/evaluated tools and sources to get the board up and running:

  • Free tools for ARM development (gcc-none-eabi toolchain, OpenOCD)
  • STM32CubeMX and sample code by ST
  • Code::Blocks as an IDE
  • Python with PySerial and matplotlib for scripting
  • SoX

More notes are collected here...


In the current test, every touch pad (13 in total) plays a sample stored in SPI flash. Reads it out, writes it to one of the two DMA buffers in RAM, and then the hardware moves the data (currently 8-bit samples at roughly 22 kHz -> trial and error tuning of TIM6) via DMA (double buffered) to the DAC and converts it there to an analog voltage.

(The code is a mess and has to be cleaned up. - I somehow like to go back to messy C coding, after spending lots of time with high level object oriented stuff, spending way too much time with plumbing and syntax cosmetics, making sure things are reusable and work everywhere. - Firmware can be messy I guess. Nobody cares when it works on the actual device. And there's only that specific hardware after all, so things will behave very deterministically. - However, that attitude will only work when things are tested out. It should be cleaned up, because I'm sure things will be tricky when I come back that project later... - Also, it makes sense to split things into files, use proper formatting, naming etc. Put things into functions... I've already hit the RAM limit of that tiny device by just putting in too many arrays into the spaghetti mess, causing the stack to overflow.. --- SO beware: this is only a proof of concept test, nothing more.

A word on STM docs and tools. Overall this STM32Cube tool is really useful generating the necessary initialization code and drivers (HAL) to work with. On the downside of that, I couldn't find any proper documentation on all the HAL functions, beside the comments in the source files and all the scattered ST example projects. That makes things quite annoying to work with. I actually really prefer to use those HAL functions instead of twiddling bits in all the registers myself. However, without proper documentation things feel more like a puzzle game in a cryptic world without a map. )

Cappaddy rev0.03 caseV4 DSCN1096.jpg

Tool: Serial Monitor

After using alway Processing to display serial data, I've discovered a nice python library to draw all kinds of plots and visualize data, called matplotlib. It proved to be useful to display very basic serial debug data in realtime, like the 13 TSC channel values here:


Cappaddy rev0.03 matplotlib 00a.jpg

Tool: Flash Downloader

In order to get data (audio samples) into the SPI flash on the board, the microcontroller has to play the middleman between the host PC and the flash. Things would be much easier with a standard SD card, but it was a fun exercise to get this working... The idea was, to make the microcontroller receive the data over UART, and send it down to the flash over SPI.

Again, Python is also a nice helper here to send out the sample data and talk to the hardware, using PySerial.

First, the samples have to be converted to raw 8-bit mono 22'050 Hz using SoX (later 12-bit samples should be used...), see below. Then the Python script takes the raw samples, and transmits the bytes in chunks of a certain size to the microcontroller, that is in flash programming mode. To keep the process error free, a CRC check on the received data and a verification of all written data to the flash is made. - First all that took quite a bit of time, and writing the full 16 MB of flash would have taken hours... But switching to the right flash programming commands (write flash pages (of 256 bytes) instead of single bytes for example), raising the serial baud rate to max 115200 and some other refinements took the programming time of a couple of kilobytes down to a reasonable point of a couple of seconds/minutes. - NOR flash memory has to be erased before it can be written (subsectors of 4K), and it is generally much slower to write to it, than to read from it. Since this has to be done only once to get the samples into the device it isn't really a problem. Reading from the flash afterwards goes surprisingly fast and is easier to do, as I had to find out...

All wav header data is stripped off the files before sending them out. Filename/identifier (8 characters), some info on the sample data (sample rate/depth) and most importantly the flash offset address is written to the first sector of the flash in table, in order to find the data later for playing it back...


The script can be started in the folder where the raw sample files reside while the board is listening in flash programming mode like that:

$ ./ -d /dev/ttyUSB0

serial 2 spi flash programmer started...
in< CMD_numbytes_chunk?:256
chunk size set to 256
in< CMD_nextfile?
current file (0): cartoon_0101.mp3_8bit_22050Hz_mono.raw
out> OK
in< ok
in< CMD_filename?
out> crtn0101
in< received filename: crtn0101
in< CMD_numbytes_total?
out> 0069C0 
in< number of bytes in file total: 0x0069C0
in< deleting flash subsector at 0x10000
in< flash subsector 1/7 deleted
in< deleting flash subsector at 0x11000
in< flash subsector 2/7 deleted
in< deleting flash subsector at 0x12000
in< flash subsector 3/7 deleted
in< deleting flash subsector at 0x13000
in< flash subsector 4/7 deleted
in< deleting flash subsector at 0x14000
in< flash subsector 5/7 deleted
in< deleting flash subsector at 0x15000
in< flash subsector 6/7 deleted
in< deleting flash subsector at 0x16000
in< flash subsector 7/7 deleted
in< CMD_bytespls?:256
[                                        ]
in< CMD_crc?
out_byte> 0xEC 
in< CRC OK!
in< writing 256 bytes to flash at 0x10000
in< CMD_bytespls?:256
[                                        ]
in< CMD_crc?
out_byte> 0xA8 
in< CRC OK!
in< writing 256 bytes to flash at 0x10100
in< CMD_bytespls?:256
[.                                       ]
in< CMD_crc?
out_byte> 0x89 
in< CRC OK!
in< writing 64 bytes to flash at 0x65900
in< CMD_complete?
out> OK
in< transfer complete
in< CMD_nextfile?
out> NO
in< finish
in< found flash snd entries: 13
in< sound entry: 0
in< ----------------
in< index: 0
in< name: crtn0101
in< byte_count: 0x6a00 (26.5000 KB)
in< start_address: 0x10000
in< sample_rate: 1
in< sample_depth: 0
in< sound entry: 1
in< ----------------
in< index: 1
in< name: crtn0104
in< byte_count: 0xe380 (56.8750 KB)
in< start_address: 0x17000
in< sample_rate: 1
in< sample_depth: 0
in< sound entry: 2
in< ----------------


Remarks / Conclusions

So far, all the used parts seem to work fine and I'd use them again.

There are still lots of issues that need to solved. For example, the SPI flash has some strange behavior when writing to it (write in progress flag keeps up). The STM32 TSC peripheral has not been tuned yet (very low res measurements), and the DAC playback sample rate was tuned by trial'n'error. There were some DMA underruns when switching samples fast... Some kind of debouncing/hystersis for the touch pads should be added, and the reading should be averaged to make play smoother... Volume control, dynamic fadeout, + other stuff.

The project is probably on halt for a while. Basic facilities are working now...


  • 1 huge sample + offset test
  • change playback rate (timer)
  • REX style loop player
  • loop samples + fadeout? loop points?
  • add button to change playback mode/preset etc.
  • add leds for feedback?
  • add pot / wheel for volume control
  • add audio jack for line out?
  • 1 pcb. 2 sided. touch pads and speaker and battery on it. CHEAP?
  • sd card instead of SPI flash?
  • resistive pads instead of capative?
  • capacitive pads: easy to breakout -> makey makey style? clips?
  • sequenced play. record?
  • case / touch pads: make completely new concept.
  • case: make wire hole bigger.
  • case: rubber material?
  • increase TSC resolution, tune it!
  • make 12bit version
  • add hysteresis for better play.
  • make play smooth. no stutters.
  • 1 time calibration?