Dead Simple Ultrasonic Data Communication

Some of the best hacks are the ones which seem perfectly obvious in hindsight; a solution to the problem that’s so elegant, you wonder how it never occurred to you before. Of course we also love the hacks that are so complex your eyes start to water, but it’s nice to have a balance. This one, sent in by [Eduardo Zola] is definitely in the former group.

In the video after the break, [Eduardo] demonstrates his extremely simple setup for using ultrasonic transducers for one-way data communication. Powered by a pair of Arduinos and using transducers salvaged from the extremely popular HC-SR04 module, there’s a good chance a lot of readers can recreate this one on their own bench with what they’ve got lying around. In this example he’s sending strings of text from one computer to another, but with a little imagination this can be used for all sorts of projects.

For the transmitter, the ultrasonic transducer is simply tied to one of the digital pins on the Arduino. The receiver is a bit more complex, requiring a LM386 amplifier and LM393 comparator to create a clean signal for the second Arduino to read.

But how does it work? Looking through the source code for the transmitter and receiver, we can see it’s about as basic as it gets. The transmitter Arduino breaks down a given string into individual characters, and then further converts the ASCII to eight binary bits. These bits are sent out as tones, and are picked up on the receiving end. Once the receiver has collected a decent chunk of tones, it works through them and turns the binary values back into ASCII characters which get dumped over serial. It’s slow, but it’s simple.

If you’re looking for something a bit more robust, check out this guide on using GNU Radio with ultrasonics.

9 thoughts on “Dead Simple Ultrasonic Data Communication

    1. Not just unidirectional; this could be used for half-duplex comms, since it looks like it doesn’t transmit anything unless there’s something in the serial port buffer to send. You just need to switch to receive mode (and run the receiver loop) until something shows up on the Arduino’s serial input port. It should even be possible to use the same transducer for transmit and receive, just by setting the output pin to high-Z when receiving. Just one more I/O pin for the output from the LM393.

  1. You should also be able to replace the ultrasonic transducers out for an LED & phototransistor and have this work with light. The first IR TV remotes replaced ultrasonic remotes this way, and I understand that’s why we have the 38kHz carrier that is common on IR control signals.

    1. Just one concern: I think the receiver code doesn’t discriminate between frequencies at all – I think it relies on the transducer itself for tuning. This wouldn’t be the case for a phototransistor, so it might be susceptible to interference from other light sources such as fluorescent lamps. However, I seem to recall reading in a HaD article that the commonly used IR receiver module used in TVs somehow only detects a carrier close to 38 kHz, so if you got some of those, it might work without any other modifications beyond changing the carrier frequency to 38 kHz. Here it is: If you really want to use regular photodiodes, it also might be within the Arduino’s capabilities to detect the signal with a certain amount of selectivity, but that’s hardly a simple modification of the code. What COULD be a simple modification, though, is to put an LC band-pass filter between the amplifier and the comparator, which is kind of what those TV IR receivers do.

  2. So, what you’ve got there is an Arduino being used as a modem. Excellent. How does it encode the bits? Looks like pulse width modulation of a carrier, of sorts – it doesn’t use the width of the modulated pulse, but the width of the time between pulses, which is just inverted PWM.

    My first thought was, this would be great for sending remote control signals to a model submarine. Peter Sripol built a submarine out of a toaster, which he demonstrates in fresh water using a regular RC radio. He claims it will work in salt water, too, but I believe he means the mechanical portions of it; I seriously doubt that an RC radio signal will get through more than an inch or two of seawater.

    But if we were going that way, RC transmitters use modulated pulses of widths varying from 1 to 2 ms, which at 40 kHz would be between 40 and 80 cycles of carrier – plenty enough to be able to detect while rejecting out-of-band noise. So this might be another application for the same hardware and only slightly different code.

    Looking at the receiver side, though, maybe I’m reading it wrong – I’m not that familiar with the Arduino library – but it doesn’t look like any detection of the 40 kHz carrier is being done. Possibly the bandwidth of the transducer itself is what rejects out of band noise. But anyway, it looks to me like it would be even easier to code it to generate servo pulses.

  3. The RX code just counts how many ones there are in a 10ms time span using digitalRead() (which takes 3.6us to execute, according to the Internet). Well, it’s simple, it works, data gets transmitted, client gets happy, developer gets money for new gadgets…
    (I’m not the author nor am I related to him in any way)

Leave a Reply

Fill in your details below or click an icon to log in: Logo

You are commenting using your account. Log Out /  Change )

Google+ photo

You are commenting using your Google+ account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )


Connecting to %s

This site uses Akismet to reduce spam. Learn how your comment data is processed.