Using A Headphone Jack As A UART

We’ve seen audio ports being used to establish a communications channel between a computer and a microcontroller before, but nothing quite as slick as this. [Gordon] is using a webpage running on a tablet to send Javascript to a microcontroller where the entire program is interpreted.

[Gordon] is using the Espruino Pico, a board that’s on Kickstarter right now. This tiny board is built around a javascript interpreter, allowing code to be written and updated on the fly without mucking around with bootloaders.

This technique can be expanded to provide bidriectional communication between a microcontroller and a computer. On the project Github, [Gordon] used the microphone pin on a TRRS jack to sent data to a computer. It needs two more resistors, but other than that, it’s as simple as the one-way communications setup.

[Gordon] put together a few demos of the program, including one that will change the color of some RGB LEDs in response to input on a webpage.

38 thoughts on “Using A Headphone Jack As A UART

  1. I’ve done something similar, except in my case, I used one audio channel as a clock, and the other for data. A webpage loaded 255 pre-rendered samples. Javascript on the page would send the samples out as audio which was interpreted by a µC as generic synchronous serial protocol. To achieve bidirectionality, the µC was connected to the same computer via USB and enumerated as a HID / keyboard device. The we page / javascript was able to transmit commands to the device via audio,and the device could respond by sending keystrokes to the we page.

  2. I did this a couple of years ago to make Android powered universal remote. The whole circuit consisted of one comparator translating whatever voltage my phone was outputting to TTL, which in turn was read via AVR blinking the IR led as requested.
    At 44100 samples/second I got a bit faster speeds than 9600, but I don’t remember how high I managed to get.
    Unless something changed since Android 2.3 bidirectional audio isn’t possible since the task of reading the input audio stream fast enough to read the serial data would block all other tasks on the device.

          1. When the headphone cable is unplugged (and turn the volume down quite a bit so it doesn’t mess with the speakers), can you hear sounds coming out when you press a button? If not, you’d have to find a way to debug the webpage on the iPhone and see if it’s producing any errors? It might be better to ask on as this thread is getting quite long! (You might also need to invert the output polarity which you can do by setting a variable on your webpage – it might be Apple produce a negative output for a 1 or vice-versa)

  3. Sounds like a very handy hack.
    The connector in the drawing shows three connections: left, right, sleeve(common)

    A non-mobile simple tablet wouldn’t have a mic contact lead in earphone connector, right?

    I can understand the tablet sends sound and that sound is converted to 1 and 0 by the R-C
    but how is any data flowing back from espruino to the tablet?
    Does the tablet “listen” to its audio-out ?
    Thanks for anyone knowledgable enough.

    1. 2 of the 3 examples just transmit – in which case you need one resistor, one capacitor, and a standard 3 pole headphone jack.

      The full bidirectional terminal uses the Mic input with a 4 pole connector (circuit diagram on the forum post). I think a surprising amount of tablets do have a mic input on it – you might want to use it for Skype/etc.

      1. Thanks for the quick explanation, will check mic on tablets, good luck with your kickstarter stretch goals, more everyday examples would help these goals. Also thanks for doubling the espruino RAM for free !

  4. Cool. I almost didn’t read the article. I really didn’t get what was special about this from the summary. There isn’t any software at the microcontroller demodulating FSK like in most of the audio-serial setups I’ve seen. It’s all in that little RC circuit, he’s getting actual 1 and 0 voltages out of that.


    1. Cool but let’s keep it a secret, because ftdi will not like that.
      For entry level or low-budget users, it could mean less ftdi chips in arduino and the like.
      BTW is there any known solution for arduinos that lack usb-serial?
      and work with avr dude/avr studio ?

  5. It looks cool, but this business of waiting 1 second for a capacitor to charge up is off putting. Is this just at startup?

    Second, from my understanding the mic input on a PC or smartphone is AC coupled.
    How reliably could you send continuous sequences of 0xFF 0xFF… characters or any sequences with a DC component?

    1. OK in serial_to_audio.js you wait 1 second for the cap to charge, send your data, then wait another second? So if you are sending 1 byte it will take 2 seconds before you can send the next one.

      How much data can you send in 1 packet? Numbers please.

      1. Get rid of all of the circuitry above, throw in an opamp configured as a comparator and run above 9600 all day?
        On Android you can (or at least used be able to, I haven’t touched it since 2.3) access raw PCM stream going straight to the audio DAC. Your packet length is only limited by how large buffer you can allocate and pass along and your baudrate is only limited by how many samples/bit you want to allocate. Theoretically running serial link at 44100 bps should be possible, worst case scenario half of that if you need to satisfy DC decoupling with Manchester code.

        1. I should have better defined “packet”. I take packet to mean the number of signalling bits sandwiched between the first 1s delay and the 2nd 1s delay.

          I don’t think my question matters, because the espruino developer will avoid questions calling him out on his 9600 baud cliam.

          1. I think this is pretty well answered on the forum, but if you want your audio used all the time, there’s no need for the 1s delay. You just wait 1s for the capacitor to charge, send all the data you want at 9600 baud and then wait another 1s for a smooth discharge. You could start transmitting right away, but you might end up with a few garbled bytes.

  6. back in the day telecomms got around digital line conditions of 0xff by encoding with hdb3 or b6zs , substitution after a certain count of 1’s. A trivial conversion (for todays systems).

    1. The audio output is creating a signal that is interpreted by the Microcontroller’s UART. There’s no special software on the microcontroller – it believes that it is communicating with a totally standard UART – the JavaScript on your PC is effectively emulating one.

Leave a Reply

Please be kind and respectful to help make the comments section excellent. (Comment Policy)

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