for a school project, i am making an LED compass, in the sense that i have a compass sensor, an accelerometer, and a ring of charlieplexed LEDs on the sleeve of a sweatshirt. i want the LED closest to north to be lit up, when the board is held level. the problem currently is that the slightest variations in roll or pitch throw off the compass readings so much, its starting to seem infeasible. my current source code is as follows.
#include <Wire.h>
#include <Charlieplex.h>
#define NUMBER_OF_PINS 4
int valY; // variable where Y data is stored
int valX; // variable where X data is stored
int accely = 1; // setup pin assignment for Y data
int accelx = 2; // setup pin assignment for X data
int HMC = 0x42;
int slaveAddress; // this is calculated in the setup() function
byte headingData[2];
int i, headingValue;
byte pins[] = {5,6,7,8};
Charlieplex charlieplex = Charlieplex(pins,NUMBER_OF_PINS); //initialize object
charliePin led1 = { 0 , 3 }; //led1 is indicated by current flow from 0 to 3
charliePin led2 = { 3 , 2 };
charliePin led3 = { 3 , 0 };
charliePin led4 = { 3 , 1 };
charliePin led5 = { 2 , 3 };
charliePin led6 = { 2 , 0 };
charliePin led7 = { 2 , 1 };
charliePin led8 = { 1 , 2 };
charliePin led9 = { 1 , 0 };
charliePin led10 = { 1 , 3 };
charliePin led11 = { 0 , 2 };
charliePin led12 = { 0 , 1 };
void setup()
{
slaveAddress = HMC >> 1; // Shift the device's documented slave address (0x42) 1 bit right
Serial.begin(9600);
Wire.begin();
}
void loop()
{
Wire.beginTransmission(slaveAddress); // Send a "A" command to the compass, this requests the current heading data
Wire.send("A"); // The "Get Data" command
Wire.endTransmission();
delay(10); // The compass needs at a delay to catch up
Wire.requestFrom(slaveAddress, 2); // Request the 2 byte heading (MSB comes first)
i = 0; // Read the 2 heading bytes, MSB first
while(Wire.available() && i < 2) // For example: a heading of 1345 would be 134.5 degrees
{
headingData[i] = Wire.receive();
i++;
}
{
valY = analogRead(accely);
valX = analogRead(accelx);
}
headingValue = headingData[0]*256 + headingData[1]; // Put the MSB and LSB together
Serial.print("Current heading: ");
Serial.print(int (headingValue / 10)); // The whole number part of the heading
Serial.print(".");
Serial.print(int (headingValue % 10)); // The fractional part of the heading
Serial.println(" degrees");
Serial.print(valY); // the accel Y data
Serial.print(" ");
Serial.println(valX); // the accel X data
delay(500);
{
charlieplex.charlieWrite(led1,HIGH);
}
}
Is there a way for me to use the accelerometer to smooth out the compass readings? essentially, i only need the compass to have 12 degrees of resolution, lighting up one of the twelve LEDs accordingly.
any other advice or criticism is more than welcome.
i was thinking about something like that, but i didnt think it would work. really, what i need is for my compass to output 0-360, like its supposed to. it seems like if its even a fraction of a degree off perfectly level, it doesnt work at all. i was wondering if i could use the accelerometer data to correct the compass for the offset in angle.
Current heading: 30 degrees
491 548
Current heading: 39 degrees
494 516
Current heading: 39 degrees
493 515
Current heading: 44 degrees
496 512
Current heading: 49 degrees
501 513
Current heading: 57 degrees
501 506
Current heading: 66 degrees
504 507
Current heading: 71 degrees
502 508
Current heading: 76 degrees
505 505
Current heading: 83 degrees
499 500
Current heading: 98 degrees
505 505
Current heading: 117 degrees
506 497
Current heading: 143 degrees
507 499
Current heading: 191 degrees
514 495
Current heading: 244 degrees
514 494
Current heading: 296 degrees
531 510
Current heading: 264 degrees
511 480
by the grace of god it seems to be working okay now. that was starting and stopping just shy or north (because its attached to my arm and i am attached to my computer x] )
and pointers on how i should assign ranges such as 1-30 degreed to led1 and 31-61 to led2 ? or is it just really simple?
Some HMC compasses have built-in filtering you can enable.
Are you running high current traces near the compass? The
current flow will produce magnetic fields that could cause
unstable readings.
sadly, because this is a school funded project, i had to go with this Compass Module - HMC6352 - SEN-07915 - SparkFun Electronics which has no such features.
no worries though. as stated before, its a school project, and thus has almost no quality standards x] i just need to wow a few judges. right now i'm having some other trouble with my code though.
{
int a=headingValue / 10;
if (a > 0 && a < 30)
{
charlieplex.charlieWrite(led1, HIGH);
}
else
{
charlieplex.charlieWrite(led1, LOW);
}
}
it will light up led1 when i come between 0 and 30 degrees, but it wont turn it off when i leave that space.
The HMC6352 does have measurement averaging. You can also run at a lower
frequency (although the responsiveness does suffer). Hardware filtering
is possible although probably not on the breakout board.
sadly, with the added parenthesis it is still behaving the same way. it comes on when i want it to, but it never goes back off. also, how might i smooth these reading s with software? do you have any examples written up already?