Hey! This is an old blog post about MicroModem. For the most up-to-date info and latest downloads, check out the MicroModem page.

Legacy docs for this build can be downloaded here.
You can also use MicroModem for APRS, but the master branch doesn’t use the AX.25 protocol, so check out the AX25 branch on GitHub for an example of AX.25/APRS! There’s now a much more functional APRS-dedicated fork! Yay!

MicroModem is an educational and open-source implementation of a 1200-baud AFSK modem on the popular ATmega328p microprocessor. This makes it compatible with all Arduino boards and spinoffs using the 328p (for example the Uno, and the Microduino). Apart from a 328pBased board, you will also need to assemble 17 common electronic components to build the modem. When done, it can be used for things like ham radio APRS, TCP/IP over SLIP, experimentation with mesh-networks, long-range wireless communication with sensors (Or friends! Or strangers!).
The included “tinkering-oriented” protocol (dubbed MinimalProtocol1) let’s you send (broadcast) data that will be received by all other listening stations. MP1 also features forward error correction (12,8-hamming code), 12-byte interleaving, and automatic data compression (although not available in TCP/IP mode, due to lack of memory). It should be easy to expand the protocol to support addressing and routing, encryption, or whatever you find useful. If you have a cool idea but aren’t sure how to go about it, let me know and I will try and help!
Don’t expect live video-streaming and rocking out to DI.fm over this though. This is only 1.2 kilobits per second. Loading Hackaday RetroΒ took around 15 minutes when I tried. If you’re not using TCP/IP you will have better throughput than that though. But TCP/IP works fine for very simple synchroneous-style connections (like: connect to server -> send request -> wait for response -> send another request -> receive another response -> disconnect).
I designed MicroModem to be as simple an introduction to digital wireless communication as possible, while still being very flexible and functional. Micromodem will let you learn the basics in how to build digital wireless systems from scratch, and also offer an interesting platform to build further projects on. I hope you will find it educational and useful!
The source code for the modem firmware is very heavily commented, and should be easy to understand. In fact there is more comments than actual code most places. Some of the concepts can be a little daunting just from looking at the code, but it is actually all quite simple, when taken one step at a time. If you have any questions, drop me a comment here and I will try to help out.
All the code, schematics, PCB layout and STL/OpenSCAD files for 3D-printing a case is available on my GitHub page. If you want to build it, please readΒ this quickstart guide. If you have any questions feel free to comment here or email me!
MicroModem & Radio
MicroModem 2

53 thoughts on “MicroModem

  1. Nice. I will be checking out the compression methods you used in the hackaday article (heatshrink). Thank you for letting me stand on your shoulders πŸ™‚ When I get some more free time, I plan ot make use of what you have done and hopefully re-share.
    P.S. I like your domain name as well. My wife picked mine and I was always to lazy to change it, but I like it (penguin is hard to spell for most folks).

    1. Thanks! Heatshrink is really cool, especially since it has very low memory requirements, which was a must for this project. I am very glad you find this useful, and I hope you’ll be able to make something awesome with it!
      Just let me know if you have any question about the code or hardware!

  2. i love this and i want to play with this.
    but a bit daunting.. i can make up the hardware on some protoboard in not time.
    but most of my programming so far is within the “safe” arduino environment..
    im not too sure how to set up for compiling straight C / make file setup like this?
    AVR-GCC i guess? best get googline i suppose
    and i guess this can still run this with the arduino bootloader / avrdude?
    just upload the .hex manually.

    1. Hi Tuna!
      It’s really simple to get the software part up and running. As you said, you need AVR-GCC and basic build tools. If you’re on Ubuntu/Debian, something like this should do the trick:
      sudo apt-get install build-essential gcc-avr avr-libc binutils-avr avrdude
      You can the go to the source directory and type “make”, which will compile the source to a firmware file. I have also included a small bash script that makes flashing the built firmware a breeze, have a look at the “flash” script in the source directory. If the Arduinos serial port is /dev/ttyUSB0, you would run it something like this:
      ./flash USB0
      And as you assume, this works fine with the default Arduino bootloader πŸ™‚
      From there, you can just edit the source in your favorite editor or IDE (I use Sublime Text myself), build and flash to your hearts content!

  3. I’m curious what it’d take to extend this to other FSK usages? 45.45baud RTTY springs to mind

    1. That’s a really interesting idea! It should actually be possible without too much of a hassle by changing a few parameters in the source. Although the baudrate setting is defined as an integer, you could probably change a few things around to get exactly 45.45 baud. I might try this myself as well, but right now the first priority is to provide a few different “pre-cooked” examples for AX.25 and APRS, plus writing a good getting started guide πŸ™‚

      1. Also, as far as I remember, RTTY doesn’t use the same mark and space frequencies as 1200 baud AFSK, but this should be quite easy to change as well.

  4. Hello, Mark.
    At Notre Dame we are working on a project for which this board might fill an odd niche.
    Would you be willing to talk about it for a few minutes.
    You can email me at the address I provided.

  5. cool.. doesn’t look too bad. will give it a go
    so i guess. two modems and two radios on the same frequency
    will function like a rs232 nullmodem link
    im hoping to do some remote control over longer distance.
    have been playing with DTMF. but this clearly looks better

    1. Yeah, that’s correct. The way that the protocol works functions just like that. And you definitely have a lot more options with this than with DTMF! What are you going to control, btw?

  6. Would it be possible to publish PDF’s of at least the schematic, so that one doesn’t need EAGLE installed to recreate the project? This looks like it would work really well for a High altitude balloon project or for telemetry from a Model rocket. You don’t always need gobs of bandwith, and a NRF chip or Zigbee just doesnt have the long range capability that this could offer.

    1. Absolutely! In fact, it is already there πŸ™‚ Check out the two PDFs at https://github.com/markqvist/MicroModem/tree/master/Design
      Yeah, I think it would definitely be useful for stuff like that! If your transmitter is located up high you get very long range from just a simple 5w UHF transmitter. For a transmitter just 3000 meters up in the air, the radio horizon is around 230 kilometers πŸ™‚

    2. Also check out the Fritzing sketches if you have that installed πŸ™‚

  7. control? well. i actually have a few little projects in mind..
    one just needs to turn a light on and off… so. dtmf and a (any) radio with a keypad
    might still be the way for that one. kinda like a long range heads up (doorbell)….
    im thinking control of a “robot” rover of sorts.. just need to find a 7W video feed transmitter now

  8. Hi Mark
    Much interested in your project. Thanks for sharing.
    I’m currently trying to use my Eclipse + AVR-Eclipse Environment to build it (I’m not very good at this), but despite including the bertos and Modem directories in the project settings, I’m stuck while compiling hashtable.c => error: cfg/cfg_hashtable.h: No such file or directory – And actually, there is no cfg_hashtable.h file in your github repository. Did i miss something ?
    Thanks !

    1. Hi Laurent!
      That sounds strange… I don’t see why it would even want to include that hashtable stuff… Before trying to put it into the eclipse environment, did you try building just from the directory downloaded from the git repo? Also, what OS are you using?

    2. Ah, wait, I think i know what’s wrong now.
      Even though I removed a lot of the unnecessary BertOS stuff, there’s probably still some stuff left that’s not needed. When you created an Eclipse project with the source files, I would guess Eclipse included all files inside the repo in it’s build instructions, and thus it fails because it’s trying to compile a file that has missing source dependencies. Can you first try just executing “make” inside the MicroModem directory? If it builds like that, it’ll be a matter of getting the eclipse project set up correctly, which I can probably try to do. Just need to download a copy of eclipse and generate the proper build files πŸ™‚

    3. Hi again!
      I just installed eclipse and the avr plugin, and created a new project with the source files for the modem, and it compiled fine! These are the steps I took:
      – In eclipse, create a new project (File -> New -> Project…)
      – In the new project box, select C/C++ -> “Makefile Project with Existing Code”
      – Select a name, and locate the MicroModem folder for “Existing Code Location”
      – Select “AVR-GCC Toolchain” in “Toolchain for indexer settings”
      – Click “Finish”
      After following these steps, the project builds in Eclipse πŸ™‚ I hope this works for you! Otherwise let me know!

  9. What a cool and tiny project. If you ever thing of selling them let us know.

  10. so i have built up two circuits on veroboard.slightly modified circuit to work with my radios (DJ-V17) (PTT is activated by pulling microphone line to gound via 10k)
    R6 1k was tripping them to transmit 100% so i took that out.
    and added 10k between PTT + and Microphone (so through 10K then the Mosfet to GND)
    seems to work good My radioes do transmit and i can hear “modem noise” at the recieving end when not plugged in
    but connecting two terminals 1200bps 8N1 NO flow control just prints garbage
    i have played with the volume on the Radioes to get nice “Recieve LED”
    not too low. not too high.. i guess. but no luck so far getting text across.
    the transmissions of “alot of text” seems to get broken into bursts.
    is this normal? or do i have trouble with my PTT circuit.
    i was expecting a continus 1200bps burst for the duration of data transmission ?
    was critical for the microphone level out? maby i can find a smaller / larger resistor that
    does not triger the PTT
    any suggestions?
    pretty close but no cigar yet sigh πŸ˜‰

  11. oh.. and i am trying the two boards with direct wires.. taking the radios out for now.
    audio lines crossed.. still no good ;(

    1. Hi Tuna!
      I guess I should have noted clearly somewhere that the serial connection to the computer is 9600 baud 8N1 and no flow control. I had to put it at 9600 since SLIP (TCP/IP over serial) seems to be unable to do anything else than that speed, at least the implementation I have been using, so try that!
      I will try out your changes to the PTT circuit, it might make more sense that way!
      The “burstiness” is probably due to me having left some rather absurd timing for CSMA, I will change that tomorrow to more sensible values and upload it to the repo.
      Also, R6 and R5 makes up a voltage divider that brings the output level down to microphone level, about 20mV peakt-to-peak. If you took out R6 it should be back at line level, and you should be able to connect wires directly between the modems. It’s strange that this was tripping the PTT though, I don’t really understand that… Are you sure it was not R9 you took out? Either way, if you want to go directly with wires through the modems, you need to take the audio output before it is brought down to mic level, since the ADC on the ATmega is too unsensitive to register audio in the millivolt range. But if you put line level audio into the MIC port of a radio, it will get too distorted to demodulate properly.

  12. Mark I posted in the comment thread on HackADay. I’d really like to show my coworkers one of these. Are you still sending out units to test? How do I find your email so I can send you my address?
    Thanks for your time,

    1. Hi Brandon! Thanks for your interest. I had originally reserved the remaining three boards I had for the first three that requested them i the HaD thread, but only one of them got back to me, so I still have 2 boards left, and I’ll be happy to send you one. If you click the “PGP key” link in the menu, you can see my email address in the filename of the key (it’s just “mark” at this domain). Send me your address, and I’ll mail you a board!

  13. Hi, thanks for posting this design.. I’ve loaded the firmware to an Arduino UNO and setup the circuit as per your schematic diagram.
    I’ve not hook it up to the radio but tap the mic output to a headphones/speakers after C2 but before R5/R6 … The sound is too soft when I press any key into the Serial Monitor, can this trigger the VOX ? I’ve also hook the Rx and Tx to the Rigol oscilloscope to see the signals…
    As for the Line In, I could not detect or decoded any messages in the Serial when I run the TNC Test CD http://wa8lmf.net/TNCtest/ ..
    Any ideas on how to troubleshoot this ?? Thanks..

    1. Hi Stanley!
      First of all, try to hook up your oscilloscope to the TX output of the modem and see what the voltage level of the signal is. Before the R5/R6 divider, you should have a level of about 2 volts peak to peak. After the divider, the level should be around 20 millivolts peak-to-peak. The level after the divider will be very soft, and way to soft to drive a speaker or headphones, but most radios will need this low level, because they expect a signal from a microphone, otherwise, the audio will get distorted. What radio are you using? Most handhelds will trigger the VOX fine with a 20mv signal, but you will get better performance if you use the PTT circuitry.
      If you are trying to decode APRS packets, you need to use the firmware in the AX.25 branch! The standard branch does not use the AX.25 protocol, but another protocol I wrote to illustrate some concepts such as forward error correction. So the “default” firmware build will not decode APRS packets. Take a look at this branch:
      This branch has a precompiled firmware for AX.25/APRS packets, and should decode from the test cd just fine!
      Let me know how it goes! I hope you get it to work for you!

      1. Dear Markqvist,
        Thanks for your quick reply… really appreciate it ..
        After I flash the APRS firmware from yr AX.25 branch, I managed to decode the APRS Test CD when I put the sound volume at Max, and can decode most of the messages …
        As for the Tx, I accidentally wire the 270R in series between the C2 and therefore the output voltage was at 20mV .. Once I fixed the circuit, I’m getting a 1.76 P-to-P voltage as per the measurement from the oscilloscope.
        I hook up the Line Out Tx to the Rx and the Serial Monitor is able to decode the “Test APRS packet”..
        Thanks for your assistance ..
        My next step is to hook it up to the Wouxun UVDP1 handy …

        1. Great to hear Stanley!
          I’m glad you found the problem and got it working! I have that handy as well, and the PTT circuit should work with that out of the box. Although I have found that the squelch is a little slow at opening up on that radio, but maybe it is just mine. Good luck!

          1. Dear Markqvist,
            I’m confused about the China/Kenwood PTT pinout as there are too many versions of the diagram on the Internet.
            Can you share with me your working diagram ?
            The 3.5mm is MIC and PTT and the 2.5mm is for Speakers …

          2. Hi Stanley
            Sure, if you have a look at the schematic I made here:
            The topmost section of it is the PTT circuit. It is very simple, only two components. The version I made uses a 2N7000 MOSFET transistor to trigger the PTT. Here is how it works:
            – On the 3.5mm MIC jack, there is about +3v on the GND pin (the “sleeve”)
            – When this +3v is connected to the GND pin of the 2.5mm speaker jack, the PTT triggers.
            – The MOSFET makes a connection between these two points when pin D3 is made HIGH. Toggling the pin to HIGH happens automatically in the firmware everytime something is to be sent out.
            Please try to see if this circuit works for you. I have tested it on three Baofengs and a Wouxun, and it worked good for them, and was the easiest and simplest way I could come up with.
            Also remember that you need a MOSFET, a normal bipolar junction transistor wont work like this.
            So to recap:
            – Connect MIC GND to PTT_V+
            – Connect SPK GND to GND
            – Connect SPK output to LINE_LEVEL_IN
            – Connect MIC input to MIC_LEVEL_OUT
            I can’t remember off the top of my head, whether the MIC and SPK jacks use the ring or the tip pin of the jacks, but you can take your scope and measure on the SPK jack to check it out, and just try both with MIC jack until you hit the one that works.
            Hope you make this work!

    2. Also, if you continue to have problems, take a photo of your circuit and send it to me, I will have a look if something is wrong!

    1. Glad to hear you got it working!
      So awesome to see the packets picked up! Thanks for sharing that πŸ™‚

  14. As my circuit is fully working ( LineOut, LineIn and PTT ), I made another Arduino UNO Modem with identical circuit & firmware on both UNO ( MP1 protocol with DEBUG turned on ).
    When I connect the Modem #1 LineOut to Modem #2 LineIn and vice-versa and another wire connecting both the Gnd …
    I could not decode any of the packets …
    For debugging, I tap a speaker to the connection on both sides ( LineIn / LineOut , I can hear the tone but the input LED or Serial screen could not decode the signal .. )
    Can you suggest some idea on how to troubleshoot this ? Is my direct connection wire correct ?
    As for the AX.25 branch, I added the SSID to my callsign, but it did not show up in aprs.fi
    #define YOUR_CALLSIGN “9W2SVT-3”
    Is this the correct way to put the SSID into the codes ?
    Once again, thanks for your help on this matter…

    1. Hi Stanley!
      Sorry for the slow reply, I’ve had a lot of work the last couple of days. First of all, regarding the callsign, this is the correct way to do it:
      #define YOUR_CALLSIGN “OZ7TMD”
      You enter the SSID in the AX25_CALL function, so if you want ssid 3, you do it like this:
      Hope that makes sense πŸ™‚
      Also, if you have a speaker connected to the circuit, it wont be able to decode, since the speaker is providing too big a load for the arduino to register the signal. All the signal is “sucked up” by the speaker. If you remove the speaker, and there is still no receive LED, please take a closeup photo of your wiring and send it to me, I will try and see if I can figure out what is wrong!

  15. Hi, and thanks for sharing this. I made the circuit, and it works like a charm with the modem firmware loaded to the arduino.
    I tried to use a BJT (2N3904, TO92) for PTT, disregarding your warning that it might get stuck on transmit. It worked just fine in the UHF band, but not in VHF. So, not having a suitable MOSFET at hand I thought I’d try a BJT in a TO18 package (you know, those with the tin-can housing). It happened to be the 2N2222. Maybe the metal package works like some sort of RF shield, or maybe I was just lucky, but it works.
    Thanks again. And do keep up the good work!
    73 de LB3MG

    1. Hi Bernt!
      Thanks for sharing your experience! That’s great, hadn’t thought of that, but you are probably right that the metal is shielding it better than the polyester package! The most important thing is it’s working πŸ˜€ Good stuff!

  16. Hello guys, i’ve been trying to make 2 of this amazing modems work but i don’t seem to make it, do the data go in and out the serial port of each arduino, i would really be thankfull if anyone could help me πŸ™

  17. Hi Mark! Great job you are doing – nice site, nice pictures of nice projects! I am jelly I do not have the gift of sharing my projects the beautiful way πŸ˜‰
    I am just going to set up some experimental aprs igate possibly using a raspberry. I am not sure whether to use soundmodem, or sth like your micromodem. What do you think?

    1. Hi Adam!
      Thanks for the kind words!
      Well, soundmodem works really well, and it’s pretty easy to get set up following some of the available tutorials on the web. Only issue is the Raspberry doesn’t have recording device on it’s onboard soundcard, only line output. I actually did this myself at some point, and what I did was to use an old USB headset I had laying around. You can just cut it up and solder on connectors for your radio, and it works pretty well. Either way, you will need some additional hardware for the Pi, and in my opinion, nothing beats having a real dedicated modem. It’s also much easier to set up, since you just need to input the serial port and off you go. It’s not terribly hard to build one if you have the components and a breadboard, or you can always buy one from me πŸ™‚

  18. Hi Mark!
    You are right, the raspberry does not feature an audio-in.
    I’ve just spent a weekend with the modems and radios πŸ™‚ First I was trying to get the WhereAVR project decoding my packets and have left a load of time on it. Then I figured out, that it is my shitty radio Baofeng UV-5R giving signal somehow distorted, that it is almost impossible to decode..
    I’ve taken a look at the micromodem’s code and it seems to me, that micromodem has a more robust demodulation algorithm, than WhereAVR. It will be just more difficult to get it compiled, as the project structure is somehow complicated with all the bertos stuff. I am using AVR Studio IDE. For now, I have just flashed the binary. I’ve had an atmega328p lying around, though it was more difficult to find a 16 MHz crystal, but succeeded.
    And it works! I think it is gonna be my favourite πŸ˜‰
    In the lab it worked with Quansheng TG-UV2 low cost, but hardly with the Baofeng UV-5R. I am looking for some tests in the real world!
    Thank you!

    1. It’s right that the UV-5R can be a little finicky in getting the levels right, but in my experience I have decoded lots and lots of packets with MicroModem and an UV-5R, so it should be possible to get it working fine.
      But don’t use the old MicroModem code with BertOS! You should use the new version I completely rewrote to get out of the BertOS dependencies. It is much more simple and clean, and much easier to compile and get working. The demodulation is also a tad bit more optimised in that version πŸ™‚

  19. I’m working on a handheld data capture device – input from a numeric keypad – with APRS connectivity. I think your code may help with the APRS part. I wonder if I can get the same Arduino to run the keyboard and the APRS modem. Off to the breadboard…

Leave a Reply

Your email address will not be published. Required fields are marked *