Pages: [1]   Go Down
Author Topic: SOLVED:LMS303 sample reading  (Read 1412 times)
0 Members and 1 Guest are viewing this topic.
Offline Offline
Jr. Member
**
Karma: 0
Posts: 66
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

I am using a LMS303 on a polo breakout board using the Lib available in the playground with my own calibration added

the heading readings are a bit jumpy, +3 degree range pretty much,

i was wanting to sample the readings then get the average

but if you do that with heading readings when it gets around to the 360 mark and you are jumping to 1 again, if you average those you are way off.

example:  (360+359+360+1+360 + 1)/6 = 240

is their another way i can go about this to get my readings a bit more accurate?
« Last Edit: August 03, 2011, 03:32:02 pm by btsp » Logged

Offline Offline
Jr. Member
**
Karma: 0
Posts: 66
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

would something along the lines of somehow reading in quadrants?

quad 1 smiley-mad-90  ( 0-90 degrees)
quad 2 :90-0  (90-180 degrees)
quad 3 smiley-mad-90  (180-270 degrees)
quad 4 :90-0  (270-360 degrees)

 if i could indicate which quadrant they are coming from..does this sound like it should work?

Logged

nr Bundaberg, Australia
Offline Offline
Tesla Member
***
Karma: 126
Posts: 8471
Scattered showers my arse -- Noah, 2348BC.
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

There's probably a really simple mathematical way to do this, but maths isn't my strong point so maybe the following brute-strength approach.

It's only a problem in the 360/0 boundary area. So let's define a band around that of maybe +-10, ie 350 to 10. Any readings outside this band are treated normally.

However if you get readings inside the band you switch to a mode that adds 360 to any values < 350, does the averaging, then subtracts 360 if the results is > 360.

If you get an average that falls outside the band you revert to the standard method.

(360+359+360+(1+360)+360 + (1+360))/6 = 360

(358+359+(5+360)+(4+360)+(3+360)+(1+360))/6 = 361.8, subtract 360 = 1.8

EDIT: all 360s should probably be 359s.
______
Rob


« Last Edit: July 27, 2011, 06:37:21 pm by Graynomad » Logged

Rob Gray aka the GRAYnomad www.robgray.com

Offline Offline
Jr. Member
**
Karma: 0
Posts: 66
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

ah nice idea thank you

i made a code that seems to work at the moment.
This will not work if there is odd spikes in the readings, but that's alright ill be able to ignore those.

Code:

int total = 0;
      for (int _sample = 0; _sample < 10; _sample++) {
        read(); // read the magnometer values
heading_samples[_sample] = heading((vector){0,-1,0}); //create heading
         
         if ( (heading_samples[_sample] > 350 ) || (heading_samples[_sample] < 10 )){
                hstate = 1;
                       
          }
         
         if (hstate != 1)
             {
                 hstate = 2; //if no numbers above 350 or below 10 take normal average
             }
     }
                 
          switch(hstate)
              {
                case 1:
                     for(int _sample = 0; _sample < 10; _sample++){
                          if ( heading_samples[_sample]  < 350 )
                                {
                                  heading_samples[_sample] += 360; //add 360 if below 10
                                }
                       
                         total += heading_samples[_sample];  //sum up readings
                        }
                       total /= 10;
                       heading  = total;
                     
                      if (heading >= 360){
                      heading - 360;
                      }                           
                      return heading
                      hstate =0;
                      break;
               
                case 2:
                          for(int _sample = 0; _sample < 10; _sample++){
                                total += heading_samples[_sample];
                          }
                           total /= 10;
                           heading  = total;         
                           hstate =0;
   return heading
                          break;
     
   } 


any suggestions to clean up code please do
thanks again
Logged

nr Bundaberg, Australia
Offline Offline
Tesla Member
***
Karma: 126
Posts: 8471
Scattered showers my arse -- Noah, 2348BC.
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

I had a think about this after switching off my computer last night. I think all you need to detect is the case when 2 or more readings differ by more than the expected jitter.

So I modified your code to do this, plus simplified the rest of the code. I hope I didn't stuff it up on the process smiley


Code:
#define FUDGE_FACTOR 100  // any number > the expected jitter will do
#define SPECIAL 1
#define NORMAL 2
#define N_SAMPLES 10
#define BAND 10

int heading_samples[N_SAMPLES];
int hstate;

// dummy funcs just to get it to compile

void setup () {}

void loop () {}

int read () {}

int getHeading () {
  int total = 0, min = 0, max = 0;

  for (int _sample = 0; _sample < N_SAMPLES; _sample++) {
    read(); // read the magnometer values
    // I don't have "vector" so commented the next line out
//heading_samples[_sample] = heading((vector){0,-1,0}); //create heading

    if (heading_samples[_sample] < min) min = heading_samples[_sample];
    if (heading_samples[_sample] > max) max = heading_samples[_sample];

    hstate = (max - min > FUDGE_FACTOR) ? SPECIAL : NORMAL;
  }

  for(int _sample = 0; _sample < N_SAMPLES; _sample++){
    total += heading_samples[_sample];  //sum up readings
    if ( heading_samples[_sample] < 360 - BAND && hstate == SPECIAL)
    {
      total += 360; //add 360 if not above 350
    }
  }

  total /= N_SAMPLES;
  if (total >= 360){
    total -= 360;
  }                           
  return total;



______
Rob
Logged

Rob Gray aka the GRAYnomad www.robgray.com

Offline Offline
Jr. Member
**
Karma: 0
Posts: 66
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Rob,

thanks for simplifying the code i am yet to test it out but just a question,

what does:

hstate = (max - min > FUDGE_FACTOR) ? SPECIAL : NORMAL; 

that do?
Logged

nr Bundaberg, Australia
Offline Offline
Tesla Member
***
Karma: 126
Posts: 8471
Scattered showers my arse -- Noah, 2348BC.
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

It's a shorthand version of

Code:
if (max - min > FUDGE_FACTOR)
  hstate = SPECIAL;
else
  hstate = NORMAL; 

It's called a ternary operator

x = test ? true_result : false_result;

http://cprogramminglanguage.net/c-ternary-operator.aspx

much like IIF in many other languages.

______
Rob
« Last Edit: July 28, 2011, 10:05:32 am by Graynomad » Logged

Rob Gray aka the GRAYnomad www.robgray.com

Offline Offline
Jr. Member
**
Karma: 0
Posts: 66
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

ah thanks.

well ran the code, everything is good except around the 350 mark.

I am going to look into it more and get back to you

Logged

Offline Offline
Jr. Member
**
Karma: 0
Posts: 66
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

found the error,
was the max/min reset values.

had min and max both at 0

min should be at 359 and max at 0.

she works great now,

thanks again
« Last Edit: July 28, 2011, 10:59:54 am by btsp » Logged

nr Bundaberg, Australia
Offline Offline
Tesla Member
***
Karma: 126
Posts: 8471
Scattered showers my arse -- Noah, 2348BC.
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

No problems, I might file that away for future use myself smiley

______
Rob
Logged

Rob Gray aka the GRAYnomad www.robgray.com

Pages: [1]   Go Up
Jump to: