in-accurate compass readings with servos running

I have been struggling to get my LSM303DLHC to return accurate compass readings when the servos on the robot are in use. The robot is a parallax BOE-BOT chassis with 2 continuous parallax servos in a differential setup and a servo rotating a ping sensor on the front of the chassis. I have tried moving the compass up to about 13cm or 5" away from the nearest servo, but with such a small chassis it is difficult to locate the compass further away with sticking on a "pole" that would leave it exposed to colliding with objects the robot cannot see.

All the following were taken while the compass was facing south (180 degrees)
Here is a set of readings after calibration with all the servos off.
180 181 181 181 180 181 180 182 181 181 180 180 182

Here is a set with just the drive servos running
188 185 193 186 183 188 181 169 182 173 193 166 194 183 192 170 174 176 167

Here is a set with just the turret servo running
178 164 177 179 181 189 179 198 186 164 177 179 189 179 190 166 181 180

And lastly here is a set with all 3 servos moving:
180 214 181 169 160 189 183 190 177 175 189 211 176 193 165 182 204 189

I have read about soothing out the compass signal by averaging out readings and have been trying different calibrations and calibrating at different gain levels, etc. (so far to no avail).

I am looking for any advice and the experience others have had on ways to deal with this issue. Is the noise from the servos possible to "calibrate out" at this physical distance from the servos? Is it possible to shield the compass with some sort of container for the LSM303DLHC? Has anyone else done an averaging or smoothing on a compass which was giving off such noisy results?

Thanks,

Brian

I have read about soothing out the compass signal by averaging out readings and have been trying different calibrations and calibrating at different gain levels, etc. (so far to no avail).

Can you show code how you did that as the values shown look quite well average-able or you could take a running median

Succes..

thanks for the links, I will try them out. I was going to do some "smoothing" regardless so I might as well see how much it corrects the issue with the current noise level.

Here is the code (pulled out from the rest) My compass is a pointer. Most of this is pretty standard I think.

  // the following is setup in when my Robot.cpp class is instantiated.

  // set up the compass
  compass = new LSM303();
  LSM303::vector running_min = {2047, 2047, 2047}, running_max = {-2048, -2048, -2048};
  
  // initialize the compass
  Wire.begin();
  compass->init(LSM303DLHC_DEVICE, LSM303_SA0_A_AUTO);
  compass->enableDefault();
  compass->writeAccReg(LSM303_CTRL_REG1_A, 0x27); // Bump accelerometer from 50 hz to 400 hz
  
  compass->setMagGain(LSM303::magGain_25);

  // calibrate
  compass->m_min.x = -449; compass->m_min.y = -440; compass->m_min.z = -405;
  compass->m_max.x = 223; compass->m_max.y = 321; compass->m_max.z = 389;


  // the following is called in a getHeading method anytime the heading reading is called for

  compass->read();
  int heading = compass->heading((LSM303::vector){0,-1,0});

I am still hoping to get the noise out even if the averaging works pretty well. Having that much deviation in the numbers has got to lead to error occasionally, even with the smoothing...

Thanks,

Brian

I don't know this particular device, but most other digital sensors require a "settling" time between readings. Have you considered introducing a brief delay between samples?

Secondly, noise is the devil in any high speed circuit. Motor noise in particular, when the motors share a common power/ground with the MCU, are introducing glitches that affect pretty much anything similarly connected. A simple filter is to introduce 0.01mF caps between the power and ground supply, or if possible across the motor terminals directly.

An alternative solution is to add an external servo driver board, most of which have reasonably good filtering.

Well a compass is trying to measure the very weak magnetic field of the earth and motors are in effect giant electromagnets in comparison so it's not surprising to me that running the motors creates problems for the compass sensor. And as the strength of the magnetic field created by the motors will most likely vary a lot depending on the amount of power they are being driven at (if PWM driven) and any varying amount of mechanical load on the motors at any specific time. With that consideration I would think it would be darn near impossible to try and 'calibrate' the effect of the motors for the compass. At best you would have to try some kind of mechanical magnetic shielding around the motors, as in special and expensive Mu metals as were used to shield CRTs in expensive test equipment.

Lefty

@arbutus
My posted code does not show it but the getHeading() method that does the read of the compass is run every 100ms by my home made scheduler..

I am really intrigued about what you are saying about the noise being more of sharing a common power / ground (all my components do) I will read up more on introducing a capacitor. I might have a question or two on it as i get into it. But being that moving the compass around trying to increase physical distance was getting me about nothing your idea makes perfect sense.

@retrolefty
Yes the servos are pwm driven, thanks for the search terms on the shielding material, will take a look and see what i uncover.

Thank you,

Brian