The compass breakout HMC6352 can be powered with 2.7 to 5.2 volts. The Arduino UNO that was used here operates at 5 volts, but it does have a 3.3 volt supply pin. Unfortunately the motor shield covered up the Arduino 3.3v power supply. There were a few comments about using the compass breakout at 5 volts. Most comments said it is within the stated operating limits and it should work at 5 volts. One comment said their compass breakout ran fine at 5 volts for about 30 minutes, then went up in a puff of smoke.
So as an alternative to using 5 volts, a voltage divider was used. The calculations were done using Hyperphysics Voltage Divider with R1 being 3 parallel 1 k ohm resisters and R2 being a single 1 k ohm resister, using 5 volts this would give a high load resistance voltage of about 3.7 volts. The compass breakout uses about 1 mA of current which at 3.7 volts is equivalent to a resistance of about 3 k ohms. Assuming 3 k ohms as the load resistance gives an operating voltage of about 3.5 volts. This is well within the operating voltage of the compass breakout. The equivalent resistance of the voltage divider is 1.333 k ohms, so at 5 volts it would waste 3.75 mA of current. The compass breakout uses about 1 mA, so that is a total current draw of about 4.75 mA. The Arduino 5 volt pin should not be used to supply more that 30 mA, so this seems well within the limits there too.
The simple BLDR program was used to test the compass breakout. That wiring diagram was also used, except for the voltage divider. After seeing that the compass breakout was working, the motor control was added to control the direction of the robot using the compass. This program has the robot drive using the compass heading of 180 degrees, that is magnetic south. The speed numbers will vary depending on the motors used and the voltage driving the motors.
A jumper switch was added from Arduino A0 to control the motors. When the jumper switch connected to a ground pin, the motors will not run. This allows you to start and stop the motors while testing the movement.
#include
#include
int HMC6352SlaveAddress = 0x42;
int HMC6352ReadAddress = 0x41; //"A" in hex, A command is:
int headingValue;
AF_DCMotor motorR(3, MOTOR12_64KHZ); // create motor #1, 64KHz pwm
AF_DCMotor motorL(1, MOTOR12_64KHZ); // create motor #3, 64KHz pwm
int switchPin = A0; // select the input pin for the potentiometer
int switchValue = 0; // variable to store the value coming from the sensor
int speedL = 190;
int speedR = 200;
int speedD = 50;
void setup() {
// "The Wire library uses 7 bit addresses throughout.
// If you have a datasheet or sample code that uses 8 bit address,
// you'll want to drop the low bit (i.e. shift the value one bit to the right),
// yielding an address between 0 and 127."
// I know 0x42 is less than 127, but this is still required
HMC6352SlaveAddress = HMC6352SlaveAddress >> 1;
Wire.begin();
Serial.begin(9600); // set up Serial library at 9600 bps
motorR.setSpeed(speedL); // set the speed to 200/255
motorL.setSpeed(speedR); // set the speed to 200/255
}
void loop() {
switchValue = analogRead(switchPin); // read the value from the sensor
if (switchValue > 0) {
//"Get Data. Compensate and Calculate New Heading"
Wire.beginTransmission(HMC6352SlaveAddress);
Wire.send(HMC6352ReadAddress); // The "Get Data" command
Wire.endTransmission();
//time delays required by HMC6352 upon receipt of the command
//Get Data. Compensate and Calculate New Heading : 6ms
delay(6);
Wire.requestFrom(HMC6352SlaveAddress, 2); //get the two data bytes, MSB and LSB
//"The heading output data will be the value in tenths of degrees
//from zero to 3599 and provided in binary format over the two bytes."
byte MSB = Wire.receive();
byte LSB = Wire.receive();
float headingSum = (MSB << 8) + LSB; //(MSB / LSB sum)
float headingInt = headingSum / 10;
Serial.print(headingInt);
Serial.println(" degrees");
if (headingInt < 180) {
Serial.println("Right");
motorR.setSpeed(speedR+speedD); // set the speed to 200/255 motorL.setSpeed(speedL-speedD); // set the speed to 200/255
} else if (headingInt > 180) {
Serial.println("Left");
motorR.setSpeed(speedR-speedD); // set the speed to 200/255
motorL.setSpeed(speedL+speedD); // set the speed to 200/255
} else {
Serial.println("Straight");
motorR.setSpeed(speedR); // set the speed to 200/255
motorL.setSpeed(speedL); // set the speed to 200/255
}
motorR.run(FORWARD); // turn it on going forward
motorL.run(FORWARD);
delay(100);
}
motorR.run(RELEASE);
motorL.run(RELEASE);
}