Here is the sketch. It compliles, loads and works fine on the Genuine Mega 2560. The LCD display does not give an accurate heading because it's based on the NMEA sentence extraction from the GPS. However, the GPS module contains an HMC5883L chip that I wish to get accurate heading data from. But I can't find the correct code to access the chip. The module has 2 separate wires for the HMC chip. The wires are currently connected to serial2 ports on the Arduino.
// Connect Deegoo-FPV NEO-N8M gps TX Yellow to serial3 RX pin 15 and gps RX White to TX pin 14
// Connect Deegoo-FPV NEO-M8N compass Brown to serial2 RX pin 17 and compass grey to TX pin 16
// Deegoo-FPV has NEO-N8M & intergated HCM5883L Compass
//Connect I2C LCD 20 x 4 Yellow to SCL Pin 21 Green to SDA Pin 20
// Set Serial3 to 38400
// Set Serial Begin to 9600
// Set Monitor to 9600
#include <TinyGPS++.h>
#include <Wire.h>
#include <LCD.h>
#include <LiquidCrystal_I2C.h>
#include <hd44780.h> // main hd44780 header
#include <hd44780ioClass/hd44780_I2Cexp.h> // i2c expander i/o class header
hd44780_I2Cexp lcd; // declare lcd object: auto locate & config exapander chip
TinyGPSPlus gps; // create gps object
// LCD geometry
const int LCD_COLS = 20;
const int LCD_ROWS = 4;
void setup()
{
lcd.begin(LCD_COLS, LCD_ROWS);
// Print a message to the LCD.
lcd.backlight();
lcd.setCursor(6, 0);
lcd.print("Satellite");
lcd.setCursor(5, 1);
lcd.print("Acquisition");
lcd.setCursor(5, 2);
lcd.print("In Progress");
lcd.setCursor(3, 3);
lcd.print("Please Wait.....");
delay(10000);
lcd.clear();
Serial.begin(9600); // connect serial for debugging
Serial.println("Pending GPS Receive Signal:");
Serial3.begin(38400); // connect gps sensor
}
void loop(){
while(Serial3.available()){ // check for gps data
if(gps.encode(Serial3.read()))// encode gps data
{
if (gps.satellites.value() > 0) {
//Latitude
lcd.setCursor(0, 0);
lcd.print("Latitude: ");
lcd.print(gps.location.lat(),6);
//Longitude
lcd.setCursor(0, 1);
lcd.print("Longitude:");
lcd.print(gps.location.lng(),6);
//Heading
lcd.setCursor(0, 2);
lcd.print("Heading: ");
lcd.print(gps.course.deg(),0);
//Speed
lcd.setCursor(0, 3);
lcd.print("Speed: ");
lcd.print(gps.speed.mph(),1);
// Number of satellites connected
lcd.setCursor(11, 3);
lcd.print(" Sats: ");
lcd.print(gps.satellites.value());
delay(2000);
}
}
}
}
Please post a link to the module data sheet or product page.
The long obsolete and discontinued HMC5883L chip communicates via I2C, not UART serial.
Well that explains a lot. Now I see that I cannot use the HMC5883L on that device as I am already using the SCL/SDA ports on the Mega. Do you have a better suggestion as to what device I can add for compass data?
No problem, the I2C port is a bus that supports more than one device. Each connected device must have a distinct I2C address.
However, logic level shifters are required when connecting 3.3V sensors like the HMC5883L to 5V Arduinos like the Mega 2560.
Any modern magnetometer will work as a compass. Sparkfun, Adafruit and Pololu (among others) sell hobby modules with the logic level shifters built in.
// Sketch using Arduino Mega 2560 for GPS & Magnetometer outputing to LCD display
// Connect Deegoo-FPV NEO-N8M gps TX Yellow to serial3 RX pin 15 and gps RX White to TX pin 14
//GY-511 - Magnetometer with HCM5883L SCL to SCL1 on Arduino SDA to SDA1 on Arduino
//Connect I2C LCD 20 x 4 Yellow to SCL Pin 21 Green to SDA Pin 20
// All Data and Clock wires from GPS and Magnetometer connect via EPLZON Full-Duplex Logic Level Shifter
// Set Serial3 to 38400
// Set Serial Begin to 9600
// Set Monitor to 9600
#include <TinyGPS++.h>
#include <Wire.h>
#include <LCD.h>
#include <LiquidCrystal_I2C.h>
#include <hd44780.h> // main hd44780 header
#include <hd44780ioClass/hd44780_I2Cexp.h> // i2c expander i/o class header
#define Magnetometer_mX0 0x03
#define Magnetometer_mX1 0x04
#define Magnetometer_mZ0 0x05
#define Magnetometer_mZ1 0x06
#define Magnetometer_mY0 0x07
#define Magnetometer_mY1 0x08
#define Magnetometer 0x1E //I2C 7bit address of HMC5883L
int mX0, mX1, mX_out;
int mY0, mY1, mY_out;
int mZ0, mZ1, mZ_out;
float heading, headingDegrees, headingFiltered, declination;
float Xm,Ym,Zm;
hd44780_I2Cexp lcd; // declare lcd object: auto locate & config exapander chip
TinyGPSPlus gps; // create gps object
// LCD geometry
const int LCD_COLS = 20;
const int LCD_ROWS = 4;
void setup()
{
lcd.begin(LCD_COLS, LCD_ROWS);
// Print a message to the LCD.
lcd.backlight();
lcd.setCursor(6, 0);
lcd.print("Satellite");
lcd.setCursor(5, 1);
lcd.print("Acquisition");
lcd.setCursor(5, 2);
lcd.print("In Progress");
lcd.setCursor(3, 3);
lcd.print("Please Wait.....");
delay(10000);
lcd.clear();
//Initialize Serial and I2C communications
Serial3.begin(38400); // connect gps sensor
Serial.begin(9600);
Wire.begin();
delay(100);
Wire.beginTransmission(Magnetometer);
Wire.write(0x02); // Select mode register
Wire.write(0x00); // Continuous measurement mode
Wire.endTransmission();
}
void loop(){
while(Serial3.available()){ // check for gps data
if(gps.encode(Serial3.read()))// encode gps data
{
if (gps.satellites.value() > 0) {
//Latitude
lcd.setCursor(0, 0);
lcd.print("Latitude: ");
lcd.print(gps.location.lat(),6);
//Longitude
lcd.setCursor(0, 1);
lcd.print("Longitude:");
lcd.print(gps.location.lng(),6);
//Heading
lcd.setCursor(0, 2);
lcd.print("Heading: ");
lcd.print(gps.course.deg(),0);
//Speed
lcd.setCursor(0, 3);
lcd.print("Speed: ");
lcd.print(gps.speed.mph(),1);
// Number of satellites connected
lcd.setCursor(11, 3);
lcd.print(" Sats: ");
lcd.print(gps.satellites.value());
delay(2000);
}
{
//---- X-Axis
Wire.beginTransmission(Magnetometer); // transmit to device
Wire.write(Magnetometer_mX1);
Wire.endTransmission();
Wire.requestFrom(Magnetometer,1);
if(Wire.available()<=1)
{
mX0 = Wire.read();
}
Wire.beginTransmission(Magnetometer); // transmit to device
Wire.write(Magnetometer_mX0);
Wire.endTransmission();
Wire.requestFrom(Magnetometer,1);
if(Wire.available()<=1)
{
mX1 = Wire.read();
}
//---- Y-Axis
Wire.beginTransmission(Magnetometer); // transmit to device
Wire.write(Magnetometer_mY1);
Wire.endTransmission();
Wire.requestFrom(Magnetometer,1);
if(Wire.available()<=1)
{
mY0 = Wire.read();
}
Wire.beginTransmission(Magnetometer); // transmit to device
Wire.write(Magnetometer_mY0);
Wire.endTransmission();
Wire.requestFrom(Magnetometer,1);
if(Wire.available()<=1)
{
mY1 = Wire.read();
}
//---- Z-Axis
Wire.beginTransmission(Magnetometer); // transmit to device
Wire.write(Magnetometer_mZ1);
Wire.endTransmission();
Wire.requestFrom(Magnetometer,1);
if(Wire.available()<=1)
{
mZ0 = Wire.read();
}
Wire.beginTransmission(Magnetometer); // transmit to device
Wire.write(Magnetometer_mZ0);
Wire.endTransmission();
Wire.requestFrom(Magnetometer,1);
if(Wire.available()<=1)
{
mZ1 = Wire.read();
}
//---- X-Axis
mX1=mX1<<8;
mX_out =mX0+mX1; // Raw data
// From the datasheet: 0.92 mG/digit
Xm = mX_out*0.00092; // Gauss unit
//* Earth magnetic field ranges from 0.25 to 0.65 Gauss, so these are the values that we need to get approximately.
//---- Y-Axis
mY1=mY1<<8;
mY_out =mY0+mY1;
Ym = mY_out*0.00092;
//---- Z-Axis
mZ1=mZ1<<8;
mZ_out =mZ0+mZ1;
Zm = mZ_out*0.00092;
//Calculating Heading
heading = atan2(Ym, Xm);
// Correcting the heading with the declination angle depending on your location
// You can find your declination angle at: http://www.ngdc.noaa.gov/geomag-web/
// At my location it's 13 degrees => 0.226 rad
declination = 0.226;
heading += declination;
// Correcting when signs are reveresed
if(heading <0) heading += 2*PI;
// Correcting due to the addition of the declination angle
if(heading > 2*PI)heading -= 2*PI;
headingDegrees = heading * 180/PI; // The heading in Degrees unit
// Smoothing the output angle / Low pass filter
headingFiltered = headingFiltered*0.85 + headingDegrees*0.15;
//Sending the heading value through the Serial Port to Processing IDE
Serial.println(headingFiltered);
//lcd.print(gps.course.deg(),0);
delay(50);
}
}
}
}
So there is the code I'm using. The GPS works fine. The magnetometer works fine. But when I combine them the LCD goes blank. It compiles with no errors. At the moment the magnetometer outputs to the serial monitor instead of the LCD. It looks to me like Serial3 never becomes available so the sketch exits the loop and only the mag gives the correct output to the monitor. If I remove all the mag code, the output to the lcd looks perfect.
The posted code does not compile without errors. There are too many brackets "{".
It looks to me like Serial3 never becomes available
That is easy enough to check and fix. GPS units output NMEA sentences regardless of whether they have a satellite fix. Put in Serial.print statements to make sure.
With TinyGPS++, the following is not the correct way to determine whether you have a valid location. Study the example code and documentation more carefully.
if (gps.satellites.value() > 0) {