Help trying to display compass reading onto 16x2 Lcd

Hi Guys, I have a HMC5883L Compass connected to an arduino UNO. When I open the serial monitor I get the heading in degrees which is what I want. I no want to send the heading to an lcd display.
I have also connected the Lcd to the UNO and displayed the word HELLO WORLD as stock which prints onto the screen so i know the Lcd is hooked up correctly.

THE PROBLEM
I have tried to merge the 2 codes together, which i have pasted below. I cant seem to get the Lcd to display the heading. Has anyone got any pointers.

Many thanks Ian

CODE:

#include <Wire.h>
#include <HMC5883L.h>
HMC5883L compass;
int error = 0;
#include <LiquidCrystal.h>
LiquidCrystal lcd(12, 11, 5, 4, 3, 2);

void setup()
{

lcd.begin(16, 2);
Serial.begin(9600);
Serial.println("Starting the I2C interface.");
Wire.begin();
Serial.println("Constructing new HMC5883L");
compass = HMC5883L();
Serial.println("Setting scale to +/- 1.3 Ga");
error = compass.SetScale(1.3);
if(error != 0)
Serial.println(compass.GetErrorText(error));
Serial.println("Setting measurement mode to continous.");
error = compass.SetMeasurementMode(Measurement_Continuous);
if(error != 0)
Serial.println(compass.GetErrorText(error));

}
void loop()
{
MagnetometerRaw raw = compass.ReadRawAxis();
MagnetometerScaled scaled = compass.ReadScaledAxis();
int MilliGauss_OnThe_XAxis = scaled.XAxis;
float heading = atan2(scaled.YAxis, scaled.XAxis);
float declinationAngle = 0.0457;
heading += declinationAngle;
if(heading < 0)
heading += 2PI;
if(heading > 2
PI)
heading -= 2*PI;
float headingDegrees = heading * 180/M_PI;
Output(headingDegrees);
}
void Output(float headingDegrees)
{
Serial.print(headingDegrees);
Serial.println(" Degrees \t");
delay(900);
lcd.write(Serial.read());
}

Have you tried to print floats on the LCD?

lcd.print(3.14159265);

hi Rob,
I have no idea what that is meant to do, i am new to this.

Thanks

lcd.print() prints to lcd , but it might be that the lcd library does not support the printing of floats.

I suspect this float stuff is all rubbish. You should be able to send the same information in the same way to the monitor, the LCD, and the SD,

Serial.print(variable);
lcd.print(variable);
myFile.print(variable);

and you say the serial is no problem.

If your HELLO WORLD has the command lcd.write, I'm wrong, but I think the real problem might be that you are sayng "lcd.write" where you should be saying "lcd.print". If you change all the writes to print, it might work.

What are you trying to do with this

lcd.write(Serial.read());

You need to access the data to send to the lcd the same way you get it for the serial.I believe Serial.read is for reading data/characters from the computer, not the arduino. Maybe

lcd.print(headingDegrees);
lcd.print" Degrees   \t";

will work, then format on the lcd like you want. You have to use seperate commands for Serial.print and lcd.print.

TomJ

@Nick_Pyner
+1
lcd.write() => lcd .print()

robtillaart:
lcd.write() => lcd .print()

I don't understand this. Are you saying the lcd.write is the equivalent or superior to lcd.print?

So it's OK to replace lcd.print with lcd.write?

lcd.write will only send one byte to the lcd, it is the basic mechanism
lcd.print uses write under the hood to sen int's and longs and strings etc.

with the arrow I meant replace the lcd.write in your code with lcd.print

robtillaart:
lcd.write will only send one byte to the lcd, it is the basic mechanism

Actually, this is incorrect.
the write() function is overloaded.
There are 3 versions of write()

  • write(unsigned char) outputs a single byte.
  • write(const char * str) which is assumed to be a pointer to a C string
    so the function will output all the characters in the in the C string pointed to by the pointer.
  • write(const uint8_t *buffer, size_t size) which outputs the specified number of bytes
    starting at the buffer pointer.

The standard LiquidCrystal library (which appears to be what is being used) supports
printing floats.

It isn't clear what the intent of this code is and it
looks like it may not do what is probably expected:
void Output(float headingDegrees)
{
Serial.print(headingDegrees);
Serial.println(" Degrees \t");
delay(900);
lcd.write(Serial.read());
}
It prints some information on the serial port then
after waiting 900ms (just less than 1 second), it will then call Serial.read() to read a single character
from serial port buffer.
The read() function returns either 1 single character from the UART/Serial buffer or -1 if no characters are in the buffer.
Serial.read() is not blocking i.e. it will not wait for input. It will immediately return with either a single character from
the RX buffer or a -1 if none are available.

If no character is available the -1 or 0xffff will be passed to lcd.write(), lcd.write() is only looking
at the lower 8 bits so it will end up sending a 0xff to the LCD. A 0xff on many hd44780 displays
will be full block of pixels.


So this Output() function seems very strange to me.
It outputs some information to the serial port, then it tries to read a single character from the serial port.
If there is a character in the serial RX buffer, the character is pushed to the lcd, if there is no character
in the serial RX buffer, a 0xff is send to the lcd which on most lcds will be a full block of pixels.
I'm assuming this is not the desired behavior.

--- bill

Actually, this is incorrect.

That is correct, there are three, but the first overload will be used.

I cant seem to get the Lcd to display the heading. Has anyone got any pointers.

OK, it seems that all pointers given are not understood well enough,

Have you tried printing the variable headingDegrees directly?

void Output(float headingDegrees)
{
  Serial.print(headingDegrees);
  Serial.println(" Degrees   \t");
  lcd.write(headingDegrees); //<<<<<<<<<<<<<<
}

Note: you cannot read back from serial what you wrote to it unless there is an echo app on the other site

I'm trying to do the exact same project and with help from here, I've got it!!! Here's the code!!

Key was lcd.print(heading)

#include <LiquidCrystal.h>
LiquidCrystal lcd(8, 9, 4, 5, 6, 7);

#include <Wire.h>
#include <HMC5883L.h>

HMC5883L compass;

int incomingByte = 0;   // for incoming serial data. REMOVED, NO EFFECT
int error = 0;

void setup()
{
 Serial.begin(9600);
 Wire.begin();
 
 compass = HMC5883L(); //new instance of HMC5883L library
 setupHMC5883L(); //setup the HMC5883L
 
  lcd.begin(16, 2);
  lcd.setCursor(0,0);
  lcd.print("COMPASS ver 1"); 
  lcd.setCursor(0,1);
  lcd.print("Heading=");
}
void loop()
{
  lcd.setCursor(10,1);     // move cursor to second line "1" and 10 spaces over
  {
  float heading = getHeading();
 Serial.println(heading); //REMOVED, NO EFFECT
 
 lcd.print(heading); //PRINTS HEADING!
 
  delay(100); //only here to slow down the serial print
  }
}
void setupHMC5883L(){
 int error; 
 error = compass.SetScale(1.3);
 if(error != 0) Serial.println(compass.GetErrorText(error));
 error = compass.SetMeasurementMode(Measurement_Continuous);
 if(error != 0) Serial.println(compass.GetErrorText(error));
}
float getHeading(){
 MagnetometerScaled scaled = compass.ReadScaledAxis();
 float heading = atan2(scaled.YAxis, scaled.XAxis);
 if(heading < 0) heading += 2*PI;
 if(heading > 2*PI) heading -= 2*PI;
 return heading * RAD_TO_DEG;
 }

It works, I had just // out some settings to reset the serial data. Fixed it and re pasted sketch in post above.

http://forum.arduino.cc/index.php?topic=292039.msg2040569#msg2040569