I wonder if it'd be a relatively straightforward exercise to read data from a 3.5mm audio jack using an Arduino and a raspberry pi. The communication will be one-way only: raspberry pi transmits data to Arduino, so the Arduino will do the reading. Does anyone know how this could be accomplished without using a modem?

  • 1
    \$\begingroup\$ You're going to use the audio interface or are you planning on wiring the jack to some pins on the Raspberry? In the later case you could use just about any communication protocol. \$\endgroup\$
    – Arsenal
    Sep 30 '16 at 9:43
  • \$\begingroup\$ @Arsenal I'm hoping to use just the audio jack (TRRS). \$\endgroup\$
    – John M.
    Sep 30 '16 at 11:29
  • \$\begingroup\$ I think that audio jack is highly prone to be contaminated with fatty dirt by your hand, resulting in conducting problems. \$\endgroup\$
    – Ayhan
    Sep 30 '16 at 12:30
  • \$\begingroup\$ @luchador the audio jack is probably the least likely of all the connectors on the RPi to be contaminated in that way, since it's designed for use in consumer devices that are carried around indoors, outdoors, in pockets and frequently plugged/unplugged. \$\endgroup\$ Sep 30 '16 at 15:02
  • \$\begingroup\$ Is it stereo or mono? If mono, I think FSK should work. I don't think it would matter whether your output is a square wave or a sine wave. Use zero crossing interval to estimate frequency. If you only have mono, the receiver will have to somehow keep in sync with the transmitter. There is a lot to this but I am sure it can be done. If it is stereo, you can basically use one channel as a "clock" and the other as a "data" line. Even if the receiving end is an ADC, this can be decoded pretty easily from the data stream. \$\endgroup\$
    – mkeith
    Sep 30 '16 at 15:48

The other answers seem to involve using 3.5 mm jacks and an audio cable just to carry a typical serial digital signal from the Raspberry Pi GPIO ports: e.g. wiring asynchronous serial, SPI or I2C to a dedicated external 3.5 mm jack which is not the audio jack on the Pi.

I interpreted the question more along the lines "can I transmit digital data to a microcontroller using the Raspberry Pi audio output"

Yes, but it gets more complicated. The raspberry pi audio output looks like this:

Two pulse-width modulated (PWM) square waves are produced by the Broadcomm SoC (off screen), and are then low-pass filtered (to produce an analog waveform) and fed into the 3.5mm jack. DC blocking capacitors ensure that the output has no DC offset. The diodes protect against voltage transients.

The audio output is (capacitively) AC coupled; The DC blocking capacitors together with the load and source impedance will act as a high pass filter, blocking frequencies below a few tens of Hertz. Thus you cannot use DC-imbalanced signals to communicate.

You have to encode or modulate the digital data somehow, so that you can pass it trough an AC coupled line. There are many suitable encoding schemes, most notably manchester coding, 8b/10b encoding or 4b/5b encoding. Such signals can then be decoded at the arduino end by feeding the signal to the analog comparator input, feeding the comparator output to the Timer 1 input capture unit (so that every reveived rising and falling edge gets a timestamp), and then decoding the stream in software. As the audio output is designed with the human hearing range in mind, I wouldn't expect a bitrate greater than about 10 kbps (probably much less, depending on the encoding scheme used).

There are also various simple modulation schemes such as Frequency Shift Keying, Phase Shift Keying, Pulse Position Modulation and On-Off Keying which can be demodulated relatively easily with just the analog comparator and a hardware timer.

If you want to go grazy you can also synthesize a digitally modulated analog waveform at the raspberry pi end, sample it with the arduino ADC and demodulate in the digital domain. With something like quadrature amplitude modulation you could get a fairly respectable data rate even with the limited bandwidth and processing power available, at the cost of more software complexity.

Modulation differs from encoding in that you modify properties of a constant repeating waveform with the data being transmitted instead of modifying the signal itself. Modulation permits transmitting a signal of a certain frequency range at a different frequency range, which is crucial for e.g. radio communication but isn't needed in this case as your original signal (baseband) is already in the frequency range of the communication channel, so encoding without any modulation can be used. Combining encoding and modulation is also possible.

  • \$\begingroup\$ By demodulating, would I end up running a software modem on the Arduino? Something like this uses FSK, but for some reason it needs a shield. I guess the rpi will need to run a "soft-modem" with FSK encoding as well? Something like minimodem? \$\endgroup\$
    – John M.
    Sep 30 '16 at 14:53
  • \$\begingroup\$ Excellent answer. A few years ago I built a very similar system to what you describe, using Manchester encoding (though FSK would probably have worked better). \$\endgroup\$ Sep 30 '16 at 15:04
  • \$\begingroup\$ @JohnMunroe Indeed. That "shield" is nothing but a bunch of common passive components. For the receiver (the part that you need) there's a DC blocking capacitor followed by voltage divider of two resistors which biases the received data to 2.5 V, and a small capacitor to reduce susceptibility to interference. A reference voltage for the comparator is simply generated with a trimmer resistor which also acts as a controllable voltage divider. \$\endgroup\$
    – jms
    Sep 30 '16 at 15:06
  • 2
    \$\begingroup\$ @JohnMunroe The data from the pi is AC, varying from positive to negative voltages. The analog comparator in the arduino can only compare voltages in the range between 0 V and 5 V. Biasing the signal to 2.5 V adds 2.5 V to the average voltage, so that the signal is always in the middle of the voltage range. \$\endgroup\$
    – jms
    Sep 30 '16 at 15:45
  • 1
    \$\begingroup\$ In my situation I was using the audio output from a smartphone rather than a RPi, and wanted it to work with a variety of phones. They have different HPF cutoff frequencies which IIRC ended up biting off more or less of the spectral content of the Manchester encoded data. With FSK or other modulation schemes you can more readily control the bandwidth of the signal to keep it firmly in the range that will safely pass. AGC on the receiver is easier too. \$\endgroup\$ Sep 30 '16 at 16:43

A unidirectional serial connection requires only 2 lines - ground and signal. Both the boards you mention expose hardware serial interfaces allowing reasonably fast serial communication, and they have software support for serial communication.

It's possible, albeit ill-advised, to connect UART to UART directly. More reasonably, a pull-up resistor, some series resistance to limit the current when shorted or if the Arduino input was accidentally switched to output and ESD protection could be added, staying with the inverted levels. The Pi is 3.3V and most Arduinos are 5V but the ATMega chip is guaranteed to read a 3.0V input as 1 with a 5V supply so it should function.

Or add an RS-232 driver to one side and an RS-232 receiver to the other to use standard RS-232 levels, at the expense of something like a MAX232 chip and 5 capacitors at each end. The higher voltages of RS-233 levels might be more reliable with a low quality connector, and the noise immunity would be many times higher.

If you don't need to send scads of data, a common protocol is 9600 baud, no parity, 1 stop bit, which allows almost 1K bytes per second to be transmitted.

  • \$\begingroup\$ I'm actually trying to use just the 3.5mm audio jack. So I guess the Arduino will need to read the sound wave? If that's the case, how could the sound wave be read? \$\endgroup\$
    – John M.
    Sep 30 '16 at 11:22
  • \$\begingroup\$ You mean the audio jack on the raspberry pi? That will not be straightforward. \$\endgroup\$ Sep 30 '16 at 11:24
  • \$\begingroup\$ @Sphero How come? Could I use some kind of a soft-modem? Something like github.com/arms22/SoftModem ? \$\endgroup\$
    – John M.
    Sep 30 '16 at 11:44
  • \$\begingroup\$ Sure, that could certainly work if the Arduino is not doing much of anything else and the low data rate is okay for you. \$\endgroup\$ Sep 30 '16 at 14:13

Seeing as how a 3.5mm jack connection gives you 2, 3 or 4 lines (maybe more, no doubt others can tell us). You can quite easily use it to transmit digital data via any one of a plethora of serial communication protocols. Off the top of my head: RS232, SPI, I2C, Single Wire Interface, no doubt many others, including your own one if you felt so inclined.

The hard bit will be making sure that both the sender and receiver are set up correctly, which we can go into detail about once we know how many lines your 3.5mm jack has, which protocol you want to use, physical distance of communication and data rates required.

Alternatively, if you just want to read the sound wave off the audio jack, you can connect to the ADCs of the Arduino, assuming the voltage levels are within safe operating range. The limitations on this will how quickly you want to sample the data, how much noise rejection you want, voltage range, resolution and accuracy of the reading.

Basically what I'm saying is: Yes. If you want more details, ask a more specific question.

  • \$\begingroup\$ Rather than using the GPIO, I'm hoping to use the audio jack only. So would I be confined to reading the sound wave? \$\endgroup\$
    – John M.
    Sep 30 '16 at 11:30

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.