Creating an I2C sonar for Arducopter

I've created an I2C digital signal sonar module to avoid the noise problems I have been having with the current analog signal sonar module.


Seeing all the problems we are having with noisy sonar data got me thinking

Where does the noise come from? Is it:

  • RF noise from the ESCs affecting the sonar module directly ?
  • RF noise from the ESCs affecting the analog signal line between the sonar and APM?
  • Noise on the DC power supply affecting the Sonar module?
  • Something else?

The current popular solution of remote mounting the sonar has probably eliminated DC power as the primary source of our noise. In other words - if noisy DC power was the ource of the noise problem then no matter where you mount the sonar you would still have the noise. Regardless if DC noise were still an issue Maxbotics has a solution to DC noise in their FAQ.

Personally I've found that remote mounting the sonar module has only partially solved my noise problems. This is probably due to the Sonar power and signal cable passing within 10mm of one of the ESCs near where it plugs in to the APM on my arducopter.

(This photo shows how close my ESC is to the analog port on the IMU Shield)


So I wondered if I could get rid of the analog signal path and see how the sonar noise changed. This has led me to put together a I2C sonar module. This communicates digitally between the sonar and APM using the I2C port on the APM IMU shield. It also allows you to use the PWM output from the sonar which Maxbotics recommends as "the most accurate"



All that is needed is an Arduino, an I2C cable and some software.

Arduino mini

DIY Drones GPS Cable

The GPS cable supplies power and connects data lines between the Arduino and APM IMU Shield (you need to cut one end off the cable)

APM IC2 Function Arduino Mini

PIN1 <-----> GND <-----> GND

PIN2 <-----> 5V <-----> VCC

PIN3 <-----> SDA <-----> A4

PIN4 <-----> SCL <-----> A5


Three Wires connect the Arduino to the Sonar

Arduino Function Sonar

GND <-----> GND <-----> GND

VCC <-----> 5V <-----> V+

D5 <-----> PWM <-----> PIN2


Here is what it looks like mounted on the sonar - with double sided tape

The sonar is on a standard jdrones sonar mount


The Arduino then needs to be programmed as an I2C slave.

Here is my code

You must use an FTDI cable to program an Arduino Mini

The code continuously reads and stores the sonar distance as a PWM signal from the module.

It responds to any I2C request for data with a two byte integer representing the current sonar range in cm.

Additionally it has the ability to return noise filtered sonar data.

Note the MaxBotix experts strongly recommend a mode or median filter not averaging filter.

Currently the code can be requested to return spike filtered, median or mode filtered data.


I have modified the Arducopter code to use this I2C sonar and started testing

Here is my sonar library

If the testing all works OK I'll see if Chris or Jason want to put it in the code repository



To put it simply the results so far are great!

Indoor and outdoor tethered tests show no noise and no data problems

Here is a graph showing Sonar data in red and baro in green.

first segment is with motors running second with motors off

Its too windy to fly here today (in the Aussie vernacular: It's strong enough to blow ya dog off its chain!)

Stay tuned!




Views: 19750

Comment by Andrew Radford on July 29, 2011 at 1:56am

Don't some of the sensor models already have PWM (and serial?) out? I remember seeing that in a datasheet somewhere...

Comment by agmatthews on July 29, 2011 at 2:44am


Yep you are right

The Maxbotix Sonars have PWM and Serial as standard.

The serial ports on the APM main board are already in use and at 9600bps its a bit slow and the maxbotics implementation of serial is a bit screwy with inverted RS-232 - that rules all but out serial.

PWM is the recommended "most accurate" way of using the Maxbotics modules (from the data sheet), however measuring the pulse length on a digital pin on a ATMega / Arduino with the 'pulseIn' function is a blocking action (ie the rest of the code stops while it measures the pulse).

I did not want to put any blocking code on the main autopilot and risk slowing down the DCM/IMU functions. So I run all the PWM code and all the noise filtering on the Arduino mini. The main Arducopter code then just does an I2C request for the data when it wants it

I used the barometer code in APM_BMP085 library as a template. I'll attach my library up above in the main post

There's plenty of spare capability on the Arduino mini in this example.

I've been wondering what else I could use it for...... any suggestions


Comment by Bernard Michaud on July 29, 2011 at 6:17am

How about shielded wire to prevent RF from getting involved in noise building (Sonar power and signal cable proximity). As anyone tryed this before ?

Comment by agmatthews on July 29, 2011 at 6:26am
Some folks are reporting good results with shielded cable AND relocating their sonar. So it's a bit hard to tell which one fixed the noise problem.
Ive not seen any results either good or bad with just shielded cable on the analog signal.

I could diminish the noise on my sonar by moving one ESC about 10mm away from the cable/IMU board. However it would return just when I didn't want it too.
Comment by diego colonnello on July 29, 2011 at 7:20am

this can be done with the Parallax PING))) sensor????

Comment by Bernard Michaud on July 29, 2011 at 7:34am

Need to know what is Parralax PING sensor. Thanks

3D Robotics
Comment by Chris Anderson on July 29, 2011 at 8:03am

Impressive! Have you compared that with the recommended solution of just mounting the regular sensor three inches away from the ArduCopter body?


Comment by afernan on July 29, 2011 at 3:26pm
I,m tested all posibilities. I,ve started shielding all power and signal cables AND moving far from ESC the sonar (not to much, to avoid longer cables) . It solved completely the problem. Then I relaxed a bit the thing, and I put again standar rc cables, but sonar moved away. Still very good, but sometimes crazy jumps apeared (noise).

My final conf is shielding only the signal cable, moved away ESC and avoid connectors (cable directly welded to APM). The result is a rock solid alt-hold. I'll post some video.
Comment by agmatthews on July 29, 2011 at 4:03pm
@Chris, I proved that in my case the noise was at least partly the result of the conar cable passing too close to one of the ESCs. @afernan seems to have done a different series of tests with the same result (ie it's the cable where the noise is coming from rather than the sonar module)

Shielded cable or going I2C allows folks to continue use Jani's jdrones sonar mounts.

The I2C experiment is probably a bit over the top when shielded cable gives similar results but it was an interesting journey and gives a template for adding future sensors or outputs without needing any APM hardware pins
Comment by agmatthews on July 29, 2011 at 4:18pm

@diego colonnello and @Bernard Michaud

Yes you could easily modify this you use a Parallax PING))) sensor

Following this tutorial you would just change the readsonar.pde in my code to interact with the parrallax sensor by sending a pulse to it before waiting for data back

Something like this:

int ReadSonarPulse()
long val = 0;

  digitalWrite(SONAR_PULSE_IN_PIN, LOW);
  digitalWrite(SONAR_PULSE_IN_PIN, HIGH);
  digitalWrite(SONAR_PULSE_IN_PIN, LOW);
  val = pulseIn(SONAR_PULSE_IN_PIN, HIGH,(US_PER_CM*MAX_RANGE)+1000); 
  val = val / US_PER_CM; 
  return((int) val);


You need to be a member of DIY Drones to add comments!

Join DIY Drones


Season Two of the Trust Time Trial (T3) Contest 
A list of all T3 contests is here. The current round, the Vertical Horizontal one, is here

© 2020   Created by Chris Anderson.   Powered by

Badges  |  Report an Issue  |  Terms of Service