A Near-Ultrasound (NUS) Data Link

We were requested to investigate “near ultrasound” (NUS) links as part of our research on developing the Simmel reference design for a privacy-preserving COVID-19 contact tracing device. After a month of poking at it, the TL;DR is that, as suspected, the physics of NUS is not conducive to reliable contact tracing. While BLE has the problem that you have too many false positive contacts, NUS has the problem of too many false negatives: pockets, purses, and your own body can effectively block the signal.

That being said, we did develop a pretty decent-performing NUS data link, so we’ve packed up what we did into an open source reference design that you can clone and use in your own projects.


Top trace: demodulated data at 1 meter, 50dB background noise. Bottom trace: raw signal, normalized so it is visible. Without normalization the trace just looks like a flat line.

I imagine one use for this would be a way to provision IoT devices: the “how do I get wifi credentials into an IoT device that lacks both screen and keyboard?” problem. With the addition of a ~$1 microphone to a Cortex-M4 class device, you get a short-range data link to a host device, such as a phone. You can use a web page (via Javascript) to generate the modulated audio directly (relevant example), thus bypassing a host of multi-platform issues, or you can generate a file off-line and send it to any standard music player.

The TL;DR on the link is it uses a 20,833Hz carrier modulated with BPSK. We use PSK31 coding, so our baud rate is ~651 symbols per second (this is the 1/0 symbol rate before Varicode encoding). This isn’t breaking any speed records, but it’s good enough to send a UUID and some keys over the air in a couple seconds. Tests show decent performance over a distance of 1 meter with about 60dB ambient noise (normal conversation or background music playing at the same time).

The demodulator uses a Costas loop. We’ve documented its details, including comments on porting to other chipsets than the NRF52.

We also have a reference modulator using a non-linear transducer (e.g. a piezo element), which uses some of the more advanced features of the NRF52 PWM block to eliminate audible sidebands. We also have a rough C program to generate a .wav file, which needs to be run through a high-pass filter using e.g. Audacity to eliminate the low-frequency modulation sidebands; but the resulting .wav file can be played directly on your smartphone and it will demodulate correctly.


Acknowledgements: Sean ‘xobs’ Cross is an equal contributor to this research. This research is funded through the NGI0 PET Fund, a fund established by NLnet with financial support from the European Commission’s Next Generation Internet programme, under the aegis of DG Communications Networks, Content and Technology under grant agreement No 825310.

4 Responses to “A Near-Ultrasound (NUS) Data Link”

  1. Japree says:

    Will you publish the schematic ?

  2. willmore says:

    As a ham, some of what you said was confusing. Specifically “We use PSK31 coding, so our baud rate is ~651 symbols per second”. PSK31 uses 31 baud. You’re using PSK651. ;) It just call it a PSK31 *like* coding.

    I need to look at your PSK modulation code to see why you need a high pass filter. Last time I had to generate PSK in real time, I had an interupt driven loop which ran a DDS and multiplied it by a sample of the baseband waveform generated from the main loop of the program. The resultant value was stuffed into an ouptut port and into an attached R2R ladder. The next variant used PWM as an output much like your design does. I need to look at your code for that as well. There’s a number of tricks you can use to reduce side bands and other modulation artifacts. I assume you’re using phase correct PWM ouptput modes, but I’ll go check.

    This is a really cool project. You might want to reach out to the MEGA65 people as they’re doing something similar: https://c65gs.blogspot.com/2020/06/ultrasonic-communications-for-mega65.html

    • bunnie says:

      Thanks for the clarification. Yes, we modified PSK31 to fit our parameters, so it’s not actually PSK31. However, wasn’t quite sure what the proper descriptive name of such a coding scheme would be other than describing it as BPSK with Varicode? I think “PSK31-like” is a good suggestion that calls out the fact that it’s a derivative work.

      The initial modulator code is really naive, it just takes a sine wave and abruptly inverts it based on the symbol input. It’s not how you’re “supposed” to do it, but also, our actual transducer is a piezo device that only has two states (on and off), so any modulation technique that requires more than 1 bit of resolution isn’t going to work. So, we just wrote a naive modulator to do some initial link feasibility tests, and focused more of the effort on ironing out the kinks in the PWM modulator.