How to make this display a negative value correct

I am using this little routine to display a value on a LCD display:

String displayAxis(double axis)  {
  static char Buffer[7];
  String SString = "";
  if(axis < 10.0)   { 
    SString += " "; 
  }
  if(axis < 100.0)  { 
    SString += " "; 
  }
  dtostrf(axis,4, 2, Buffer);
  return SString += Buffer;
}

this is the calling code:

      lcdSerial.setCursor(0,1);
      lcdSerial << " X/Y  " << displayAxis((float)newXAxis) << " " << displayAxis((float)newYAxis);
      lcdSerial.setCursor(0,2);
      lcdSerial << "Rotor " << displayAxis((long)rotorXAxis) << " " << displayAxis((long)rotorYAxis);

But if the number is negative it jumps to the next line.
The LCD used is a 20x4 character display and the maximum number to be displayed is 180.00 and the negative number looks like -9.00.

Any help would be welcome

your code does not show something obvious wrong to me.

try this..., no string class needed ...

char * displayAxis(double axis)  {
  static char buffer[9];
  uint8_t idx = 0;
  if (axis < 10.0)  buffer[idx++] = ' ';
  if(axis < 100.0) buffer[idx++] = ' ';
  dtostrf(axis,4, 2, &buffer[idx]);
  return buffer;
}

Here is a test snippet which consistently writes to the second line:

        lcd.clear();
        lcd.setCursor(0,1);
        int newAxis = 100; 
        
        //String Buffer =  displayAxis(newAxis);
        //lcd.print(Buffer); 
        lcd.print(newAxis); 
        break;

and here is my code which works just fine when I comment the test code out:

        lcd.clear(); 
        lcd.print("Running....");
        lcd.setCursor(0,2); 
        lcd.print(freq1);  // initial entry frequency  
         break;

I would suspect the formating in display Axis, also if you suing same LCD library keep in mind it MAY not initialize properly.
The one I am using has a note that it initilaizes properly only on factory default - on power. up.
I cannot make my to behave any differently after power -up.
Good luck.
Vaclav

I was able to make it fail using LCD 16x2 setup

setCurstor(0,1) and output more that 16 characters to the first line - works fine on first try
output less than 16 characters next time and it goes to the second line

Remove the setCursor (0,1)
output less than 16 characters and it goes to first line OK

The gotcha is - the LCD line has MORE than visible # of characters in a line and they do not get cleared by the LCD clear function.
So they are there (probably some kinda of character count) and the next write gets rolled over to the second line.

Another reason to ditch the LiquidCrystal,h library IMHO.

My workaround - limit # of characters per line - for now.

Cheers
Vaclav

The tests for the magnitude of axis only work for positive axis, not negative - the absolute
value should be taken before comparing to 10.0 or 100.0

MarkT:
The tests for the magnitude of axis only work for positive axis, not negative - the absolute
value should be taken before comparing to 10.0 or 100.0

But then remains the question how to print the -n sign?

If the value is less than zero, print a '-' character.

You should read the document. If your maximal is 100.00 and possibly -100.00 as minimal, then you need 7 total spaces and DON'T pad it with spaces, cause dtostrf does it already.

liudr:
You should read the document. If your maximal is 100.00 and possibly -100.00 as minimal, then you need 7 total spaces and DON'T pad it with spaces, cause dtostrf does it already.

I am surely missing something here as i dont see dtostrf padding spaces.
Now i have this code but stil no succes with the neg numbers.
I must bre dumber than dumb but i dont see it.

char * displayAxis(double axis)  {
  boolean isNeg = false;
  static char buffer[9];
  uint8_t idx = 0;
  uint8_t idl = 3;
  axis = axis/100;
  if(axis < 0.0) { 
//    buffer[idx++] = '-'; 
    Serial << "NEG" << endl;
    isNeg = true;
  }
  if(axis < 100.0 && !isNeg) { 
    buffer[idx++] = ' '; 
    idl = 2; 
  }
  if (axis < 10.0 && !isNeg) { 
    buffer[idx++] = ' '; 
    idl = 1; 
  }
  dtostrf(axis,idl, 2, &buffer[idx]);
  return buffer;
}

The idl should be the total number of spaces so it should not be 1 or 2, unless your number has just 1 or 2 spaces:

100.00 has a total of 6 spaces so the idl in your code should be 6.

i dont see dtostrf padding spaces.

It's implied by the 2nd argument being the "minimum" field width. It probably pads on the wrong side of the number, though.

dtostrf handles the minus sign as well. But your original code will generate 7 characters for -9.0: (two spaces, because -9 is less than both 10 and 100, a minus sign, a 9, a decimal point, and two zeros.) This may overflow the buffer and cause unpredictable behavior.

(Hmm. In fact, dtostrf() seems to pad the way you'd want it to. So if the number is never larger than 999.99 (or smaller than -999.99) you can probably get what you want with:

char * displayAxis(double axis)  {
  static char buffer[8];
  dtostrf(axis,7, 2, buffer);
  return buffer;
}
01234567890123456789
float: ' 987.12'
negat: '-747.45'

These things are worth debugging without the LCD in the equation, until you're sure that the strings you're getting are what you want.)

OP should read dtostrf() document, period. I've used it for quite some time and it always behaves as expected with positive and negative, no need to manually pad.