ESP32 TNC and Audio Relay for HF/VHF Packet Radio

Wireless packet radio interface for HF/VHF/UHF transceivers, using ESP32 as KISS TNC or audio relay for use with soft modems

Similar projects worth following
This ESP32-based device provides Wifi, Bluetooth, and USB serial connections between a host computer and an HF, VHF, or UHF transceiver to facilitate digital data transmission. The device offers two operating modes and an html user interface for mode selection, configuration, and signal analysis.

In audio relay mode, the device simply streams digital audio between the radio and the host computer with no onboard digital signal processing, leaving modulation and demodulation to modem software (i.g. soundmodem, FLdigi, VARA, etc.) running on the host computer.

In packet mode, the device acts as a KISS TNC, passing AX.25 packets to and from the host computer and modulating/demodulating packets via 300bd or 1200bd FSK.

For this project, I will interface with an Icom ID-5100a and a Baofeng HT, but the physical radio interfaces will be easily adaptable to virtually any HF/VHF/UHF radio.

This project aims to develop a dirt-cheap, open-source, highly reconfigurable, wireless PC-radio interface to support various packet radio modes.  This ESP32-based device attaches to the mic/audio-in and speaker/audio-out jacks of virtually any ham radio and connects to a controlling PC via USB, Wifi, or Bluetooth.  The device provides two operating modes:  1) audio relay services for use with modem software on the controlling PC, and 2) as a packet radio modem.  It will be functionally similar to a combination of a wireless version of the Signalink USB soundcard ($140) and a Mobilinkd TNC3 ($120), for a small fraction of the price of each of these commercial units individually.  I'm estimating ~$20 for parts.

This project started on a whim.  I am a new ham, with a mobile radio, a couple of HTs, a modest budget, and an interest in supporting emergency communications.  After I joined the local ARES chapter in March, I tuned in to an over-the-air activity day, learned about this group's use of Winlink for coordination between EMCOMM stations, and observed an exercise simulating an emergency scenario.  Unable to participate without a digital interface for my radios, I dug through my parts bin and had the idea of using an ESP32 as a Bluetooth audio relay.  That got me thinking about many other ways the ESP32 could be used as a packet radio interface, not only as an audio relay but also as a full-blown packet modem, an audio signal analyzer, and an APRS modem or gateway.

For this project, I will interface to an Icom ID-5100a and a Boafeng UV-5R, since that's what I have, but the modem will be easily reconfigurable for virtually any HF or VHF/UHF radio, with some manual cable or headset hacking.  I intend to minimize parts as much as possible, although some electronics in addition to the ESP32 are inherently necessary, i.g. for audio leveling and bias.  Lastly, this will be a learning experience.  I intend to take the hard way and reinvent the wheel in many cases in order to truly understand how packet radio works and to be able to optimize as needed.  Lastly, I will document my progress here for anyone interested in the thought process, and I will make demos available as I go along, and ultimately the entire codebase will be on github.  

I hope someone finds some part of this useful.  If that's you, please leave a comment to let me know :)



 ☑  Design data vis UI
 ☑  Develop analog->digital conversion (Rx)
 ☑  Develop digital->analog conversion (Tx)
 ☑  Develop audio streaming over UDP (PC->ESP32 ☑, ESP32->PC ☑)
 ☐  Develop audio streaming over BT (deprioritized)
 ☑  Develop KISS interface
 ☑  Research and prioritize modulation modes
 ☐  Develop FSK modulation
 ☐  Develop FSK demodulation - IN PROGRESS
 ☐  Design and test radio interface circuits (☑ UV-5R)
 ☐  Design state machine for switching between modes (☑ Audio relay Tx/Rx only)
 ☐  Design html UI
 ☐  Test with Winlink (☑ Audio relay with Soundmodem)
 ☐  Test with APRS  (☑ Audio relay with Soundmodem)

Some considerations regarding interfaces:

  • Strong desire to handle up to 9600 baud on VHF.
    • (9600 not possible without access to radio modulator)
      • perhaps I can add this later if people with compatible radios show interest
    • Priority:  AFSK 1200 bd
    • maybe BPSK 1200 Bd, BPSK 2400 Bd, QPSK 2400 bps, QPSK 3600 bps?
    • other modes via soundcard modem, with ESP32 as audio relay
  • Ideally, the device should also support HF as well, at lower baud.
    • case I get an HF or tri-band rig later, or for other users
    • Priority:  HF Packet, 300 baud
    • other modes via soundcard modem, with ESP32 as audio relay
  • Support APRS (should be easy since...
Read more »

  • 1 × ESP32 (ESP-WROOM-32) development board Other variants should work but you may need to adjust pin numbers
  • 1 × 0.1 uF Capacitor 0.047 - 0.47 uF
  • 1 × 10k potentiometer 5-50k will do

  • Looking for suggestions, collaborators

    Ryan Kinnett06/30/2020 at 21:27 0 comments

    Hi all,

    I rushed to get this working last week, ahead of Field Day, thinking I would use it to snag some digital contacts and bonus objectives, although I didn't end up using it.  Nevertheless, I'm thrilled that it's working and I have tons of ideas about where to go from here.  

    In the near-term, I'll focus on getting it working more reliably with Winlink to support ARES practice operations.  I also plan to use this in conjunction with a satellite tracker project (writeup coming soon..) to bounce APRS messages off ISS and other packet relays sats.

    I'm thinking that I'll rewrite the title and description of this project to make this purely an audio relay for PC-based modem software.  That is, unless any followers here want to advocate for onboard modulation/demodulation as I had originally planned?  I've already done most of the hard parts for this, just need to carry it across the finish line, but I'm losing steam.

    I haven't yet built up a self-served html interface page.  I'll probably do that in coming weeks and will report back when it's done.  As part of this, I want to set up wifi credential handling to be similar to many commercial IOT devices, where it defaults to beaconing its own AP which you can log into and use the html configuration page to direct it to your home wifi.

    After that, I'll probably slow down my time investments in this project unless I can drum up more interest to keep me motivated.

    So, anyone out there interested in working with me on this project?

    I could use casual suggestions, testers, collaborators, anything.

    Would anyone want to try building your own if I write up instructions?

    I have to admit, my code is a bit amateurish, cobbled together from many disparate pieces, and the organization is haphazard.  It could use a critical eye from legit programmers if anyone wants to dig into it.

    I'm also thinking that I'll just wire up the audio bias/level circuits and PTT circuit point-to-point on perf board unless I can get someone to help design a legit circuit board as a backpack for ESP32 devkit boards with headers.  I also need to work out power interfaces, either a LiPo interface or a buck/boost converter to abstract power from the radio.  This project currently runs off USB port power.

    Another intriguing idea (which I likely won't get to anytime soon unless someone wants to help with it) is making this work as an APRS iGate.  This would require finishing development of onboard AFSK demodulation, plus AX.25 packet handling, but once that's in place, forwarding captured messages to would be a breeze.

    Please drop a line if you have ideas or are interested in testing and/or collaborating.



  • It works! 2-Way Network Audio Relay

    Ryan Kinnett06/24/2020 at 10:00 0 comments

    I'm happy to report that the 2-way network audio interface branch of this project is fully operational!

    I have to admit, I dove into this quite naively, expecting it to be trivial to splice my audio-in and audio-out demos together with some simple logic to handle transitions between transmitting and receiving modes.  That mode switching logic did fall into place quite easily, but there were many other issues that made this an uphill battle.

    First, when I embarked on developing this audio relay method, I was planning to take advantage of both of the ESP32's I2S engines, assigning one to audio input and the other to audio output.  Turns out the onboard DAC and ADCs are only accessible through the base I2S engine, I2S0.  The fun thing is, if you try to assign I2S1 to handle the built-in DAC, the ESP32 crashes, with useful debugging info in the backtrace, whereas if you assign I2S1 to handle the built-in ADC, it doesn't crash, it just silently doesn't work.  This set me a back several days.  After finally realizing that both streams would need to go through I2S0, it took another several more days to work out the right sequence of function calls (and timing!) to reliably hot swap the I2S0 interface between the DAC and the ADC.

    The need to thread both audio-in and audio-out through a single I2S engine forced me to confront mode switching sooner than I had planned, but on the plus side, that turned out to be quite easy to do.  In a nutshell, the switching logic is embedded in the UDP-receive loop;  it transitions to transmitting mode when receiving non-zero data from the PC, otherwise falls back to receiving mode.  In pseudocode:

    For each iteration of the UDP-receive loop,
        If UDP received && valid VBAN packet && contains non-zero data,
            reset no-data counter
            if mode==RECEIVING,
                transition to TRANSMITTING
                send [N] zeroes to DAC to transmit quiescent tx-delay
            send packet to DAC
        Otherwise (no UDP or not VBAN or packet contains all zeroes),
            increment no-data counter
            if mode==TRANSMITTING && no-data counter >= persistence,
                transition to RECEIVING

    In the above pseudocode, each of the "transition to" lines is a function call to a mode transition handler which basically shuts down i2s, clears the DMA buffer, triggers or releases PTT depending on the commanded new mode, and restarts i2s with either the DAC driver for transmission or the ADC driver for receiving.  Note that, immediately after transitioning to TRANSMITTING mode, I send several DMA  buffer widths of zeroes to I2S to have it stream quiescence for a brief period after triggering PTT and before writing packet data to analog-out.  This is basically a crude, hardcoded-for-now implementation of what's commonly referred to as "tx-delay".  I'll parameterize this later and make it configurable via html interface.

    Another problem I ran into was configuring the DMA buffer lengths.  In the outgoing audio stream (PC->ESP32), VBAN automatically selects packet widths between 64 samples per packet when the sampling rate is 11025Hz, and 256 samples per packet when sampling 44100 Hz or faster.  So VBAN sampling rates of 11025, 22050, and 44100 each produce power-of-two samples per packet, whereas even-thousands sampling rates (i.g. 12000, 24000, 32000) generate packets with non-power-of-two samples per packet.  Why does this matter?  It seems I2S works best with power-of-two DMA buffer widths, otherwise...

    Read more »

  • Streaming Audio from PC to ESP32 Analog-Out

    Ryan Kinnett05/27/2020 at 10:13 0 comments

    Short update on a significant breakthrough:  I worked out a reasonably reliable outgoing audio chain, using VBAN to send audio data packets over WiFi to the ESP32.  The ESP32 unpacks the audio stream and funnels the data into direct memory access buffers which i2s then pipes to an analog-out pin.  Ultimately this will serve as the conduit for sending packet data from SoundModem, running on the PC, over to the ESP32 and ultimately into the mic port of the VHF/UHF transceiver.

    Demo code here:

    That code could be useful for many things beyond my intended purpose.  An intercom system, for example, or an audio endpoint for streaming music or anything you want from your PC.  How about a drone-carried PA?  The ESP32's built-in DAC is only 8 bits, not good enough to serve as a network audio receiver for a legit HiFi stereo system, but I think I'll build one anyway, maybe using an off-the-shelf ESP32 audio dev board with higher resolution DACs and linear amplifiers.  That should integrate very easily with this method since I'm already using i2s.

    I previously worked out audio sampling and streaming from ESP32 to PC to relay audio received from the radio to SoundModem for demodulation.  With these two pieces in place, I'm now ready to design a state machine to juggle transmit and receive modes.  The high-level switching logic should be simple, but I'm not sure how easy it will be to dynamically change i2s input/output modes on the fly..

  • Streaming Received Audio over Wifi/UDP

    Ryan Kinnett05/18/2020 at 03:36 0 comments

    It’s been a few weeks since my last post, but I have  made steady progress on several fronts.  I have focused mostly on the hardest part of this project:  real-time onboard FSK demodulation.  

    I explored two approaches for audio sampling:  one using I2S and DMA, similar to the fast audio streaming demo I described in a previous log, and another using a timer + ISR approach as described by Ivan Voras here.  I will write more about these experiments later, in an update to this log, or in a separate one.  I was able to get both working 90% smoothly, but the streams would drop out every few seconds, for a fraction of a second.  After days of trying to optimize the code and clean up these dropouts, I haven’t yet gotten to the bottom of it.  I had Arduino OTA enabled and was printing to serial, doing some non-trivial batch sample processing, and streaming data over web sockets, all at the same time.  I have not yet tried isolating these interfaces to identify the bottleneck.  Will do that soon.

    Despite the intermittent dropouts, I did have some success testing a tone identification method which will likely serve as the core of my onboard demodulation process.  I implemented the dual sine filter algorithm described in a late edit to my earlier log regarding demodulation techniques.  I set up a websocket to stream the isolated 1200 Hz and 2200 Hz magnitude values along with raw audio, and tested with a tone generator. It worked beautifully!  I’ll post more about this after I work out the periodic dropouts issue.

    What’s next with development of FSK demodulation?  Getting the 1200/2200 Hz discrimination algorithm working was a big step.  After I get to the bottom of the dropouts problem, the next lesser challenges will be 1) implementing some sort of normalization and thresholding process, 2) first-frame identification, and 3) automatic sample phase optimization/synching.

    Onboard demodulation is coming along, but still has a long way to go to make it reliable.

    The more exciting news for this log is that I got half of the 2-way audio relay mode working.  The ESP samples analog audio, buffers and streams over wifi, via UDP and the VBAN protocol.  A VB-Audio Virtual Cable running on the PC receives the audio stream and presents as a soundcard driver.  I am very impressed by the VBAN utilities, which are fully functional donationware, and will happily endorse that project as I get this one off the ground.  It seems to be working smoothly.  I don’t hear noticeable dropouts when I sample general audio through the ESP32, although VBAN does report some packet losses which I have not yet investigated.  I will post my Arduino sketch of this test soon.  Should be handy for intercom systems.

    I initially tested this received-audio sampling and streaming method by playing Stephen Smith (WA8LMF)’s APRS audio sample CD as analog input into the ESP32, streaming the digitized audio over UDP to VBAN Voicemeeter, then decoding the audio stream using UZ7HO’s soundmodem.  This setup reliably decoded messages from the test CD.  I have not systematically characterized reliability by counting total decoded packets for each track, which seems to be a common benchmarking practice.  I later hooked up my Baofeng UV-5R audio-out to the ESP32 and successfully decoded many live APRS transmissions.  This is huge!


    I posted demo code here:

    One thing worth noting, I originally planned to have the ESP32 broadcast audio without specifying a destination address, but found this approach to be choppy and intermittent, completely unusable.  After some googling, I found that UDP broadcast and multicast transmission modes are not generally recommended for even moderate data volume applications.  I will need...

    Read more »

  • Oooh Shiny Object! (fast data visualization)

    Ryan Kinnett04/27/2020 at 01:24 0 comments

    While reading about analog-digital conversion (ADC) on the ESP32, I found many references and examples using I2S to sample a GPIO pin at a configurable rate.  Most notably, github user zekageri had posted several questions in the forums about glitches he was seeing in his streaming ADC data, and he shared this video of his ESP32-served web interface plotting data samples at 44.1kHz.  What is this magic?  WebSockets!  A relatively new and highly streamlined TCP-based protocol, facilitating fast and efficient data transfer.  Zekageri posted an early version of his code on github, but I couldn't get it to work out of the box.  I basically started from scratch, using some of the general concepts from his project, and evolved it considerably.

    Fast streaming data visualization

    This fast-streaming data visualization will be key to tuning my demodulation code which I will start testing imminently.  This data vis approach will also be a great tool to add to the tool box for fine tuning during operation later, i.g. to make sure incoming and outgoing audio streams are properly scaled and biased and not clipping.

    Test/Dev Process

    I threw the ESP32 on a breadboard and wired up a bias circuit by coupling an audio cable to a potentiometer as a voltage divider, pulling the signal up to about midway between ground and the ESP32's 3.3V regulated pin so that the ADC can ingest the full signal without clipping the lower half.  Here's the basic audio-in bias circuit:

    I added that 8 Ohm speaker on the right channel for fun.  I might incorporate a speaker into the final design later, with a proper amplifier.

    Next, I plugged the audio cable into the speaker jack on my laptop and used this handy online tone generator to send audio signal to the ESP32.  Before plugging in the ESP32, I tested the signal level with my oscilloscope and verified it was within the 0-3.3V measurement range of the ESP32 ADC.

    Here's the data visualization code:

    Basically, the ESP32 buffers many samples in DMA, via I2S, and the main loop periodically pulls that buffer and sends it over WebSocket as binary data.  The ESP32 serves a webpage with a CanvasJS plotting method to dynamically plot incoming data.

    It took a lot of work to understand an inversion issue and that the ESP32 puts random (okay maybe not random; I'm not sure what it is) ones and zeroes in the upper 4 bits of each 16 bit sample.  The ADC measures in 12 bits, and I assumed the ESP32 would pack those 12-bit measurements into 16-bit values with zeroes in the upper bits, but I was wrong and that took a few frustrating hours to figure out.  Anyways, that's fixed, and now I know how to sample audio efficiently.

    Check out the demo:

    This should be useful for so many projects..

    I hope you found this useful.  If so, please leave a comment!  Thanks, 73

  • Researching FSK demodulation methods

    Ryan Kinnett04/25/2020 at 10:48 1 comment


    This post summarizes my piecemeal, spotty, experimental, and in some cases probably incorrect understanding of the methods described herein.  This was all new to me before this project, and it still is, so don't take anything here as gospel.

    About Frequency-Shift Keying (FSK)

    Key characteristics of FSK are two discrete audio tones representing "marks" and "dashes", aka binary ones and zeroes, with smooth transitions between tones.  FSK is a non-returning-to-zero (NRZ) type encoding method, meaning each bit is explicitly represented by one frequency or another, as opposed to representing zeroes as lack of signal.  300-baud FSK (aka Bell 103 standard) is common on HF (SSB).  In this mode, an audio signal is composed of a continuous sine wave in which the frequency varies smoothly between two arbitrary frequencies, separated by 200 Hz, representing a stream of ones and zeroes at 300 symbols per second.  The modem injects this audio stream into a mic port of an HF transmitter which mixes the pre-modulated AF signal and transmits as SSB.  1200 bd FSK is more common on VHF (FM).  1200 bd packet uses 1200 Hz and 2200 Hz tones representing ones and zeroes, respectively, per the Bell 202 standard.  Note that this peculiar selection of tones avoids aliasing but also slightly complicates the process of digital demodulation.  Also note that the baud rate matches the frequency of the lower tone, meaning that just one single cycle of 1200 Hz tone fits within each symbol period - this turns out to be a driving factor in which tone differentiation methods can be used.

    9600 baud is also possible, but requires a compatible radio which gives the modem direct control of the RF modulator, and even higher symbol rate modes are built on top of that.  

    This project will initially focus on 1200 FSK since I currently only have access to VHF/UHF radios without modulator ports.

    By the way, for context, FSK is one of several physical-layer modulation techniques used to encode digital data into audio frequency and ultimately RF.  The content of that digital data is coordinated between the link and application layers.  My primary use case for this project is to support Winlink for emergency comms, using the ESP32 either as a KISS TNC or as an audio relay.  In both of these modes, link layer coordination is handled by software on the PC and there is no need for the modem to implement higher-order protocols (AX.25).  However, I am also interested in supporting APRS, which probably will require onboard link control and AX.25 packetization.  In any case, my main point here is to explain the origin of the digital data that's going through FSK modulation and demodulation.  We will deal with link control infrastructure and packetization later.


    Pulling bits out of the air

    There are several ways to approach FSK demodulation, each with different levels of capability and resource requirements.  

    The Fast Fourier Transform (FFT) is more or less the go-to method for differentiating between frequency components in a digitized analog signal for many, miscellaneous applications throughout engineering.  That said, the FFT is not particularly well suited for embedded FSK demodulation.  The FFT calculates energy in discrete frequency bins between zero and Fs/2, and these calculations are intertwined and inseparable.  Since we're only interested in two specific frequencies, most of the information generated by the FFT would be thrown away.  Further, FFTs are typically evaluated in adjacent, non-overlapping sample windows, with no information carried over from one window to the next.  Additional layers of complexity could work around these issues but generally would not be practical on an embedded microprocessor, even on one as capable as the ESP32.  

    The next step closer is the Goertzel...

    Read more »

  • Assignable KISS interface!

    Ryan Kinnett04/11/2020 at 09:17 0 comments

    I wrote my own KISS library, and I framed it such that any arduino Stream object may be assigned to the KISS and logging interfaces.  This will help later when I develop an html configuration page and need to change interfaces on the fly.

    I posted a demo here:

    In this demo, I associate the KISS interface with Bluetooth serial, and I assign logging to the (USB) serial port.  I'm using Winlink to generate KISS messages over Bluetooth and am showing the message parsing in the Arduino Serial Monitor window:

    This demo is one-way only, from host to TNC. I have not yet worked out functions for encapsulating received AX.25 packets into KISS frames, and more generally, I have not worked out AFSK modulation and demodulation at all.

    I expect AFSK modulation will be a piece of cake since I have already worked out the method to extract to-be-transmitted AX.25 packets from KISS frames, with KISS special character handling, so now it's just a matter of generating AFSK from the binary packets.  I don't need to know anything about the AX.25 protocol since the KISS interface is just the transport for AX.25 packets which are to be transmitted verbatim, except for special character handling.  Demodulation will be more interesting.  I'm hoping digitization of the frequency-modulated audio signal is straightforward, although others have reported problems with ADC timing on the Esp32.  I have not yet researched DSP methods for frequency-ID to convert the digitized frequency-modulated audio signal into binary and ultimately reassemble the received AX.25 packet.  Also, is error checking handled at the physical layer or at the link layer?  Encapsulating received AX.25 packets into KISS frames should be easy.

    Next step:  AFSK modulation

  • Incremental Progress

    Ryan Kinnett04/07/2020 at 01:39 0 comments

    I made a little progress over the weekend.

    First, I rigged up my ID-5100a with an RJ45 splitter between the mic and the radio base so I could tap into the 8Vdc, PTT, and mic audio pins to observe these signals during normal operation.  The 8Vdc and PTT signals made sense, but I'm a bit baffled by the mic "audio" signal.  I expected to see an obvious "line level" audio signal, proportional in frequency and amplitude to the volume of my voice, but I saw nothing of the sort.  Instead, the voltage between the Mic Input and Mic Ground pins was basically 8Vdc plus a 300 mV pk-pk signal in the 2 MHz range.  What the heck?  Zooming in it does not look like some sort of digitized serial stream.  I scoped the other wires but couldn't find anything resembling an AF signal while I was talking into the keyed mic (and also hearing my own transmission, received on an HT).  What gives?  Still kinda baffled by this. 

    Anyways, I see that Signalink jumpers the ID-5100a Mic Ground to common ground with PTT ground, and wires the Signalink MIC (output) pin directly to the ID-5100a Mic Input line.  I can't find an explicit description, I presume the Signalink just sends line level AF through that connection.  I might ask the ID-5100a facebook group about this since several guys in that group use Signalink with this radio.


    I found several Arduino KISS/AX.25/APRS examples online, but none were implemented in a way that was intuitive to me, so I started down the path of defining my own KISS library and AFSK mod/demod elements.  I'll borrow bits and pieces from other projects to get forward error correction and other functions working quickly.

    Starting from scratch, it turns out SerialBT is super easy to work with, and persistent, so I can reflash and test incrementally without my PC dropping the BLE association.  I easily set up Winlink in Packet mode through KISS interface, and pointed that to the serial com port of the ESP32 BLE receive channel, received KISS messages on the ESP32 and echoed them back to the USB serial interface.  The KISS TNC control messages immediately made sense but I haven't yet worked out the first data message which I presume is some sort of AX.25 CQ message.

    Screenshots later..

  • Practicality Issues

    Ryan Kinnett04/05/2020 at 00:10 0 comments

    Bidirectional audio streams?

    Not sure how to implement bidirectional audio over BT with ESP32's single BT radio.  ESP32 can be configured as an A2DP source or sink, but not both simultaneously, apparently.  What I originally had mind was that the ESP32 would present itself as a BT headset, such that soundcard modulation software (i.g. soundmodem, FLdigi, etc) running on the terminal PC can select the ESP32 as both the input and output audio device, and use either as needed.  Since bidirectional A2DP does not appear to be a thing, in order to make this BT audio relay concept work, I would need to either find a way to dynamically switch between source and sink modes, or attach a peripheral BT transceiver and maintain parallel BT A2DP source and sink links.

    I don't know if switching BT modes dynamically will break the Windows audio device targets, or if there is some way to maintain both links even while the ESP32 is not listening on one or the other.  If I can find a way to switch between source and sink modes without breaking the Windows audio targets, then the next step would be to figure out how to trigger mode switching.  The Winlink packet mode settings allow you to specify a com port for PTT, and that com port can be set to a virtual com port routing over TCP.  That should be feasible, albeit convoluted.  This makes the other idea, attaching a second BT radio to the ESP32, seem more appealing, but I was hoping to keep the parts list and cost as low as possible.  I might experiment with A2DP streaming and mode switching later.  For now I am deprioritizing audio relay over Bluetooth capabilityIf anyone reads this and has ideas, please let me know asap!

    I'm also looking into audio streaming over TCP or UDP.  I think bidirectionality will be easier to implement this way.  Similar to the concept above, I would use third-party virtual sound card software to forward encoded audio over wifi.

    Not sure yet which Windows virtual audio device to use.  PulseAudio seems like a good choice but I'm not familiar with it.  Also, VB-Audio has an app for that, though it doesn't seem to support sample rates lower than 44100 Hz which is much faster than I need.  I could use suggestions..

    Summary of Planned Modes:

    I've narrowed down to 2 operating modes:  audio relay mode via UDP over wifi, and packet mode with KISS via BLE, TCP, and USB serial.

  • Research...

    Ryan Kinnett04/04/2020 at 00:23 0 comments

    Where to start?

    There are other ways to do this.  

    Perhaps the cheapest approach would be to just build custom cables to tap the radio AF-in and PTT pins on the Mic port and AF-out from the SP2 port, wire those directly to my computer's aux-out and mic jacks, and use a software modem.  Gain/level control and PTT may require some circuitry in between.  It is also possible to control the radio (PTT, VFO selection, set frequency, etc) over a TTL serial connection provided on the center ring of the SP2 port.

    Similarly, a 2-way Bluetooth audio device could be used to relay AF to and from a PC running sound modem software with the BT device selected as the audio input and output device.  This approach lets you eliminate electrical connections to your control computer.  One could design an analog circuit to pull in PTT when audio is streaming from the controlling PC, or devise some other way to toggle PTT wirelessly, potentially over a separate BT device running as a serial port.  

    This is what got me thinking about the ESP32 which could serve as a 2-way BT audio device and either decide digitally when to trigger PTT, or provide a telnet terminal which the control software on the PC can use to command PTT.  Plus, there are tons of other things you can do with an ESP32 driving the radio.

    This also got me thinking that the ESP32 is plenty powerful enough to handle onboard AF modulation and demodulation, eliminating the need for a software modem on the PC.  Instead, one could implement KISS protocol over Bluetooth serial profile or over 802.11 telnet to control the TNC and send and receive digital packets.  

    This is hardly a new idea, it's just new to me.  Other projects use various forms of microcontrollers with a bluetooth serial interface over I2C or similar.  For instance, the  mobilinkd TNC3 and  MicroModem projects, both of which seem to be well supported and well worth the investment.  It turns out Mobilinkd is also actively looking at moving to the ESP32 but hesitated due to bugs in power management in BLE mode which have since been fixed.

    I am very tempted to buy the mobilinkd TNC3 but figured I might as well try building something similar since I have some spare Esp32s and miscellaneous components, plus test equipment, and since various parts of the needed code base already exist in various forms for other platforms.  Also, it turns out @Evan has already started porting Mark Qvist's APRS work to the ESP32.  I'll try Evan's LibAPRS branch and go from there.  There are a few other Arduino KISS TNC projects that also look promising, but are targeted for older, slower boards.  Some look easier than others to port to the ESP32.

    If all fails, I will likely break down and buy a mobilinkd TNC3 or wait for an ESP32-based version.

    Some thoughts about interfaces:

    • Strong desire to handle up to 9600 baud on VHF.
      • (9600 not possible without access to radio modulator)
        • perhaps I can add this later if people with compatible radios show interest
      • Priority:  AFSK 1200 bd
      • maybe BPSK 1200 Bd, BPSK 2400 Bd, QPSK 2400 bps, QPSK 3600 bps?
      • other modes via soundcard modem, with ESP32 as audio relay
    • Ideally, the device should also support HF as well, at lower baud.
      • case I get an HF or tri-band rig later, or for other users
      • Priority:  HF Packet, 1200 baud
      • other modes via soundcard modem, with ESP32 as audio relay
      • Support APRS (should be easy since open source libraries are available)
    • 5 4 ways to transfer data between PC and modem:
      • AF relay mode:  audio to/from PC software modem, 
        • over Bluetooth (A2DP 2-way?) (deprioritized)
        • over 802.11 (UDP if TCP not practical)
      • KISS over bluetooth low energy (BLE) serial profile, or ...
    Read more »

View all 10 project logs

Enjoy this project?



Ale o co chodzi wrote 12/10/2023 at 16:43 point


meybe on free (no licence ) band too , lora, 433MHz etc.

meybe add FAX.25 protocol

  Are you sure? yes | no

Derek Murawsky wrote 10/27/2023 at 02:04 point

I love the idea of doing the mod/de-mod on the chip specifically because then you could have a standalone digipeter/igate without the need for anything else, like a pi. Having that bit of software on the esp32 would open up so much, especially when paired with a cheap 2m radio or, even better, just the module from one.

I'd be interested in building something like that. Not much of a cider, but happy to try to help. :) 

  Are you sure? yes | no

doc.tom.talley wrote 01/17/2023 at 13:28 point

Have you considered interfaces to radios like the ICOM usb cat interfaces.  I'm new to the esp32 but had all the wstjx and winlink software running on my pc.  It died and now I'm dealing with a new windows 11 machine.  It sure makes sense to use something like the esp32.  Also bought yaesu tms300 which has tnc on board, just needs protocol matching state machine and terminal interface...could we talk.

  Are you sure? yes | no

Tachion wrote 10/14/2022 at 19:45 point


is possible add language to harware? lua/mruby/python

Do You know meshstatic?

  Are you sure? yes | no

maximo barawid wrote 06/01/2022 at 10:37 point

Interest in building this project and try if it can be used for our emcomm.  

  Are you sure? yes | no

tom2000 wrote 03/23/2022 at 23:04 point

A very interesting project, but it seems like work has stalled.

Have you thought of solving your issues with encoding/decoding audio in other ways, like using dedicated integrated circuits? For example the CC1101 is capable of FSK / GFSK / etc. up to 500 kbps and can be accessed via SPI and also contains a transceiver in the 70 cm band (about 10 mW). There are also ready to use boards with this IC and a power amplifier, that allows sending with 100 mW / 1 W / etc. out there for a few bucks.

  Are you sure? yes | no

Mr Keuz wrote 02/18/2022 at 18:24 point

Hi, very interesting project. 

My my old dream is to have a modem via radio. I'm currently playing with software-modem via Direwolf. Through direct audio achieved speeds up to 19200. Now I am assembling a stand with two Baofeng UV-5R. The speed will most likely be lower, but it is important for me to send telemetry through such a modem. And the most important thing is that the modem works on the HF band (lover than VHF / UHF).

While researching ax.25 technologies I found the project "fx25-kiss-tnc" which is built on top esp32. But most importantly, it uses the ultra-budget TCM3105 chip. This is a single chip fsk modem (up 1200 bod). You may be interested. 

The project itself is here:

The main thing I wanted to convey is that there is such a TCM3105 chip. And it can greatly simplify development. The only thing in this case, yes, there is a vendor lock for this chip.

Software implementation of demodulation looks more elegant.

  Are you sure? yes | no

ee334 wrote 06/16/2021 at 20:40 point

is possible using this in ISM band? packet radio on PMR no licence emergency communication

  Are you sure? yes | no

lalmi ahmed wrote 10/04/2020 at 22:04 point

great job , wish you the best

  Are you sure? yes | no

Dennis Delin wrote 09/02/2020 at 09:29 point

Ahh what a lovely project!
And something that would be very nice for me aswell. Currently trying to research a generic way to send generic data in a broadcast maner over AFSK FM voice channel. In many ways like APRS. The idea is to use the smartphone to interface with any voice channel radio to transmit some data, eg. short text messages or gps position. Like where you are going with the general audio relay project but for me it will not work with a wifi connection as I will need to an internet connection on the phone at the same time, and therefore bluetooth A2DP profile would be a more ideal solution for that. Maybe that could be integrated aswell. Would love to help out!

  Are you sure? yes | no

Ryan Kinnett wrote 09/30/2020 at 21:35 point

Thanks Dennis.  There is a lot left to be done with this or a similar project but I ran out of steam working on it all on my own, and I'm not planning to get back to it anytime soon.  If you want to kick off your own project, I would be happy to help with that.

  Are you sure? yes | no

Dan Maloney wrote 04/03/2020 at 17:28 point

Nice job - might help me build a TNC for my quad-band mobile rig.

  Are you sure? yes | no

Ryan Kinnett wrote 04/03/2020 at 18:44 point

Thanks Dan, but this hasn't been built yet.  I'm still researching digital modes at this point.  I'm prioritizing elements of this project to get my rig working Winlink with my local ARES group.  If you have any tips, suggestions, or requests, please let me know.

Also see @Evan 's project here:

His port of Mark Qvist's APRS libraries will probably be my starting point for VHF packet, although I have found a potentially simpler Arduino implementation that I might also try.

  Are you sure? yes | no


[this comment has been deleted]

Ryan Kinnett wrote 04/03/2020 at 19:06 point

I'm planning to set this up with abstract interfaces with screw terminals so I can manually wire it to either my Icom mobile rig or my Baofeng HTs.  For the Icom rig, I will need to hack up an ethernet cable and a stereo audio cable.  For the Baofengs, I'll need to hack up a headset.

I'm focusing on VHF and HF digital packet modes, several of which are also compatible with UHF, so I don't see why it wouldn't work on PMR although I haven't researched FCC rules on that.  I am not planning to implement any digital voice modes, which is probably what you're looking for.  That said, if someone were to point me to a good working example of an Arduino implementation then I could add this to the stack, but it would be low priority for me.

I think your question about joining with a router is about how to connect it to your wifi network, is that corret?  Initially, the firmware will hardcode my own wifi network SSID and password so that it automatically joins my home network.  Later, I will set up an adaptive method similar to basically all IoT devices:  by default it will set itself up as its own access point and provide a configuration html page through which users can input their own network's SSID and password which will save to flash and become the default wifi configuration thereafter.

  Are you sure? yes | no

Similar Projects

Does this project spark your interest?

Become a member to follow this project and never miss any updates