Skip to content

Proto #5 Mercury 16

Andras Fuchs edited this page Apr 14, 2018 · 96 revisions

Mercury-16 will be a software-hardware combination to provide an 16-channel bio-potential reading.
If this prototype proves to be useful its extension to more channels would be fairly straightforward, so we could finally get closer to the Flat Detector Panel (FDP) implementation. This prototype will be implemented with Atmel's Xplained Kits. This allows us to make the development less painful and pave the road for the Mercury-64, which is going to have ATxmegas with its own PCB.

Hardware Components

1x Atmel-ICE programmer and debugger
3x ATxmega256A3BU Xplained Kit
4x 15cm long, 2x5 colored ribbon cables with IDC connectors with gold contact finish
2x 91cm long, 2x5 colored ribbon cables with IDC connectors with gold contact finish
1x Mini breadboard
6x 2x5 pin header
1x 65 jumper wire kit
3x A male to mini B male USB cable


Atmel XMEGA-A3BU Xplained

3 Atmel XMEGA-A3BU Xplained Kits


Development costs: $255 + $1 postage + $24 import tax (10%) + $18 VAT (7%)

New Equipment: $134

  • $134 - 1x ATATMEL-ICE (Tariff Code: 8471.50.0150 -> 40%-20%(WTO-10%) import tax)

New Materials: $121

  • $ 94 - 3x ATXMEGAA3BU-XPLD (Tariff Code: 8471.41.0150 -> 40%-20%(WTO)-10% import tax)
  • $ 5 - 4x H3CCH-1006M (Tariff Code: 8544.42.9090)
  • $ 5 - 2x H3CCH-1036M (Tariff Code: 8544.42.9090)
  • $ 3 - 1x 1597-1268 (Tariff Code: 8537.10.9150)
  • $ 3 - 6x S2021EC-05 (Tariff Code: 8536.69.4040)
  • $ 5 - 1x 377-2093 (Tariff Code: 8544.49.3080)
  • $ 7 - 3x AE1450 (Tariff Code: 8544.42.9090)

Fabrication: $94 + $12 postage + 27% VAT

  • $ 47 - 1x BBD proto#5 FPD rev A
  • $ 47 - 1x BBD proto#5 FPD rev B

Net cost per unit


2016-12-09 DigiKey #48722567 - Order Placed
2016-12-10 DigiKey #48722567 - Dispatched USPS Tracking #EC577797721US
2016-12-21 DigiKey #48722567 - Delivered


All of the XMEGA kits except one is called cell. The cell is a sensor-hub, so its function is to collect data from multiple sensors, connected to its ADC channels. The exception is called the organizer, which collects the data from the cells, organizes the data and sends it through its USB interface to the PC.
Every cell has 8 sensors and 1 emitter arranged in a 3x3 2D matrix. Cells can be daisy-chained, so the theoretical limit of cells depends only on the protocol.
Organizer speed is critical and since XMEGAs support only USB 2.0 it will mean a serious bottleneck.

Bandwidth bottlenecks

We generate 12 bit/sample data, 2 megasamples/second for every sensor. Every 8 sensors will be connected to one ATxmega64A3U, and all ATxmega64A3Us will be connected trough UART to ATxmega256A3U. The ATxmega256A3U will format and forward the data trough USB to the PC. The PC will compute the FFTs of the datastreams using the available CPUs or GPUs.

The clock speed for all the ATxmegas will be 32Mhz. If the speed is not enough, XMEGAs can be overclocked to 64-70Mhz, so it would double the speed.

Since every sensor generates 12x2048x1024 bits of data every second, and we are planning to have at least 8 sensors per cell, the data rate on the bus should be at least 192Mbps multiplied by the number of cells. That looks enormous.

On the other hand, a trick could be to compress the data what will be sent from the cell to the organizer. The 8 sensors of a cell will always be positioned close to each other, so their values will be similar in most cases. We could send the first sensors data as a 12-bit value, but after the next 7 sensors' data would be transformed to the 4-bit difference to its precursor. To compress the data even further, we could send only the sensor's value's difference from the previous one, represented with 4 bits.
According to my real-world tests however, these compression techniques would distort the data so much, that is would not really be useful.
Coming from the other end, let's assume, that we will use the USART's 16Mbps bus to send data from the cells to the organizer. Supposing that we will have a 15% overhead we have 13.6Mbps bandwidth to use. How many sensors can we connect to that bus at what sample rate?

  • cell count = (sensor / 8)
  • organizer's USART bandwidth = 13.6Mbps
  • cell's bandwidth = organizer's bandwidth / cell count
  • sensor's bandwidth = sample rate * 12 bit

So, we get the following:
13.6Mbps = sensor count * sample rate * 12 bit
sensor count = 1.13Mbps / sample rate

The MPCM's addressing protocol also sets a limit of 256x8 = 2'048 sensors per organizer, but that's obviously higher than the speed limitation we have.

Realistically the sensor density could be increased up until the 1 sensor/1 cm^2, so the total area scanned could reach 1040 cm^2, which is like a 32x32cm square.
If we would like to increase the covered area even more we need to keep in mind that the XMEGA's USB speed is also limited to 12Mbps, so it might be more wise to use an external USB (3.1, 10Gbps) chip and send the data to that from multiple organizers.

For this version though, the 2Mbps UART and the 12Mbps USB is more than enough, even if we don't compress the data on the cells.

Antenna designs

One of the most important parts of the system is its Flat Detector Panel. This FDP contains all the sensors (antennas) arranged as a 2D-matrix. Each sensor's signal represents one pixel of data.

PCB design of the Flat Detector Panel
Fabricated Flat Detector Panel

Software components

Serial Bootloader

Custom bootloader will be needed for the cells, because we want to refresh their firmware in-system, once they are installed on the board. This is a low priority now, can be postponed until Mercury-64.
Atmel AVR2054: Serial Bootloader User Guide, its images and source code and a more general article about bootloaders.


Two firmwares will be needed: one for the cells and one for the organizer.

USB driver

The previous prototype has a driver, but it uses the Atmel COM port emulation of the USB port. This method is not fast enough for the Mercury, so it must be rewritten to support native USB port handling.
In order to make this work, I need a kernel-mode driver, a user-mode dll, and a .NET wrapper.

Kernel-mode drivers:

  • WinUSB (v10.0.14393, 2016-07-16, winusb.sys, comes with Windows, supports Windows only)
  • libusbK (v3.0.7, 2014-04-27, needs installation, supports Windows only)
  • libusb-win32 (v1.2.6.0, 2012-01-17, needs installation, supports Linux, Mac OS X, BSDs)

User-mode DLLs:

  • libusb (v1.0.21, 2016-12-30, supports WinUSB, libusb-win32, libusbK)
  • WinUSB (v10.0.14393, 2016-07-16, winusb.dll, comes with Windows, supports WinUSB only)
  • libusbK (v3.0.7, 2014-04-27, supports libusbK only)

.NET Wrappers:

  • LibUsbDotNet (v2.2.8, 2010-10-29, wraps the newer libusb (libusb-1.0.dll), but it's incomplete)
  • libusbK (v3.0.7, 2014-04-27, wraps libusbK)
  • WinUSBNet (v1.0.2, 2016-02-14, wraps WinUSB)

The most commonly recommended USB library for .NET is LibUsbDotNet. but it's most recent version is 2.2.8, released on 2010-10-29.
The good news is though that the libusb - which is LibUsbDotNet is based on - is still maintained at its GitHub repo. The commits are recent, but the latest Windows binaries (v1.0.21) were built on 2016-12-30.
Libusb recommends to use libusbK which has C# support. Its latest version is 3.0.7 (2014-04-27).
To generate the Windows driver I will need the latest Zadig, its latest version is 2.2 (2016-01-22).
After collecting a lot of information about the project, I think I will go with the WinUSB + WinUSB + WinUSBNet combination, because that seems to be the faster route. If it doesn't work, then I switch to WinUSB + libusb + my own wrapper for libusb. (An issue was opened by me on GitHub to create a .NET wrapper for libusb.)

On the hardware side, I could use LUFA to send data through USB, but even its creator @abcminiuser recommends to use ASF's USB stack instead.

Since 2008 there is a USB Personal Healthcare Device Class (PHDC) standard, which is aimed for medical devices, so I should probably implement that.
Since 2011 Microsoft's driver supports WCID, which is only nice-to-have, but looks cool.
My own USB Vendor ID comes with an USB-IF membership, which costs $4000/year.

CPU and GPU FFT processor

FFTW is a C subroutine library for computing the discrete Fourier transform (DFT) in one or more dimensions, of arbitrary input size, and of both real and complex data (as well as of even/odd data, i.e. the discrete cosine/sine transforms or DCT/DST).
clFFT is a software library containing FFT functions written in OpenCL. In addition to GPU devices, the library also supports running on CPU devices to facilitate debugging and heterogeneous programming.
A C# wrapper will be needed to be written.

WAV and EDF/BDF generator

I wrote a RIFF WAVE generator for the previous prototype, and with a small modification it will work perfectly with this one.
EDF/BDF generator is a low priority for now, it would be useful only with EDFBrowser.


In order to spare as much development time as possible, connecting the Mercury to any well-developed open-source software might be a good idea.


Scilab is an open source, cross-platform numerical computational package and a high-level, numerically oriented programming language. It can be used for signal processing, statistical analysis, image enhancement, fluid dynamics simulations, numerical optimization, and modeling, simulation of explicit and implicit dynamical systems and symbolic manipulations.
I created a small script to analyze WAV data. Since I already had a WAV file generator for testing, it worked great with the generated data stream. The script isn't efficient at all, but at least it is good for basic testing.
Waveform, FFT and intensity display - SciLab


ParaView is an open-source, multi-platform data analysis and visualization application. ParaView users can quickly build visualizations to analyze their data using qualitative and quantitative techniques. The data exploration can be done interactively in 3D or programmatically using ParaView’s batch processing capabilities.
ParaView has awesome 3D presentation features, so it would be obvious to develop a solution where the data from Mercury would be fed to its rendering engine.
One possible way to achieve this is to use the OpenFOAM file format. Two readers are available: one is the built in PV4FoamReader of the paraFoam GUI and the other is a more optimized Parallelized Native OpenFOAM Reader for ParaView.
Another option is the VTK file format. There is a VTK C# library called ActiViz.NET which make the writing and reading of these files painless. There are many C# examples like the VTP file writer, and here are some example VTK files.
It turned out that the VTK file format is old and deprecated, there is a new XML-based VTS format for the newer ParaViews. Also the ActiViz.NET package isn't free anymore they charge 1800 EURs for that if you want to get the new version unless you compile it for yourself. This option would be alright, it the publicly available source of it would be updated to use the more recent MSVC compilers, but it doesn't. I contacted Kitware and their developers are working on that at the moment, but it's still not ready to make it work with VS2010 and above (because of the missing CastXML integration).
Because of these unfortunate developments, I decided to write my own VTS file writer and it works just fine.
Performing FFT in ParaView is also possible, there are two public methods for it: paraview.simple.TableFFT and paraview.simple.FFTOfSelectionOverTime. In this forum, there is also an sample implementation. Performance-wise the FFT in ParaView is much poorer than the FFTW library I use.
With all the challenges mentioned above, I finally was able generate a simulated 3D model animation. It also became clear that real-time streaming of the data isn't possible with ParaView 5.2, so it could be used only for post-event analysis.
3D model of FFT channels - ParaView


In order to be able to visually present the pre-processed raw data, we will need to generate a file format which is accepted by Gerbil. The candidates are PNG and TIFF, both lossless. They can be combined in Gerbil as a hyperspectral snapshot image. As a low priority feature it would be also great to generate an x265 MP4 in a specific frequency range. FFmpeg might be our friend here.

BBD Interface

Bio Balance Detector Interface is a basic, console application. It is able to display the output of the driver, so it's well suitable for testing.
It has a view different views and filters. In the following samples I touch the sensors and the view show the changes accordingly.

Waveform View:
Waveform view

Spectrum View:
Spectrum view

Matrix View:
Matrix view

Xplained Kits in Action

The organizer is sending data to and receiving data from the slaves.
BBD Mercury-16 in organizer mode



  • Stage #1 - Generator test
    • Sin wave generator
    • WAV file writer
  • Stage #2 - Connectivity
    • SciLab WAV reader
    • ParaView VTS file writer
  • Stage #3 - FFT
    • FFTW filter
    • Moving average filter
  • Stage #4 - ADC data from Mercury
    • Send raw data from ADC
    • Accept and reply to commands from PC
  • Stage #5 - Real-time visualization
    • VisualOutput console implementation
    • Lab streaming layer (LSL) output
  • Stage #6 - Multiple cells
    • MPCM USART communication between cell (sensor-hub) and organizer
    • ChannelMapper on the organizer
  • Stage #7 - Interactive parameters
    • Change sample rate on-the-fly (1k to 2M sps)
    • Change bit rate on-the-fly (8 bit, 12 bit, 16 bit oversampling)
    • Change channel number on-the-fly
    • Change channel arrangement on-the-fly
    • Change FFT size on-the-fly

Net hours

Data workflow

3x3 sensors for every cell (XMEGA Kit or ATxmega64A3U) >-- 12-bit signed int ADC data trough UART --> organizer (XMEGA Kit or ATxmega256A3U) >-- 16ch x 16-bit signed int data through USB --> PC USB driver (WinUSB or libusb) >--> BBD Driver

The BBD Driver is capable of using filters and redirect its output to several channels (even at the same time).

The following units are implemented:

  • Sources (hardware and software inputs)
    • Software sine wave generator
    • BBD 8x8 Matrix input (Proto#4)
    • BBD Mercury-16 input (Proto#5)
  • Filters (data manipulation algorithms)
    • Bypass filter
    • Fill filter
    • Moving average filter
    • FFTW (CPU) filter
  • Outputs (file, visual and stream outputs)
    • WAV file output
    • ParaView VTS file output
    • Visual output (console)
    • Lab streaming layer (LSL) output
    • PNG series for Gerbil



Electromagnet tests @ KIBU 2017-11-21

The signal generator used is a RIGOL DG1032 with 5Vpp and the Oscilloscope is a RIGOL DS1074.
KIBU workbench

Coil A: Murata Power Solutions Inc 330UH 780MA 215 MOhm
Coil B: Bourns Inc. 470UH 140MA 6.5 Ohm TH
Coil C: Bourns Inc. 330UH 540MA 850 MOhm
Coil D: Murata Power Solutions Inc 330UH 2.8A 150 MOhm
Coil E: Sumida America Components 680UH 650MA 1.1 Ohm TH

Coil A Coil B Coil C Coil D Coil E
100 Hz N/A < 0.5% < 0.5% < 0.5% 1%
1 kHz N/A 2% 2% 3% 6%
10 kHz N/A 15% 20% 25% 60%
100 kHz N/A 100% 170% 200% 250%


These electromagnets will be not good as low frequency emitters, I need to find some other types, if I insist on having an emitter (for different treatments).

Antenna tests @ 2018-04-05

I've tested the different antennas of the Flat Panel Detector rev. B.
All tests were made at the same location, measuring the background noise only. The MCU run @ 48Mhz, ADC @ 93kHz in a burst mode @ 4kHz, 12bit with an internal reference of 1V and 8x gain. The driver applied a normalization on the 3-second buffer, didn't use averaging, but it used a 10x signal gain. The values below are the 3-second-averaged peak-to-peak values displayed by the BBD Driver.

2D sensor list

The 3D antennas are:

  • H: 2x20 cm long, thin aluminum wires (without insulation)
  • I: 2x20 cm long, copper wires (without insulation)
  • J: 20 long, thin aluminum wire loop (without insulation)
Sensor / antenna ADC channel Measurements (avg, min-max)
Disconnected 00 0.0400, 0.0391 - 0.0421
Disconnected 01 0.0440, 0.0421 - 0.0470
Disconnected 02 0.0427, 0.0391 - 0.0452
Disconnected 03 0.0429, 0.0385 - 0.0458
Disconnected 04 0.0357, 0.0348 - 0.0366
Disconnected 05 0.0362, 0.0330 - 0.0390
Disconnected 06 0.0717, 0.0659 - 0.0799
Disconnected 07 0.0488, 0.0427 - 0.0519
2D sensor A (P01-01) 00 0.1887, 0.1654 - 0.1941
2D sensor A (P01-02) 00 0.1949, 0.1862 - 0.2033
2D sensor A (P01-03) 00 0.1935, 0.1697 - 0.2094
2D sensor B (P01-04) 00 0.1819, 0.1666 - 0.1960
2D sensor C (P04-03) 00 0.2103, 0.1776 - 0.2301
2D sensor C (P05-03) 00 0.2226, 0.2002 - 0.2318
2D sensor C (P06-03) 00 0.2162, 0.1934 - 0.2240
2D sensor D (P04-04) 00 0.2167, 0.2045 - 0.2318
2D sensor D (P05-04) 00 0.2184, 0.1898 - 0.2350
2D sensor D (P06-04) 00 0.2124, 0.1807 - 0.2277
2D sensor E (P07-03) 00 0.1919, 0.1691 - 0.2026
2D sensor F (P07-04) 00 0.1684, 0.1648 - 0.1721
2D sensor G (P10-03) 00 0.1790, 0.1520 - 0.2051
2D sensor G (P10-04) 00 0.2017, 0.1923 - 0.2063
3D sensor H decoupled 00 0.2263, 0.2198 - 0.2344
3D sensor H coupled 00 0.2332, 0.2064 - 0.2441
3D sensor I decoupled 00 0.2552, 0.2436 - 0.2673
3D sensor I coupled 00 0.2986, 0.2637 - 0.3320
3D sensor J coupled 00 0.2225, 0.2063 - 0.2368
2D sensor C (P04-01) 00 0.0756, 0.0696 - 0.0781
2D sensor C (P05-01) 01 0.1068, 0.0952 - 0.1098
2D sensor C (P06-01) 02 0.0755, 0.0720 - 0.0787
2D sensor C (P04-02) 03 0.0618, 0.0586 - 0.0641
2D sensor C (P05-02) 04 0.0802, 0.0708 - 0.0873
2D sensor C (P04-03) 05 0.0931, 0.0903 - 0.1025
2D sensor C (P05-03) 06 0.1162, 0.1056 - 0.1196
2D sensor C (P06-03) 07 0.0848, 0.0800 - 0.0922


The final goal should be the have a 3D printed copper antenna at each ADC input. Since it's difficult and expensive to pull off, the spiral 2D sensor will be the best option to go on with the testing.
There was a error during these measurements when measured the 2D sensors, because the 3D copper antenna was attached and modified the quality of the 2D sensors. The copper antenna should be removed first, and do these tests again.
Important conclusion that the ADC channels have different sensitivity, so we'll need to correct the measured values according to that.
Copper and silver have very good resistance properties: if silver has an electrical resistivity of 100% given they have the same length and thickness, copper has 105.6%, annealed copper has 108.2%, gold has 153.5%, aluminum has 166.7%, zinc has 371.1%, nickel has 439.6% and tin has 685.5% of that resistance. Brass (copper+zinc) and bronze (copper+tin+(aluminium, manganese, nickel or zinc)) are copper alloys so their properties can be good, but we need to know the exact ratios.

Shapeways' 1.5cm Merkaba is available in the following conductive materials:

Material Alloy ratios Relative conductivity Price
Raw silver 100% silver 100% 24 USD
Raw brass 15% zinc, 5% tin, and 80% copper ~35-40% 15 USD
Raw bronze 10% tin and 90% copper ~45% 15 USD

Antenna tests @ 2018-04-06

After I removed the aluminum and copper antennas, I re-did the following measurements.

Sensor / antenna ADC channel Measurements (avg, min-max)
2D sensor A (P01-03) 00 0.1632, 0.1563 - 0.1746
2D sensor A (P02-03) 00 0.1895, 0.1697 - 0.2051
2D sensor A (P03-03) 00 0.1919, 0.1819 - 0.2014
2D sensor B (P01-04) 00 0.1536, 0.1392 - 0.1770
2D sensor B (P02-04) 00 0.1798, 0.1556 - 0.2020
2D sensor B (P03-04) 00 0.1943, 0.1739 - 0.2130
2D sensor C (P04-03) 00 0.1968, 0.1710 - 0.2154
2D sensor C (P05-03) 00 0.1992, 0.1800 - 0.2136
2D sensor C (P06-03) 00 0.1957, 0.1813 - 0.2038
2D sensor D (P04-04) 00 0.1944, 0.1703 - 0.2057
2D sensor D (P05-04) 00 0.1795, 0.1482 - 0.2179
2D sensor D (P06-04) 00 0.2023, 0.1953 - 0.2082
2D sensor E (P07-03) 00 0.2039, 0.1758 - 0.2142
2D sensor E (P08-03) 00 0.1964, 0.1758 - 0.2050
2D sensor E (P09-03) 00 0.2172, 0.1733 - 0.2484
2D sensor F (P07-04) 00 0.1937, 0.1813 - 0.2124
2D sensor F (P08-04) 00 0.2023, 0.1892 - 0.2063
2D sensor F (P09-04) 00 0.1893, 0.1814 - 0.2063
2D sensor G (P10-03) 00 0.2102, 0.1759 - 0.2246
2D sensor G (P10-04) 00 0.2023, 0.1764 - 0.2106


Even I kept the panel at the same spot, the channels had cross-over. It looks like that the hardware designs main challenge will be the separation of these weak signals until they reach the ADC. This means that the wires to the ADC must be as short and as thick as possible, and all of the wires must be thoroughly isolated from each other while their lengths should be exactly the same.
Side note: with the x8 MCU gain, x10 driver gain and 1V reference the value range of -1.0 and +1.0 the measured values show that we are measuring (1000 mV / 80 * (0.2100 - 0.1700)/(2.0)) = 0.25mV peak-to-peak changes.

Open questions

  • Is (a bandgap) DAC usable as an AREF to ADC?
  • Is signed, differential ADC usage possible? Which pins can be used reference points? -> (possible negative inputs: ADCA0-3, ADCB0-3)


  • AREF is needed
  • individual analog filtering is needed for the channels
  • DAC for emitter on cell
  • 6 pins between cells (VCC, GND, TXD, RXD, SCL, AREF)
  • run Goertzel algorithm on cell
  • bandwidth is a strict limitation
  • XMEGA64A4 might be not enough for the cell, so XMEGA256A4 would be better
  • USB throughput is around 750 kb/s (High Speed is not supported by XMEGA)
  • PHDC might be good later, but not critical at the moment
  • GPU FFT might be not needed
  • hardware design principles: short, thick, fixed sized wire from sensor to ADC
  • 12bit ADC with 1V is not sensitive enough even with the x8 gain
You can’t perform that action at this time.