Autonomous Car Navigation Programming problems

I am having trouble getting my code to work with a HMC5883L in my autonomous car project. It is supposed to navigate using GPS and Compass.

The following is my code for the compass:

#include <Wire.h>
#include <Servo.h>

#define Addr 0x1E               // 7-bit address of HMC5883 compass

Servo myservo;

void setup() {
  Serial.begin(250000);
  Serial.println();
  Wire.begin();

  myservo.attach(9);
  myservo.write(90);
  
  // Set operating mode to continuous
  Wire.beginTransmission(Addr); 
  Wire.write(byte(0x02));
  Wire.write(byte(0x00));
  Wire.endTransmission();
}

void loop() {
  int x, y, z;

  // Initiate communications with compass
  Wire.beginTransmission(Addr);
  Wire.write(byte(0x03));       // Send request to X MSB register
  Wire.endTransmission();

  Wire.requestFrom(Addr, 6);    // Request 6 bytes; 2 bytes per axis
  if(Wire.available() <=6) {    // If 6 bytes available
    x = Wire.read() << 8 | Wire.read();
    z = Wire.read() << 8 | Wire.read();
    y = Wire.read() << 8 | Wire.read();
  }
  // If compass module lies flat on the ground with no tilt,
  // just x and y are needed for calculation
  float heading=atan2(x, y)/0.0174532925;
  if(heading < 0) heading+=360;
  heading=360-heading; // N=0/360, E=90, S=180, W=270
  Serial.println(heading);  
  delay(500);

  // Drive Section
  
  if (heading < 180) {
    myservo.write(110);
    if (heading < 5 or heading > 355){
      myservo.write(90);
} else if (heading > 180) {
    myservo.write(80);
    if (heading < 5 or heading > 355){
      myservo.write(90);
    }
  }
}
}

The last part (Drive Section) is the steering servo. I want it to turn into the heading it needs as fast as possible. Therefore, if the current heading is more than 180 degrees from zero (the heading I want), it will turn the other way. When it is within 5 degrees of 0, it should right itself and go back to zero. However, when I move it around, it will only do the self-centering in Setup and the >180/<180 part. How do I make it so that whenever I move it within that heading, it sets itself to 90? (I want it to be able to do that indefinitely, so I can just pick it up and spin it around and have it orient itself correctly)

Also, I am having trouble with an Adafruit Ultimate GPS Breakout. How do I separate the lat/long from the GPRMC sentence? I can only get the entire sentence, but I only need the lat/long.

Thank you for any help, I'm a newb and sorta lost with a project due pretty soon. Thanks!

if(Wire.available() <=6) {    // If 6 bytes availableReally?
One is less than six.
So is zero.

I didn't write that part, that's from the Example library. How exactly is that relevant tho...?

Let's say there are no bytes available.
Zero is less than six, so you go off and read all six of the bytes that aren't there.
I think that may be relevant, don't you?

that's from the Example librar

Which example, please?

Ok, so say I totally understand what you mean... What should I do? Is it not getting information?

Also, the example is from somewhere on one of these forums... Not really sure but I think it might be from I2Cdevlib, I only have the manufacturer library loaded right now.

If you totally understood, you'd know to only read six bytes when you're sure that there are six bytes to read.

So how should I change it to work then... How do I make it be sure there are six bytes?

I honestly don't know where you're going with this, I'm new, man...

I'd play around with this line (ignore the comment, obviously)if(Wire.available() <=6) {    // If 6 bytes available

Maybe if you spent some of the five minutes that you've got between posts experimenting . . ?

Ok, I have discovered two things:

  1. When I set the byte thing to anything lower than 6, it only says 360.0 in the Serial Monitor.

and,

  1. The program does work, it's just a but of a small opening for the servo to correct itself.

If this is what you meant, how do I make it work better?

  1. When I set the byte thing to anything lower than 6, it only says 360.0 in the Serial Monitor.

I don't know what that means.

Maybe we can pick this up (later) in the morning.

What I meant was:

if(Wire.available() <=6) { // If 6 bytes available

^ that 6...

Ok, thank you for your help. I won't be on in the morning, as I'm a high schooler, but I would appreciate it if you would continue to help me. Good help like this is hard to find.

Thank you!

Hint: check out the meaning of "==" in C/C++, or better yet, look up "logical operators" for the complete overview.

Ok, so the way I understand it, if there are 6 or less wires available, the statement is true?

Wire.available() returns the number of bytes available. Instead of checking that there's less than 6, you need to check to see if there's at least 6.

if(Wire.available() <=6) {    // If 6 bytes available

Are you seriously looking at this and can't figure out what to change to make it only true if there are MORE than 6 bytes instead of LESS than 6 bytes available to read?

Delta_G:

if(Wire.available() <=6) {    // If 6 bytes available

Are you seriously looking at this and can't figure out what to change to make it only true if there are MORE than 6 bytes instead of LESS than 6 bytes available to read?

Want to bet whether or not there will be a thread later on in the Website and Forum section, about how less-than-helpful we are?

Ok. I believe I have fixed it. It looks like this now:

if(Wire.available() >=6) {    // If 6 bytes available

What exactly will it change though? My original problem with the program is that the servo does not move accordingly when it is between the specified headings... Was this the problem? I don't exactly what that line was for (It's an adapted program I found on here.)

Stingray63Vette:
I don't exactly what that line was for (It's an adapted program I found on here.)

It may well be part of your problem because if you were trying to read bytes that hadn't been sent yet then your compass readings were garbage and you can't get a heading off garbage values.

You shouldn't use lines of code you don't understand. Hack and paste coding gets you into trouble like this where you have a program that doesn't work and you don't know enough about it to even approach the why. When you copy a code and it has a part that you don't understand, go try to figure it out or ask here what it is for.

You've got a lot of logic problems like that. Here's another one:

 if (heading < 180) {
    myservo.write(110);
    if (heading < 5 or heading > 355){
      myservo.write(90);

So if the heading is less than 180, what do you think the chances are that it is greater than 355? So that's a pretty useless test. With all of that in there, it is hard to parse through and find what's actually causing your particular issue. So we're trying to clean this up to the point that we can address that problem.

In response to Delta G, the vehicle holding the compass would start moving after the servo was turned. However, I have not written that code yet. I was just spinning it on the table to see what it did.

I'm going to assume that's mostly fixed. Right now I have everything disassembled for installation into the test vehicle.

I know the hack and paste thing is not the best idea- I rarely do that with other codes. However, I'm sort of strapped for time as we have two weeks for this project.

I am also confused on some MPU 6050 data as well. When I try to call sensor data in, I get nothing. I don't really understand that either. Ther's not much info on just using it on here; it's all serial monitor example programs.

I was trying to do it in another program, but I just have no idea what to do. How do I use digital data like analog?? Does it have to do with SDL and SDA?

MPU 6050 is attached as follows on my Mega:

VCC to 5v
GND to GND
SDA to solder breadboard, which joins with the compass sensor
SCL to solder breadboard, which joins with the compass sensor
INT to Digital 2

I am trying to bring the m/s^2 data in for some operations before usage. I don't know how to make X and Y axis output into usable numbers, like a potentiometer and LED setup.

The way I have it wired, it joins SDA and SDL with a compass. An I2C Test found both devices operational, and I think I know how to call those sensors in and name them.

Could you help me or point me in the right direction? Couldn't find much, my stuff is sorta specific.

Thank you so much, I would be completely lost without you guys.