Testing the dronecell or other GSM modem

In this page you will find information about testing and using the dronecell or another GSM modem with APM's new AP_Modem library

The current code is still in early development, is buggy and requires some experience to compile and deploy. But, it works and it allows telemetry to flow over TCP or UDP anywhere around the world, directly from your drone!


- APM1 or APM2 can be used. The code is different slightly, so test each separately

- A dronecell or any other AT-command compatible modem

- A data-plan SIM card

- (Optional) Dynamic DNS or fixed IP for convenience

Skills: You will need to be able to compile the ardupilot-mega code from source and install it on the hardware. 

1 Getting the hardware

If you do not have a dronecell, you can try buying one online from diydrones or another store. You might find it difficult to source one. 

Other than the dronecell, you could try another GSM module. The closest is the Arduino GSM shield sold on Amazon which includes a SIM900 GSM module, which is the same brand as the dronecell modem. 

The code should work for any GSM modem that supports AT commands. The only changes would be in the init_script. If you are brave, try another type of GSM/GPRS modem.

SIM Card: Need a compatible GSM network. I personally use the T-Mobile pre-paid SIM card with $2 per day cost (for any day it is tuned on) and up to 200MB of data. It cost me only $10 to buy, all cash, no contract, no names, no addresses ;-)

2. Getting the software [UPDATED x 2]

The software is available as a new branch of the code, based on ArduCopter2.6 and ArduPlane2.4. (ie, the current master branch).

Using GIT

If you are familiar with git, you can pull the modem_test branch from google and compile it, from here:


You will need to checkout the modem_test branch

git checkout modem_test

then compile and install

Download a pre-compiled HEX file to flash

ArduCopter 2.6

Downloading Manually  [ This approach is no longer practical ]

3. Preparing the hardware

The dronecell comes with a default speed of 38400. Other modems may be set to 9600, or any other speed. The APM1 telemetry port is at 57600. So the two must match. You have three options:

a) Change SERIAL3_BAUD to 38400  in ardupilot code. My libraries respect whatever you set and will work with it. Then the dronecell will work. But xbees won't. So you will have to swap the speed in the code back and forth between 38400 and 57600 to use other radios.

b) A better option is to set the dronecell to 57600 permanently. Connect to dronecell serial to a serial2USB (FTDI) cable a terminal (the one in Arduino IDE will do) and change it to 57600. If you don't have an FTDI cable, you can slave the modem to any Arduino board by connecting it to TX0 and RX0 and then running an empty script ("Basic" in ArduinoIDE). 

Commands are:


changes speed to 57600


writes the change to memory permanently.

c) If option (b) is too complex, then you can also do the following... do (a) to have APM able to speak to the dronecell at 38400. Then change the init_script (in Cellular_Modem.cpp) and add the following in the fifth or sixth line (doesn't matter really exactly where, just after the initial 4 commands):



That will have the APM tell the dronecell to switch baud rates. The rest of the script will fail (APM is still trying to talk 38400 at this point, but the dronecell is now listening at 57600). Change the SERIAL3_BAUD back to 57600, and now dronecell (and everything else) speak 57600. 

4) Configuring the Software

You will need to make changes to the settings to reflect your SIM card provider

Open AP_Modem.h and find these lines:

#define VAL_APN         "internet" // value for the APN
#define VAL_USER        "" // value for the user name
#define VAL_PW          ""      // value for the password

The settings above are the ones that worked for the T-mobile SIM card. Most SIM cards no longer use a "username" and "password" to log onto the data network, so those usually remain blank. The APN is carrier specific, though many use "internet" as the APN, so try that.


Once you've made the changes, compile and install the code.

5. Connecting the modem

You will need to connect the modem to the telemetry port. Look at the instructions for Xbee, and see where the telemetry port is on your board. If you already use Xbee, this is easy ;-)

Connect RX, TX and GND to the modem. I can't remember if it is TX->TX or TX->RX, but if the modem isn't responding, try switching around. Having an FTDI cable to troubleshoot or an extra Arduino will help a lot.


A GSM modem will draw up to 2.0-2.5A in bursts when transmitting. You cannot power it from the APM. You probably cannot power it from an ESC BEC, though you could try. I power it from a 10A rated BEC (Castle BEC). You can also use a separate battery and BEC to power it. Whatever you do, you need to meet two requirements:

1) provide at least 2.5A clean power at 5V

2) power modem and APM from same power*

* They must share a GND for the TTL to work. If you have two power sources and share a GND, you may create a weird path through your board from one power source to the other. *ZAP*. Easier to run both off a sufficiently strong BEC or battery.


6. Set the parameters [NEW]



MDM_BLIND 1.000000 -- Set to 1, to dial blindly. Set to 0 to validate the modem response

MDM_DEBUG 0.000000 -- Set to 1 for debug messages on the console 

MDM_ENABLED 1.000000 - Enable

MDM_IP1 192.000000  - First byte of IP address
MDM_IP2 168.000000 - Second byte of IP address
MDM_IP3 0.000000
MDM_IP4 161.000000 - Fourth byte...

MDM_PORT 14550.000000  - Port number 

MDM_PROTO 0.000000 - Protocol - UDP=0, TCP=1

MDM_RATE 115.000000 - Serial speed - short form (1=1024,2,4,9,19,38,57,115=115200)

MDM_SERIAL 3.000000 - Serial port (0 is Serial/console, 3 is Serial3/telemetry)

MDM_STATE 0.000000 - Don't change, used to see what state we're in

7. Setup the GCS

The GCS will need to connect to the Internet with a public IP address and the ability to receive traffic on UDP/14550 (or if you changed that, whatever you set). The IP address must be fixed or have a dynamic DNS name, or you will have to set it in the code each time you re-connect. I use a dynamic DNS for convenience. For testing, a fixed IP will work fine. 

Make sure the port is open on any firewalls or gateways and the traffic can get through. 

With Mission Planner, you will set it to UDP and to listen on port 14550.

8. Start the APM

If you are connected on the USB, you will see the modem initialization in ridiculous line-by-line detail (if debug is on). It looks like this:

Init ArduCopter V2.6-modem

Free RAM: 4096
FW Ver: 118

load_all took 67us

--MODEM starting on Serial 3 @ 115200 baud
Press ENTER 3 times for CLI

ublox update:35: gps read timeout 3662 0


9. Success (??)

If all goes well, here's what should happen:

- Your APM starts up

- The APM sends the init script to the modem

- The modem establishes an Internet link and then start copying traffic (bridging) over UDP or TCP. 

- The APM sends Telemetry data, once it is done initializing. 

- The telemetry data flows through the modem, across the Internet and to the UDP port. This takes about 30sec to a minute to start arriving the first time. 

Wait for a bit for the flow to start, then start MP and tell it to listen on UDP 14550. If all goes well, it will say "Getting parameters" and then connect in the usual way.

You will notice about a 2 second "lag" between activity on the drone and activity on the GCS. You move the drone, the horizon moves on the GCS two seconds later. That is because of the latency introduced by the Internet routers. It can be optimized (and will), but will always be a bit lagged compared to line-of-sight speed-of-light radios. However, despite the latency, the system is not losing packets at 57600 and the flow is consistent and good. So except for joystick flying, you can do your mission planning, PID tuning and such easily over IP.

Comments, questions or support requests below. 


You need to be a member of Telemetry over cellular IP to add comments!

Comment by Paul Henckel on November 15, 2013 at 4:29pm

Has anyone tried this with ArduPilot 3.1?

Comment by Richard Sterling on July 2, 2013 at 4:38pm

Can anyone help me the hex file page is no longer available, does anyone have it or knows where I can find it?

Comment by Adam Scriven on February 6, 2013 at 9:27pm

Hello, sorry to resurrect an old thread, but I'm wondering if there's a more UMTS/HSPA compatible device? I'm actually looking for the cellphone voice/sms/data 'thing' for at least 3 projects, but can't find any suitable for most Canadian carries (IIRC they would also be compatible with AT&T), specifically UMTS/HSPA+ 850/1900, and MUST have voice capabilities (don't want to rely on VoIP/data-voice solutions for voice, want to use existing cellphone voice network).

Thanks very much!

Comment by Jeffrey Nichols on February 5, 2013 at 8:01pm


I have loaded your ArduCopter code to my APM2.5 and have it running connected to my PC via USB. I have my droncell clone (icomsat1.1) connected to my APM2.5. What I can't figure out is how to accomplish step 6 above - how do I change those settings? CLI is working but I can't figure that out.



Comment by John on December 8, 2012 at 9:30pm

I'm having a tough time getting my dronecell up and going. 

I'm using a Tmobile 2 dollar per day plan. 

I have a DNS setup mydrone.dnsdynamic.com

I'm having a tough time editing the code from source to work. 

Does anyone have a working arduplane code with drone cell they can share? I will update with my DNS and ip info. Please PM


Comment by John on December 2, 2012 at 5:46pm

Is there a precompiled hex for arduplane?

Comment by Veikko Vierola on October 27, 2012 at 9:37am

Been a bit busy lately. I will try to test the higher byte size soon...

Comment by Søren Kuula on October 26, 2012 at 2:07pm


I'm trying to get updated in the state of progress in GPRS telemtry for APM...

Does someone have it running in other than transparent mode already?

I have made an experimental sort of state machine that initializes the SIM900 and makes an UDO connection. It will recover if the modem is restarted, or if it is that itself. Currently, it runs in Java on a PC or similar, but I will eventually rewrite it in C++ and then as an Arduino lib. But maybe someone is ahead of me?

But I don't understand why the NAT would be the problem cause I have open ip and no gates closed?

The NATs must learn which UDP port number on the great Internet should forward to which IP address behind it. This normally requires that the host with that IP address has recently sent out an UDP message with the same local port number. With Mission Planner behind a NAT, one may end up with the APM sending messages to the NAT that it can't forward, and a Mission Planner sitting waiting for data that does not arrive.

Soren, how should I change the 10 bytes send size?



replace the second 10 by something larger.



Comment by Veikko Vierola on October 15, 2012 at 11:13am

Soren and Aslak...Thanks for the answers...

I managed to get the udp working with QGroundcontrol but not with Mission Planner ever? But I don't understand why the NAT would be the problem cause I have open ip and no gates closed? Soren, how should I change the 10 bytes send size?

"QGroundControl on the other hand sends some heartbeats from the beginning, punching the necessary hole in the NATs." -> I just wonder why is the Mission Planner not programmed to send these heartbeats from the beginning???? So that it would be possible make the connection to Mission Planner......

By the way is the UDB connection 2-way connection?? Can Isend commands to APM via udp?

Comment by Søren Kuula on October 11, 2012 at 10:38am


Andreas, I get an error from GIT when trying to clone your repo. It there a way to fix it? "fatal: Couldn't find remote ref HEAD".

Does your code use transparent mode on the SIM900 or not? Does it try to chunk 1 Mavlink message to 1 UDP message?

Veikko: I have looked at your config (and tried it too - play it into the SIM900 from a terminal and then plug the modem into the telemetry port). There is something I thinks needs to be changed:

AT+IPR=57600                Set baud rate
+++ATH0                        Hang up
AT+CFUN=1,1                 Some power mgmt
AT V1 E1 X1 S0=0           V1=use text response format ("CONNECT" instead of "1" etc)
                                      X1=Do not tell about busy signals and dialtones in responses.
                                     S0=do not answer calls.
                                      E1=Enable echo
AT+CREG=2                       Registration Enable URCs with stat and location and cell ID
AT+CMEE=2                       Enable verbose error return codes
AT+CR=1                         Enable reporting of type of service at call setup
AT+CRC=1                        Enable reporting of typt of service at ring
AT+CSNS=4                       Single numbering scheme=data     
AT+CSMINS=1                     Enable URC at SIM insertion/removal     
AT+CSCLK=0                      Disable slow clock (sleep mode)
AT+CIURC=1                      Enable "Call Ready" URC at startup  
AT+CGEREP=2                     Buffer URCs in TE until TE link becomes available        
AT+CIPMUX=0                     No multiplexer
AT+CIPMODE=1                    Transparent mode on
AT+CIPCCFG=8,10,10,0         Transparent IP: 8 retries, 10 *200ms wait, 10 send size (waaaay too small!), escape sequence is off

AT+CMUX=0,0,1,127,10,3,30,10,2  Multiplexer setup (but multiplexer is disabled)
AT+CIICR                        Bring up wireless connection with GPRS or CSD
AT+CIFSR                        Get local IP address

Your transparent mode set-up limits UDP message size to 10 bytes, which is also what I observed. That is too little. The multiplexer is being configured but not used, the same for some incoming call stuff.

I think the reason that you can't get Mission Planner to get any data is NATs in the networks. Same thing happened to me. Mission Planner just sits there listening to UDP, but befoer it sends some data, a NAT on the Internet link would not ne able to forward incoming UDP messages to your computer. QGroundControl on the other hand sends some heartbeats from the beginning, punching the necessary hole in the NATs.

As far as I can see, the only feasible way to get a link going mobile-Internet-mobile is to use a data relay server in the middle. At least to initiate the connection (see "UDP hole punching" on Wikipedia). What I have now is a fixed IP address server with some software on it that I have thrown together, that accepts a number of TCP and UDP "connections" and relays to all except the sender what comes in on a connection. That works OK.

Don't use TCP for the drone to Internet link. It will be unable to recover from any bad link situation that comes along (in my experience).

Kind regards


Comment by Aslak Shallo on September 25, 2012 at 12:04am

Hi Veikko,

How's it going with the testing? Have you managed to get Dronecell to communicate with MP over UDP?

Comment by Veikko Vierola on September 18, 2012 at 10:47am

More DroneCell testing results...

I entered all DroneCell AT commands below to the modem with Tera Term (terminal), row by row manually.

AT V1 E1 X1 S0=0                            

After the last command modem reported that the connection is established, then I switched the tx rx cabels from the modem to the APM telem port tx rx, started QGROUNDCONTROL and it's udp connection and voilà! the connection worked. When I banked or rotated the APM the horizon moved accordingly on the QGROUNDCONTROL screen (about 0.5 to 1.0 delay). I managed to repeat this test 4 times with QGROUNDCONTROL, but not once with the MIssion Planner!!!???. I wonder why the Mission Planner does not receive the udp data???



Comment by Veikko Vierola on September 10, 2012 at 8:42am


I was thinking that it would be very nice if DroneCell had the same kind of configurator as the 3DR radio has, something like this. Maybe it could be easier to use in the beginning?

Comment by Veikko Vierola on September 4, 2012 at 3:17pm


Getting close now.....

I was able to make tcp connection between dronecell and my computer with 3G modem. I used Terminal and Dronecell in the other end and Tera Term and 3G modem in the other end. I think the problem has been that when I've been trying to make TCP connection to DroneCell it has always rejected the connection because DC didn't have server setup on. I was even able to send a text file with full page of text just ticked binary option from Tera Term send file window. Now I'm sure that also I'm able to make DroneCell communicating over TCP connection via internet. Tomorrow I'll try to figure out why M-Planner doesn't get heatbeats, maybe wrong baudrate or something???

Here was the solution:


Comment by Andreas M. Antonopoulos on September 3, 2012 at 2:32pm


I have not tried this configuration because I have a smartphone with hotspot capability, so I used that. It allowed incoming UDP and it worked for me. However, from your setup I think it is hard to determine where the problem exists. 

I think it is best to test the Dronecell and the 3G modem separately, as follows

Test 1: APM->Dronecell->Internet->DSL->Home PC

Use wireshark or tcpdump to see if data is coming to PC. Or just put Mission Planner and listen for a connection

Test 2: APM->USB->MAVproxy to UDP->Internet->3G modem->Laptop

See if Mission Planner on Laptop can see APM

if both Test 1 and Test 2 work, but your test with both does not, then something else is broken.

That way you can determine which part is problematic. 

hope this helps


Comment by Veikko Vierola on September 3, 2012 at 1:21pm

Hi, a bit help is needed here to figure out what is wrong.

This is the setup I'm trying to get working (test code made by Andreas) . I have tried everything to make this but can not establish the connection. Is this even possible configuration? Do I really need a fixed ADSL etc. on my mission planner computer to get this work? Has anyone else managed to get this kind of setup working (APM1->DRONECELL->NETWORK->3G USB MODEM->COMPUTER)? Does anyone know how to make sure that the DroneCell is sending the data to network? How to listen to some port? WireShark, TCP DUMP???

Comment by Veikko Vierola on September 2, 2012 at 7:46am

Now back to basics. Is this the right way of thinking? Please correct if there is something wrong.


Set OPERATOR APN to modem.cpp
Set COMPUTER IP (use ipconfig on CMD to see the ip) to the Mission Planner MDM parameters
Set protocol 0=UDP to the Mission Planner MDM parameters
Set user defined UDP PORT NUMBER to the Mission Planner MDM parameters
Set user defined UDP PORT NUMBER when opening the udp connection with Mission Planner


Set operators APN to modem.cpp
Set protocol 1=TCP to the Mission Planner MDM parameters
Set user defined TCP PORT NUMBER to the Mission Planner MDM parameters
Set DRONECELL IP (use arduino IDE serial monitor to see what ip the modem has) and user defined TCP PORT number when opening the tcp connection with Mission Planner

@Andreas, could it be possible to have one more visible status parameter to the Mission Planner so that you could see the DroneCell ip-address without Arduino IDE....

Comment by Veikko Vierola on August 29, 2012 at 1:32pm


Ok, thanks. Next I need to put the FTDI between APM and DC to check if the modem responses are reasonable too. Do you have any idea how to check if the modem is really sending the mavlink data to the internet to some ip/port? Now I can only see that the data is getting out from APM tx....

Comment by Andreas M. Antonopoulos on August 29, 2012 at 1:19pm

That is exactly wht it should look like Veikko.

mavlink is a binary protocol. The header of each mavlink packet contains certain patterns (the Q character is one that repeats in every packet).

This looks like the APM is executing the intialization sequence exactly as it should: delay mavlink, send the init strings, then start mavlink over the established TCP or UDP connection.

Comment by Veikko Vierola on August 29, 2012 at 1:10pm

Hi, few questions:

1. Does anyone know how the MavLink data should look like in hyper terminal. I connected FTDI to APM TX and this is how the modem commands looked like:

After connecting to the internet the APM starts to feed the MavLink data, but I'm notr sure if it is suppose to look like this (strange symbols no readable numbers or text).

2. If I want to listen traffic between APM and modem with hyper terminal, how should I connect the FTDI cable between them? In the previous example I just listened the APM tx feed, DroneCell was not connected...

© 2014   Created by Chris Anderson.   Powered by

Badges  |  Report an Issue  |  Terms of Service