Here is the code and a description of the hardware. The project is a robotic sailboat
I am using the Mega 2560 and the 16 x 12 bit PWM Servo Shield.
The 3 sensors are Adafruit Ultimate GPS Breakout v3 with active antenna, Adafruit LMS303 magnetic compass, and US Digital magnetic encoder
There is an additional 6V battery power supply for the servo shield
Most connections are on the shield: Servos, encoder on digital pin 7, and compass on SCL SDA pins.
I communicate with the GPS is via Software Serial and was not able to use pins 3,2 as I did when I started with the Arduino Uno. They are now on pins 53, 52
All connections are soldered except those from the shield to the Arduino and the 53, 53 pins on the Mega (came with stacking pins and no place to solder)
I have attached stripped down code that simply reads the 3 sensors and shows the data. I don't command the servos yet, but it works with other code. As I describe in my previous post, the GPS data is not read completely and GPS.newNMEAreceived() does not return true.
The data string I get is $GPRMC,020013.000,A,4222.5409,N,07109.1704,W,0.42,15.22,180714,
this seems to be everything but the checksum.
I would really like to get a functioning GPS asap as I am using this project in a class and it is currently my roadblock. I appreciate any thoughts/ideas/help!
Code: Select all
/* Reads all sensors and attempts to command boat
7/17/2014 */
#include <Adafruit_PWMServoDriver.h>
#include <Wire.h>
#include <Adafruit_Sensor.h>
#include <Adafruit_LSM303_U.h>
#include <Adafruit_GPS.h>
#include <SoftwareSerial.h>
/*----------------------SET UP SERVOES-------------------------------*/
//servos will bo on Servo Shield in places 0 and 1
// called this way, it uses the default address 0x40
Adafruit_PWMServoDriver pwm = Adafruit_PWMServoDriver();
/*----------------------SET UP COMPASS-------------------------------*/
//Assign unique ID to compass sensor
Adafruit_LSM303_Mag_Unified MagComp = Adafruit_LSM303_Mag_Unified(12345);
/*----------------------SET UP GPS-----------------------------------*/
// For the Adafruit GPS module with software serial:
// Connections: GPS Power pin to 5V, GPS Ground pin to ground
// GPS TX (transmit) and GPS RX (receive) to pins 3 and 2
#define gpsTX 53 //GPS communication pins
#define gpsRX 52
// Define a new software serial port on the Arduino called gpsSerial:
SoftwareSerial gpsSerial(gpsTX, gpsRX);
Adafruit_GPS GPS(&gpsSerial);
//#define GPSECHO true
/*----------------------SET UP WIND SENSOR---------------------------*/
// Wind Sensor MA3 Global Variables
#define windpin 7 //Wind sensor input pin
unsigned long duration;
int WindDirection;
/*----------------------USEFUL GLOBAL VARIABLES----------------------*/
// Things we can get from the sensors
float relWind = 0; // From wind sensor (degrees)
float absBoatHeading = 0; // From compass (degrees)
float absBoatPositionX = 0; // From the GPS (meters)
float absBoatPositionY = 0; // From the GPS (meters)
float startingPositionX = 0; // From the GPS (meters)
float startingPositionY = 0; // From the GPS (meters)
// Useful variables
int GPS_counter = 0;
int rudderCMD = 0;
int sailCMD = 0;
bool verbose = true;
float pi = 3.14159;
void setup()
{
// Set baud rate for the serial monitor
Serial.begin(9600);
Serial.println("Code starting up, beginning intialization...");
int ch1; // channel values
int ch2;
#define SERVOMIN 150 // this is the 'minimum' pulse length count (out of 4096)
#define SERVOMAX 600 // this is the 'maximum' pulse length count (out of 4096)
/*----------------------SET UP GPS SENSOR----------------------------*/
// Adafruit MTK GPS setup code
// First, set the baud rate. 9600 NMEA is the default baud rate
GPS.begin(9600);
// Second, turn on only the "minimum recommended" data
GPS.sendCommand(PMTK_SET_NMEA_OUTPUT_RMCONLY);
// Last, set update rate to 1hz so the code can read the data and print it
// TODO: try higher if necessary
GPS.sendCommand(PMTK_SET_NMEA_UPDATE_1HZ);/* */
// This will run on startup and will save that position as the (0,0) origin
//all variables are global, so we do not pass them to the function or get any in return
getAbsBoatPosition();
startingPositionX = absBoatPositionX;
startingPositionY = absBoatPositionY;
/*----------------------SET UP SENSOR---------------------------*/
pinMode(windpin, INPUT);
MagComp.begin();
} // End of setup
void loop()
{
/*----------------------GET THE SENSOR VALUES------------------------*/
relWind = getRelativeWind(); //read wind sensor
absBoatHeading = getAbsBoatHeading(); //read compass
// Get the GPS data every 100 loops b/c it runs so slowly
if (GPS_counter == 5) {
// When you call this code it updates the variables instead of returning
// This is because C can't return multiple things at once
getAbsBoatPosition();
delay(500);
GPS_counter = 0;
}
else
{GPS_counter += 1;}
delay (250); // main code for logic goes here
/*----------------------COMMAND THE MOTORS--------------------------*/
//commandMotors(rudderIn, true, sailwinchIn, true, rudderCMD, sailCMD);
} // End of loop()
/*----------------- FUNCTIONS TO READ ALL SENSORS--------------------*/
float getRelativeWind()
{
//read MA3 PWM output
duration = pulseIn(windpin, HIGH);
// use a calibration routine to find max pulse width which is typ 1023
// after calibrating, convert to heading in degrees
WindDirection= map(duration, 0, 1010, 0, 360);
// constrain value between 0 and 360 to get rid of noisy outliers
WindDirection = min(max(WindDirection, 0), 360);
if (verbose) {
Serial.print("Relative wind direction: ");
Serial.println(WindDirection);
}
return WindDirection;
}
float getAbsBoatHeading()
{
sensors_event_t event;
MagComp.getEvent(&event);
// Calculate the angle of the vector y, x and convert from radians to degrees
float heading = atan2(event.magnetic.y, event.magnetic.x)*180.0/pi;
if (heading < 0) heading += 360;
if (heading > 360) heading -= 360;
if (verbose) {
//Serial.print("y reading: "); Serial.print(event.magnetic.y);
//Serial.print(" --- x reading: "); Serial.println(event.magnetic.x);
Serial.print("Compass Heading: "); Serial.println(heading);
}
return heading;
}
void getAbsBoatPosition()
{
while (gpsSerial.available()) {
char c = GPS.read();
delay(1);
Serial.print(c);
}
Serial.println("got GPS data using GPS.read");
if (GPS.newNMEAreceived())
{
if (verbose)
{
Serial.print("\n\n");
// Print the string and set the newNMEAreceived() flag to false
Serial.println(GPS.lastNMEA());
GPS.parse(GPS.lastNMEA());
Serial.print("\n read and parsing");
Serial.print("\nTime: ");
Serial.print(GPS.hour, DEC); Serial.print(':');
Serial.print(GPS.minute, DEC); Serial.print(':');
Serial.print(GPS.seconds, DEC); Serial.print('.');
Serial.print("Fix: "); Serial.print((int)GPS.fix);
Serial.print(" quality: "); Serial.println((int)GPS.fixquality);
if (GPS.fix) {
Serial.print("Location: ");
Serial.print(GPS.latitude, 4); Serial.print(GPS.lat);
Serial.print(", ");
Serial.print(GPS.longitude, 4); Serial.println(GPS.lon);
}
}
// Make the boat position relative to where it was started
absBoatPositionX = absBoatPositionX - startingPositionX;
absBoatPositionY = absBoatPositionY - startingPositionY;
}
else Serial.println("GPS data not received");
}