Issues with showing text on OLED display SSD1351

Hello,

I am using following components:

  • Arduino Nano
  • RGB OLED display 1,5" : Waveshare, 128x128 Pixels, SPI

I want to use the display as a speedmeter just with a simple code:

#include <Adafruit_GFX.h>
#include <Adafruit_SSD1351.h>
#include <SPI.h>
#include <Fonts/FreeMonoBold12pt7b.h>
#include <stdio.h>

// Definitions for Display
#define SCREEN_WIDTH  128
#define SCREEN_HEIGHT 128
#define RST_PIN  8
#define DC_PIN   7 //9 
#define CS_PIN   10
#define MOSI_PIN 11
#define SCLK_PIN 13
// Color definitions
#define	BLACK           0x0000
#define	BLUE            0x001F
#define	RED             0xF800
#define	GREEN           0x07E0
#define CYAN            0x07FF
#define MAGENTA         0xF81F
#define YELLOW          0xFFE0  
#define WHITE           0xFFFF

Adafruit_SSD1351 oled = Adafruit_SSD1351(SCREEN_WIDTH, SCREEN_HEIGHT, &SPI, CS_PIN, DC_PIN, RST_PIN);


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

  oled.begin();  
  oled.fillRect(0, 0, 128, 128, BLACK);
  ...
}

void loop() {
  oled.setFont(NULL);
  oled.setTextSize(2);
  oled.setTextColor(WHITE);
  oled.setCursor(0,0);
  oled.println("Speed:");

  oled.setFont(&FreeMonoBold12pt7b);
  oled.setTextColor(WHITE, BLACK);
  oled.println(actualSpeed());
  
  delay(20);
}

actualSpeed() is providing the speed as double.

Now I have some questions:

  1. Remove rest of the line:
    Without oled.setFont(&FreeMonoBold12pt7b); I am getting a proper view on the display:

But when speed was higher (like 23.65) and then getting lower again, the last digit is not removed:

The speed value is correctly updating, by overwriting the old value, but how can I clean the space behind thre speed-value?

  1. Using individual fonts:
    When using an individual font (having code oled.setFont(&FreeMonoBold12pt7b); included),
    2.a: the speed value is somehow overlapping the text.line above ("Speed:"):
    2.b: the old speed-value is not being deleted before placing the new speed-value:

How can I fix this?

As I am not an Arduino-/c-expert, I wonder, if you might give me some hints about how to adjust the code, to fix the issues.

Thanks a lot.

What is this?

If you have values that go from units to tens to hundreds, I "pad" the unused places, for example:

if (actualSpeed < 10) oled.print(" "); // pad units
if (actualSpeed < 100) oled.print(" "); // pad tens
oled.println(actualSpeed());

Hi,

"..." means that I left out some code not being relevant for the initial problem.

I now found out at least some solutions:

instead of using println (print line) I used print:

  oled.print(actualSpeed());
  oled.print(" "); 

This helps removing characters from last shown value. If system has shown 22.34 and then want to show 8.23, it will not end up in 8.234 (4 from 22.34), but correctly is showing 8.23.

By using setCursor, I can define the starting point (x/y coordinates) of where the next text shall appear:

  oled.setCursor(100,90);
  oled.print(actualSpeed());
  oled.print(" "); 

Using setTextColor (with defining backgroud color) helps hiding former figures, when overwriting existing text with new values:

  oled.setTextColor(WHITE, BLACK);
  oled.print(actualSpeed());

BUT I still wonder, how to manage other fonts:

How can I manage to overwrite existing text with new text without still having the old text in the background?

  oled.setFont(&FreeSansBold9pt7b);
  //oled.setTextSize(3);
  oled.setTextColor(WHITE, BLACK);
  oled.print(actualSpeed());

This is how my overall code looks like:

#include <Adafruit_GFX.h>
#include <Adafruit_SSD1351.h>
#include <SPI.h>
//#include "OLED_Driver.h"
//#include "GUI_paint.h"
//#include "DEV_Config.h"
//#include "Debug.h"
#include <Fonts/FreeSansBold9pt7b.h>
//#include <stdio.h>

// Definitions for Speedsensor
#define HALL_SENSOR_TRIGGER_PIN 0 // Hall-Sensor connected to D2 (Interrupt 0)
#define TIRE_PERIMETER 104 // dimension of tire in cm

// Definitions for Display
#define SCREEN_WIDTH  128
#define SCREEN_HEIGHT 128
#define RST_PIN  8
#define DC_PIN   7 //9 
#define CS_PIN   10
#define MOSI_PIN 11
#define SCLK_PIN 13
// Color definitions
#define	BLACK           0x0000
#define	BLUE            0x001F
#define	RED             0xF800
#define	GREEN           0x07E0
#define CYAN            0x07FF
#define MAGENTA         0xF81F
#define YELLOW          0xFFE0  
#define WHITE           0xFFFF

Adafruit_SSD1351 oled = Adafruit_SSD1351(SCREEN_WIDTH, SCREEN_HEIGHT, &SPI, CS_PIN, DC_PIN, RST_PIN);


volatile unsigned long lSpeedDuration = 0;
volatile unsigned long lSpeedLastTime = millis();
volatile double dLastUnchangedSpeed = 0;
volatile unsigned long dLastUnchangedSpeedTime = millis();
volatile double dMaxSpeed = 0;



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

  oled.begin();  
 // oled.fillRect(0, 0, 128, 128, BLACK);
 // oled.println("Luca Infento");
//   oled.println("Booting");
//   oled.print(".");
//   delay(500);
//   oled.print(".");
//   delay(500);
//   oled.print(".");
//   delay(500);
//   oled.print(".");
//   delay(500);
//   oled.print(".");
//   delay(500);
 
  //clear display
  oled.fillScreen(BLACK); //fillRect(0, 0, 128, 128, BLACK);

  // attachInterrupt(interrupt-port,function to be called,mode);
  // Modi LOW,CHANGE,RISING,FALLING
  attachInterrupt(HALL_SENSOR_TRIGGER_PIN, measureSpeed, RISING);

}

void loop() {

  oled.setFont(NULL);
  oled.setTextSize(2);
  oled.setTextColor(WHITE);
  oled.setCursor(0,0);
  oled.println("Speed:");

  oled.setCursor(10,80);
  oled.setFont(&FreeSansBold9pt7b);
  //oled.setTextSize(3);
  oled.setTextColor(WHITE, BLACK);
  oled.print(actualSpeed());
  oled.print(" "); 
  oled.setFont(NULL);
  oled.setTextSize(1);
  oled.setTextColor(WHITE, BLACK);
  oled.setCursor(100,90);
  oled.println("km/h");

  oled.drawLine(0, 115, 128, 115, YELLOW);
  oled.setFont(NULL);
  oled.setTextSize(1);
  oled.setTextColor(YELLOW, BLACK);
  oled.setCursor(0,120);
  oled.print("max. Speed: ");
  //oled.setCursor(70,120);
  oled.print(dMaxSpeed);
  //oled.setCursor(102,120);
  oled.print("km/h");

  delay(200);


}

void measureSpeed() {
  unsigned long lStartTime = millis();
  lSpeedDuration = lStartTime - lSpeedLastTime; // time in ms for one round of the tire
  lSpeedLastTime = lStartTime;  
}

double actualSpeed(){
  double lRPM;
  double dSpeed;

  if (lSpeedDuration == 0) {
      lRPM = 0;
  } else {
      lRPM = 60000 / lSpeedDuration;
  }

  dSpeed = lRPM * TIRE_PERIMETER / 100 * 60 / 1000;

  // set speed to 0, if speed hasn't changed for a while
  if (dSpeed == dLastUnchangedSpeed) {
    if ((millis() - dLastUnchangedSpeedTime) > 2000) {
      dSpeed = 0;
      lSpeedDuration = 0;
    }
  } else {
    dLastUnchangedSpeedTime = millis();
    dLastUnchangedSpeed = dSpeed;
  }
  
  if (dMaxSpeed < dSpeed) {
    dMaxSpeed = dSpeed;
  }

  return dSpeed;
}

Couple of things you need to be careful of:

First, the default font used by Adafruit's libraries has the ability to overwrite the previous text by specify a font color and a background color, "setTextColor(WHITE, BLACK)" as an example. The true type fonts DO NOT behave like this, the fonts are transparent, only writing the text color and leaving the background as it is. To erase the background text, you will need to either draw a box over the old text using the background color, or a slightly faster technique is to save the value that was previously printed to the screen and print it with the text color set to the background color before printing the new value.

Second, when setting the cursor position, the default font is referenced to the cursor being at the upper left corner of the character, while the true type fonts are referenced to the cursor being at the lower left corner (at what Adafruit refers to as the baseline of the text, I don't recall if this includes portions of the character that go below the "baseline" such as the lower portion of "y"). This is why changing font resulted in the numbers overwriting "speed" in your original code.

One other comment, a common technique with displays is to only display a value when it changes, so that you do not get a perceptible blinking when erasing and rewriting the same value continuously. This involves saving the previous value that was displayed and comparing it with the current value to see if it has changed. Re-displaying portions of the display that never change is also not needed, such as printing "speed" every time through loop.

Hi David,

thank you so much! Great ideas. I just tried to get them in.

I excluded all static content into a separate procedure, which will get triggered only once in the setup() function.

Then I stored the last speed-value and write it agian in black, before writing the new speed.
Surprising to me, that I cannot do it right after each other:

    oled.setCursor(10,80);
    oled.setFont(&FreeSansBold24pt7b);
    oled.setTextColor(BLACK);
    oled.println(dLastSpeed);

    oled.setCursor(10,80);
    oled.setFont(&FreeSansBold24pt7b);
    oled.setTextColor(WHITE);
    oled.println(dDisplaySpeed);

...will not make it properly. Then I still see old values in white.

    oled.setCursor(10,80);
    oled.setFont(&FreeSansBold24pt7b);
    oled.setTextColor(BLACK);
    oled.println(dLastSpeed);

    oled.setFont(NULL);

    oled.setCursor(10,80);
    oled.setFont(&FreeSansBold24pt7b);
    oled.setTextColor(WHITE);
    oled.println(dDisplaySpeed);

... will make it, BUT the speed-value is flickering.
Do you have any further hints?

Set the font before setting the cursor position, otherwise the cursor may shift when changing from the default font to the free font.

Only print the value when it changes to reduce the blinking.

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.