Fixed decimal place on a Nokia 5110 using the PCD8544 library

As part of a larger project I need to get a compass system working so I've made a stand alone system using an Arduino Mega, a LSM303DLHC compass and a Nokia 5110 display, it's also battery powered. Everything is working fine with one small thing I would like to have, a fixed decimal place on the readout of the heading.

With a serial print statement you can define the number of decimal places like this "Serial.println(headingct, 2);"

I've tried the same format with writing to the LCD, "lcd.print(headingct, 2);" That doesn't work. Actually by changing that number it defines the total of digits in the displayed value but all with a floating decimal point. Obviously this is a function of the PCD8544.h library that I am using. I've looked through the library documentation, but I'm not very strong on how and what a library can do.

I've seen examples where people have divided the floating point number into 2 parts, the whole number and the fractional, then put them together as a string to be displayed. As with any programming problem there are always several ways to do the same thing. I'm looking for suggestions as to different and the better way to do this. As I see it I have a couple of options.

  1. See if there is a way to do this with the PCD8544 library
  2. Use a different library that has that function
  3. Divide the number into 2 parts and make a string
  4. Live with it as is. Other than my OCD to have it that way it's not a big deal, other things to work on

Below is my code, it is dived into 2 tabs, the main loop and the functions to read the LSM303 and tilt compensate the reading.

I could not include all of the code as it exceeded the max number of characters so I've just included the main loop.

Thanks in advance for all suggestions and comments
John

Main Loop

// Nokia demo from Raplh Bacon
// Added LSM303 Compass

#include "Arduino.h"
#include <PCD8544.h>
#include "Wire.h"
#include <Adafruit_Sensor.h>
#include <Adafruit_LSM303.h>


// Create the LCD object (using a library class)
static PCD8544 lcd;

// LSM303 variables

Adafruit_LSM303 lsm;

float Mx, My, Mz; // Raw Magnetometer measurements
float Mxc, Myc, Mzc; // Calibrated Magnetometer measurements
float Mxcn, Mycn, Mzcn; // Normalized Magnetometer measurements


float Ax, Ay, Az; // Raw Accelerometer measurments
float Axc, Ayc, Azc;  // Calibrated Accelerometer mesurements
float Axcn, Aycn, Azcn; // Normalized Accelerometer measurements


float norm_a, norm_m;

double pitch, roll;
double pitch_print, roll_print;
double tiltcnf;

double Xh, Yh;  // Tilt compensated values for heading calculation
float headingct; // Calibrated and tilt compensated heading


//calibrated_values[3] is the global array where the calibrated data will be placed
//calibrated_values[3]: [0]=Xc, [1]=Yc, [2]=Zc
float calibrated_mag_values[3];
float calibrated_acc_values[3];

float alpha = 0.25; // Low-Pass Filtercoefficient

// Filtered Magnetometer measurements
float Mxcnf = 0;
float Mycnf = 0;
float Mzcnf = 0;

// Filtered Accelerometer measurements
float Axcnf = 0;
float Aycnf = 0;
float Azcnf = 0;



// =============================================================================
// SETUP     SETUP     SETUP     SETUP     SETUP     SETUP     SETUP     SETUP
// =============================================================================
void setup() {
  Serial.begin(9600);
   Wire.begin();
   lsm.begin();
  
  // Nokia 5110 has 84W x 48H pixels
  lcd.begin(84, 48);
  lcd.clear();

  Serial.println("Setup Completed");
}

// =============================================================================
// LOOP     LOOP     LOOP     LOOP     LOOP     LOOP     LOOP     LOOP     LOOP
// =============================================================================
void loop() {
  
  // call compass sketch
  compass();

// Nokia Display***************************************  
 
  // Position is COL, ROW
  lcd.setCursor(0, 0);

  // For PRINT statement it works out the actual pixel start point
  lcd.print("Heading");

   // set the LCD contrast...
    short level = 63; //contrast level = 0 to 127);
    lcd.setContrast(level);

     // Write out the heading
   
    lcd.setCursor(0, 2);
    lcd.print(headingct, 2); // DEC


} // end void loop

Please provide a clickable link to the GitHub page for the PCD8544 library you're using.

I started out with a demo project for the Nokia from the Ralph Bacon Youtube channel, He has some good projects and very informative. Here's the link

Thanks

The PCD8544 class inherits from Print:

class PCD8544: public Print {

Therefore, "lcd.print(headingct, 2);" should do exactly the same thing with the number of digits after the decimal point as "Serial.println(headingct, 2);". I'd think I'd start by looking into why it appears not to with your code.

Thanks for looking into that but I guess that is the question, why doesn't it work? When I change the number in that statement it changes the number of total digits for example

with lcd.print(headingct, 1) I get 5 characters from 1.234 to 123.4
with lcd.print(headingct, 2) I get 6 characters from 1.2345 to 123.45
with lcd.print(headingct, 3) I get 7 characters from 1.23456 to 123.456

So it does make a change but not in the way that serial.print does, I've tried that and it does limit the decimal place no matter the size of the whole number, and the decimal is floating based on the whole number. The compass reads from 0 to 359, so I only get 3 characters max for the whole number

Thanks again
John

Stumpy_L:
Thanks for looking into that but I guess that is the question, why doesn't it work? When I change the number in that statement it changes the number of total digits for example

with lcd.print(headingct, 1) I get 5 characters from 1.234 to 123.4
with lcd.print(headingct, 2) I get 6 characters from 1.2345 to 123.45
with lcd.print(headingct, 3) I get 7 characters from 1.23456 to 123.456

I don't understand what that means. What is the VALUE of the 'headingct' you're trying to print?

Stumpy_L:
Here's the link
GitHub - RalphBacon/Nokia-5110-TFT: Connect your Arduino to the ubiquitous Nokia 5110 TFT

I don't know what that means either, and I wouldn't rush to that link, the 5110 was probably obsolete before TFT was invented.

I assume you know the range of the readings and I guess all you need is leading blanks. So simple code might be

if var<100.0
{ 
lcd.print(" ");
}
if var<10.0
}
lcd.print(" ");
{

You can do the same sort of thing with cursor control.

First to explain what I was trying to point out as far as the number of characters, The compass gives me a value between 0 and 360 with a large number of decimal places if I don't use the format. If I use, lcd.print(headingct, 2) I get a total of 6 characters on the display

if the value is 5.7685345 then the display shows 5.6685
if the value is 25.764532 then the display shows 25.764
if the value is 275.963426 then the display shows 275.96

Always 6 characters but the number of decimal places changes based on the number of characters in the whole number portion.

I don't know why he has TFT in the file name. All I know is if I load his demo code into the Nokia it works. I then modified his code to add my compass in. Maybe it would be best to just use a different library like the adafruit graphics one that I have also used in some of their examples.

Thanks for your time
John

Are you sure the space is completely blank before doing the print? Perhaps you're looking at characters left over from a previous print.

The standard Philips PCD8544 is fine. The only problem with it is that the pin connections are included, which is clearly not a problem for you.

I'm sure there is a command for for limiting the number of decimal places, and I thought that what you have is it, and you would always get two dp. I won't ask why you would have two dp from a compass. I have never had to address this myself as my sensors only deliver to two places, and thus the problem is about leading blanks.

Respecting gfvalvo's point, I understand you do not have a problem with trailers. If you do, inserting a trailing blank is a quick'n'dirty fix.

gfvalvo, I think you have found the problem and I should have thought of it earlier as I ran into this before. It is not clearing the previous reading so when my whole number goes from 3 places to 1 the decimal has shifted to the left with only 2 places but I am still seeing the last 2 digits of the previous number. I will have to clear the reading first then write a new value.

I wont be able to test this until later today but I'm sure that is the problem. I will post what I find out after testing it.

Thanks so much, I always great great answers from this forum
John

gfvalvo, Thanks for reminding me, that was the problem. As I mentioned I had this problem before and looked into that sketch to see how I fixed it. I converted the float to a str, define the number of digits, including the decimal point and the number of decimal places,

dtostrf(headingct, 6, 2, str); then just printed the string lcd.print(str);

This solved a couple of problems, it not only keeps it to 2 decimal places it also keeps the decimal point in a fixed spot on the display no matter the number of digits in the whole number. I didn't have to print a blank value to clear the previous value as that causes the display to flicker.

Thanks again for all the comments and discussion
John