Tag Archives: Ultrasound

Ultrasonic Communications Link

After finishing the Software Defined Radio project, I really wanted to play around with the other side of the data chain, mainly, signal generation. I’m by no means an RF designer, I know a little about antennas and transmission lines and even if I could design a transmitter I’m not at all clear about all the laws and regulations surrounding amateur RF transmissions. So instead of an electromagnetic based transmitter, I decided to stay more in my comfort zone and implement an ultrasound based communications link. I wanted to create a signal that could be amplified and played on an ultrasound transducer, transmitted through water, and received by a second transducer for demodulation. Specifically, I wanted to use an FPGA to take in a baseband audio signal, modulate it onto a passband signal and then use a digital-to-analog converter to synthesize the signal. This post will describe the system I ended up using and some of the results and data I collected.

System Overview

I again chose to use the Virtex 5 as the FPGA. Two main reasons, the first was the gigabit ethernet connection available with this evaluation board. I’ve used a number of USB modules to transfer data to and from an FPGA, and there is no real comparison to the flexibility and speed offered by the GbE connection. The other reason was an old prototype board made by a labmate of mine, Dalong Liu. He was investigating an arbitrary waveform generator awhile ago and created a prototype board for the Max5858. There is actually a third reason and that’s the DSP48 slices. These allow for very efficient implementation of many DSP operations. The virtex-5 sx50t which I used here has 288 DSP48 slices. For a single channel application such as this, this many DSP48 slices is more than enough.

The Max5858 is a dual-channel, 300 MHz, 10-bit DAC . It is a fairly sophisticated DAC, it allows for 2x, and 4x onboard interpolation and can multiplex the channels to save on IO pins. I used the DAC in the multiplexed configuration with 4x interpolation enabled. This allowed me to clock data into the DAC at 50 MHz while still sampling the output at 200 MHz. The output was fed into a linear amplifier and sent to a high power ultrasound transducer with a center frequency of 2.5 MHz. This was sent across a water tank to a hydrophone that was connected to the SDR system described in the previous post.

You can see the water tank setup below. The transmitting transducer is highlighted in blue and the hydrophone is highlighted in green. These were spaced about 20 to 30 centimeters apart.
Transmit and Receive Tank Setup

Data Download

The first issue in this system implementation is just getting the data down to the FPGA. I’m dealing with many different data rates. There is the rate at which data is generated, the rate at which data is transferred, and the rate at which data is played out. If the rate at which data is generated does not match the rate at which data is played out, then some decimation or interpolation will be required. Even if the rates are supposed to be equal, they will almost certainly not be EXACTLY equal. This can cause you to, eventually, gain or lose a sample unexpectedly. This is a major issue in high speed serial links as well.

In order to deal with this issue, I created a 32K FIFO on the FPGA. This FIFO took in 16 bit data from the CPU on one side, and dispensed the data to the modulation cores on the other. The data was dispensed at a software adjustable rate depending on how the data was created. For most of the results I present here, I used a 25 ksps or a 50 ksps data rate.

To begin, I would allow the FIFO to fill with a thousand samples and then enable the modulation core to begin removing samples from the FIFO. I separated occupancy of the FIFO into a number of zones, an underflow warning zone, an all clear zone, and an overflow warning zone. As the occupancy transitioned these zones, a UDP packet would be sent to the CPU alerting to this transition. These packets allowed the CPU to perform its own flow control. So once the modulation core had removed enough samples to move the FIFO from the all clear zone to the underflow warning zone, a message would be sent back to the CPU and the CPU would stream additional data down to the FPGA to push it back into the all clear zone.

I was fairly generous in the limits of these zones. Latency wasn’t a big issue for me here so I was more than willing to pad the zones to ease the response time needed by the CPU. I ended up calling anything under 1024 samples the underflow warning zone, and if I had only 1024 free spaces left in the FIFO, I would call this my overflow warning zone, everything else was the all clear zone. The figure below shows the FIFO arrangement along with the UDP packets transmitted at each transition. In the extreme case that I actually did suffer a buffer underflow or overflow, I would transmit this information back to the CPU as well. Though in practice this never happened.

FIFO Diagram with status updates

This scheme worked very well and was able to stream data down to the FPGA continuously. For these experiments I used wav files and would have a server just wait for the request for data packet before transmitting down the next 1600 samples. If I were to incorporate a live signal source such as a microphone I would need to add some additional flow control on the host side, but the FPGA side could remain untouched.

AM Modulation

AM modulation is relatively straightforward to implement on the FPGA. A diagram of the system is shown below along with the data types and widths I used at each stage. The generic form of an AM modulation signal is: (0.5 + m(t))*sin(2*pi*fc), where m(t) is the message signal. I was able to save myself the bother of adding my message signal onto a constant 0.5 by using the trick that you can convert a two’s complement number (which my message was stored as) into an offset binary number by just inverting the most significant bit. This offset binary signal is then multiplied with a carrier wave generated by a Xilinx DDS core. I added one addition scaling step at the output so I could easily vary the amplitude of the signal.

FPGA AM Modulation Implementation

To test this AM modulating system I connected the DAC output directly to the ADC on the SDR, and instead of decimating and retrieving the IQ data as I normally do, I sampled at 20 MHz and streamed the data directly back to the computer for analysis.

Below you can see a Middle C tone (~261.6 Hz) modulated onto a 1 MHz carrier. I believe for this particular test I used about 95% modulation.

1 MHz Carrier Modulated with a Middle C Tone

I sampled the envelope of this signal at 25 ksps and below you can see the result of this quantization. The envelope level only changes every 40 us resulting in the staircase appearance of the signal.

Quantized AM Envelope

Below you can see the spectrum centered around the carrier, with the single frequency sidebands on either side.

AM Spectrum at Carrier

Of course, sampling any signal introduces copies of the spectrum at integer multiples of the sampling frequency. In the spectrum below you can see the replicated spectrums at 25 KHz intervals. This is a sample and hold scheme, which should attenuate the spectral images in a sinc like manner. You can see this in the attenuated images the further you move away from the carrier frequency.

Images due to Sampling the Envelope

The close up of the first replica shows what we would expect, both sidebands without a carrier. What’s really needed here is a final bandpass filter on the output to pass only the carrier and sidebands and eliminate all the spectral images.

First Image

This simple test verified that the system was work as expected and I moved onto implementing the FM modulator.

FM Modulation

I’m essentially using a direct FM generation technique to create the FM signal. The amplitude of the incoming signal directly modulates the carrier frequency. The nice thing about doing this in the digital realm is that I have complete control over the frequency deviation. I am not limited by the linear range of a varactor diode to control the carrier frequency.

You can see in the system diagram below, I scale the incoming audio signal to directly control the frequency deviation of the FM modulation. The numerically controlled oscillator is driven at 50 MHz with a 32 bit frequency word. This introduces a frequency scaling of 50e6/2^32 (~0.0116) on the incoming signal. A maximum amplitude signal (+-32767) would create a frequency deviation about the carrier of only ~381 Hz. This is relatively small. The scaling factor between the FIFO and the numerically controlled oscillator allows this frequency deviation value to be increased at my discretion. The output of this multiplier is added on to the static carrier frequency to form the input frequency word to the oscillator. Just like the AM modulator,  the data stream is run through one last scaling unit to allow control over the output amplitude before being presented to the DAC.

FPGA FM Modulation Implementation

The design philosophy behind both the AM and the FM modulator is that the host should not have to modify its data based on the type of modulation performed on the FPGA. The host can stream the 16 bit, signed data down to the FPGA in the same manner for both FM and AM modulation. This ability allowed me to test the FM modulator with the same data as the AM modulator, the Middle C tone.

Below you can see the spectrum for a the Middle C tone with a modulation index of 5.8 (i.e. the frequency deviation divided by the sinusoidal message frequency). The spectrum of an FM signal modulated by a sinusoid has a close form solution which consists of a summation of sinusoids weighted by bessel functions of the first kind. I’ve placed black dots on the spectrums below that show the ideal magnitude of these spectral components based on the modulation index used.

FM Spectrum Sinusoid, Modulation Index 5.8

As we increase the modulation index, the bandwidth used by the system increases. There is a very simple way to estimate the bandwidth used by an FM signal, it’s called Carson’s Rule. This says that the bandwidth of an FM signal can be approximated by the expression 2(Fd + Fm) where Fd is the frequency deviation and Fm is the maximum frequency content in the message signal. In the previous case, the frequency deviation was approximately 1,526 Hz which, according to Carson’s rule would give a bandwidth of about 3.6 KHz. For the case below we would expect a bandwidth of twice that, 7.2 Khz. Keep in mind that these bandwidths include both the upper and the lower sidebands, while these plots show only the upper sidebands. It’s clear that while Carson’s rule correctly estimates where the power is contained, there are significantly spectral components outside this bandwidth.

FM Spectrum Sinusoid, Modulation Index 11.6


The overall system ended up working quite nicely. I was able to transmit voice and music with both AM and FM. It was a bit of a shock after I set everything up and turned on the amplifier to hear my own voice coming out of the speakers on the receivers. I was not expecting everything to work on the first try. I ended up testing both voice and music transmissions. All results here used a 3.5 MHz center frequency for the modulation. I recorded my own voice for the voice transmissions and used a song from a Flaming Lips CD I had laying around for the music.

Voice Transmission

The voice transmission consisted of me saying, “This is a test, 1, 2, 3 ,4 over.” The initial tests consisted of a simple loopback test to guage to the quality of the direct connection. I tested carrier frequencies from 1 Mhz to 10 MHz and was able to hear no difference in performance between any of the carriers.  So I then moved to the real thing, transmitting the audio through the ultrasound transducers.

The figure below shows the demodulated signal received on the hydrophone. The demodulation procedure was very straightforward. I used Matlab to first find the envelope of the signal, isolated the segment corresponding to my voice and removed the D.C. bias. This can be performed with a single line of Matlab code: Audio = detrend(abs(hilbert(Signal))); Here Signal contains the modulated voice, and Audio is the demodulated audio signal shown below. You can listen to the demodulated signal AM signal here.

AM Voice DemodulationAs I explain in the SDR post, the data is collected as IQ baseband. This is kind of interesting for an AM signal, since if all frequencies were exactly correct, we would demodulate the AM signal simply through the IQ demodulation. The AM modulation process multiplies a message signal by a carrier, just like the IQ process multiplies the incoming signal by a carrier. If the modulation carrier and the IQ carrier were at the exact same frequency, they would cancel each other out (minus some dc bias term due to any phase different). However, as you can see in the figure below, the IQ data still has a sinusoidal modulation, even though the IQ demodulator was tuned to the same frequency as the AM modulator. Why is this? Because the oscillators used to generator the AM signal and the IQ signal are not perfect. Theses tiny differences lead to the sinusoidal modulation seen here. The red represents the real part of the signal and the green represents the imaginary.

IQ Voice SignalThe figure below is just a close up few of the IQ data. You can see that the two frequencies are not off by much, only about 11 to 12 Hz.

Close Up IQ Voice SignalAfter the success of the AM modulation I was anxious to try out the FM modulation. Here again, the demodulation was done with Matlab. I used what amounts to the following line of code to demodulate the signal, Audio  = diff( unwrap( atan2( imag(Signal), real(Signal) ) ) ); This uses the atan2 function to calculate the angle of the frequency phasor. I remove the 2 pi discontinuities with the unwrap function, and then isolate the message signal with the diff command (i.e. takes the difference between neighboring elements in the series). Below you can see the demodulated FM signal and you can listen to that signal here.

Demodulated FM Voice Signal

For those who are interested in playing around with the demodulation here are the modulated AM Voice and FM Voice wav files as received by the hydrophone.

Music Transmission

The voice transmissions were nice and I was very happy they worked, but it didn’t provide a very vibrant signal to test the quality of the link, for that I relied on some music. I band limited the music to 5 KHz and setup the CPU data server to stream the music continuously down to the FPGA for easy testing.

Below you can see the received spectrum for the AM signal. You can seen a nice peak at the carrier with the audio contained nicely within +-5 KHz. You can listen to a segment of this audio here.

AM Music Spectrum

The final test I did was to use the FM modulator to transmit the music. For this I used a modulation scaling factor of 8. This scaling factor gives a max frequency deviation of 3 KHz for a maximum amplitude signal. You can listen to the demodulated FM signal here.

For all the transmission tests attempted, the audio quality was so nice I really wished I had a larger tank and a more dynamic environment to test out the communications link. I think it would be frowned upon if I brought the FPGAs and transducers over to the campus natatorium, so I tried to create my own forms of interference.

The first thing I did was to physically remove the hydrophone. You can listen to that here. Obviously, once the hydrophone was removed we lost all transmission, but when it was placed back in you begin to hear the audio again.

The other thing I tried was creating bubbles between the source transducer and the hydrophone. I wasn’t able to create a wall of bubbles, but I was able to create a decent stream. You can really hear the effect these had on the audio quality, FM Music with Bubbles

Future Work

I would really like to try and expand this communications link to incorporate data transfer. I’d like to explore some spread spectrum modulation techniques on the FPGA. This FPGA has a lot of reserve power so I could potentially implement some DSP intensive algorithms. This sort of a setup could be a challenge at high data rates since the ultrasound will bounce around for awhile allowing for significant multipath interference.