jremington:
You did not post any integers. You posted some small floating point numbers, that were not varying by much.
To make a compass, it is essential to calibrate the magnetometer, following this tutorial.
Then use
float heading = atan2(magy, magx)*180.0/PI; //in degrees
if (heading < 0.0) heading = heading+360.0// map to 0-359
In this case you don't need to worry about the units of the measurement.
Is the code you posted to calibrate the magnetometer?
Following your tutorial we need to find a bias that is affecting the measurement
of the magnetometer by calibrating it. Then we just need to substract the bias from the measurements
and we have calibrated values right?
If im right this script shows how to do it.
So your code is just for mapping the values to 0-360 degrees?
johnwasser:
Instead of taking an average of three measurements very close together you might be better served with a longer term moving average. I would sample at half the local AC frequency to try to avoid any AC hum.
const unsigned ACLineFrequency = 60;
const unsigned SamplesPerACCycle = 2; // We take two samples, 180° out of phase, during each AC cycle
// Let's make the averaging time one second
const unsigned SampleCount = ACLineFrequency * SamplesPerACCycle;
const unsigned long SampleIntervalMicroseconds = 1000000UL / SampleCount;
// You need a set of these for each value to be averaged
float Samples[SampleCount] = {0.0};
float SampleTotal = 0;
float SampleAverage = 0;
// You only need one set of these for all values
unsigned SampleIndex = 0;
unsigned long LastSampleTime;
float GetNewValue()
{
return 1.0; // Put your sensor reading code here
}
void AddSample()
{
// You need these three line for each value being sampled
SampleTotal -= Samples[SampleIndex]; // Remove the value falling out of the buffer
Samples[SampleIndex] = GetNewValue();
SampleTotal += Samples[SampleIndex];
// This is only done once per sample interval
SampleIndex = (SampleIndex + 1) % SampleCount;
}
void setup()
{
// Pre-fill the sample buffer
for (unsigned i = 0; i < SampleCount; i++)
{
AddSample();
delayMicroseconds(SampleIntervalMicroseconds); // Crude, but close enough for the first second.
}
LastSampleTime = micros();
// Do this line for each value:
SampleAverage = SampleTotal / SampleCount;
}
void loop()
{
unsigned long currentMicros = micros();
if (currentMicros - LastSampleTime >= SampleIntervalMicroseconds)
{
LastSampleTime += SampleIntervalMicroseconds;
AddSample();
// Do this line for each value:
SampleAverage = SampleTotal / SampleCount;
}
}
Ah this is much better now. Where do you get the values from ACLineFrequency and SamplesPerCycle?
Why 60 and 2 cycles?
The code works only for one dimension right?(x,y,z) When i use the code of jremingto to map the values
to 360 degrees i have to repeat the average calculation for another dimension ?
And im very thankful for all your responses!