How to remove trailing numbers of an int

I’m working on an arduino rpm gauge for my car and it works great except for one small issue. I’m not sure if trailing numbers is the correct term but this is what happens when I run my code. As long as the rpm being displayed on the LCD stays in the length of 3 digits(<999 rpm’s) the data is displayed correctly. Above 1000 rpm’s when 4 digits are being displayed it also works correctly. Once the rpm’s fall back below 1000 the first 3 digits are the correct rpm but there is still a fourth digit that is being displayed and it doesn’t change until the rpm’s go back over 1000 then the fourth digit displays the correct rpm again.

Example: 800rpm shows as 800, 1200rpm shows as 1200, back to 800rpm and it might show as 8004. The last digit is always a random number. I have no idea what this is called or how to fix it. Here is the code I’ve been using to try and figure this out but I’m no expert and would appreciate any help.

#include <UTFT.h>
#include <Arduino.h>
#include <OBD2UART.h>


// Declare fonts
extern uint8_t SevenSegNumFontPlusPlus[];
extern uint8_t GroteskBold32x64[];

//Pins
UTFT myGLCD(ITDB43,38,39,40,41); 

COBD obd;


void RPM()
{
      int value;
      obd.readPID(PID_RPM, value);
      myGLCD.printNumI(value, 280, 145); 
      
}


void setup()
{
  // Begin obd and connect, init Lcd
  myGLCD.InitLCD();
  myGLCD.clrScr();
  obd.begin();
  
  myGLCD.setBackColor(0, 0, 0);  //Screen color
  myGLCD.setFont(GroteskBold32x64);
  myGLCD.setColor(255, 215, 0);  //font color
  do
  {
   myGLCD.print("Wait...", CENTER, 110); 
  }
  while (!obd.init());
  myGLCD.clrScr();
  myGLCD.setColor(255, 255, 255);
  myGLCD.setFont(SevenSegNumFontPlusPlus);

  
void loop()
{
    RPM();
}

It seems like the length must get set by the highest number of digits that are displayed. So once it has displayed the four digits, it automatically keeps it set at 4.

This might be a cheat of a workaround but can you set the length argument to the printNumI method to 4 and use a space as the filler?

e.g.: myGLCD.printNumI(value, 280, 145, 4, ' ');

I think that the problem is that you don't 'clear' the line where you are writing the RPM. So the last digit that you see is from the previous reading that was 4 digits. So if the last reading before was 1001 and the new one is 999, the result is 9991.

So you need to write 4 spaces first to clear and next write the real value.

You can also use sprintf to format the text as an easy work around; demo for serial port below.

void setup()
{
  // buffer; 4 digits and terminating nul
  char rpmBuffer[5];
  
  Serial.begin(115200);

  int rpm = 999;

  // left padded with space
  sprintf(rpmBuffer, "'%4d'", rpm);
  Serial.println(rpmBuffer);

  // right padded with space
  sprintf(rpmBuffer, "'%-4d'", rpm);
  Serial.println(rpmBuffer);
}

void loop()
{

}

The single ticks are there to make the spaces 'visible'; result

' 999'
'999 '

I use a simple trick dtostrf(value,NumberStringLength,Precision,CharString)

char S[30]; // more characters than you will ever use
int val = 100; // The value to convert to a string. can be byte, int or float and signed or unsigned.
len = 4;// this will fit the value into a 4 char string 
// making len = -4 will left justify the number (cool) spaces and negative sign will be used for proper display
prec = 0; // how many decimal places (0 for int)
dtostrf((float)val,len,prec,S);
lcd.setCursor(0, 0);
lcd.print(S);

Instead of this:

myGLCD.printNumI(value, 280, 145);

try using this:

myGLCD.printNumI(value, 280, 145, 4); // take up 4 digits worth of room

As I think has already been mentioned, it's not a data type problem.

When the LCD gets written, each spot remembers what it was told. No sense changing what doesn't need to change. But that means the stuck digit sticks if it doesn't get told to change. Simplest fix is just adding lcd.clear(); at the beginning or ending of the loop, or just prior to the printing.

The stuff other people said will work too, probably forces a literal "space" to be written when no digits are there, or you can force a 0 at the left most if it's always forced to present the data as a 4 digit and gets a 3 digit number.

INTP: The stuff other people said will work too, probably forces a literal "space" to be written when no digits are there, or you can force a 0 at the left most if it's always forced to present the data as a 4 digit and gets a 3 digit number.

I left that out as I did not expect it to be useful for rpm ;)

  // left padded with zeroes
  sprintf(rpmBuffer, "'%04d'", rpm);

I didn't read all that well into the code, maybe his LCD is a bit fancier than what I've been working with.

Now that I looked at the code, there's a library for hooking up to a car's OBD? Man, just what I need, another thing to waste time exploring. :)

INTP: . . . hooking up to a car's OBD?

On Board Diagnostics ?

Yes?

I plug my car into my laptop to run codes and change things here and there, guess it makes sense Arduino can do a few things.

Thank you all for the help. I haven’t had the chance to try all of these yet, but I did try setting the length to 4 and using a “space” as a filler. It works great. I tried lcd.clrscr() but I wanted to avoid this to keep the screen from having to reprint all of the other data and causing the screen to flash. This is the change I made.

void RPM()
{
      int x = myGLCD.getDisplayXSize() / 2;
      int y = myGLCD.getDisplayYSize() / 2;
      int value;
      obd.readPID(PID_RPM, value);
      if(value <= 999)
      {
        myGLCD.printNumI(value, x, y, 4, '/');
      }
      else
      {
        myGLCD.printNumI(value, x, y, 4);
      }
}

For those interested in more info about arduino and obd2, this is where I got the adapter. freematics.com
Again, Thanks.

I have no experience using this unit but from the description in their user manual, I think the if statement is unnecessary. If the number is already four numerals long, it should just ignore the filler character.