Right Align & Fast Update on Dispaly Required

I've been away from Arduining (?) for a while so please forgive the low level question.

I'm trying to display the real-time angle of a rotary table (driven by a stepper motor) on a milling machine. Currently using an LCD for testing but the final build will use a much faster OLED display.

The range of values I need to display are -359.99 to 359.99 degrees and for ease of reading I need to display these right aligned so that zero reads as [-xx0.00] with blank spaces where the x's are spaces and the minus sign is only displayed for negative values and and no leading zeros.

I know I can do this with a bunch of "if - then" code to check for things such as angle <100 or >-10, etc. and then print to the display at various positions, but I need improved update speed, I'd like this to update at the fastest possible rate the display can handle.

I have searched around and ended up getting more confused, for example, various topics recommend using printf or snprintf, but they often devolve into arguments between more experienced programmers. Also, this is currently being tested on an Arduino Nano 3.0 which I understand may or may not play well with snprintf.

Or is there another best practice? Again, speed is more important in this case than program size.

Thanks in advance

What flavor of OLED you thinking about? Possibly an Adafruit one?

-jim lee

On a nano sprintf() and snprintf() do not support float, so you cannot use those. dtostrf() will convert a float to a char array for printing, but the sign is floating instead of a fixed position. If you check for a negative number, you can print the sign separately then print the number as positive.

Have not tested to see how much time this takes, but I suspect any noticeable slowness in the display is caused elsewhere in the code, or you are updating much more than just the seven characters used for this number.

void setup() {
  Serial.begin(9600);
}

void loop() {
  float x = -359.99;
  disp(x);
  x = 359.87;
  disp(x);
  x = -9.87;
  disp(x);
  delay(5000);
}

void disp(float f) {
  char buff[8];
  if (f < 0) { //check for negative number
    Serial.print("-"); //manually print the negative sign
    dtostrf(-f, 6, 2, buff); //print the negative number as positive
  } else {
    dtostrf(f, 7, 2, buff); //print the positive number, allowing an extra space for the sign
  }
  Serial.print(buff);
  Serial.println(); //add newline for serial display, not needed for LCD
}

Are you using a fixed width font, or a proportional font, on the OLED?
Most LCDs use fixed width, so blanking things with spaces is easy.
The same applies to OLED if using fixed width fonts.

However, lots/most, OLED implementations/libraries use proportional fonts, and here using spaces to blank out unused more significant digits probably won’t help you. A space is rarely the same width as a digit in a proportional font....

Your library may have a right align print function. If so use that. Print the minus and absolute value separately.
If not maybe it has a string measure function, so you can use that to create a right align print.

If all else fails, then convert the value to a string and write your own “width” routine. Usually digits have fixed width (in any proportional font designed by a semi-competent individual anyway!) and then you just need a special case for the decimal point.

You will also need to cope with blanking any previously displayed more significant digits, and as I said spaces won’t help much with that. Although sometimes you can get lucky that two spaces are the exact width of one digit.

So you either clear the entire area first (with a rectangle fill) or work out the space between the right edge of any possibly displayed minus, and the left edge of the right aligned value, and just blank that area. The problem with clearing the entire area, as opposed to overwriting, is you may get flicker.

It’s either that, or write special cases for each and every value range as you suggest. My preference would be write a generic routine as described above that can cope with any length.

jimLee:
What flavor of OLED you thinking about? Possibly an Adafruit one?

-jim lee

Haven't tried the OLED yet, that is a later upgrade....maybe.

pcbbc:
Are you using a fixed width font, or a proportional font, on the OLED?
Most LCDs use fixed width, so blanking things with spaces is easy.
The same applies to OLED if using fixed width fonts.

Same as above regarding the OLED, but thanks for the head's up regarding spacing issues.

david_2018:
On a nano sprintf() and snprintf() do not support float, so you cannot use those. dtostrf() will convert a float to a char array for printing, but the sign is floating instead of a fixed position. If you check for a negative number, you can print the sign separately then print the number as positive.

Have not tested to see how much time this takes, but I suspect any noticeable slowness in the display is caused elsewhere in the code, or you are updating much more than just the seven characters used for this number.

Thanks very much for the code sample, I will give it a try. Sorry if I don't reply soon, it might be the weekend before I have time.

david_2018:

void setup() {

Serial.begin(9600);
}

void loop() {
  float x = -359.99;
  disp(x);
  x = 359.87;
  disp(x);
  x = -9.87;
  disp(x);
  delay(5000);
}

void disp(float f) {
  char buff[8];
  if (f < 0) { //check for negative number
    Serial.print("-"); //manually print the negative sign
    dtostrf(-f, 6, 2, buff); //print the negative number as positive
  } else {
    dtostrf(f, 7, 2, buff); //print the positive number, allowing an extra space for the sign
  }
  Serial.print(buff);
  Serial.println(); //add newline for serial display, not needed for LCD
}

Sorry it took so long to reply - been busy. This code works a treat. Thanks david_2018