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: 19699

Comment by agmatthews on July 30, 2011 at 4:00am

Some lessons learnt from today:

Firstly Noise is difficult to track down. Just when I though I had a noise free solution it was back, definitely coming from the ESC / motor wiring somewhere. All I had to do was move the ESC wiring a few mm and noise was back. Grrrr. So it looks like the noise is probably a combination of sources including the ESCs having a direct influence on the sonar module itself. @Chris was right all along. Moving the module away OR moving the wires away fixes the problem. Lesson number one learnt - the sonar is now out on the forward motor arm.

Lesson two was harder to track down. Put simply if you stuff an integer in to a byte it works most of the time. My code above tries to return the integer in the read() function as a byte. tut tut...fixed now.

Lesson three. The more you look the more you find. At the moment it appears that sonar code in the ACM source has a few problems. First it averages the sonar values - something Maxbotics insists is WRONG! Second it does not allow for the fact that the sonars have a hard limit at the top and bottom end >765mm and <20mm. For example it appears that the code keeps blending the sonar and barometer out to 1500cm - at this point the sonar would have been steady at 765mm for 600mm or so. Time to do some remedial coding

Comment by Pieter van Woerkom on July 30, 2011 at 6:28am

Found a nice example of a maxbotix mode filter.


Have applied it to my raw sonar readings and it works great. Could be a nice improvement to APM.


3D Robotics
Comment by Chris Anderson on July 30, 2011 at 7:28am
We do all sorts of software filtering already, but have learned that sometimes you just need to stop the noise at its source, in this case by moving it away from the ESCs.
Comment by agmatthews on July 30, 2011 at 7:54am


That the same template I used for my mode filter

Cleans up slightly noisy data well

Comment by agmatthews on July 30, 2011 at 8:02am

@chris have a read of this post from maxbotics  particularly the bit about filtering.

Looking through the APM code we appear to be doing an "average filter" on the sonar in RangeFinder.cpp exactly what maxbotics tells us not to do.

I have swapped this for a Mode filter (same as Pieter recommends above) with good results

I'm currently looking at the code in update_alt() that does the blending between sonar and barometer as it seems to ignore the sonar maximum range value.


Comment by Jason Short on July 30, 2011 at 9:35am

I'll remove that filter and replace it with a mode filter, no problem.  Can you post your code?

I actually only mix the barometer in from 4 to 6 meters. That 1500 you see is a 15m emergency cutoff so a bad sonar doesn't send it to the stratosphere.


Comment by Jason Short on July 30, 2011 at 11:05am

OK, Mode filter class is coded up and running. I'll include it on the version 2.0.38


Comment by agmatthews on July 30, 2011 at 3:52pm

@jason if you are still chasing it my mode filter code is in the "" in the blog post above. Note, it is important to have it calculate the median if a mode value does not exist


Comment by Randy on July 30, 2011 at 8:29pm


     Great detailed analysis and post.


In the "somthing else" category of possible causes, I had thought that the noise could be caused by peripheral sound interference so I bought one of these more expensive weather resistant maxbotix sensors but it has exactly the same issues.


Comment by Pieter van Woerkom on July 31, 2011 at 12:45am

Allso have a look at my post about shielding LINK


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

Join DIY Drones

© 2020   Created by Chris Anderson.   Powered by

Badges  |  Report an Issue  |  Terms of Service